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/. */
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
,
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
)
35 Storage::Storage(nsPIDOMWindowInner
* aWindow
, nsIPrincipal
* aPrincipal
,
36 nsIPrincipal
* aStoragePrincipal
)
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;
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;
59 bool Storage::StoragePrefIsEnabled() {
60 return StaticPrefs::dom_storage_enabled();
63 int64_t Storage::GetSnapshotUsage(nsIPrincipal
& aSubjectPrincipal
,
65 aRv
.Throw(NS_ERROR_NOT_IMPLEMENTED
);
69 bool Storage::CanUseStorage(nsIPrincipal
& aSubjectPrincipal
) {
70 if (!StoragePrefIsEnabled()) {
74 return aSubjectPrincipal
.Subsumes(mPrincipal
);
78 JSObject
* Storage::WrapObject(JSContext
* aCx
,
79 JS::Handle
<JSObject
*> aGivenProto
) {
80 return Storage_Binding::Wrap(aCx
, this, aGivenProto
);
85 class StorageNotifierRunnable
: public Runnable
{
87 StorageNotifierRunnable(nsISupports
* aSubject
, const char16_t
* aStorageType
,
88 bool aPrivateBrowsing
)
89 : Runnable("StorageNotifierRunnable"),
91 mStorageType(aStorageType
),
92 mPrivateBrowsing(aPrivateBrowsing
) {}
96 nsCOMPtr
<nsIObserverService
> observerService
=
97 mozilla::services::GetObserverService();
98 if (observerService
) {
99 observerService
->NotifyObservers(mSubject
,
101 ? "dom-private-storage2-changed"
102 : "dom-storage2-changed",
109 nsCOMPtr
<nsISupports
> mSubject
;
110 const char16_t
* mStorageType
;
111 const bool mPrivateBrowsing
;
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;
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
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
,
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
) {
152 SchedulerGroup::Dispatch(r
.forget());
156 } // namespace mozilla::dom