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 #ifndef mozilla_dom_localstorage_LSObject_h
8 #define mozilla_dom_localstorage_LSObject_h
11 #include "ErrorList.h"
12 #include "mozilla/AlreadyAddRefed.h"
13 #include "mozilla/Assertions.h"
14 #include "mozilla/Maybe.h"
15 #include "mozilla/RefPtr.h"
16 #include "mozilla/UniquePtr.h"
17 #include "mozilla/dom/Storage.h"
18 #include "mozilla/ipc/PBackgroundSharedTypes.h"
19 #include "nsCycleCollectionParticipant.h"
21 #include "nsISupports.h"
22 #include "nsStringFwd.h"
23 #include "nsTArrayForwardDeclare.h"
25 class nsGlobalWindowInner
;
28 class nsISerialEventTarget
;
29 class nsPIDOMWindowInner
;
41 class LSRequestChildCallback
;
42 class LSRequestParams
;
43 class LSRequestResponse
;
46 * Backs the WebIDL `Storage` binding; all content LocalStorage calls are
47 * handled by this class.
49 * ## Semantics under e10s / multi-process ##
51 * A snapshot mechanism used in conjuction with stable points ensures that JS
52 * run-to-completion semantics are experienced even if the same origin is
53 * concurrently accessing LocalStorage across multiple content processes.
55 * ### Snapshot Consistency ###
57 * An LSSnapshot is created locally whenever the contents of LocalStorage are
58 * about to be read or written (including length). This synchronously
59 * establishes a corresponding Snapshot in PBackground in the parent process.
60 * An effort is made to send as much data from the parent process as possible,
61 * so sites using a small/reasonable amount of LocalStorage data will have it
62 * sent to the content process for immediate access. Sites with greater
63 * LocalStorage usage may only have some of the information relayed. In that
64 * case, the parent Snapshot will ensure that it retains the exact state of the
65 * parent Datastore at the moment the Snapshot was created.
67 class LSObject final
: public Storage
{
68 using PrincipalInfo
= mozilla::ipc::PrincipalInfo
;
70 friend nsGlobalWindowInner
;
72 UniquePtr
<PrincipalInfo
> mPrincipalInfo
;
73 UniquePtr
<PrincipalInfo
> mStoragePrincipalInfo
;
75 RefPtr
<LSDatabase
> mDatabase
;
76 RefPtr
<LSObserver
> mObserver
;
78 uint32_t mPrivateBrowsingId
;
79 Maybe
<nsID
> mClientId
;
80 Maybe
<PrincipalInfo
> mClientPrincipalInfo
;
83 nsString mDocumentURI
;
85 bool mInExplicitSnapshot
;
89 * The normal creation path invoked by nsGlobalWindowInner.
91 static nsresult
CreateForWindow(nsPIDOMWindowInner
* aWindow
,
95 * nsIDOMStorageManager creation path for use in testing logic. Supports the
96 * system principal where CreateForWindow does not. This is also why aPrivate
97 * exists separate from the principal; because the system principal can never
98 * be mutated to have a private browsing id even though it can be used in a
99 * window/document marked as private browsing. That's a legacy issue that is
100 * being dealt with, but it's why it exists here.
102 static nsresult
CreateForPrincipal(nsPIDOMWindowInner
* aWindow
,
103 nsIPrincipal
* aPrincipal
,
104 nsIPrincipal
* aStoragePrincipal
,
105 const nsAString
& aDocumentURI
,
106 bool aPrivate
, LSObject
** aObject
);
108 void AssertIsOnOwningThread() const { NS_ASSERT_OWNINGTHREAD(LSObject
); }
110 const RefPtr
<LSDatabase
>& DatabaseStrongRef() const { return mDatabase
; }
112 const nsString
& DocumentURI() const { return mDocumentURI
; }
114 bool InExplicitSnapshot() const { return mInExplicitSnapshot
; }
116 LSRequestChild
* StartRequest(const LSRequestParams
& aParams
,
117 LSRequestChildCallback
* aCallback
);
119 // Storage overrides.
120 StorageType
Type() const override
;
122 bool IsForkOf(const Storage
* aStorage
) const override
;
124 int64_t GetOriginQuotaUsage() const override
;
126 void Disconnect() override
;
128 uint32_t GetLength(nsIPrincipal
& aSubjectPrincipal
,
129 ErrorResult
& aError
) override
;
131 void Key(uint32_t aIndex
, nsAString
& aResult
, nsIPrincipal
& aSubjectPrincipal
,
132 ErrorResult
& aError
) override
;
134 void GetItem(const nsAString
& aKey
, nsAString
& aResult
,
135 nsIPrincipal
& aSubjectPrincipal
, ErrorResult
& aError
) override
;
137 void GetSupportedNames(nsTArray
<nsString
>& aNames
) override
;
139 void SetItem(const nsAString
& aKey
, const nsAString
& aValue
,
140 nsIPrincipal
& aSubjectPrincipal
, ErrorResult
& aError
) override
;
142 void RemoveItem(const nsAString
& aKey
, nsIPrincipal
& aSubjectPrincipal
,
143 ErrorResult
& aError
) override
;
145 void Clear(nsIPrincipal
& aSubjectPrincipal
, ErrorResult
& aError
) override
;
147 //////////////////////////////////////////////////////////////////////////////
148 // Testing Methods: See Storage.h
149 void Open(nsIPrincipal
& aSubjectPrincipal
, ErrorResult
& aError
) override
;
151 void Close(nsIPrincipal
& aSubjectPrincipal
, ErrorResult
& aError
) override
;
153 void BeginExplicitSnapshot(nsIPrincipal
& aSubjectPrincipal
,
154 ErrorResult
& aError
) override
;
156 void CheckpointExplicitSnapshot(nsIPrincipal
& aSubjectPrincipal
,
157 ErrorResult
& aError
) override
;
159 void EndExplicitSnapshot(nsIPrincipal
& aSubjectPrincipal
,
160 ErrorResult
& aError
) override
;
162 bool GetHasSnapshot(nsIPrincipal
& aSubjectPrincipal
,
163 ErrorResult
& aError
) override
;
165 int64_t GetSnapshotUsage(nsIPrincipal
& aSubjectPrincipal
,
166 ErrorResult
& aError
) override
;
168 //////////////////////////////////////////////////////////////////////////////
170 NS_DECL_ISUPPORTS_INHERITED
171 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(LSObject
, Storage
)
174 LSObject(nsPIDOMWindowInner
* aWindow
, nsIPrincipal
* aPrincipal
,
175 nsIPrincipal
* aStoragePrincipal
);
179 nsresult
DoRequestSynchronously(const LSRequestParams
& aParams
,
180 LSRequestResponse
& aResponse
);
182 nsresult
EnsureDatabase();
187 * Invoked by nsGlobalWindowInner whenever a new "storage" event listener is
188 * added to the window in order to ensure that "storage" events are received
189 * from other processes. (`LSObject::OnChange` directly invokes
190 * `Storage::NotifyChange` to notify in-process listeners.)
192 * If this is the first request in the process for an observer for this
193 * origin, this will trigger a RequestHelper-mediated synchronous LSRequest
194 * to prepare a new observer in the parent process and also construction of
195 * corresponding actors, which will result in the observer being fully
196 * registered in the parent process.
198 nsresult
EnsureObserver();
201 * Invoked by nsGlobalWindowInner whenever its last "storage" event listener
207 * Internal helper method used by mutation methods that wraps the call to
208 * Storage::NotifyChange to generate same-process "storage" events.
210 void OnChange(const nsAString
& aKey
, const nsAString
& aOldValue
,
211 const nsAString
& aNewValue
);
213 // Storage overrides.
214 void LastRelease() override
;
218 } // namespace mozilla
220 #endif // mozilla_dom_localstorage_LSObject_h