Bug 1889091 - Part 6: Remove "scratch" register parameter from emitPushArguments...
[gecko.git] / dom / storage / Storage.cpp
blob3602dcb9b16d49baf1df6aba7143c54a9ee4a43f
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/. */
7 #include "Storage.h"
8 #include "StorageNotifierService.h"
10 #include "mozilla/dom/StorageBinding.h"
11 #include "mozilla/dom/StorageEvent.h"
12 #include "mozilla/dom/StorageEventBinding.h"
13 #include "mozilla/BasePrincipal.h"
14 #include "mozilla/Preferences.h"
15 #include "mozilla/SchedulerGroup.h"
16 #include "mozilla/Services.h"
17 #include "mozilla/StaticPrefs_dom.h"
18 #include "mozilla/StorageAccess.h"
19 #include "nsIObserverService.h"
20 #include "nsPIDOMWindow.h"
22 namespace mozilla::dom {
24 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Storage, mWindow, mPrincipal,
25 mStoragePrincipal)
27 NS_IMPL_CYCLE_COLLECTING_ADDREF(Storage)
28 NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(Storage, LastRelease())
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
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);
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);
51 mPrivateBrowsing = access == StorageAccess::ePrivateBrowsing;
52 mPrivateBrowsingOrLess = access <= StorageAccess::ePrivateBrowsing;
56 Storage::~Storage() = default;
58 /* static */
59 bool Storage::StoragePrefIsEnabled() {
60 return StaticPrefs::dom_storage_enabled();
63 int64_t Storage::GetSnapshotUsage(nsIPrincipal& aSubjectPrincipal,
64 ErrorResult& aRv) {
65 aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
66 return 0;
69 bool Storage::CanUseStorage(nsIPrincipal& aSubjectPrincipal) {
70 if (!StoragePrefIsEnabled()) {
71 return false;
74 return aSubjectPrincipal.Subsumes(mPrincipal);
77 /* virtual */
78 JSObject* Storage::WrapObject(JSContext* aCx,
79 JS::Handle<JSObject*> aGivenProto) {
80 return Storage_Binding::Wrap(aCx, this, aGivenProto);
83 namespace {
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) {}
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);
105 return NS_OK;
108 private:
109 nsCOMPtr<nsISupports> mSubject;
110 const char16_t* mStorageType;
111 const bool mPrivateBrowsing;
114 } // namespace
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;
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);
137 event->SetPrincipal(aPrincipal);
139 // This will send the event to any registered window.
140 StorageNotifierService::Broadcast(event, aStorageType, aIsPrivate,
141 aImmediateDispatch);
143 // This runnable is mainly used by devtools. Windows receive notification by
144 // StorageNotifierService.
146 RefPtr<StorageNotifierRunnable> r =
147 new StorageNotifierRunnable(event, aStorageType, aIsPrivate);
149 if (aImmediateDispatch) {
150 Unused << r->Run();
151 } else {
152 SchedulerGroup::Dispatch(r.forget());
156 } // namespace mozilla::dom