tor-browser

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

StorageNotifierService.cpp (4115B)


      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 "StorageNotifierService.h"
      8 
      9 #include "StorageUtils.h"
     10 #include "mozilla/ClearOnShutdown.h"
     11 #include "mozilla/StaticPtr.h"
     12 #include "mozilla/dom/StorageEvent.h"
     13 #include "nsThreadUtils.h"
     14 
     15 namespace mozilla::dom {
     16 
     17 namespace {
     18 
     19 // This boolean is used to avoid the creation of the service after been
     20 // distroyed on shutdown.
     21 bool gStorageShuttingDown = false;
     22 
     23 StaticRefPtr<StorageNotifierService> gStorageNotifierService;
     24 
     25 }  // namespace
     26 
     27 /* static */
     28 StorageNotifierService* StorageNotifierService::GetOrCreate() {
     29  MOZ_ASSERT(NS_IsMainThread());
     30  if (!gStorageNotifierService && !gStorageShuttingDown) {
     31    gStorageNotifierService = new StorageNotifierService();
     32    ClearOnShutdown(&gStorageNotifierService);
     33  }
     34 
     35  return gStorageNotifierService;
     36 }
     37 
     38 StorageNotifierService::StorageNotifierService() {
     39  MOZ_ASSERT(NS_IsMainThread());
     40  MOZ_ASSERT(!gStorageNotifierService);
     41 }
     42 
     43 StorageNotifierService::~StorageNotifierService() {
     44  MOZ_ASSERT(NS_IsMainThread());
     45  MOZ_ASSERT(!gStorageNotifierService);
     46  gStorageShuttingDown = true;
     47 }
     48 
     49 /* static */
     50 void StorageNotifierService::Broadcast(StorageEvent* aEvent,
     51                                       const char16_t* aStorageType,
     52                                       bool aPrivateBrowsing,
     53                                       bool aImmediateDispatch) {
     54  MOZ_ASSERT(NS_IsMainThread());
     55 
     56  RefPtr<StorageNotifierService> service = gStorageNotifierService;
     57  if (!service) {
     58    return;
     59  }
     60 
     61  RefPtr<StorageEvent> event = aEvent;
     62 
     63  for (const auto& observer : service->mObservers.ForwardRange()) {
     64    // Enforce that the source storage area's private browsing state matches
     65    // this window's state.  These flag checks and their maintenance independent
     66    // from the principal's OriginAttributes matter because chrome docshells
     67    // that are part of private browsing windows can be private browsing without
     68    // having their OriginAttributes set (because they have the system
     69    // principal).
     70    if (aPrivateBrowsing != observer->IsPrivateBrowsing()) {
     71      continue;
     72    }
     73 
     74    // No reasons to continue if the principal of the event doesn't match with
     75    // the window's one.
     76    if (!StorageUtils::PrincipalsEqual(
     77            aEvent->GetPrincipal(), observer->GetEffectiveStoragePrincipal())) {
     78      continue;
     79    }
     80 
     81    const auto pinnedObserver = observer;
     82 
     83    RefPtr<Runnable> r = NS_NewRunnableFunction(
     84        "StorageNotifierService::Broadcast",
     85        [pinnedObserver, event, aStorageType, aPrivateBrowsing,
     86         aImmediateDispatch]() {
     87          // Check principals again. EffectiveStoragePrincipal may be changed
     88          // when relaxed.
     89          if (!aImmediateDispatch &&
     90              !StorageUtils::PrincipalsEqual(
     91                  event->GetPrincipal(),
     92                  pinnedObserver->GetEffectiveStoragePrincipal())) {
     93            return;
     94          }
     95 
     96          pinnedObserver->ObserveStorageNotification(event, aStorageType,
     97                                                     aPrivateBrowsing);
     98        });
     99 
    100    if (aImmediateDispatch) {
    101      r->Run();
    102    } else {
    103      nsCOMPtr<nsIEventTarget> et = pinnedObserver->GetEventTarget();
    104      if (et) {
    105        et->Dispatch(r.forget());
    106      }
    107    }
    108  }
    109 }
    110 
    111 void StorageNotifierService::Register(StorageNotificationObserver* aObserver) {
    112  MOZ_ASSERT(NS_IsMainThread());
    113  MOZ_ASSERT(aObserver);
    114  MOZ_ASSERT(!mObservers.Contains(aObserver));
    115 
    116  mObservers.AppendElement(aObserver);
    117 }
    118 
    119 void StorageNotifierService::Unregister(
    120    StorageNotificationObserver* aObserver) {
    121  MOZ_ASSERT(NS_IsMainThread());
    122  MOZ_ASSERT(aObserver);
    123 
    124  // No assertion about mObservers containing aObserver because window calls
    125  // this method multiple times.
    126 
    127  mObservers.RemoveElement(aObserver);
    128 }
    129 
    130 }  // namespace mozilla::dom