LocalStorage.cpp (6160B)
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 #include "LocalStorage.h" 8 9 #include "LocalStorageCache.h" 10 #include "LocalStorageManager.h" 11 #include "StorageUtils.h" 12 #include "mozilla/Preferences.h" 13 #include "mozilla/dom/PermissionMessageUtils.h" 14 #include "mozilla/dom/StorageBinding.h" 15 #include "mozilla/dom/StorageEvent.h" 16 #include "mozilla/dom/StorageEventBinding.h" 17 #include "mozilla/ipc/BackgroundChild.h" 18 #include "mozilla/ipc/PBackgroundChild.h" 19 #include "nsContentUtils.h" 20 #include "nsIPrincipal.h" 21 #include "nsServiceManagerUtils.h" 22 #include "nsThreadUtils.h" 23 24 namespace mozilla { 25 26 using namespace ipc; 27 28 namespace dom { 29 30 NS_IMPL_CYCLE_COLLECTION_CLASS(LocalStorage) 31 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(LocalStorage, Storage) 32 NS_IMPL_CYCLE_COLLECTION_UNLINK(mManager) 33 NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE 34 NS_IMPL_CYCLE_COLLECTION_UNLINK_END 35 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(LocalStorage, Storage) 36 CycleCollectionNoteChild( 37 cb, NS_ISUPPORTS_CAST(nsIDOMStorageManager*, tmp->mManager.get()), 38 "mManager"); 39 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 40 41 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(LocalStorage) 42 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) 43 NS_INTERFACE_MAP_END_INHERITING(Storage) 44 45 NS_IMPL_ADDREF_INHERITED(LocalStorage, Storage) 46 NS_IMPL_RELEASE_INHERITED(LocalStorage, Storage) 47 48 LocalStorage::LocalStorage(nsPIDOMWindowInner* aWindow, 49 LocalStorageManager* aManager, 50 LocalStorageCache* aCache, 51 const nsAString& aDocumentURI, 52 nsIPrincipal* aPrincipal, 53 nsIPrincipal* aStoragePrincipal, bool aIsPrivate) 54 : Storage(aWindow, aPrincipal, aStoragePrincipal), 55 mManager(aManager), 56 mCache(aCache), 57 mDocumentURI(aDocumentURI), 58 mIsPrivate(aIsPrivate) { 59 mCache->Preload(); 60 } 61 62 LocalStorage::~LocalStorage() = default; 63 64 int64_t LocalStorage::GetOriginQuotaUsage() const { 65 return mCache->GetOriginQuotaUsage(this); 66 } 67 68 uint32_t LocalStorage::GetLength(nsIPrincipal& aSubjectPrincipal, 69 ErrorResult& aRv) { 70 if (!CanUseStorage(aSubjectPrincipal)) { 71 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); 72 return 0; 73 } 74 75 uint32_t length; 76 aRv = mCache->GetLength(this, &length); 77 return length; 78 } 79 80 void LocalStorage::Key(uint32_t aIndex, nsAString& aResult, 81 nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) { 82 if (!CanUseStorage(aSubjectPrincipal)) { 83 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); 84 return; 85 } 86 87 aRv = mCache->GetKey(this, aIndex, aResult); 88 } 89 90 void LocalStorage::GetItem(const nsAString& aKey, nsAString& aResult, 91 nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) { 92 if (!CanUseStorage(aSubjectPrincipal)) { 93 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); 94 return; 95 } 96 97 aRv = mCache->GetItem(this, aKey, aResult); 98 } 99 100 void LocalStorage::SetItem(const nsAString& aKey, const nsAString& aData, 101 nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) { 102 if (!CanUseStorage(aSubjectPrincipal)) { 103 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); 104 return; 105 } 106 107 nsString data; 108 bool ok = data.Assign(aData, fallible); 109 if (!ok) { 110 aRv.Throw(NS_ERROR_OUT_OF_MEMORY); 111 return; 112 } 113 114 nsString old; 115 aRv = mCache->SetItem(this, aKey, data, old); 116 if (aRv.Failed()) { 117 return; 118 } 119 120 if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) { 121 OnChange(aKey, old, aData); 122 } 123 } 124 125 void LocalStorage::RemoveItem(const nsAString& aKey, 126 nsIPrincipal& aSubjectPrincipal, 127 ErrorResult& aRv) { 128 if (!CanUseStorage(aSubjectPrincipal)) { 129 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); 130 return; 131 } 132 133 nsAutoString old; 134 aRv = mCache->RemoveItem(this, aKey, old); 135 if (aRv.Failed()) { 136 return; 137 } 138 139 if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) { 140 OnChange(aKey, old, VoidString()); 141 } 142 } 143 144 void LocalStorage::Clear(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv) { 145 if (!CanUseStorage(aSubjectPrincipal)) { 146 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); 147 return; 148 } 149 150 aRv = mCache->Clear(this); 151 if (NS_WARN_IF(aRv.Failed())) { 152 return; 153 } 154 155 if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) { 156 OnChange(VoidString(), VoidString(), VoidString()); 157 } 158 } 159 160 void LocalStorage::OnChange(const nsAString& aKey, const nsAString& aOldValue, 161 const nsAString& aNewValue) { 162 NotifyChange(/* aStorage */ this, StoragePrincipal(), aKey, aOldValue, 163 aNewValue, /* aStorageType */ u"localStorage", mDocumentURI, 164 mIsPrivate, /* aImmediateDispatch */ false); 165 } 166 167 void LocalStorage::ApplyEvent(StorageEvent* aStorageEvent) { 168 MOZ_ASSERT(aStorageEvent); 169 170 nsAutoString key; 171 nsAutoString old; 172 nsAutoString value; 173 174 aStorageEvent->GetKey(key); 175 aStorageEvent->GetNewValue(value); 176 177 // No key means clearing the full storage. 178 if (key.IsVoid()) { 179 MOZ_ASSERT(value.IsVoid()); 180 mCache->Clear(this, LocalStorageCache::E10sPropagated); 181 return; 182 } 183 184 // No new value means removing the key. 185 if (value.IsVoid()) { 186 mCache->RemoveItem(this, key, old, LocalStorageCache::E10sPropagated); 187 return; 188 } 189 190 // Otherwise, we set the new value. 191 mCache->SetItem(this, key, value, old, LocalStorageCache::E10sPropagated); 192 } 193 194 void LocalStorage::GetSupportedNames(nsTArray<nsString>& aKeys) { 195 if (!CanUseStorage(*nsContentUtils::SubjectPrincipal())) { 196 // return just an empty array 197 aKeys.Clear(); 198 return; 199 } 200 201 mCache->GetKeys(this, aKeys); 202 } 203 204 bool LocalStorage::IsForkOf(const Storage* aOther) const { 205 MOZ_ASSERT(aOther); 206 if (aOther->Type() != eLocalStorage) { 207 return false; 208 } 209 210 return mCache == static_cast<const LocalStorage*>(aOther)->mCache; 211 } 212 213 } // namespace dom 214 } // namespace mozilla