Merge backout.
[mozilla-central.git] / dom / src / storage / nsDOMStorageMemoryDB.cpp
blob220ba527f2aecf2b98b2c28563a4a69a63d35158
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Mozilla Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2009
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Neil Deakin <enndeakin@sympatico.ca>
24 * Honza Bambas <honzab@firemni.cz>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #include "nsCOMPtr.h"
41 #include "nsDOMError.h"
42 #include "nsDOMStorage.h"
43 #include "nsDOMStorageMemoryDB.h"
44 #include "nsNetUtil.h"
46 nsresult
47 nsDOMStorageMemoryDB::Init(nsDOMStoragePersistentDB* aPreloadDB)
49 if (!mData.Init(20))
50 return NS_ERROR_OUT_OF_MEMORY;
52 mPreloadDB = aPreloadDB;
53 return NS_OK;
56 static PLDHashOperator
57 AllKeyEnum(nsSessionStorageEntry* aEntry, void* userArg)
59 nsDOMStorageMemoryDB::nsStorageItemsTable *target =
60 (nsDOMStorageMemoryDB::nsStorageItemsTable *)userArg;
62 nsDOMStorageMemoryDB::nsInMemoryItem* item =
63 new nsDOMStorageMemoryDB::nsInMemoryItem();
64 if (!item)
65 return PL_DHASH_STOP;
67 aEntry->mItem->GetValue(item->mValue);
68 nsresult rv = aEntry->mItem->GetSecure(&item->mSecure);
69 if (NS_FAILED(rv))
70 item->mSecure = PR_FALSE;
72 target->Put(aEntry->GetKey(), item);
73 return PL_DHASH_NEXT;
76 nsresult
77 nsDOMStorageMemoryDB::GetItemsTable(nsDOMStorage* aStorage,
78 nsInMemoryStorage** aMemoryStorage)
80 if (mData.Get(aStorage->GetScopeDBKey(), aMemoryStorage))
81 return NS_OK;
83 *aMemoryStorage = nsnull;
85 nsInMemoryStorage* storageData = new nsInMemoryStorage();
86 if (!storageData)
87 return NS_ERROR_OUT_OF_MEMORY;
89 if (!storageData->mTable.Init()) {
90 delete storageData;
91 return NS_ERROR_OUT_OF_MEMORY;
94 if (mPreloadDB) {
95 nsresult rv;
97 nsTHashtable<nsSessionStorageEntry> keys;
98 keys.Init();
100 rv = mPreloadDB->GetAllKeys(aStorage, &keys);
101 NS_ENSURE_SUCCESS(rv, rv);
103 mPreloading = PR_TRUE;
104 keys.EnumerateEntries(AllKeyEnum, &storageData->mTable);
105 mPreloading = PR_FALSE;
108 mData.Put(aStorage->GetScopeDBKey(), storageData);
109 *aMemoryStorage = storageData;
111 return NS_OK;
114 struct GetAllKeysEnumStruc
116 nsTHashtable<nsSessionStorageEntry>* mTarget;
117 nsDOMStorage* mStorage;
120 static PLDHashOperator
121 GetAllKeysEnum(const nsAString& keyname,
122 nsDOMStorageMemoryDB::nsInMemoryItem* item,
123 void *closure)
125 GetAllKeysEnumStruc* struc = (GetAllKeysEnumStruc*)closure;
127 nsSessionStorageEntry* entry = struc->mTarget->PutEntry(keyname);
128 if (!entry)
129 return PL_DHASH_STOP;
131 entry->mItem = new nsDOMStorageItem(struc->mStorage,
132 keyname,
133 EmptyString(),
134 item->mSecure);
135 if (!entry->mItem)
136 return PL_DHASH_STOP;
138 return PL_DHASH_NEXT;
141 nsresult
142 nsDOMStorageMemoryDB::GetAllKeys(nsDOMStorage* aStorage,
143 nsTHashtable<nsSessionStorageEntry>* aKeys)
145 nsresult rv;
147 nsInMemoryStorage* storage;
148 rv = GetItemsTable(aStorage, &storage);
149 NS_ENSURE_SUCCESS(rv, rv);
151 GetAllKeysEnumStruc struc;
152 struc.mTarget = aKeys;
153 struc.mStorage = aStorage;
154 storage->mTable.EnumerateRead(GetAllKeysEnum, &struc);
156 return NS_OK;
159 nsresult
160 nsDOMStorageMemoryDB::GetKeyValue(nsDOMStorage* aStorage,
161 const nsAString& aKey,
162 nsAString& aValue,
163 PRBool* aSecure)
165 if (mPreloading) {
166 NS_PRECONDITION(mPreloadDB, "Must have a preload DB set when preloading");
167 return mPreloadDB->GetKeyValue(aStorage, aKey, aValue, aSecure);
170 nsresult rv;
172 nsInMemoryStorage* storage;
173 rv = GetItemsTable(aStorage, &storage);
174 NS_ENSURE_SUCCESS(rv, rv);
176 nsInMemoryItem* item;
177 if (!storage->mTable.Get(aKey, &item))
178 return NS_ERROR_DOM_NOT_FOUND_ERR;
180 aValue = item->mValue;
181 *aSecure = item->mSecure;
182 return NS_OK;
185 nsresult
186 nsDOMStorageMemoryDB::SetKey(nsDOMStorage* aStorage,
187 const nsAString& aKey,
188 const nsAString& aValue,
189 PRBool aSecure,
190 PRInt32 aQuota,
191 PRBool aExcludeOfflineFromUsage,
192 PRInt32 *aNewUsage)
194 nsresult rv;
196 nsInMemoryStorage* storage;
197 rv = GetItemsTable(aStorage, &storage);
198 NS_ENSURE_SUCCESS(rv, rv);
200 PRInt32 usage = 0;
201 if (!aStorage->GetQuotaDomainDBKey(!aExcludeOfflineFromUsage).IsEmpty()) {
202 rv = GetUsage(aStorage, aExcludeOfflineFromUsage, &usage);
203 NS_ENSURE_SUCCESS(rv, rv);
206 usage += aKey.Length() + aValue.Length();
208 nsInMemoryItem* item;
209 if (!storage->mTable.Get(aKey, &item)) {
210 if (usage > aQuota) {
211 return NS_ERROR_DOM_QUOTA_REACHED;
214 item = new nsInMemoryItem();
215 if (!item)
216 return NS_ERROR_OUT_OF_MEMORY;
218 storage->mTable.Put(aKey, item);
219 storage->mUsageDelta += aKey.Length();
221 else
223 usage -= aKey.Length() + item->mValue.Length();
224 if (usage > aQuota) {
225 return NS_ERROR_DOM_QUOTA_REACHED;
229 storage->mUsageDelta += aValue.Length() - item->mValue.Length();
231 item->mValue = aValue;
232 item->mSecure = aSecure;
234 *aNewUsage = usage;
236 return NS_OK;
239 nsresult
240 nsDOMStorageMemoryDB::SetSecure(nsDOMStorage* aStorage,
241 const nsAString& aKey,
242 const PRBool aSecure)
244 nsresult rv;
246 nsInMemoryStorage* storage;
247 rv = GetItemsTable(aStorage, &storage);
248 NS_ENSURE_SUCCESS(rv, rv);
250 nsInMemoryItem* item;
251 if (!storage->mTable.Get(aKey, &item))
252 return NS_ERROR_DOM_NOT_FOUND_ERR;
254 item->mSecure = aSecure;
256 return NS_OK;
259 nsresult
260 nsDOMStorageMemoryDB::RemoveKey(nsDOMStorage* aStorage,
261 const nsAString& aKey,
262 PRBool aExcludeOfflineFromUsage,
263 PRInt32 aKeyUsage)
265 nsresult rv;
267 nsInMemoryStorage* storage;
268 rv = GetItemsTable(aStorage, &storage);
269 NS_ENSURE_SUCCESS(rv, rv);
271 nsInMemoryItem* item;
272 if (!storage->mTable.Get(aKey, &item))
273 return NS_ERROR_DOM_NOT_FOUND_ERR;
275 storage->mUsageDelta -= aKey.Length() + item->mValue.Length();
276 storage->mTable.Remove(aKey);
278 return NS_OK;
281 static PLDHashOperator
282 RemoveAllKeysEnum(const nsAString& keyname,
283 nsAutoPtr<nsDOMStorageMemoryDB::nsInMemoryItem>& item,
284 void *closure)
286 nsDOMStorageMemoryDB::nsInMemoryStorage* storage =
287 (nsDOMStorageMemoryDB::nsInMemoryStorage*)closure;
289 storage->mUsageDelta -= keyname.Length() + item->mValue.Length();
290 return PL_DHASH_REMOVE;
293 nsresult
294 nsDOMStorageMemoryDB::ClearStorage(nsDOMStorage* aStorage)
296 nsresult rv;
298 nsInMemoryStorage* storage;
299 rv = GetItemsTable(aStorage, &storage);
300 NS_ENSURE_SUCCESS(rv, rv);
302 storage->mTable.Enumerate(RemoveAllKeysEnum, storage);
303 return NS_OK;
306 nsresult
307 nsDOMStorageMemoryDB::DropStorage(nsDOMStorage* aStorage)
309 mData.Remove(aStorage->GetScopeDBKey());
310 return NS_OK;
313 struct RemoveOwnersStruc
315 nsCString* mSubDomain;
316 PRBool mMatch;
319 static PLDHashOperator
320 RemoveOwnersEnum(const nsACString& key,
321 nsAutoPtr<nsDOMStorageMemoryDB::nsInMemoryStorage>& storage,
322 void *closure)
324 RemoveOwnersStruc* struc = (RemoveOwnersStruc*)closure;
326 if (StringBeginsWith(key, *(struc->mSubDomain)) == struc->mMatch)
327 return PL_DHASH_REMOVE;
329 return PL_DHASH_NEXT;
332 nsresult
333 nsDOMStorageMemoryDB::RemoveOwner(const nsACString& aOwner,
334 PRBool aIncludeSubDomains)
336 nsCAutoString subdomainsDBKey;
337 nsDOMStorageDBWrapper::CreateDomainScopeDBKey(aOwner, subdomainsDBKey);
339 if (!aIncludeSubDomains)
340 subdomainsDBKey.AppendLiteral(":");
342 RemoveOwnersStruc struc;
343 struc.mSubDomain = &subdomainsDBKey;
344 struc.mMatch = PR_TRUE;
345 mData.Enumerate(RemoveOwnersEnum, &struc);
347 return NS_OK;
351 nsresult
352 nsDOMStorageMemoryDB::RemoveOwners(const nsTArray<nsString> &aOwners,
353 PRBool aIncludeSubDomains,
354 PRBool aMatch)
356 if (aOwners.Length() == 0) {
357 if (aMatch) {
358 return NS_OK;
361 return RemoveAll();
364 for (PRUint32 i = 0; i < aOwners.Length(); i++) {
365 nsCAutoString quotaKey;
366 nsresult rv;
367 rv = nsDOMStorageDBWrapper::CreateDomainScopeDBKey(
368 NS_ConvertUTF16toUTF8(aOwners[i]), quotaKey);
370 if (!aIncludeSubDomains)
371 quotaKey.AppendLiteral(":");
373 RemoveOwnersStruc struc;
374 struc.mSubDomain = &quotaKey;
375 struc.mMatch = aMatch;
376 mData.Enumerate(RemoveOwnersEnum, &struc);
379 return NS_OK;
382 nsresult
383 nsDOMStorageMemoryDB::RemoveAll()
385 mData.Clear(); // XXX Check this releases all instances
386 return NS_OK;
389 nsresult
390 nsDOMStorageMemoryDB::GetUsage(nsDOMStorage* aStorage,
391 PRBool aExcludeOfflineFromUsage, PRInt32 *aUsage)
393 return GetUsageInternal(aStorage->GetQuotaDomainDBKey(!aExcludeOfflineFromUsage),
394 aExcludeOfflineFromUsage, aUsage);
397 nsresult
398 nsDOMStorageMemoryDB::GetUsage(const nsACString& aDomain,
399 PRBool aIncludeSubDomains,
400 PRInt32 *aUsage)
402 nsresult rv;
404 nsCAutoString quotadomainDBKey;
405 rv = nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(aDomain,
406 aIncludeSubDomains,
407 PR_FALSE,
408 quotadomainDBKey);
409 NS_ENSURE_SUCCESS(rv, rv);
411 return GetUsageInternal(quotadomainDBKey, PR_FALSE, aUsage);
414 struct GetUsageEnumStruc
416 PRInt32 mUsage;
417 PRInt32 mExcludeOfflineFromUsage;
418 nsCString mSubdomain;
421 static PLDHashOperator
422 GetUsageEnum(const nsACString& key,
423 nsDOMStorageMemoryDB::nsInMemoryStorage* storageData,
424 void *closure)
426 GetUsageEnumStruc* struc = (GetUsageEnumStruc*)closure;
428 if (StringBeginsWith(key, struc->mSubdomain)) {
429 if (struc->mExcludeOfflineFromUsage) {
430 nsCAutoString domain;
431 nsresult rv = nsDOMStorageDBWrapper::GetDomainFromScopeKey(key, domain);
432 if (NS_SUCCEEDED(rv) && IsOfflineAllowed(domain))
433 return PL_DHASH_NEXT;
436 struc->mUsage += storageData->mUsageDelta;
439 return PL_DHASH_NEXT;
442 nsresult
443 nsDOMStorageMemoryDB::GetUsageInternal(const nsACString& aQuotaDomainDBKey,
444 PRBool aExcludeOfflineFromUsage,
445 PRInt32 *aUsage)
447 GetUsageEnumStruc struc;
448 struc.mUsage = 0;
449 struc.mExcludeOfflineFromUsage = aExcludeOfflineFromUsage;
450 struc.mSubdomain = aQuotaDomainDBKey;
452 if (mPreloadDB) {
453 nsresult rv;
455 rv = mPreloadDB->GetUsageInternal(aQuotaDomainDBKey,
456 aExcludeOfflineFromUsage, &struc.mUsage);
457 NS_ENSURE_SUCCESS(rv, rv);
460 mData.EnumerateRead(GetUsageEnum, &struc);
462 *aUsage = struc.mUsage;
463 return NS_OK;