tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

LocalStorageManager2.cpp (18396B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "LocalStorageManager2.h"
      8 
      9 // Local includes
     10 #include "ActorsChild.h"
     11 #include "LSObject.h"
     12 
     13 // Global includes
     14 #include <utility>
     15 
     16 #include "MainThreadUtils.h"
     17 #include "jsapi.h"
     18 #include "mozilla/Assertions.h"
     19 #include "mozilla/ErrorResult.h"
     20 #include "mozilla/OriginAttributes.h"
     21 #include "mozilla/RefPtr.h"
     22 #include "mozilla/RemoteLazyInputStreamThread.h"
     23 #include "mozilla/dom/LocalStorageCommon.h"
     24 #include "mozilla/dom/PBackgroundLSRequest.h"
     25 #include "mozilla/dom/PBackgroundLSSharedTypes.h"
     26 #include "mozilla/dom/PBackgroundLSSimpleRequest.h"
     27 #include "mozilla/dom/Promise.h"
     28 #include "mozilla/dom/quota/PrincipalUtils.h"
     29 #include "mozilla/dom/quota/PromiseUtils.h"
     30 #include "mozilla/ipc/BackgroundChild.h"
     31 #include "mozilla/ipc/BackgroundUtils.h"
     32 #include "mozilla/ipc/PBackgroundChild.h"
     33 #include "mozilla/ipc/PBackgroundSharedTypes.h"
     34 #include "nsCOMPtr.h"
     35 #include "nsDebug.h"
     36 #include "nsError.h"
     37 #include "nsIEventTarget.h"
     38 #include "nsILocalStorageManager.h"
     39 #include "nsIPrincipal.h"
     40 #include "nsIRunnable.h"
     41 #include "nsPIDOMWindow.h"
     42 #include "nsStringFwd.h"
     43 #include "nsThreadUtils.h"
     44 #include "nscore.h"
     45 #include "xpcpublic.h"
     46 
     47 namespace mozilla::dom {
     48 
     49 namespace {
     50 
     51 class AsyncRequestHelper final : public Runnable,
     52                                 public LSRequestChildCallback {
     53  enum class State {
     54    /**
     55     * The AsyncRequestHelper has been created and dispatched to the
     56     * RemoteLazyInputStream Thread.
     57     */
     58    Initial,
     59    /**
     60     * Start() has been invoked on the RemoteLazyInputStream Thread and
     61     * LocalStorageManager2::StartRequest has been invoked from there, sending
     62     * an IPC message to PBackground to service the request.  We stay in this
     63     * state until a response is received.
     64     */
     65    ResponsePending,
     66    /**
     67     * A response has been received and AsyncRequestHelper has been dispatched
     68     * back to the owning event target to call Finish().
     69     */
     70    Finishing,
     71    /**
     72     * Finish() has been called on the main thread. The promise will be resolved
     73     * according to the received response.
     74     */
     75    Complete
     76  };
     77 
     78  // The object we are issuing a request on behalf of.  Present because of the
     79  // need to invoke LocalStorageManager2::StartRequest off the main thread.
     80  // Dropped on return to the main-thread in Finish().
     81  RefPtr<LocalStorageManager2> mManager;
     82  // The thread the AsyncRequestHelper was created on.  This should be the main
     83  // thread.
     84  nsCOMPtr<nsIEventTarget> mOwningEventTarget;
     85  // The IPC actor handling the request with standard IPC allocation rules.
     86  // Our reference is nulled in OnResponse which corresponds to the actor's
     87  // __destroy__ method.
     88  LSRequestChild* mActor;
     89  RefPtr<Promise> mPromise;
     90  const LSRequestParams mParams;
     91  LSRequestResponse mResponse;
     92  nsresult mResultCode;
     93  State mState;
     94 
     95 public:
     96  AsyncRequestHelper(LocalStorageManager2* aManager, Promise* aPromise,
     97                     const LSRequestParams& aParams)
     98      : Runnable("dom::LocalStorageManager2::AsyncRequestHelper"),
     99        mManager(aManager),
    100        mOwningEventTarget(GetCurrentSerialEventTarget()),
    101        mActor(nullptr),
    102        mPromise(aPromise),
    103        mParams(aParams),
    104        mResultCode(NS_OK),
    105        mState(State::Initial) {}
    106 
    107  bool IsOnOwningThread() const {
    108    MOZ_ASSERT(mOwningEventTarget);
    109 
    110    bool current;
    111    return NS_SUCCEEDED(mOwningEventTarget->IsOnCurrentThread(&current)) &&
    112           current;
    113  }
    114 
    115  void AssertIsOnOwningThread() const {
    116    MOZ_ASSERT(NS_IsMainThread());
    117    MOZ_ASSERT(IsOnOwningThread());
    118  }
    119 
    120  nsresult Dispatch();
    121 
    122 private:
    123  ~AsyncRequestHelper() = default;
    124 
    125  nsresult Start();
    126 
    127  void Finish();
    128 
    129  NS_DECL_ISUPPORTS_INHERITED
    130 
    131  NS_DECL_NSIRUNNABLE
    132 
    133  // LSRequestChildCallback
    134  void OnResponse(LSRequestResponse&& aResponse) override;
    135 };
    136 
    137 class SimpleRequestResolver final : public LSSimpleRequestChildCallback {
    138  RefPtr<Promise> mPromise;
    139 
    140 public:
    141  explicit SimpleRequestResolver(Promise* aPromise) : mPromise(aPromise) {}
    142 
    143  NS_INLINE_DECL_REFCOUNTING(SimpleRequestResolver, override);
    144 
    145 private:
    146  ~SimpleRequestResolver() = default;
    147 
    148  void HandleResponse(nsresult aResponse);
    149 
    150  void HandleResponse(bool aResponse);
    151 
    152  void HandleResponse(const nsTArray<LSItemInfo>& aResponse);
    153 
    154  // LSRequestChildCallback
    155  void OnResponse(const LSSimpleRequestResponse& aResponse) override;
    156 };
    157 
    158 nsresult CheckedPrincipalToPrincipalInfo(
    159    nsIPrincipal* aPrincipal, mozilla::ipc::PrincipalInfo& aPrincipalInfo) {
    160  MOZ_ASSERT(NS_IsMainThread());
    161  MOZ_ASSERT(aPrincipal);
    162 
    163  nsresult rv = PrincipalToPrincipalInfo(aPrincipal, &aPrincipalInfo);
    164  if (NS_WARN_IF(NS_FAILED(rv))) {
    165    return rv;
    166  }
    167 
    168  if (NS_WARN_IF(!quota::IsPrincipalInfoValid(aPrincipalInfo))) {
    169    return NS_ERROR_FAILURE;
    170  }
    171 
    172  if (aPrincipalInfo.type() !=
    173          mozilla::ipc::PrincipalInfo::TContentPrincipalInfo &&
    174      aPrincipalInfo.type() !=
    175          mozilla::ipc::PrincipalInfo::TSystemPrincipalInfo) {
    176    return NS_ERROR_UNEXPECTED;
    177  }
    178 
    179  return NS_OK;
    180 }
    181 
    182 }  // namespace
    183 
    184 LocalStorageManager2::LocalStorageManager2() {
    185  MOZ_ASSERT(NS_IsMainThread());
    186  MOZ_ASSERT(NextGenLocalStorageEnabled());
    187 }
    188 
    189 LocalStorageManager2::~LocalStorageManager2() { MOZ_ASSERT(NS_IsMainThread()); }
    190 
    191 NS_IMPL_ISUPPORTS(LocalStorageManager2, nsIDOMStorageManager,
    192                  nsILocalStorageManager)
    193 
    194 NS_IMETHODIMP
    195 LocalStorageManager2::PrecacheStorage(nsIPrincipal* aPrincipal,
    196                                      nsIPrincipal* aStoragePrincipal,
    197                                      Storage** _retval) {
    198  MOZ_ASSERT(NS_IsMainThread());
    199  MOZ_ASSERT(aPrincipal);
    200  MOZ_ASSERT(aStoragePrincipal);
    201  MOZ_ASSERT(_retval);
    202 
    203  // This method was created as part of the e10s-ification of the old LS
    204  // implementation to perform a preload in the content/current process.  That's
    205  // not how things work in LSNG.  Instead everything happens in the parent
    206  // process, triggered by the official preloading spot,
    207  // ContentParent::AboutToLoadHttpDocumentForChild.
    208  return NS_ERROR_NOT_IMPLEMENTED;
    209 }
    210 
    211 NS_IMETHODIMP
    212 LocalStorageManager2::CreateStorage(mozIDOMWindow* aWindow,
    213                                    nsIPrincipal* aPrincipal,
    214                                    nsIPrincipal* aStoragePrincipal,
    215                                    const nsAString& aDocumentURI,
    216                                    bool aPrivate, Storage** _retval) {
    217  MOZ_ASSERT(NS_IsMainThread());
    218  MOZ_ASSERT(aPrincipal);
    219  MOZ_ASSERT(aStoragePrincipal);
    220  MOZ_ASSERT(_retval);
    221 
    222  nsCOMPtr<nsPIDOMWindowInner> inner = nsPIDOMWindowInner::From(aWindow);
    223 
    224  RefPtr<LSObject> object;
    225  nsresult rv = LSObject::CreateForPrincipal(inner, aPrincipal,
    226                                             aStoragePrincipal, aDocumentURI,
    227                                             aPrivate, getter_AddRefs(object));
    228  if (NS_WARN_IF(NS_FAILED(rv))) {
    229    return rv;
    230  }
    231 
    232  object.forget(_retval);
    233  return NS_OK;
    234 }
    235 
    236 NS_IMETHODIMP
    237 LocalStorageManager2::GetStorage(mozIDOMWindow* aWindow,
    238                                 nsIPrincipal* aPrincipal,
    239                                 nsIPrincipal* aStoragePrincipal, bool aPrivate,
    240                                 Storage** _retval) {
    241  MOZ_ASSERT(NS_IsMainThread());
    242  MOZ_ASSERT(aPrincipal);
    243  MOZ_ASSERT(aStoragePrincipal);
    244  MOZ_ASSERT(_retval);
    245 
    246  return NS_ERROR_NOT_IMPLEMENTED;
    247 }
    248 
    249 NS_IMETHODIMP
    250 LocalStorageManager2::CloneStorage(Storage* aStorageToCloneFrom) {
    251  MOZ_ASSERT(NS_IsMainThread());
    252  MOZ_ASSERT(aStorageToCloneFrom);
    253 
    254  // Cloning is specific to sessionStorage; state is forked when a new tab is
    255  // opened from an existing tab.
    256  return NS_ERROR_NOT_IMPLEMENTED;
    257 }
    258 
    259 NS_IMETHODIMP
    260 LocalStorageManager2::CheckStorage(nsIPrincipal* aPrincipal, Storage* aStorage,
    261                                   bool* _retval) {
    262  MOZ_ASSERT(NS_IsMainThread());
    263  MOZ_ASSERT(aPrincipal);
    264  MOZ_ASSERT(aStorage);
    265  MOZ_ASSERT(_retval);
    266 
    267  // Only used by sessionStorage.
    268  return NS_ERROR_NOT_IMPLEMENTED;
    269 }
    270 
    271 NS_IMETHODIMP
    272 LocalStorageManager2::GetNextGenLocalStorageEnabled(bool* aResult) {
    273  MOZ_ASSERT(NS_IsMainThread());
    274  MOZ_ASSERT(aResult);
    275 
    276  *aResult = NextGenLocalStorageEnabled();
    277  return NS_OK;
    278 }
    279 
    280 NS_IMETHODIMP
    281 LocalStorageManager2::Preload(nsIPrincipal* aPrincipal, JSContext* aContext,
    282                              Promise** _retval) {
    283  MOZ_ASSERT(NS_IsMainThread());
    284  MOZ_ASSERT(aPrincipal);
    285  MOZ_ASSERT(_retval);
    286 
    287  nsCString originAttrSuffix;
    288  nsCString originKey;
    289  nsresult rv = aPrincipal->GetStorageOriginKey(originKey);
    290  aPrincipal->OriginAttributesRef().CreateSuffix(originAttrSuffix);
    291  if (NS_FAILED(rv)) {
    292    return NS_ERROR_NOT_AVAILABLE;
    293  }
    294 
    295  mozilla::ipc::PrincipalInfo principalInfo;
    296  rv = CheckedPrincipalToPrincipalInfo(aPrincipal, principalInfo);
    297  if (NS_WARN_IF(NS_FAILED(rv))) {
    298    return rv;
    299  }
    300 
    301  RefPtr<Promise> promise;
    302 
    303  if (aContext) {
    304    rv = quota::CreatePromise(aContext, getter_AddRefs(promise));
    305    if (NS_WARN_IF(NS_FAILED(rv))) {
    306      return rv;
    307    }
    308  }
    309 
    310  LSRequestCommonParams commonParams;
    311  commonParams.principalInfo() = principalInfo;
    312  commonParams.storagePrincipalInfo() = principalInfo;
    313  commonParams.originKey() = originKey;
    314 
    315  LSRequestPreloadDatastoreParams params(commonParams);
    316 
    317  RefPtr<AsyncRequestHelper> helper =
    318      new AsyncRequestHelper(this, promise, params);
    319 
    320  // This will start and finish the async request on the RemoteLazyInputStream
    321  // thread.
    322  // This must be done on RemoteLazyInputStream Thread because it's very likely
    323  // that a content process will issue a prepare datastore request for the same
    324  // principal while blocking the content process on the main thread.
    325  // There would be a potential for deadlock if the preloading was initialized
    326  // from the main thread of the parent process and a11y issued a synchronous
    327  // message from the parent process to the content process (approximately at
    328  // the same time) because the preload request wouldn't be able to respond
    329  // to the Ready message by sending the Finish message which is needed to
    330  // finish the preload request and unblock the prepare datastore request.
    331  rv = helper->Dispatch();
    332  if (NS_WARN_IF(NS_FAILED(rv))) {
    333    return rv;
    334  }
    335 
    336  promise.forget(_retval);
    337  return NS_OK;
    338 }
    339 
    340 NS_IMETHODIMP
    341 LocalStorageManager2::IsPreloaded(nsIPrincipal* aPrincipal, JSContext* aContext,
    342                                  Promise** _retval) {
    343  MOZ_ASSERT(NS_IsMainThread());
    344  MOZ_ASSERT(aPrincipal);
    345  MOZ_ASSERT(_retval);
    346 
    347  RefPtr<Promise> promise;
    348  nsresult rv = quota::CreatePromise(aContext, getter_AddRefs(promise));
    349  if (NS_WARN_IF(NS_FAILED(rv))) {
    350    return rv;
    351  }
    352 
    353  LSSimpleRequestPreloadedParams params;
    354 
    355  rv = CheckedPrincipalToPrincipalInfo(aPrincipal, params.principalInfo());
    356  if (NS_WARN_IF(NS_FAILED(rv))) {
    357    return rv;
    358  }
    359 
    360  params.storagePrincipalInfo() = params.principalInfo();
    361 
    362  rv = StartSimpleRequest(promise, params);
    363  if (NS_WARN_IF(NS_FAILED(rv))) {
    364    return rv;
    365  }
    366 
    367  promise.forget(_retval);
    368  return NS_OK;
    369 }
    370 
    371 NS_IMETHODIMP
    372 LocalStorageManager2::GetState(nsIPrincipal* aPrincipal, JSContext* aContext,
    373                               Promise** _retval) {
    374  MOZ_ASSERT(NS_IsMainThread());
    375  MOZ_ASSERT(aPrincipal);
    376  MOZ_ASSERT(_retval);
    377 
    378  RefPtr<Promise> promise;
    379  nsresult rv = quota::CreatePromise(aContext, getter_AddRefs(promise));
    380  if (NS_WARN_IF(NS_FAILED(rv))) {
    381    return rv;
    382  }
    383 
    384  LSSimpleRequestGetStateParams params;
    385 
    386  rv = CheckedPrincipalToPrincipalInfo(aPrincipal, params.principalInfo());
    387  if (NS_WARN_IF(NS_FAILED(rv))) {
    388    return rv;
    389  }
    390 
    391  params.storagePrincipalInfo() = params.principalInfo();
    392 
    393  rv = StartSimpleRequest(promise, params);
    394  if (NS_WARN_IF(NS_FAILED(rv))) {
    395    return rv;
    396  }
    397 
    398  promise.forget(_retval);
    399  return NS_OK;
    400 }
    401 
    402 LSRequestChild* LocalStorageManager2::StartRequest(
    403    const LSRequestParams& aParams, LSRequestChildCallback* aCallback) {
    404  AssertIsOnDOMFileThread();
    405 
    406  mozilla::ipc::PBackgroundChild* backgroundActor =
    407      mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
    408  if (NS_WARN_IF(!backgroundActor)) {
    409    return nullptr;
    410  }
    411 
    412  auto actor = new LSRequestChild();
    413 
    414  if (!backgroundActor->SendPBackgroundLSRequestConstructor(actor, aParams)) {
    415    return nullptr;
    416  }
    417 
    418  // Must set callback after calling SendPBackgroundLSRequestConstructor since
    419  // it can be called synchronously when SendPBackgroundLSRequestConstructor
    420  // fails.
    421  actor->SetCallback(aCallback);
    422 
    423  return actor;
    424 }
    425 
    426 nsresult LocalStorageManager2::StartSimpleRequest(
    427    Promise* aPromise, const LSSimpleRequestParams& aParams) {
    428  MOZ_ASSERT(NS_IsMainThread());
    429  MOZ_ASSERT(aPromise);
    430 
    431  mozilla::ipc::PBackgroundChild* backgroundActor =
    432      mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
    433  if (NS_WARN_IF(!backgroundActor)) {
    434    return NS_ERROR_FAILURE;
    435  }
    436 
    437  auto actor = new LSSimpleRequestChild();
    438 
    439  if (!backgroundActor->SendPBackgroundLSSimpleRequestConstructor(actor,
    440                                                                  aParams)) {
    441    return NS_ERROR_FAILURE;
    442  }
    443 
    444  RefPtr<SimpleRequestResolver> resolver = new SimpleRequestResolver(aPromise);
    445 
    446  // Must set callback after calling SendPBackgroundLSRequestConstructor since
    447  // it can be called synchronously when SendPBackgroundLSRequestConstructor
    448  // fails.
    449  actor->SetCallback(resolver);
    450 
    451  return NS_OK;
    452 }
    453 
    454 nsresult AsyncRequestHelper::Dispatch() {
    455  AssertIsOnOwningThread();
    456 
    457  nsCOMPtr<nsIEventTarget> domFileThread =
    458      RemoteLazyInputStreamThread::GetOrCreate();
    459  if (NS_WARN_IF(!domFileThread)) {
    460    return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
    461  }
    462 
    463  nsresult rv = domFileThread->Dispatch(this, NS_DISPATCH_NORMAL);
    464  if (NS_WARN_IF(NS_FAILED(rv))) {
    465    return rv;
    466  }
    467 
    468  return NS_OK;
    469 }
    470 
    471 nsresult AsyncRequestHelper::Start() {
    472  AssertIsOnDOMFileThread();
    473  MOZ_ASSERT(mState == State::Initial);
    474 
    475  mState = State::ResponsePending;
    476 
    477  LSRequestChild* actor = mManager->StartRequest(mParams, this);
    478  if (NS_WARN_IF(!actor)) {
    479    return NS_ERROR_FAILURE;
    480  }
    481 
    482  mActor = actor;
    483 
    484  return NS_OK;
    485 }
    486 
    487 void AsyncRequestHelper::Finish() {
    488  AssertIsOnOwningThread();
    489  MOZ_ASSERT(mState == State::Finishing);
    490 
    491  if (NS_WARN_IF(NS_FAILED(mResultCode))) {
    492    if (mPromise) {
    493      mPromise->MaybeReject(mResultCode);
    494    }
    495  } else {
    496    switch (mResponse.type()) {
    497      case LSRequestResponse::Tnsresult:
    498        if (mPromise) {
    499          mPromise->MaybeReject(mResponse.get_nsresult());
    500        }
    501        break;
    502 
    503      case LSRequestResponse::TLSRequestPreloadDatastoreResponse:
    504        if (mPromise) {
    505          const LSRequestPreloadDatastoreResponse& preloadDatastoreResponse =
    506              mResponse.get_LSRequestPreloadDatastoreResponse();
    507 
    508          const bool invalidated = preloadDatastoreResponse.invalidated();
    509 
    510          if (invalidated) {
    511            mPromise->MaybeReject(NS_ERROR_ABORT);
    512          } else {
    513            mPromise->MaybeResolveWithUndefined();
    514          }
    515        }
    516        break;
    517      default:
    518        MOZ_CRASH("Unknown response type!");
    519    }
    520  }
    521 
    522  mManager = nullptr;
    523  mPromise = nullptr;
    524 
    525  mState = State::Complete;
    526 }
    527 
    528 NS_IMPL_ISUPPORTS_INHERITED0(AsyncRequestHelper, Runnable)
    529 
    530 NS_IMETHODIMP
    531 AsyncRequestHelper::Run() {
    532  nsresult rv;
    533 
    534  switch (mState) {
    535    case State::Initial:
    536      rv = Start();
    537      break;
    538 
    539    case State::Finishing:
    540      Finish();
    541      return NS_OK;
    542 
    543    default:
    544      MOZ_CRASH("Bad state!");
    545  }
    546 
    547  if (NS_WARN_IF(NS_FAILED(rv)) && mState != State::Finishing) {
    548    if (NS_SUCCEEDED(mResultCode)) {
    549      mResultCode = rv;
    550    }
    551 
    552    mState = State::Finishing;
    553 
    554    if (IsOnOwningThread()) {
    555      Finish();
    556    } else {
    557      MOZ_ALWAYS_SUCCEEDS(
    558          mOwningEventTarget->Dispatch(this, NS_DISPATCH_NORMAL));
    559    }
    560  }
    561 
    562  return NS_OK;
    563 }
    564 
    565 void AsyncRequestHelper::OnResponse(LSRequestResponse&& aResponse) {
    566  AssertIsOnDOMFileThread();
    567  MOZ_ASSERT(mState == State::ResponsePending);
    568 
    569  mActor = nullptr;
    570 
    571  mResponse = std::move(aResponse);
    572 
    573  mState = State::Finishing;
    574 
    575  MOZ_ALWAYS_SUCCEEDS(mOwningEventTarget->Dispatch(this, NS_DISPATCH_NORMAL));
    576 }
    577 
    578 void SimpleRequestResolver::HandleResponse(nsresult aResponse) {
    579  MOZ_ASSERT(NS_IsMainThread());
    580  MOZ_ASSERT(mPromise);
    581 
    582  mPromise->MaybeReject(aResponse);
    583 }
    584 
    585 void SimpleRequestResolver::HandleResponse(bool aResponse) {
    586  MOZ_ASSERT(NS_IsMainThread());
    587  MOZ_ASSERT(mPromise);
    588 
    589  mPromise->MaybeResolve(aResponse);
    590 }
    591 
    592 [[nodiscard]] static bool ToJSValue(JSContext* aCx,
    593                                    const nsTArray<LSItemInfo>& aArgument,
    594                                    JS::MutableHandle<JS::Value> aValue) {
    595  JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
    596  if (!obj) {
    597    return false;
    598  }
    599 
    600  for (size_t i = 0; i < aArgument.Length(); ++i) {
    601    const LSItemInfo& itemInfo = aArgument[i];
    602 
    603    const nsString& key = itemInfo.key();
    604 
    605    JS::Rooted<JS::Value> value(aCx);
    606    if (!ToJSValue(aCx, itemInfo.value().AsString(), &value)) {
    607      return false;
    608    }
    609 
    610    if (!JS_DefineUCProperty(aCx, obj, key.BeginReading(), key.Length(), value,
    611                             JSPROP_ENUMERATE)) {
    612      return false;
    613    }
    614  }
    615 
    616  aValue.setObject(*obj);
    617  return true;
    618 }
    619 
    620 void SimpleRequestResolver::HandleResponse(
    621    const nsTArray<LSItemInfo>& aResponse) {
    622  MOZ_ASSERT(NS_IsMainThread());
    623  MOZ_ASSERT(mPromise);
    624 
    625  mPromise->MaybeResolve(aResponse);
    626 }
    627 
    628 void SimpleRequestResolver::OnResponse(
    629    const LSSimpleRequestResponse& aResponse) {
    630  MOZ_ASSERT(NS_IsMainThread());
    631 
    632  switch (aResponse.type()) {
    633    case LSSimpleRequestResponse::Tnsresult:
    634      HandleResponse(aResponse.get_nsresult());
    635      break;
    636 
    637    case LSSimpleRequestResponse::TLSSimpleRequestPreloadedResponse:
    638      HandleResponse(
    639          aResponse.get_LSSimpleRequestPreloadedResponse().preloaded());
    640      break;
    641 
    642    case LSSimpleRequestResponse::TLSSimpleRequestGetStateResponse:
    643      HandleResponse(
    644          aResponse.get_LSSimpleRequestGetStateResponse().itemInfos());
    645      break;
    646 
    647    default:
    648      MOZ_CRASH("Unknown response type!");
    649  }
    650 }
    651 
    652 }  // namespace mozilla::dom