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