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
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.
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 ***** */
41 #include "nsDOMError.h"
42 #include "nsDOMStorage.h"
43 #include "nsDOMStorageMemoryDB.h"
44 #include "nsNetUtil.h"
47 nsDOMStorageMemoryDB::Init(nsDOMStoragePersistentDB
* aPreloadDB
)
50 return NS_ERROR_OUT_OF_MEMORY
;
52 mPreloadDB
= aPreloadDB
;
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();
67 aEntry
->mItem
->GetValue(item
->mValue
);
68 nsresult rv
= aEntry
->mItem
->GetSecure(&item
->mSecure
);
70 item
->mSecure
= PR_FALSE
;
72 target
->Put(aEntry
->GetKey(), item
);
77 nsDOMStorageMemoryDB::GetItemsTable(nsDOMStorage
* aStorage
,
78 nsInMemoryStorage
** aMemoryStorage
)
80 if (mData
.Get(aStorage
->GetScopeDBKey(), aMemoryStorage
))
83 *aMemoryStorage
= nsnull
;
85 nsInMemoryStorage
* storageData
= new nsInMemoryStorage();
87 return NS_ERROR_OUT_OF_MEMORY
;
89 if (!storageData
->mTable
.Init()) {
91 return NS_ERROR_OUT_OF_MEMORY
;
97 nsTHashtable
<nsSessionStorageEntry
> keys
;
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
;
114 struct GetAllKeysEnumStruc
116 nsTHashtable
<nsSessionStorageEntry
>* mTarget
;
117 nsDOMStorage
* mStorage
;
120 static PLDHashOperator
121 GetAllKeysEnum(const nsAString
& keyname
,
122 nsDOMStorageMemoryDB::nsInMemoryItem
* item
,
125 GetAllKeysEnumStruc
* struc
= (GetAllKeysEnumStruc
*)closure
;
127 nsSessionStorageEntry
* entry
= struc
->mTarget
->PutEntry(keyname
);
129 return PL_DHASH_STOP
;
131 entry
->mItem
= new nsDOMStorageItem(struc
->mStorage
,
136 return PL_DHASH_STOP
;
138 return PL_DHASH_NEXT
;
142 nsDOMStorageMemoryDB::GetAllKeys(nsDOMStorage
* aStorage
,
143 nsTHashtable
<nsSessionStorageEntry
>* aKeys
)
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
);
160 nsDOMStorageMemoryDB::GetKeyValue(nsDOMStorage
* aStorage
,
161 const nsAString
& aKey
,
166 NS_PRECONDITION(mPreloadDB
, "Must have a preload DB set when preloading");
167 return mPreloadDB
->GetKeyValue(aStorage
, aKey
, aValue
, aSecure
);
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
;
186 nsDOMStorageMemoryDB::SetKey(nsDOMStorage
* aStorage
,
187 const nsAString
& aKey
,
188 const nsAString
& aValue
,
191 PRBool aExcludeOfflineFromUsage
,
196 nsInMemoryStorage
* storage
;
197 rv
= GetItemsTable(aStorage
, &storage
);
198 NS_ENSURE_SUCCESS(rv
, rv
);
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();
216 return NS_ERROR_OUT_OF_MEMORY
;
218 storage
->mTable
.Put(aKey
, item
);
219 storage
->mUsageDelta
+= aKey
.Length();
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
;
240 nsDOMStorageMemoryDB::SetSecure(nsDOMStorage
* aStorage
,
241 const nsAString
& aKey
,
242 const PRBool aSecure
)
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
;
260 nsDOMStorageMemoryDB::RemoveKey(nsDOMStorage
* aStorage
,
261 const nsAString
& aKey
,
262 PRBool aExcludeOfflineFromUsage
,
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
);
281 static PLDHashOperator
282 RemoveAllKeysEnum(const nsAString
& keyname
,
283 nsAutoPtr
<nsDOMStorageMemoryDB::nsInMemoryItem
>& item
,
286 nsDOMStorageMemoryDB::nsInMemoryStorage
* storage
=
287 (nsDOMStorageMemoryDB::nsInMemoryStorage
*)closure
;
289 storage
->mUsageDelta
-= keyname
.Length() + item
->mValue
.Length();
290 return PL_DHASH_REMOVE
;
294 nsDOMStorageMemoryDB::ClearStorage(nsDOMStorage
* aStorage
)
298 nsInMemoryStorage
* storage
;
299 rv
= GetItemsTable(aStorage
, &storage
);
300 NS_ENSURE_SUCCESS(rv
, rv
);
302 storage
->mTable
.Enumerate(RemoveAllKeysEnum
, storage
);
307 nsDOMStorageMemoryDB::DropStorage(nsDOMStorage
* aStorage
)
309 mData
.Remove(aStorage
->GetScopeDBKey());
313 struct RemoveOwnersStruc
315 nsCString
* mSubDomain
;
319 static PLDHashOperator
320 RemoveOwnersEnum(const nsACString
& key
,
321 nsAutoPtr
<nsDOMStorageMemoryDB::nsInMemoryStorage
>& storage
,
324 RemoveOwnersStruc
* struc
= (RemoveOwnersStruc
*)closure
;
326 if (StringBeginsWith(key
, *(struc
->mSubDomain
)) == struc
->mMatch
)
327 return PL_DHASH_REMOVE
;
329 return PL_DHASH_NEXT
;
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
);
352 nsDOMStorageMemoryDB::RemoveOwners(const nsTArray
<nsString
> &aOwners
,
353 PRBool aIncludeSubDomains
,
356 if (aOwners
.Length() == 0) {
364 for (PRUint32 i
= 0; i
< aOwners
.Length(); i
++) {
365 nsCAutoString quotaKey
;
367 rv
= nsDOMStorageDBWrapper::CreateDomainScopeDBKey(
368 NS_ConvertUTF16toUTF8(aOwners
[i
]), quotaKey
);
370 if (!aIncludeSubDomains
)
371 quotaKey
.AppendLiteral(":");
373 RemoveOwnersStruc struc
;
374 struc
.mSubDomain
= "aKey
;
375 struc
.mMatch
= aMatch
;
376 mData
.Enumerate(RemoveOwnersEnum
, &struc
);
383 nsDOMStorageMemoryDB::RemoveAll()
385 mData
.Clear(); // XXX Check this releases all instances
390 nsDOMStorageMemoryDB::GetUsage(nsDOMStorage
* aStorage
,
391 PRBool aExcludeOfflineFromUsage
, PRInt32
*aUsage
)
393 return GetUsageInternal(aStorage
->GetQuotaDomainDBKey(!aExcludeOfflineFromUsage
),
394 aExcludeOfflineFromUsage
, aUsage
);
398 nsDOMStorageMemoryDB::GetUsage(const nsACString
& aDomain
,
399 PRBool aIncludeSubDomains
,
404 nsCAutoString quotadomainDBKey
;
405 rv
= nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(aDomain
,
409 NS_ENSURE_SUCCESS(rv
, rv
);
411 return GetUsageInternal(quotadomainDBKey
, PR_FALSE
, aUsage
);
414 struct GetUsageEnumStruc
417 PRInt32 mExcludeOfflineFromUsage
;
418 nsCString mSubdomain
;
421 static PLDHashOperator
422 GetUsageEnum(const nsACString
& key
,
423 nsDOMStorageMemoryDB::nsInMemoryStorage
* storageData
,
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
;
443 nsDOMStorageMemoryDB::GetUsageInternal(const nsACString
& aQuotaDomainDBKey
,
444 PRBool aExcludeOfflineFromUsage
,
447 GetUsageEnumStruc struc
;
449 struc
.mExcludeOfflineFromUsage
= aExcludeOfflineFromUsage
;
450 struc
.mSubdomain
= aQuotaDomainDBKey
;
455 rv
= mPreloadDB
->GetUsageInternal(aQuotaDomainDBKey
,
456 aExcludeOfflineFromUsage
, &struc
.mUsage
);
457 NS_ENSURE_SUCCESS(rv
, rv
);
460 mData
.EnumerateRead(GetUsageEnum
, &struc
);
462 *aUsage
= struc
.mUsage
;