dom/src/storage/DOMStorageCache.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/src/storage/DOMStorageCache.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,273 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef nsDOMStorageCache_h___
    1.10 +#define nsDOMStorageCache_h___
    1.11 +
    1.12 +#include "nsIURI.h"
    1.13 +#include "nsIPrincipal.h"
    1.14 +#include "nsITimer.h"
    1.15 +
    1.16 +#include "nsString.h"
    1.17 +#include "nsDataHashtable.h"
    1.18 +#include "nsHashKeys.h"
    1.19 +#include "mozilla/Monitor.h"
    1.20 +#include "mozilla/Telemetry.h"
    1.21 +#include "nsAutoPtr.h"
    1.22 +
    1.23 +namespace mozilla {
    1.24 +namespace dom {
    1.25 +
    1.26 +class DOMStorage;
    1.27 +class DOMStorageUsage;
    1.28 +class DOMStorageManager;
    1.29 +class DOMStorageDBBridge;
    1.30 +
    1.31 +// Interface class on which only the database or IPC may call.
    1.32 +// Used to populate the cache with DB data.
    1.33 +class DOMStorageCacheBridge
    1.34 +{
    1.35 +public:
    1.36 +  NS_IMETHOD_(MozExternalRefCountType) AddRef(void);
    1.37 +  NS_IMETHOD_(void) Release(void);
    1.38 +
    1.39 +  virtual ~DOMStorageCacheBridge() {}
    1.40 +
    1.41 +  // The scope (origin) in the database usage format (reversed)
    1.42 +  virtual const nsCString& Scope() const = 0;
    1.43 +
    1.44 +  // Whether the cache is already fully loaded
    1.45 +  virtual bool Loaded() = 0;
    1.46 +
    1.47 +  // How many items has so far been loaded into the cache, used
    1.48 +  // for optimization purposes
    1.49 +  virtual uint32_t LoadedCount() = 0;
    1.50 +
    1.51 +  // Called by the database to load a key and its value to the cache
    1.52 +  virtual bool LoadItem(const nsAString& aKey, const nsString& aValue) = 0;
    1.53 +
    1.54 +  // Called by the database after all keys and values has been loaded
    1.55 +  // to this cache
    1.56 +  virtual void LoadDone(nsresult aRv) = 0;
    1.57 +
    1.58 +  // Use to synchronously wait until the cache gets fully loaded with data,
    1.59 +  // this method exits after LoadDone has been called
    1.60 +  virtual void LoadWait() = 0;
    1.61 +
    1.62 +protected:
    1.63 +  ThreadSafeAutoRefCnt mRefCnt;
    1.64 +  NS_DECL_OWNINGTHREAD
    1.65 +};
    1.66 +
    1.67 +// Implementation of scope cache that is responsible for preloading data
    1.68 +// for persistent storage (localStorage) and hold data for non-private,
    1.69 +// private and session-only cookie modes.  It is also responsible for
    1.70 +// persisting data changes using the database, works as a write-back cache.
    1.71 +class DOMStorageCache : public DOMStorageCacheBridge
    1.72 +{
    1.73 +public:
    1.74 +  NS_IMETHOD_(void) Release(void);
    1.75 +
    1.76 +  DOMStorageCache(const nsACString* aScope);
    1.77 +  virtual ~DOMStorageCache();
    1.78 +
    1.79 +  void Init(DOMStorageManager* aManager, bool aPersistent,
    1.80 +            nsIURI* aFirstPartyIsolationURI, nsIPrincipal* aPrincipal,
    1.81 +            const nsACString& aQuotaScope);
    1.82 +
    1.83 +  // Copies all data from the other storage.
    1.84 +  void CloneFrom(const DOMStorageCache* aThat);
    1.85 +
    1.86 +  // Starts async preload of this cache if it persistent and not loaded.
    1.87 +  void Preload();
    1.88 +
    1.89 +  // Keeps the cache alive (i.e. present in the manager's hash table) for a time.
    1.90 +  void KeepAlive();
    1.91 +
    1.92 +  // The set of methods that are invoked by DOM storage web API.
    1.93 +  // We are passing the DOMStorage object just to let the cache
    1.94 +  // read properties like mPrivate and mSessionOnly.
    1.95 +  // Get* methods return error when load from the database has failed.
    1.96 +  nsresult GetLength(const DOMStorage* aStorage, uint32_t* aRetval);
    1.97 +  nsresult GetKey(const DOMStorage* aStorage, uint32_t index, nsAString& aRetval);
    1.98 +  nsresult GetItem(const DOMStorage* aStorage, const nsAString& aKey, nsAString& aRetval);
    1.99 +  nsresult SetItem(const DOMStorage* aStorage, const nsAString& aKey, const nsString& aValue, nsString& aOld);
   1.100 +  nsresult RemoveItem(const DOMStorage* aStorage, const nsAString& aKey, nsString& aOld);
   1.101 +  nsresult Clear(const DOMStorage* aStorage);
   1.102 +
   1.103 +  nsTArray<nsString>* GetKeys(const DOMStorage* aStorage);
   1.104 +
   1.105 +  nsIURI* FirstPartyIsolationURI() const { return mFirstPartyIsolationURI; }
   1.106 +
   1.107 +  // Whether the principal equals principal the cache was created for
   1.108 +  bool CheckPrincipal(nsIPrincipal* aPrincipal) const;
   1.109 +  nsIPrincipal* Principal() const { return mPrincipal; }
   1.110 +
   1.111 +  // Starts the database engine thread or the IPC bridge
   1.112 +  static DOMStorageDBBridge* StartDatabase();
   1.113 +  static DOMStorageDBBridge* GetDatabase();
   1.114 +
   1.115 +  // Stops the thread and flushes all uncommited data
   1.116 +  static nsresult StopDatabase();
   1.117 +
   1.118 +  // DOMStorageCacheBridge
   1.119 +
   1.120 +  virtual const nsCString& Scope() const { return mScope; }
   1.121 +  virtual bool Loaded() { return mLoaded; }
   1.122 +  virtual uint32_t LoadedCount();
   1.123 +  virtual bool LoadItem(const nsAString& aKey, const nsString& aValue);
   1.124 +  virtual void LoadDone(nsresult aRv);
   1.125 +  virtual void LoadWait();
   1.126 +
   1.127 +  // Cache keeps 3 sets of data: regular, private and session-only.
   1.128 +  // This class keeps keys and values for a set and also caches
   1.129 +  // size of the data for quick per-origin quota checking.
   1.130 +  class Data
   1.131 +  {
   1.132 +  public:
   1.133 +    Data() : mOriginQuotaUsage(0) {}
   1.134 +    int64_t mOriginQuotaUsage;
   1.135 +    nsDataHashtable<nsStringHashKey, nsString> mKeys;
   1.136 +  };
   1.137 +
   1.138 +public:
   1.139 +  // Number of data sets we keep: default, private, session
   1.140 +  static const uint32_t kDataSetCount = 3;
   1.141 +
   1.142 +private:
   1.143 +  // API to clear the cache data, this is invoked by chrome operations
   1.144 +  // like cookie deletion.
   1.145 +  friend class DOMStorageManager;
   1.146 +
   1.147 +  static const uint32_t kUnloadDefault = 1 << 0;
   1.148 +  static const uint32_t kUnloadPrivate = 1 << 1;
   1.149 +  static const uint32_t kUnloadSession = 1 << 2;
   1.150 +  static const uint32_t kUnloadComplete =
   1.151 +    kUnloadDefault | kUnloadPrivate | kUnloadSession;
   1.152 +
   1.153 +#ifdef DOM_STORAGE_TESTS
   1.154 +  static const uint32_t kTestReload    = 1 << 15;
   1.155 +#endif
   1.156 +
   1.157 +  void UnloadItems(uint32_t aUnloadFlags);
   1.158 +
   1.159 +private:
   1.160 +  // Synchronously blocks until the cache is fully loaded from the database
   1.161 +  void WaitForPreload(mozilla::Telemetry::ID aTelemetryID);
   1.162 +
   1.163 +  // Helper to get one of the 3 data sets (regular, private, session)
   1.164 +  Data& DataSet(const DOMStorage* aStorage);
   1.165 +
   1.166 +  // Whether the storage change is about to persist
   1.167 +  bool Persist(const DOMStorage* aStorage) const;
   1.168 +
   1.169 +  // Changes the quota usage on the given data set if it fits the quota.
   1.170 +  // If not, then false is returned and no change to the set must be done.
   1.171 +  bool ProcessUsageDelta(uint32_t aGetDataSetIndex, const int64_t aDelta);
   1.172 +  bool ProcessUsageDelta(const DOMStorage* aStorage, const int64_t aDelta);
   1.173 +
   1.174 +private:
   1.175 +  // When a cache is reponsible for its life time (in case of localStorage data
   1.176 +  // cache) we need to refer our manager since removal of the cache from the hash
   1.177 +  // table is handled in the destructor by call to the manager.
   1.178 +  // Cache could potentially overlive the manager, hence the hard ref.
   1.179 +  nsRefPtr<DOMStorageManager> mManager;
   1.180 +
   1.181 +  // Reference to the usage counter object we check on for eTLD+1 quota limit.
   1.182 +  // Obtained from the manager during initialization (Init method).
   1.183 +  nsRefPtr<DOMStorageUsage> mUsage;
   1.184 +
   1.185 +  // Timer that holds this cache alive for a while after it has been preloaded.
   1.186 +  nsCOMPtr<nsITimer> mKeepAliveTimer;
   1.187 +
   1.188 +  // The first party URI associated with this cache.
   1.189 +  nsCOMPtr<nsIURI> mFirstPartyIsolationURI;
   1.190 +
   1.191 +  // Principal the cache has been initially created for, this is used only
   1.192 +  // for sessionStorage access checks since sessionStorage objects are strictly
   1.193 +  // scoped by a principal.  localStorage objects on the other hand are scoped by
   1.194 +  // origin only.
   1.195 +  nsCOMPtr<nsIPrincipal> mPrincipal;
   1.196 +
   1.197 +  // The scope this cache belongs to in the "DB format", i.e. reversed
   1.198 +  nsCString mScope;
   1.199 +
   1.200 +  // The eTLD+1 scope used to count quota usage.
   1.201 +  nsCString mQuotaScope;
   1.202 +
   1.203 +  // Non-private Browsing, Private Browsing and Session Only sets.
   1.204 +  Data mData[kDataSetCount];
   1.205 +
   1.206 +  // This monitor is used to wait for full load of data.
   1.207 +  mozilla::Monitor mMonitor;
   1.208 +
   1.209 +  // Flag that is initially false.  When the cache is about to work with
   1.210 +  // the database (i.e. it is persistent) this flags is set to true after
   1.211 +  // all keys and coresponding values are loaded from the database.
   1.212 +  // This flag never goes from true back to false.
   1.213 +  bool mLoaded;
   1.214 +
   1.215 +  // Result of load from the database.  Valid after mLoaded flag has been set.
   1.216 +  nsresult mLoadResult;
   1.217 +
   1.218 +  // Init() method has been called
   1.219 +  bool mInitialized : 1;
   1.220 +
   1.221 +  // This cache is about to be bound with the database (i.e. it has
   1.222 +  // to load from the DB first and has to persist when modifying the
   1.223 +  // default data set.)
   1.224 +  bool mPersistent : 1;
   1.225 +
   1.226 +  // - False when the session-only data set was never used.
   1.227 +  // - True after access to session-only data has been made for the first time.
   1.228 +  // We also fill session-only data set with the default one at that moment.
   1.229 +  // Drops back to false when session-only data are cleared from chrome.
   1.230 +  bool mSessionOnlyDataSetActive : 1;
   1.231 +
   1.232 +  // Whether we have already captured state of the cache preload on our first access.
   1.233 +  bool mPreloadTelemetryRecorded : 1;
   1.234 +
   1.235 +  // DOMStorageDBThread on the parent or single process,
   1.236 +  // DOMStorageDBChild on the child process.
   1.237 +  static DOMStorageDBBridge* sDatabase;
   1.238 +
   1.239 +  // False until we shut the database down.
   1.240 +  static bool sDatabaseDown;
   1.241 +};
   1.242 +
   1.243 +// DOMStorageUsage
   1.244 +// Infrastructure to manage and check eTLD+1 quota
   1.245 +class DOMStorageUsageBridge
   1.246 +{
   1.247 +public:
   1.248 +  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DOMStorageUsageBridge)
   1.249 +
   1.250 +  virtual const nsCString& Scope() = 0;
   1.251 +  virtual void LoadUsage(const int64_t aUsage) = 0;
   1.252 +
   1.253 +protected:
   1.254 +  // Protected destructor, to discourage deletion outside of Release():
   1.255 +  virtual ~DOMStorageUsageBridge() {}
   1.256 +};
   1.257 +
   1.258 +class DOMStorageUsage : public DOMStorageUsageBridge
   1.259 +{
   1.260 +public:
   1.261 +  DOMStorageUsage(const nsACString& aScope);
   1.262 +
   1.263 +  bool CheckAndSetETLD1UsageDelta(uint32_t aDataSetIndex, int64_t aUsageDelta);
   1.264 +
   1.265 +private:
   1.266 +  virtual const nsCString& Scope() { return mScope; }
   1.267 +  virtual void LoadUsage(const int64_t aUsage);
   1.268 +
   1.269 +  nsCString mScope;
   1.270 +  int64_t mUsage[DOMStorageCache::kDataSetCount];
   1.271 +};
   1.272 +
   1.273 +} // ::dom
   1.274 +} // ::mozilla
   1.275 +
   1.276 +#endif

mercurial