tor-browser

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

CookieStoreNotificationWatcher.cpp (3673B)


      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 "CookieStoreNotificationWatcher.h"
      8 
      9 #include "mozilla/Services.h"
     10 #include "nsICookie.h"
     11 #include "nsICookieNotification.h"
     12 #include "nsIObserverService.h"
     13 
     14 namespace mozilla::dom {
     15 
     16 NS_IMPL_ISUPPORTS(CookieStoreNotificationWatcher, nsIObserver,
     17                  nsISupportsWeakReference)
     18 
     19 // static
     20 already_AddRefed<CookieStoreNotificationWatcher>
     21 CookieStoreNotificationWatcher::Create(bool aPrivateBrowsing) {
     22  MOZ_ASSERT(NS_IsMainThread());
     23 
     24  RefPtr<CookieStoreNotificationWatcher> watcher =
     25      new CookieStoreNotificationWatcher();
     26 
     27  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     28  if (NS_WARN_IF(!os)) {
     29    return nullptr;
     30  }
     31 
     32  nsresult rv = os->AddObserver(
     33      watcher, aPrivateBrowsing ? "private-cookie-changed" : "cookie-changed",
     34      true);
     35  if (NS_WARN_IF(NS_FAILED(rv))) {
     36    return nullptr;
     37  }
     38 
     39  return watcher.forget();
     40 }
     41 
     42 NS_IMETHODIMP
     43 CookieStoreNotificationWatcher::Observe(nsISupports* aSubject,
     44                                        const char* aTopic,
     45                                        const char16_t* aData) {
     46  MOZ_ASSERT(NS_IsMainThread());
     47 
     48  nsCOMPtr<nsICookieNotification> notification = do_QueryInterface(aSubject);
     49  NS_ENSURE_TRUE(notification, NS_ERROR_FAILURE);
     50 
     51  nsID* operationID = nullptr;
     52  nsresult rv = notification->GetOperationID(&operationID);
     53  if (NS_WARN_IF(NS_FAILED(rv))) {
     54    return NS_OK;
     55  }
     56 
     57  if (!operationID) {
     58    return NS_OK;
     59  }
     60 
     61  for (uint32_t i = 0; i < mPendingOperations.Length(); ++i) {
     62    PendingOperation& pendingOperation = mPendingOperations[i];
     63    if (pendingOperation.mOperationID.Equals(*operationID)) {
     64      pendingOperation.mCallback();
     65      mPendingOperations.RemoveElementAt(i);
     66      break;
     67    }
     68  }
     69 
     70  return NS_OK;
     71 }
     72 
     73 void CookieStoreNotificationWatcher::CallbackWhenNotified(
     74    const nsID& aOperationID, MoveOnlyFunction<void()> aCallback) {
     75  MOZ_ASSERT(NS_IsMainThread());
     76 
     77  mPendingOperations.AppendElement(
     78      PendingOperation{std::move(aCallback), aOperationID});
     79 }
     80 
     81 void CookieStoreNotificationWatcher::ForgetOperationID(
     82    const nsID& aOperationID) {
     83  MOZ_ASSERT(NS_IsMainThread());
     84 
     85  for (uint32_t i = 0; i < mPendingOperations.Length(); ++i) {
     86    PendingOperation& pendingOperation = mPendingOperations[i];
     87    if (pendingOperation.mOperationID.Equals(aOperationID)) {
     88      mPendingOperations.RemoveElementAt(i);
     89      return;
     90    }
     91  }
     92 }
     93 
     94 // static
     95 void CookieStoreNotificationWatcher::ReleaseOnMainThread(
     96    already_AddRefed<CookieStoreNotificationWatcher> aWatcher) {
     97  RefPtr<CookieStoreNotificationWatcher> watcher(aWatcher);
     98 
     99  if (!watcher || NS_IsMainThread()) {
    100    return;
    101  }
    102 
    103  class ReleaseWatcher final : public Runnable {
    104   public:
    105    explicit ReleaseWatcher(
    106        already_AddRefed<CookieStoreNotificationWatcher> aWatcher)
    107        : Runnable("ReleaseWatcher"), mDoomed(std::move(aWatcher)) {}
    108 
    109    NS_IMETHOD Run() override {
    110      mDoomed = nullptr;
    111      return NS_OK;
    112    }
    113 
    114   private:
    115    ~ReleaseWatcher() {
    116      // If we still have to release the watcher, better to leak it.
    117      if (mDoomed) {
    118        mDoomed.forget().leak();
    119      }
    120    }
    121 
    122    RefPtr<CookieStoreNotificationWatcher> mDoomed;
    123  };
    124 
    125  RefPtr<ReleaseWatcher> runnable(new ReleaseWatcher(watcher.forget()));
    126  NS_DispatchToMainThread(runnable);
    127 }
    128 
    129 }  // namespace mozilla::dom