tor-browser

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

Storage.cpp (4916B)


      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 "Storage.h"
      8 
      9 #include "StorageNotifierService.h"
     10 #include "mozilla/BasePrincipal.h"
     11 #include "mozilla/Preferences.h"
     12 #include "mozilla/SchedulerGroup.h"
     13 #include "mozilla/Services.h"
     14 #include "mozilla/StaticPrefs_dom.h"
     15 #include "mozilla/StorageAccess.h"
     16 #include "mozilla/dom/StorageBinding.h"
     17 #include "mozilla/dom/StorageEvent.h"
     18 #include "mozilla/dom/StorageEventBinding.h"
     19 #include "nsIObserverService.h"
     20 #include "nsPIDOMWindow.h"
     21 
     22 namespace mozilla::dom {
     23 
     24 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Storage, mWindow, mPrincipal,
     25                                      mStoragePrincipal)
     26 
     27 NS_IMPL_CYCLE_COLLECTING_ADDREF(Storage)
     28 NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(Storage, LastRelease())
     29 
     30 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Storage)
     31  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     32  NS_INTERFACE_MAP_ENTRY(nsISupports)
     33 NS_INTERFACE_MAP_END
     34 
     35 Storage::Storage(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal,
     36                 nsIPrincipal* aStoragePrincipal)
     37    : mWindow(aWindow),
     38      mPrincipal(aPrincipal),
     39      mStoragePrincipal(aStoragePrincipal),
     40      mPrivateBrowsing(false),
     41      mPrivateBrowsingOrLess(false) {
     42  MOZ_ASSERT(aPrincipal);
     43 
     44  if (mPrincipal->IsSystemPrincipal()) {
     45    mPrivateBrowsing = false;
     46    mPrivateBrowsingOrLess = false;
     47  } else if (mWindow) {
     48    uint32_t rejectedReason = 0;
     49    StorageAccess access = StorageAllowedForWindow(mWindow, &rejectedReason);
     50 
     51    mPrivateBrowsing = access == StorageAccess::ePrivateBrowsing;
     52    mPrivateBrowsingOrLess = access <= StorageAccess::ePrivateBrowsing;
     53  }
     54 }
     55 
     56 Storage::~Storage() = default;
     57 
     58 /* static */
     59 bool Storage::StoragePrefIsEnabled() {
     60  return StaticPrefs::dom_storage_enabled();
     61 }
     62 
     63 int64_t Storage::GetSnapshotUsage(nsIPrincipal& aSubjectPrincipal,
     64                                  ErrorResult& aRv) {
     65  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
     66  return 0;
     67 }
     68 
     69 bool Storage::CanUseStorage(nsIPrincipal& aSubjectPrincipal) {
     70  if (!StoragePrefIsEnabled()) {
     71    return false;
     72  }
     73 
     74  return aSubjectPrincipal.Subsumes(mPrincipal);
     75 }
     76 
     77 /* virtual */
     78 JSObject* Storage::WrapObject(JSContext* aCx,
     79                              JS::Handle<JSObject*> aGivenProto) {
     80  return Storage_Binding::Wrap(aCx, this, aGivenProto);
     81 }
     82 
     83 namespace {
     84 
     85 class StorageNotifierRunnable : public Runnable {
     86 public:
     87  StorageNotifierRunnable(nsISupports* aSubject, const char16_t* aStorageType,
     88                          bool aPrivateBrowsing)
     89      : Runnable("StorageNotifierRunnable"),
     90        mSubject(aSubject),
     91        mStorageType(aStorageType),
     92        mPrivateBrowsing(aPrivateBrowsing) {}
     93 
     94  NS_IMETHOD
     95  Run() override {
     96    nsCOMPtr<nsIObserverService> observerService =
     97        mozilla::services::GetObserverService();
     98    if (observerService) {
     99      observerService->NotifyObservers(mSubject,
    100                                       mPrivateBrowsing
    101                                           ? "dom-private-storage2-changed"
    102                                           : "dom-storage2-changed",
    103                                       mStorageType);
    104    }
    105    return NS_OK;
    106  }
    107 
    108 private:
    109  nsCOMPtr<nsISupports> mSubject;
    110  const char16_t* mStorageType;
    111  const bool mPrivateBrowsing;
    112 };
    113 
    114 }  // namespace
    115 
    116 /* static */
    117 void Storage::NotifyChange(Storage* aStorage, nsIPrincipal* aPrincipal,
    118                           const nsAString& aKey, const nsAString& aOldValue,
    119                           const nsAString& aNewValue,
    120                           const char16_t* aStorageType,
    121                           const nsAString& aDocumentURI, bool aIsPrivate,
    122                           bool aImmediateDispatch) {
    123  StorageEventInit dict;
    124  dict.mBubbles = false;
    125  dict.mCancelable = false;
    126  dict.mKey = aKey;
    127  dict.mNewValue = aNewValue;
    128  dict.mOldValue = aOldValue;
    129  dict.mStorageArea = aStorage;
    130  dict.mUrl = aDocumentURI;
    131 
    132  // Note, this DOM event should never reach JS. It is cloned later in
    133  // nsGlobalWindow.
    134  RefPtr<StorageEvent> event =
    135      StorageEvent::Constructor(nullptr, u"storage"_ns, dict);
    136 
    137  event->SetPrincipal(aPrincipal);
    138 
    139  // This will send the event to any registered window.
    140  StorageNotifierService::Broadcast(event, aStorageType, aIsPrivate,
    141                                    aImmediateDispatch);
    142 
    143  // This runnable is mainly used by devtools. Windows receive notification by
    144  // StorageNotifierService.
    145 
    146  RefPtr<StorageNotifierRunnable> r =
    147      new StorageNotifierRunnable(event, aStorageType, aIsPrivate);
    148 
    149  if (aImmediateDispatch) {
    150    (void)r->Run();
    151  } else {
    152    SchedulerGroup::Dispatch(r.forget());
    153  }
    154 }
    155 
    156 }  // namespace mozilla::dom