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 "nsDOMStorageDBWrapper.h"
45 #include "nsIVariant.h"
46 #include "nsIEffectiveTLDService.h"
47 #include "nsAppDirectoryServiceDefs.h"
48 #include "mozStorageCID.h"
49 #include "mozStorageHelper.h"
50 #include "mozIStorageService.h"
51 #include "mozIStorageValueArray.h"
52 #include "mozIStorageFunction.h"
53 #include "nsPrintfCString.h"
54 #include "nsNetUtil.h"
56 void ReverseString(const nsCSubstring
& source
, nsCSubstring
& result
)
58 nsACString::const_iterator sourceBegin
, sourceEnd
;
59 source
.BeginReading(sourceBegin
);
60 source
.EndReading(sourceEnd
);
62 result
.SetLength(source
.Length());
63 nsACString::iterator destEnd
;
64 result
.EndWriting(destEnd
);
66 while (sourceBegin
!= sourceEnd
) {
67 *(--destEnd
) = *sourceBegin
;
73 nsDOMStorageDBWrapper::Init()
77 rv
= mPersistentDB
.Init(NS_LITERAL_STRING("webappsstore.sqlite"));
78 NS_ENSURE_SUCCESS(rv
, rv
);
80 rv
= mChromePersistentDB
.Init(NS_LITERAL_STRING("chromeappsstore.sqlite"));
81 NS_ENSURE_SUCCESS(rv
, rv
);
83 rv
= mSessionOnlyDB
.Init(&mPersistentDB
);
84 NS_ENSURE_SUCCESS(rv
, rv
);
86 rv
= mPrivateBrowsingDB
.Init();
87 NS_ENSURE_SUCCESS(rv
, rv
);
93 nsDOMStorageDBWrapper::GetAllKeys(nsDOMStorage
* aStorage
,
94 nsTHashtable
<nsSessionStorageEntry
>* aKeys
)
96 if (aStorage
->CanUseChromePersist())
97 return mChromePersistentDB
.GetAllKeys(aStorage
, aKeys
);
98 if (nsDOMStorageManager::gStorageManager
->InPrivateBrowsingMode())
99 return mPrivateBrowsingDB
.GetAllKeys(aStorage
, aKeys
);
100 if (aStorage
->SessionOnly())
101 return mSessionOnlyDB
.GetAllKeys(aStorage
, aKeys
);
103 return mPersistentDB
.GetAllKeys(aStorage
, aKeys
);
107 nsDOMStorageDBWrapper::GetKeyValue(nsDOMStorage
* aStorage
,
108 const nsAString
& aKey
,
112 if (aStorage
->CanUseChromePersist())
113 return mChromePersistentDB
.GetKeyValue(aStorage
, aKey
, aValue
, aSecure
);
114 if (nsDOMStorageManager::gStorageManager
->InPrivateBrowsingMode())
115 return mPrivateBrowsingDB
.GetKeyValue(aStorage
, aKey
, aValue
, aSecure
);
116 if (aStorage
->SessionOnly())
117 return mSessionOnlyDB
.GetKeyValue(aStorage
, aKey
, aValue
, aSecure
);
119 return mPersistentDB
.GetKeyValue(aStorage
, aKey
, aValue
, aSecure
);
123 nsDOMStorageDBWrapper::SetKey(nsDOMStorage
* aStorage
,
124 const nsAString
& aKey
,
125 const nsAString
& aValue
,
128 PRBool aExcludeOfflineFromUsage
,
131 if (aStorage
->CanUseChromePersist())
132 return mChromePersistentDB
.SetKey(aStorage
, aKey
, aValue
, aSecure
,
133 aQuota
, aExcludeOfflineFromUsage
, aNewUsage
);
134 if (nsDOMStorageManager::gStorageManager
->InPrivateBrowsingMode())
135 return mPrivateBrowsingDB
.SetKey(aStorage
, aKey
, aValue
, aSecure
,
136 aQuota
, aExcludeOfflineFromUsage
, aNewUsage
);
137 if (aStorage
->SessionOnly())
138 return mSessionOnlyDB
.SetKey(aStorage
, aKey
, aValue
, aSecure
,
139 aQuota
, aExcludeOfflineFromUsage
, aNewUsage
);
141 return mPersistentDB
.SetKey(aStorage
, aKey
, aValue
, aSecure
,
142 aQuota
, aExcludeOfflineFromUsage
, aNewUsage
);
146 nsDOMStorageDBWrapper::SetSecure(nsDOMStorage
* aStorage
,
147 const nsAString
& aKey
,
148 const PRBool aSecure
)
150 if (aStorage
->CanUseChromePersist())
151 return mChromePersistentDB
.SetSecure(aStorage
, aKey
, aSecure
);
152 if (nsDOMStorageManager::gStorageManager
->InPrivateBrowsingMode())
153 return mPrivateBrowsingDB
.SetSecure(aStorage
, aKey
, aSecure
);
154 if (aStorage
->SessionOnly())
155 return mSessionOnlyDB
.SetSecure(aStorage
, aKey
, aSecure
);
157 return mPersistentDB
.SetSecure(aStorage
, aKey
, aSecure
);
161 nsDOMStorageDBWrapper::RemoveKey(nsDOMStorage
* aStorage
,
162 const nsAString
& aKey
,
163 PRBool aExcludeOfflineFromUsage
,
166 if (aStorage
->CanUseChromePersist())
167 return mChromePersistentDB
.RemoveKey(aStorage
, aKey
, aExcludeOfflineFromUsage
, aKeyUsage
);
168 if (nsDOMStorageManager::gStorageManager
->InPrivateBrowsingMode())
169 return mPrivateBrowsingDB
.RemoveKey(aStorage
, aKey
, aExcludeOfflineFromUsage
, aKeyUsage
);
170 if (aStorage
->SessionOnly())
171 return mSessionOnlyDB
.RemoveKey(aStorage
, aKey
, aExcludeOfflineFromUsage
, aKeyUsage
);
173 return mPersistentDB
.RemoveKey(aStorage
, aKey
, aExcludeOfflineFromUsage
, aKeyUsage
);
177 nsDOMStorageDBWrapper::ClearStorage(nsDOMStorage
* aStorage
)
179 if (aStorage
->CanUseChromePersist())
180 return mChromePersistentDB
.ClearStorage(aStorage
);
181 if (nsDOMStorageManager::gStorageManager
->InPrivateBrowsingMode())
182 return mPrivateBrowsingDB
.ClearStorage(aStorage
);
183 if (aStorage
->SessionOnly())
184 return mSessionOnlyDB
.ClearStorage(aStorage
);
186 return mPersistentDB
.ClearStorage(aStorage
);
190 nsDOMStorageDBWrapper::DropSessionOnlyStoragesForHost(const nsACString
& aHostName
)
192 return mSessionOnlyDB
.RemoveOwner(aHostName
, PR_TRUE
);
196 nsDOMStorageDBWrapper::DropPrivateBrowsingStorages()
198 return mPrivateBrowsingDB
.RemoveAll();
202 nsDOMStorageDBWrapper::RemoveOwner(const nsACString
& aOwner
,
203 PRBool aIncludeSubDomains
)
207 rv
= mPrivateBrowsingDB
.RemoveOwner(aOwner
, aIncludeSubDomains
);
208 NS_ENSURE_SUCCESS(rv
, rv
);
210 if (nsDOMStorageManager::gStorageManager
->InPrivateBrowsingMode())
213 rv
= mSessionOnlyDB
.RemoveOwner(aOwner
, aIncludeSubDomains
);
214 NS_ENSURE_SUCCESS(rv
, rv
);
216 rv
= mPersistentDB
.RemoveOwner(aOwner
, aIncludeSubDomains
);
217 NS_ENSURE_SUCCESS(rv
, rv
);
224 nsDOMStorageDBWrapper::RemoveOwners(const nsTArray
<nsString
> &aOwners
,
225 PRBool aIncludeSubDomains
, PRBool aMatch
)
229 rv
= mPrivateBrowsingDB
.RemoveOwners(aOwners
, aIncludeSubDomains
, aMatch
);
230 NS_ENSURE_SUCCESS(rv
, rv
);
232 if (nsDOMStorageManager::gStorageManager
->InPrivateBrowsingMode())
235 rv
= mSessionOnlyDB
.RemoveOwners(aOwners
, aIncludeSubDomains
, aMatch
);
236 NS_ENSURE_SUCCESS(rv
, rv
);
238 rv
= mPersistentDB
.RemoveOwners(aOwners
, aIncludeSubDomains
, aMatch
);
239 NS_ENSURE_SUCCESS(rv
, rv
);
245 nsDOMStorageDBWrapper::RemoveAll()
249 rv
= mPrivateBrowsingDB
.RemoveAll();
250 NS_ENSURE_SUCCESS(rv
, rv
);
252 if (nsDOMStorageManager::gStorageManager
->InPrivateBrowsingMode())
255 rv
= mSessionOnlyDB
.RemoveAll();
256 NS_ENSURE_SUCCESS(rv
, rv
);
258 rv
= mPersistentDB
.RemoveAll();
259 NS_ENSURE_SUCCESS(rv
, rv
);
265 nsDOMStorageDBWrapper::GetUsage(nsDOMStorage
* aStorage
,
266 PRBool aExcludeOfflineFromUsage
, PRInt32
*aUsage
)
268 if (aStorage
->CanUseChromePersist())
269 return mChromePersistentDB
.GetUsage(aStorage
, aExcludeOfflineFromUsage
, aUsage
);
270 if (nsDOMStorageManager::gStorageManager
->InPrivateBrowsingMode())
271 return mPrivateBrowsingDB
.GetUsage(aStorage
, aExcludeOfflineFromUsage
, aUsage
);
272 if (aStorage
->SessionOnly())
273 return mSessionOnlyDB
.GetUsage(aStorage
, aExcludeOfflineFromUsage
, aUsage
);
275 return mPersistentDB
.GetUsage(aStorage
, aExcludeOfflineFromUsage
, aUsage
);
279 nsDOMStorageDBWrapper::GetUsage(const nsACString
& aDomain
,
280 PRBool aIncludeSubDomains
, PRInt32
*aUsage
)
282 if (nsDOMStorageManager::gStorageManager
->InPrivateBrowsingMode())
283 return mPrivateBrowsingDB
.GetUsage(aDomain
, aIncludeSubDomains
, aUsage
);
286 // XXX Check where from all this method gets called, not sure this should
287 // include any potential session-only data
289 rv
= mSessionOnlyDB
.GetUsage(aDomain
, aIncludeSubDomains
, aUsage
);
290 if (NS_SUECEEDED(rv
))
294 return mPersistentDB
.GetUsage(aDomain
, aIncludeSubDomains
, aUsage
);
298 nsDOMStorageDBWrapper::CreateOriginScopeDBKey(nsIURI
* aUri
, nsACString
& aKey
)
302 rv
= CreateDomainScopeDBKey(aUri
, aKey
);
306 nsCAutoString scheme
;
307 rv
= aUri
->GetScheme(scheme
);
308 NS_ENSURE_SUCCESS(rv
, rv
);
310 aKey
.AppendLiteral(":");
313 PRInt32 port
= NS_GetRealPort(aUri
);
315 aKey
.AppendLiteral(":");
316 aKey
.Append(nsPrintfCString(32, "%d", port
));
323 nsDOMStorageDBWrapper::CreateDomainScopeDBKey(nsIURI
* aUri
, nsACString
& aKey
)
327 nsCAutoString domainScope
;
328 rv
= aUri
->GetAsciiHost(domainScope
);
329 NS_ENSURE_SUCCESS(rv
, rv
);
331 if (domainScope
.IsEmpty()) {
332 // About pages have an empty host but a valid path. Since they are handled
333 // internally by our own redirector, we can trust them and use path as key.
334 PRBool isAboutUrl
= PR_FALSE
;
335 if ((NS_SUCCEEDED(aUri
->SchemeIs("about", &isAboutUrl
)) && isAboutUrl
) ||
336 (NS_SUCCEEDED(aUri
->SchemeIs("moz-safe-about", &isAboutUrl
)) && isAboutUrl
)) {
337 rv
= aUri
->GetPath(domainScope
);
338 NS_ENSURE_SUCCESS(rv
, rv
);
342 rv
= CreateDomainScopeDBKey(domainScope
, aKey
);
343 NS_ENSURE_SUCCESS(rv
, rv
);
349 nsDOMStorageDBWrapper::CreateDomainScopeDBKey(const nsACString
& aAsciiDomain
,
352 if (aAsciiDomain
.IsEmpty())
353 return NS_ERROR_NOT_AVAILABLE
;
355 ReverseString(aAsciiDomain
, aKey
);
357 aKey
.AppendLiteral(".");
362 nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(const nsACString
& aAsciiDomain
,
363 PRBool aIncludeSubDomains
,
364 PRBool aEffectiveTLDplus1Only
,
369 nsCAutoString subdomainsDBKey
;
370 if (aEffectiveTLDplus1Only
) {
371 nsCOMPtr
<nsIEffectiveTLDService
> eTLDService(do_GetService(
372 NS_EFFECTIVETLDSERVICE_CONTRACTID
, &rv
));
373 NS_ENSURE_SUCCESS(rv
, rv
);
375 nsCOMPtr
<nsIURI
> uri
;
376 rv
= NS_NewURI(getter_AddRefs(uri
), NS_LITERAL_CSTRING("http://") + aAsciiDomain
);
377 NS_ENSURE_SUCCESS(rv
, rv
);
379 nsCAutoString eTLDplusOne
;
380 rv
= eTLDService
->GetBaseDomain(uri
, 0, eTLDplusOne
);
381 if (NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS
== rv
) {
382 // XXX bug 357323 - what to do for localhost/file exactly?
383 eTLDplusOne
= aAsciiDomain
;
386 NS_ENSURE_SUCCESS(rv
, rv
);
388 CreateDomainScopeDBKey(eTLDplusOne
, subdomainsDBKey
);
391 CreateDomainScopeDBKey(aAsciiDomain
, subdomainsDBKey
);
393 if (!aIncludeSubDomains
)
394 subdomainsDBKey
.AppendLiteral(":");
396 aKey
.Assign(subdomainsDBKey
);
401 nsDOMStorageDBWrapper::GetDomainFromScopeKey(const nsACString
& aScope
,
404 nsCAutoString reverseDomain
, scope
;
406 scope
.Left(reverseDomain
, scope
.FindChar(':')-1);
408 ReverseString(reverseDomain
, aDomain
);