tor-browser

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

CookieStoreNotificationWatcherWrapper.cpp (4979B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=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
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "CookieStoreNotificationWatcherWrapper.h"
      8 
      9 #include "CookieStore.h"
     10 #include "CookieStoreNotificationWatcher.h"
     11 #include "mozilla/dom/Document.h"
     12 #include "mozilla/dom/Promise.h"
     13 #include "mozilla/dom/WorkerPrivate.h"
     14 #include "mozilla/dom/WorkerRef.h"
     15 #include "nsGlobalWindowInner.h"
     16 #include "nsProxyRelease.h"
     17 
     18 namespace mozilla::dom {
     19 
     20 // static
     21 already_AddRefed<CookieStoreNotificationWatcherWrapper>
     22 CookieStoreNotificationWatcherWrapper::Create(CookieStore* aCookieStore) {
     23  MOZ_ASSERT(aCookieStore);
     24 
     25  nsIPrincipal* principal = nullptr;
     26 
     27  if (!NS_IsMainThread()) {
     28    WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
     29    MOZ_ASSERT(workerPrivate);
     30    principal = workerPrivate->GetPrincipal();
     31  } else {
     32    nsCOMPtr<nsPIDOMWindowInner> window = aCookieStore->GetOwnerWindow();
     33    MOZ_ASSERT(window);
     34 
     35    nsCOMPtr<Document> document = window->GetExtantDoc();
     36    if (NS_WARN_IF(!document)) {
     37      return nullptr;
     38    }
     39 
     40    principal = document->NodePrincipal();
     41  }
     42 
     43  if (NS_WARN_IF(!principal)) {
     44    return nullptr;
     45  }
     46 
     47  RefPtr<CookieStoreNotificationWatcherWrapper> wrapper =
     48      new CookieStoreNotificationWatcherWrapper();
     49 
     50  bool privateBrowsing = principal->OriginAttributesRef().IsPrivateBrowsing();
     51 
     52  if (!NS_IsMainThread()) {
     53    NS_DispatchToMainThread(
     54        NS_NewRunnableFunction(__func__, [wrapper, privateBrowsing] {
     55          wrapper->CreateWatcherOnMainThread(privateBrowsing);
     56        }));
     57  } else {
     58    wrapper->CreateWatcherOnMainThread(privateBrowsing);
     59  }
     60 
     61  return wrapper.forget();
     62 }
     63 
     64 CookieStoreNotificationWatcherWrapper::
     65    ~CookieStoreNotificationWatcherWrapper() {
     66  CookieStoreNotificationWatcher::ReleaseOnMainThread(
     67      mWatcherOnMainThread.forget());
     68 }
     69 
     70 void CookieStoreNotificationWatcherWrapper::CreateWatcherOnMainThread(
     71    bool aPrivateBrowsing) {
     72  MOZ_ASSERT(NS_IsMainThread());
     73  mWatcherOnMainThread =
     74      CookieStoreNotificationWatcher::Create(aPrivateBrowsing);
     75 }
     76 
     77 void CookieStoreNotificationWatcherWrapper::ForgetOperationID(
     78    const nsID& aOperationID) {
     79  if (!NS_IsMainThread()) {
     80    NS_DispatchToMainThread(
     81        NS_NewRunnableFunction(__func__, [self = RefPtr(this), aOperationID] {
     82          self->ForgetOperationID(aOperationID);
     83        }));
     84    return;
     85  }
     86 
     87  if (mWatcherOnMainThread) {
     88    mWatcherOnMainThread->ForgetOperationID(aOperationID);
     89  }
     90 }
     91 
     92 void CookieStoreNotificationWatcherWrapper::ResolvePromiseWhenNotified(
     93    const nsID& aOperationID, Promise* aPromise) {
     94  MOZ_ASSERT(aPromise);
     95 
     96  class PromiseResolver final : public Runnable {
     97   public:
     98    explicit PromiseResolver(Promise* aPromise)
     99        : Runnable("CookieStoreNotificationWatcherWrapper::PromiseResolver"),
    100          mPromise(aPromise),
    101          mEventTarget(GetCurrentSerialEventTarget()) {}
    102 
    103    NS_IMETHOD Run() override {
    104      mPromise->MaybeResolveWithUndefined();
    105      mPromise = nullptr;
    106      return NS_OK;
    107    }
    108 
    109    bool HasPromise() const { return !!mPromise; }
    110 
    111   private:
    112    ~PromiseResolver() {
    113      NS_ProxyRelease(
    114          "CookieStoreNotificationWatcherWrapper::PromiseResolver::mPromise",
    115          mEventTarget, mPromise.forget());
    116    }
    117 
    118    RefPtr<Promise> mPromise;
    119    RefPtr<nsISerialEventTarget> mEventTarget;
    120  };
    121 
    122  RefPtr<PromiseResolver> resolver(new PromiseResolver(aPromise));
    123 
    124  RefPtr<ThreadSafeWorkerRef> workerRef;
    125 
    126  if (!NS_IsMainThread()) {
    127    WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
    128    MOZ_ASSERT(workerPrivate);
    129 
    130    RefPtr<StrongWorkerRef> strongWorkerRef = StrongWorkerRef::Create(
    131        workerPrivate, "CookieStoreNotificationWatcher::PromiseResolver",
    132        [resolver = RefPtr(resolver)]() { resolver->Run(); });
    133 
    134    if (!strongWorkerRef) {
    135      // The worker is already shutting down. Let's ignore this promise.
    136      return;
    137    }
    138 
    139    workerRef = new ThreadSafeWorkerRef(strongWorkerRef);
    140  }
    141 
    142  auto callback = [resolver = RefPtr(resolver),
    143                   eventTarget = RefPtr(GetCurrentSerialEventTarget()),
    144                   workerRef = RefPtr(workerRef)] {
    145    if (resolver->HasPromise()) {
    146      RefPtr<Runnable> runnable(resolver);
    147      eventTarget->Dispatch(runnable.forget());
    148    }
    149  };
    150 
    151  if (!NS_IsMainThread()) {
    152    NS_DispatchToMainThread(NS_NewRunnableFunction(
    153        __func__, [self = RefPtr(this), callback, aOperationID] {
    154          self->mWatcherOnMainThread->CallbackWhenNotified(aOperationID,
    155                                                           callback);
    156        }));
    157    return;
    158  }
    159 
    160  if (mWatcherOnMainThread) {
    161    mWatcherOnMainThread->CallbackWhenNotified(aOperationID, callback);
    162  }
    163 }
    164 
    165 }  // namespace mozilla::dom