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/StorageAccess.h"
18 #include "nsIObserverService.h"
19 #include "nsPIDOMWindow.h"
21 namespace mozilla::dom
{
23 static const char kStorageEnabled
[] = "dom.storage.enabled";
25 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Storage
, mWindow
, mPrincipal
,
28 NS_IMPL_CYCLE_COLLECTING_ADDREF(Storage
)
29 NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(Storage
, LastRelease())
31 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Storage
)
32 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
33 NS_INTERFACE_MAP_ENTRY(nsISupports
)
36 Storage::Storage(nsPIDOMWindowInner
* aWindow
, nsIPrincipal
* aPrincipal
,
37 nsIPrincipal
* aStoragePrincipal
)
39 mPrincipal(aPrincipal
),
40 mStoragePrincipal(aStoragePrincipal
),
41 mPrivateBrowsing(false),
42 mSessionScopedOrLess(false) {
43 MOZ_ASSERT(aPrincipal
);
45 if (mPrincipal
->IsSystemPrincipal()) {
46 mPrivateBrowsing
= false;
47 mSessionScopedOrLess
= false;
49 uint32_t rejectedReason
= 0;
50 StorageAccess access
= StorageAllowedForWindow(mWindow
, &rejectedReason
);
52 mPrivateBrowsing
= access
== StorageAccess::ePrivateBrowsing
;
53 mSessionScopedOrLess
= access
<= StorageAccess::eSessionScoped
;
57 Storage::~Storage() = default;
60 bool Storage::StoragePrefIsEnabled() {
61 return mozilla::Preferences::GetBool(kStorageEnabled
);
64 int64_t Storage::GetSnapshotUsage(nsIPrincipal
& aSubjectPrincipal
,
66 aRv
.Throw(NS_ERROR_NOT_IMPLEMENTED
);
70 bool Storage::CanUseStorage(nsIPrincipal
& aSubjectPrincipal
) {
71 if (!StoragePrefIsEnabled()) {
75 return aSubjectPrincipal
.Subsumes(mPrincipal
);
79 JSObject
* Storage::WrapObject(JSContext
* aCx
,
80 JS::Handle
<JSObject
*> aGivenProto
) {
81 return Storage_Binding::Wrap(aCx
, this, aGivenProto
);
86 class StorageNotifierRunnable
: public Runnable
{
88 StorageNotifierRunnable(nsISupports
* aSubject
, const char16_t
* aStorageType
,
89 bool aPrivateBrowsing
)
90 : Runnable("StorageNotifierRunnable"),
92 mStorageType(aStorageType
),
93 mPrivateBrowsing(aPrivateBrowsing
) {}
97 nsCOMPtr
<nsIObserverService
> observerService
=
98 mozilla::services::GetObserverService();
99 if (observerService
) {
100 observerService
->NotifyObservers(mSubject
,
102 ? "dom-private-storage2-changed"
103 : "dom-storage2-changed",
110 nsCOMPtr
<nsISupports
> mSubject
;
111 const char16_t
* mStorageType
;
112 const bool mPrivateBrowsing
;
118 void Storage::NotifyChange(Storage
* aStorage
, nsIPrincipal
* aPrincipal
,
119 const nsAString
& aKey
, const nsAString
& aOldValue
,
120 const nsAString
& aNewValue
,
121 const char16_t
* aStorageType
,
122 const nsAString
& aDocumentURI
, bool aIsPrivate
,
123 bool aImmediateDispatch
) {
124 StorageEventInit dict
;
125 dict
.mBubbles
= false;
126 dict
.mCancelable
= false;
128 dict
.mNewValue
= aNewValue
;
129 dict
.mOldValue
= aOldValue
;
130 dict
.mStorageArea
= aStorage
;
131 dict
.mUrl
= aDocumentURI
;
133 // Note, this DOM event should never reach JS. It is cloned later in
135 RefPtr
<StorageEvent
> event
=
136 StorageEvent::Constructor(nullptr, u
"storage"_ns
, dict
);
138 event
->SetPrincipal(aPrincipal
);
140 // This will send the event to any registered window.
141 StorageNotifierService::Broadcast(event
, aStorageType
, aIsPrivate
,
144 // This runnable is mainly used by devtools. Windows receive notification by
145 // StorageNotifierService.
147 RefPtr
<StorageNotifierRunnable
> r
=
148 new StorageNotifierRunnable(event
, aStorageType
, aIsPrivate
);
150 if (aImmediateDispatch
) {
153 SchedulerGroup::Dispatch(TaskCategory::Other
, r
.forget());
157 } // namespace mozilla::dom