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_LSSnapshot_h 8 #define mozilla_dom_localstorage_LSSnapshot_h 9 10 #include <cstdint> 11 #include <cstdlib> 12 #include "ErrorList.h" 13 #include "mozilla/Assertions.h" 14 #include "mozilla/RefPtr.h" 15 #include "mozilla/UniquePtr.h" 16 #include "nsCOMPtr.h" 17 #include "nsTHashMap.h" 18 #include "nsHashKeys.h" 19 #include "nsIRunnable.h" 20 #include "nsISupports.h" 21 #include "nsStringFwd.h" 22 #include "nsTArrayForwardDeclare.h" 23 #include "nsTHashSet.h" 24 25 class nsITimer; 26 27 namespace mozilla { 28 namespace dom { 29 30 class LSDatabase; 31 class LSNotifyInfo; 32 class LSSnapshotChild; 33 class LSSnapshotInitInfo; 34 class LSWriteAndNotifyInfo; 35 class SnapshotWriteOptimizer; 36 37 template <typename> 38 class Optional; 39 40 class LSSnapshot final : public nsIRunnable { 41 public: 42 /** 43 * The LoadState expresses what subset of information a snapshot has from the 44 * authoritative Datastore in the parent process. The initial snapshot is 45 * populated heuristically based on the size of the keys and size of the items 46 * (inclusive of the key value; item is key+value, not just value) of the 47 * entire datastore relative to the configured prefill limit (via pref 48 * "dom.storage.snapshot_prefill" exposed as gSnapshotPrefill in bytes). 49 * 50 * If there's less data than the limit, we send both keys and values and end 51 * up as AllOrderedItems. If there's enough room for all the keys but not 52 * all the values, we end up as AllOrderedKeys with as many values present as 53 * would fit. If there's not enough room for all the keys, then we end up as 54 * Partial with as many key-value pairs as will fit. 55 * 56 * The state AllUnorderedItems can only be reached by code getting items one 57 * by one. 58 */ 59 enum class LoadState { 60 /** 61 * Class constructed, Init(LSSnapshotInitInfo) has not been invoked yet. 62 */ 63 Initial, 64 /** 65 * Some keys and their values are known. 66 */ 67 Partial, 68 /** 69 * All the keys are known in order, but some values are unknown. 70 */ 71 AllOrderedKeys, 72 /** 73 * All keys and their values are known, but in an arbitrary order. 74 */ 75 AllUnorderedItems, 76 /** 77 * All keys and their values are known and are present in their canonical 78 * order. This is everything, and is the preferred case. The initial 79 * population will send this info when the size of all items is less than 80 * the prefill threshold. 81 * 82 * mValues will contain all keys and values, mLoadedItems and mUnknownItems 83 * are unused. 84 */ 85 AllOrderedItems, 86 EndGuard 87 }; 88 89 private: 90 RefPtr<LSSnapshot> mSelfRef; 91 92 RefPtr<LSDatabase> mDatabase; 93 94 nsCOMPtr<nsITimer> mTimer; 95 96 LSSnapshotChild* mActor; 97 98 nsTHashSet<nsString> mLoadedItems; 99 nsTHashSet<nsString> mUnknownItems; 100 nsTHashMap<nsStringHashKey, nsString> mValues; 101 UniquePtr<SnapshotWriteOptimizer> mWriteOptimizer; 102 UniquePtr<nsTArray<LSWriteAndNotifyInfo>> mWriteAndNotifyInfos; 103 104 uint32_t mInitLength; 105 uint32_t mLength; 106 int64_t mExactUsage; 107 int64_t mPeakUsage; 108 109 LoadState mLoadState; 110 111 bool mHasOtherProcessObservers; 112 bool mExplicit; 113 bool mHasPendingStableStateCallback; 114 bool mHasPendingTimerCallback; 115 bool mDirty; 116 117 #ifdef DEBUG 118 bool mInitialized; 119 bool mSentFinish; 120 #endif 121 122 public: 123 explicit LSSnapshot(LSDatabase* aDatabase); 124 AssertIsOnOwningThread()125 void AssertIsOnOwningThread() const { NS_ASSERT_OWNINGTHREAD(LSSnapshot); } 126 127 void SetActor(LSSnapshotChild* aActor); 128 ClearActor()129 void ClearActor() { 130 AssertIsOnOwningThread(); 131 MOZ_ASSERT(mActor); 132 133 mActor = nullptr; 134 } 135 Explicit()136 bool Explicit() const { return mExplicit; } 137 138 nsresult Init(const nsAString& aKey, const LSSnapshotInitInfo& aInitInfo, 139 bool aExplicit); 140 141 nsresult GetLength(uint32_t* aResult); 142 143 nsresult GetKey(uint32_t aIndex, nsAString& aResult); 144 145 nsresult GetItem(const nsAString& aKey, nsAString& aResult); 146 147 nsresult GetKeys(nsTArray<nsString>& aKeys); 148 149 nsresult SetItem(const nsAString& aKey, const nsAString& aValue, 150 LSNotifyInfo& aNotifyInfo); 151 152 nsresult RemoveItem(const nsAString& aKey, LSNotifyInfo& aNotifyInfo); 153 154 nsresult Clear(LSNotifyInfo& aNotifyInfo); 155 156 void MarkDirty(); 157 158 nsresult End(); 159 160 private: 161 ~LSSnapshot(); 162 163 void ScheduleStableStateCallback(); 164 165 void MaybeScheduleStableStateCallback(); 166 167 nsresult GetItemInternal(const nsAString& aKey, 168 const Optional<nsString>& aValue, 169 nsAString& aResult); 170 171 nsresult EnsureAllKeys(); 172 173 nsresult UpdateUsage(int64_t aDelta); 174 175 nsresult Checkpoint(); 176 177 nsresult Finish(); 178 179 void CancelTimer(); 180 181 static void TimerCallback(nsITimer* aTimer, void* aClosure); 182 183 NS_DECL_ISUPPORTS 184 NS_DECL_NSIRUNNABLE 185 }; 186 187 } // namespace dom 188 } // namespace mozilla 189 190 #endif // mozilla_dom_localstorage_LSSnapshot_h 191