dom/src/storage/DOMStorageCache.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #ifndef nsDOMStorageCache_h___
michael@0 7 #define nsDOMStorageCache_h___
michael@0 8
michael@0 9 #include "nsIURI.h"
michael@0 10 #include "nsIPrincipal.h"
michael@0 11 #include "nsITimer.h"
michael@0 12
michael@0 13 #include "nsString.h"
michael@0 14 #include "nsDataHashtable.h"
michael@0 15 #include "nsHashKeys.h"
michael@0 16 #include "mozilla/Monitor.h"
michael@0 17 #include "mozilla/Telemetry.h"
michael@0 18 #include "nsAutoPtr.h"
michael@0 19
michael@0 20 namespace mozilla {
michael@0 21 namespace dom {
michael@0 22
michael@0 23 class DOMStorage;
michael@0 24 class DOMStorageUsage;
michael@0 25 class DOMStorageManager;
michael@0 26 class DOMStorageDBBridge;
michael@0 27
michael@0 28 // Interface class on which only the database or IPC may call.
michael@0 29 // Used to populate the cache with DB data.
michael@0 30 class DOMStorageCacheBridge
michael@0 31 {
michael@0 32 public:
michael@0 33 NS_IMETHOD_(MozExternalRefCountType) AddRef(void);
michael@0 34 NS_IMETHOD_(void) Release(void);
michael@0 35
michael@0 36 virtual ~DOMStorageCacheBridge() {}
michael@0 37
michael@0 38 // The scope (origin) in the database usage format (reversed)
michael@0 39 virtual const nsCString& Scope() const = 0;
michael@0 40
michael@0 41 // Whether the cache is already fully loaded
michael@0 42 virtual bool Loaded() = 0;
michael@0 43
michael@0 44 // How many items has so far been loaded into the cache, used
michael@0 45 // for optimization purposes
michael@0 46 virtual uint32_t LoadedCount() = 0;
michael@0 47
michael@0 48 // Called by the database to load a key and its value to the cache
michael@0 49 virtual bool LoadItem(const nsAString& aKey, const nsString& aValue) = 0;
michael@0 50
michael@0 51 // Called by the database after all keys and values has been loaded
michael@0 52 // to this cache
michael@0 53 virtual void LoadDone(nsresult aRv) = 0;
michael@0 54
michael@0 55 // Use to synchronously wait until the cache gets fully loaded with data,
michael@0 56 // this method exits after LoadDone has been called
michael@0 57 virtual void LoadWait() = 0;
michael@0 58
michael@0 59 protected:
michael@0 60 ThreadSafeAutoRefCnt mRefCnt;
michael@0 61 NS_DECL_OWNINGTHREAD
michael@0 62 };
michael@0 63
michael@0 64 // Implementation of scope cache that is responsible for preloading data
michael@0 65 // for persistent storage (localStorage) and hold data for non-private,
michael@0 66 // private and session-only cookie modes. It is also responsible for
michael@0 67 // persisting data changes using the database, works as a write-back cache.
michael@0 68 class DOMStorageCache : public DOMStorageCacheBridge
michael@0 69 {
michael@0 70 public:
michael@0 71 NS_IMETHOD_(void) Release(void);
michael@0 72
michael@0 73 DOMStorageCache(const nsACString* aScope);
michael@0 74 virtual ~DOMStorageCache();
michael@0 75
michael@0 76 void Init(DOMStorageManager* aManager, bool aPersistent,
michael@0 77 nsIURI* aFirstPartyIsolationURI, nsIPrincipal* aPrincipal,
michael@0 78 const nsACString& aQuotaScope);
michael@0 79
michael@0 80 // Copies all data from the other storage.
michael@0 81 void CloneFrom(const DOMStorageCache* aThat);
michael@0 82
michael@0 83 // Starts async preload of this cache if it persistent and not loaded.
michael@0 84 void Preload();
michael@0 85
michael@0 86 // Keeps the cache alive (i.e. present in the manager's hash table) for a time.
michael@0 87 void KeepAlive();
michael@0 88
michael@0 89 // The set of methods that are invoked by DOM storage web API.
michael@0 90 // We are passing the DOMStorage object just to let the cache
michael@0 91 // read properties like mPrivate and mSessionOnly.
michael@0 92 // Get* methods return error when load from the database has failed.
michael@0 93 nsresult GetLength(const DOMStorage* aStorage, uint32_t* aRetval);
michael@0 94 nsresult GetKey(const DOMStorage* aStorage, uint32_t index, nsAString& aRetval);
michael@0 95 nsresult GetItem(const DOMStorage* aStorage, const nsAString& aKey, nsAString& aRetval);
michael@0 96 nsresult SetItem(const DOMStorage* aStorage, const nsAString& aKey, const nsString& aValue, nsString& aOld);
michael@0 97 nsresult RemoveItem(const DOMStorage* aStorage, const nsAString& aKey, nsString& aOld);
michael@0 98 nsresult Clear(const DOMStorage* aStorage);
michael@0 99
michael@0 100 nsTArray<nsString>* GetKeys(const DOMStorage* aStorage);
michael@0 101
michael@0 102 nsIURI* FirstPartyIsolationURI() const { return mFirstPartyIsolationURI; }
michael@0 103
michael@0 104 // Whether the principal equals principal the cache was created for
michael@0 105 bool CheckPrincipal(nsIPrincipal* aPrincipal) const;
michael@0 106 nsIPrincipal* Principal() const { return mPrincipal; }
michael@0 107
michael@0 108 // Starts the database engine thread or the IPC bridge
michael@0 109 static DOMStorageDBBridge* StartDatabase();
michael@0 110 static DOMStorageDBBridge* GetDatabase();
michael@0 111
michael@0 112 // Stops the thread and flushes all uncommited data
michael@0 113 static nsresult StopDatabase();
michael@0 114
michael@0 115 // DOMStorageCacheBridge
michael@0 116
michael@0 117 virtual const nsCString& Scope() const { return mScope; }
michael@0 118 virtual bool Loaded() { return mLoaded; }
michael@0 119 virtual uint32_t LoadedCount();
michael@0 120 virtual bool LoadItem(const nsAString& aKey, const nsString& aValue);
michael@0 121 virtual void LoadDone(nsresult aRv);
michael@0 122 virtual void LoadWait();
michael@0 123
michael@0 124 // Cache keeps 3 sets of data: regular, private and session-only.
michael@0 125 // This class keeps keys and values for a set and also caches
michael@0 126 // size of the data for quick per-origin quota checking.
michael@0 127 class Data
michael@0 128 {
michael@0 129 public:
michael@0 130 Data() : mOriginQuotaUsage(0) {}
michael@0 131 int64_t mOriginQuotaUsage;
michael@0 132 nsDataHashtable<nsStringHashKey, nsString> mKeys;
michael@0 133 };
michael@0 134
michael@0 135 public:
michael@0 136 // Number of data sets we keep: default, private, session
michael@0 137 static const uint32_t kDataSetCount = 3;
michael@0 138
michael@0 139 private:
michael@0 140 // API to clear the cache data, this is invoked by chrome operations
michael@0 141 // like cookie deletion.
michael@0 142 friend class DOMStorageManager;
michael@0 143
michael@0 144 static const uint32_t kUnloadDefault = 1 << 0;
michael@0 145 static const uint32_t kUnloadPrivate = 1 << 1;
michael@0 146 static const uint32_t kUnloadSession = 1 << 2;
michael@0 147 static const uint32_t kUnloadComplete =
michael@0 148 kUnloadDefault | kUnloadPrivate | kUnloadSession;
michael@0 149
michael@0 150 #ifdef DOM_STORAGE_TESTS
michael@0 151 static const uint32_t kTestReload = 1 << 15;
michael@0 152 #endif
michael@0 153
michael@0 154 void UnloadItems(uint32_t aUnloadFlags);
michael@0 155
michael@0 156 private:
michael@0 157 // Synchronously blocks until the cache is fully loaded from the database
michael@0 158 void WaitForPreload(mozilla::Telemetry::ID aTelemetryID);
michael@0 159
michael@0 160 // Helper to get one of the 3 data sets (regular, private, session)
michael@0 161 Data& DataSet(const DOMStorage* aStorage);
michael@0 162
michael@0 163 // Whether the storage change is about to persist
michael@0 164 bool Persist(const DOMStorage* aStorage) const;
michael@0 165
michael@0 166 // Changes the quota usage on the given data set if it fits the quota.
michael@0 167 // If not, then false is returned and no change to the set must be done.
michael@0 168 bool ProcessUsageDelta(uint32_t aGetDataSetIndex, const int64_t aDelta);
michael@0 169 bool ProcessUsageDelta(const DOMStorage* aStorage, const int64_t aDelta);
michael@0 170
michael@0 171 private:
michael@0 172 // When a cache is reponsible for its life time (in case of localStorage data
michael@0 173 // cache) we need to refer our manager since removal of the cache from the hash
michael@0 174 // table is handled in the destructor by call to the manager.
michael@0 175 // Cache could potentially overlive the manager, hence the hard ref.
michael@0 176 nsRefPtr<DOMStorageManager> mManager;
michael@0 177
michael@0 178 // Reference to the usage counter object we check on for eTLD+1 quota limit.
michael@0 179 // Obtained from the manager during initialization (Init method).
michael@0 180 nsRefPtr<DOMStorageUsage> mUsage;
michael@0 181
michael@0 182 // Timer that holds this cache alive for a while after it has been preloaded.
michael@0 183 nsCOMPtr<nsITimer> mKeepAliveTimer;
michael@0 184
michael@0 185 // The first party URI associated with this cache.
michael@0 186 nsCOMPtr<nsIURI> mFirstPartyIsolationURI;
michael@0 187
michael@0 188 // Principal the cache has been initially created for, this is used only
michael@0 189 // for sessionStorage access checks since sessionStorage objects are strictly
michael@0 190 // scoped by a principal. localStorage objects on the other hand are scoped by
michael@0 191 // origin only.
michael@0 192 nsCOMPtr<nsIPrincipal> mPrincipal;
michael@0 193
michael@0 194 // The scope this cache belongs to in the "DB format", i.e. reversed
michael@0 195 nsCString mScope;
michael@0 196
michael@0 197 // The eTLD+1 scope used to count quota usage.
michael@0 198 nsCString mQuotaScope;
michael@0 199
michael@0 200 // Non-private Browsing, Private Browsing and Session Only sets.
michael@0 201 Data mData[kDataSetCount];
michael@0 202
michael@0 203 // This monitor is used to wait for full load of data.
michael@0 204 mozilla::Monitor mMonitor;
michael@0 205
michael@0 206 // Flag that is initially false. When the cache is about to work with
michael@0 207 // the database (i.e. it is persistent) this flags is set to true after
michael@0 208 // all keys and coresponding values are loaded from the database.
michael@0 209 // This flag never goes from true back to false.
michael@0 210 bool mLoaded;
michael@0 211
michael@0 212 // Result of load from the database. Valid after mLoaded flag has been set.
michael@0 213 nsresult mLoadResult;
michael@0 214
michael@0 215 // Init() method has been called
michael@0 216 bool mInitialized : 1;
michael@0 217
michael@0 218 // This cache is about to be bound with the database (i.e. it has
michael@0 219 // to load from the DB first and has to persist when modifying the
michael@0 220 // default data set.)
michael@0 221 bool mPersistent : 1;
michael@0 222
michael@0 223 // - False when the session-only data set was never used.
michael@0 224 // - True after access to session-only data has been made for the first time.
michael@0 225 // We also fill session-only data set with the default one at that moment.
michael@0 226 // Drops back to false when session-only data are cleared from chrome.
michael@0 227 bool mSessionOnlyDataSetActive : 1;
michael@0 228
michael@0 229 // Whether we have already captured state of the cache preload on our first access.
michael@0 230 bool mPreloadTelemetryRecorded : 1;
michael@0 231
michael@0 232 // DOMStorageDBThread on the parent or single process,
michael@0 233 // DOMStorageDBChild on the child process.
michael@0 234 static DOMStorageDBBridge* sDatabase;
michael@0 235
michael@0 236 // False until we shut the database down.
michael@0 237 static bool sDatabaseDown;
michael@0 238 };
michael@0 239
michael@0 240 // DOMStorageUsage
michael@0 241 // Infrastructure to manage and check eTLD+1 quota
michael@0 242 class DOMStorageUsageBridge
michael@0 243 {
michael@0 244 public:
michael@0 245 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DOMStorageUsageBridge)
michael@0 246
michael@0 247 virtual const nsCString& Scope() = 0;
michael@0 248 virtual void LoadUsage(const int64_t aUsage) = 0;
michael@0 249
michael@0 250 protected:
michael@0 251 // Protected destructor, to discourage deletion outside of Release():
michael@0 252 virtual ~DOMStorageUsageBridge() {}
michael@0 253 };
michael@0 254
michael@0 255 class DOMStorageUsage : public DOMStorageUsageBridge
michael@0 256 {
michael@0 257 public:
michael@0 258 DOMStorageUsage(const nsACString& aScope);
michael@0 259
michael@0 260 bool CheckAndSetETLD1UsageDelta(uint32_t aDataSetIndex, int64_t aUsageDelta);
michael@0 261
michael@0 262 private:
michael@0 263 virtual const nsCString& Scope() { return mScope; }
michael@0 264 virtual void LoadUsage(const int64_t aUsage);
michael@0 265
michael@0 266 nsCString mScope;
michael@0 267 int64_t mUsage[DOMStorageCache::kDataSetCount];
michael@0 268 };
michael@0 269
michael@0 270 } // ::dom
michael@0 271 } // ::mozilla
michael@0 272
michael@0 273 #endif

mercurial