summaryrefslogtreecommitdiffstats
path: root/dom/storage/LocalStorageManager.h
blob: cffb9c0d76084dcb7b0a9a94ba9e26127c63dd12 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_dom_StorageManager_h
#define mozilla_dom_StorageManager_h

#include "nsIDOMStorageManager.h"
#include "nsILocalStorageManager.h"
#include "StorageObserver.h"

#include "LocalStorage.h"
#include "LocalStorageCache.h"
#include "mozilla/dom/Storage.h"

#include "nsTHashtable.h"
#include "nsClassHashtable.h"
#include "nsHashKeys.h"
#include "nsTHashMap.h"

namespace mozilla {

class OriginAttributesPattern;

namespace dom {

class LocalStorageManager final : public nsIDOMStorageManager,
                                  public nsILocalStorageManager,
                                  public StorageObserverSink {
  NS_DECL_ISUPPORTS
  NS_DECL_NSIDOMSTORAGEMANAGER
  NS_DECL_NSILOCALSTORAGEMANAGER

 public:
  LocalStorageManager();

  // Reads the preference for DOM storage quota
  static uint32_t GetOriginQuota();

  // Reads the preference for DOM storage site quota
  static uint32_t GetSiteQuota();

  // Gets (but not ensures) cache for the given scope
  LocalStorageCache* GetCache(const nsACString& aOriginSuffix,
                              const nsACString& aOriginNoSuffix);

  // Returns object keeping usage cache for the scope.
  already_AddRefed<StorageUsage> GetOriginUsage(
      const nsACString& aOriginNoSuffix, uint32_t aPrivateBrowsingId);

  static nsAutoCString CreateOrigin(const nsACString& aOriginSuffix,
                                    const nsACString& aOriginNoSuffix);

 private:
  ~LocalStorageManager();

  // StorageObserverSink, handler to various chrome clearing notification
  nsresult Observe(const char* aTopic,
                   const nsAString& aOriginAttributesPattern,
                   const nsACString& aOriginScope) override;

  // Since nsTHashtable doesn't like multiple inheritance, we have to aggregate
  // LocalStorageCache into the entry.
  class LocalStorageCacheHashKey : public nsCStringHashKey {
   public:
    explicit LocalStorageCacheHashKey(const nsACString* aKey)
        : nsCStringHashKey(aKey), mCache(new LocalStorageCache(aKey)) {}

    LocalStorageCacheHashKey(LocalStorageCacheHashKey&& aOther)
        : nsCStringHashKey(std::move(aOther)),
          mCache(std::move(aOther.mCache)),
          mCacheRef(std::move(aOther.mCacheRef)) {
      NS_ERROR("Shouldn't be called");
    }

    LocalStorageCache* cache() { return mCache; }
    // Keep the cache referenced forever, used for sessionStorage.
    void HardRef() { mCacheRef = mCache; }

   private:
    // weak ref only since cache references its manager.
    LocalStorageCache* mCache;
    // hard ref when this is sessionStorage to keep it alive forever.
    RefPtr<LocalStorageCache> mCacheRef;
  };

  // Ensures cache for a scope, when it doesn't exist it is created and
  // initalized, this also starts preload of persistent data.
  already_AddRefed<LocalStorageCache> PutCache(
      const nsACString& aOriginSuffix, const nsACString& aOriginNoSuffix,
      const nsACString& aQuotaKey, nsIPrincipal* aPrincipal);

  enum class CreateMode {
    // GetStorage: do not create if it's not already in memory.
    UseIfExistsNeverCreate,
    // CreateStorage: Create it if it's not already in memory.
    CreateAlways,
    // PrecacheStorage: Create only if the database says we ShouldPreloadOrigin.
    CreateIfShouldPreload
  };

  // Helper for creation of DOM storage objects
  nsresult GetStorageInternal(CreateMode aCreate, mozIDOMWindow* aWindow,
                              nsIPrincipal* aPrincipal,
                              nsIPrincipal* aStoragePrincipal,
                              const nsAString& aDocumentURI, bool aPrivate,
                              Storage** aRetval);

  // Suffix->origin->cache map
  using CacheOriginHashtable = nsTHashtable<LocalStorageCacheHashKey>;
  nsClassHashtable<nsCStringHashKey, CacheOriginHashtable> mCaches;

  void ClearCaches(uint32_t aUnloadFlags,
                   const OriginAttributesPattern& aPattern,
                   const nsACString& aKeyPrefix);

  // Global getter of localStorage manager service
  static LocalStorageManager* Self();

  // Like Self, but creates an instance if we're not yet initialized.
  static LocalStorageManager* Ensure();

 private:
  // Keeps usage cache objects for eTLD+1 scopes we have touched.
  nsTHashMap<nsCString, RefPtr<StorageUsage> > mUsages;

  friend class LocalStorageCache;
  friend class StorageDBChild;
  // Releases cache since it is no longer referrered by any Storage object.
  virtual void DropCache(LocalStorageCache* aCache);

  static LocalStorageManager* sSelf;
};

}  // namespace dom
}  // namespace mozilla

#endif  // mozilla_dom_StorageManager_h