Merge backout.
[mozilla-central.git] / dom / src / storage / nsDOMStorageDBWrapper.cpp
blob37f0e7b1e7badb95e8ca847713cfe5e0d1ce44e8
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 "nsDOMStorageDBWrapper.h"
44 #include "nsIFile.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;
68 ++sourceBegin;
72 nsresult
73 nsDOMStorageDBWrapper::Init()
75 nsresult rv;
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);
89 return NS_OK;
92 nsresult
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);
106 nsresult
107 nsDOMStorageDBWrapper::GetKeyValue(nsDOMStorage* aStorage,
108 const nsAString& aKey,
109 nsAString& aValue,
110 PRBool* aSecure)
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);
122 nsresult
123 nsDOMStorageDBWrapper::SetKey(nsDOMStorage* aStorage,
124 const nsAString& aKey,
125 const nsAString& aValue,
126 PRBool aSecure,
127 PRInt32 aQuota,
128 PRBool aExcludeOfflineFromUsage,
129 PRInt32 *aNewUsage)
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);
145 nsresult
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);
160 nsresult
161 nsDOMStorageDBWrapper::RemoveKey(nsDOMStorage* aStorage,
162 const nsAString& aKey,
163 PRBool aExcludeOfflineFromUsage,
164 PRInt32 aKeyUsage)
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);
176 nsresult
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);
189 nsresult
190 nsDOMStorageDBWrapper::DropSessionOnlyStoragesForHost(const nsACString& aHostName)
192 return mSessionOnlyDB.RemoveOwner(aHostName, PR_TRUE);
195 nsresult
196 nsDOMStorageDBWrapper::DropPrivateBrowsingStorages()
198 return mPrivateBrowsingDB.RemoveAll();
201 nsresult
202 nsDOMStorageDBWrapper::RemoveOwner(const nsACString& aOwner,
203 PRBool aIncludeSubDomains)
205 nsresult rv;
207 rv = mPrivateBrowsingDB.RemoveOwner(aOwner, aIncludeSubDomains);
208 NS_ENSURE_SUCCESS(rv, rv);
210 if (nsDOMStorageManager::gStorageManager->InPrivateBrowsingMode())
211 return NS_OK;
213 rv = mSessionOnlyDB.RemoveOwner(aOwner, aIncludeSubDomains);
214 NS_ENSURE_SUCCESS(rv, rv);
216 rv = mPersistentDB.RemoveOwner(aOwner, aIncludeSubDomains);
217 NS_ENSURE_SUCCESS(rv, rv);
219 return rv;
223 nsresult
224 nsDOMStorageDBWrapper::RemoveOwners(const nsTArray<nsString> &aOwners,
225 PRBool aIncludeSubDomains, PRBool aMatch)
227 nsresult rv;
229 rv = mPrivateBrowsingDB.RemoveOwners(aOwners, aIncludeSubDomains, aMatch);
230 NS_ENSURE_SUCCESS(rv, rv);
232 if (nsDOMStorageManager::gStorageManager->InPrivateBrowsingMode())
233 return NS_OK;
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);
241 return rv;
244 nsresult
245 nsDOMStorageDBWrapper::RemoveAll()
247 nsresult rv;
249 rv = mPrivateBrowsingDB.RemoveAll();
250 NS_ENSURE_SUCCESS(rv, rv);
252 if (nsDOMStorageManager::gStorageManager->InPrivateBrowsingMode())
253 return NS_OK;
255 rv = mSessionOnlyDB.RemoveAll();
256 NS_ENSURE_SUCCESS(rv, rv);
258 rv = mPersistentDB.RemoveAll();
259 NS_ENSURE_SUCCESS(rv, rv);
261 return rv;
264 nsresult
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);
278 nsresult
279 nsDOMStorageDBWrapper::GetUsage(const nsACString& aDomain,
280 PRBool aIncludeSubDomains, PRInt32 *aUsage)
282 if (nsDOMStorageManager::gStorageManager->InPrivateBrowsingMode())
283 return mPrivateBrowsingDB.GetUsage(aDomain, aIncludeSubDomains, aUsage);
285 #if 0
286 // XXX Check where from all this method gets called, not sure this should
287 // include any potential session-only data
288 nsresult rv;
289 rv = mSessionOnlyDB.GetUsage(aDomain, aIncludeSubDomains, aUsage);
290 if (NS_SUECEEDED(rv))
291 return rv;
292 #endif
294 return mPersistentDB.GetUsage(aDomain, aIncludeSubDomains, aUsage);
297 nsresult
298 nsDOMStorageDBWrapper::CreateOriginScopeDBKey(nsIURI* aUri, nsACString& aKey)
300 nsresult rv;
302 rv = CreateDomainScopeDBKey(aUri, aKey);
303 if (NS_FAILED(rv))
304 return rv;
306 nsCAutoString scheme;
307 rv = aUri->GetScheme(scheme);
308 NS_ENSURE_SUCCESS(rv, rv);
310 aKey.AppendLiteral(":");
311 aKey.Append(scheme);
313 PRInt32 port = NS_GetRealPort(aUri);
314 if (port != -1) {
315 aKey.AppendLiteral(":");
316 aKey.Append(nsPrintfCString(32, "%d", port));
319 return NS_OK;
322 nsresult
323 nsDOMStorageDBWrapper::CreateDomainScopeDBKey(nsIURI* aUri, nsACString& aKey)
325 nsresult rv;
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);
345 return NS_OK;
348 nsresult
349 nsDOMStorageDBWrapper::CreateDomainScopeDBKey(const nsACString& aAsciiDomain,
350 nsACString& aKey)
352 if (aAsciiDomain.IsEmpty())
353 return NS_ERROR_NOT_AVAILABLE;
355 ReverseString(aAsciiDomain, aKey);
357 aKey.AppendLiteral(".");
358 return NS_OK;
361 nsresult
362 nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(const nsACString& aAsciiDomain,
363 PRBool aIncludeSubDomains,
364 PRBool aEffectiveTLDplus1Only,
365 nsACString& aKey)
367 nsresult rv;
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;
384 rv = NS_OK;
386 NS_ENSURE_SUCCESS(rv, rv);
388 CreateDomainScopeDBKey(eTLDplusOne, subdomainsDBKey);
390 else
391 CreateDomainScopeDBKey(aAsciiDomain, subdomainsDBKey);
393 if (!aIncludeSubDomains)
394 subdomainsDBKey.AppendLiteral(":");
396 aKey.Assign(subdomainsDBKey);
397 return NS_OK;
400 nsresult
401 nsDOMStorageDBWrapper::GetDomainFromScopeKey(const nsACString& aScope,
402 nsACString& aDomain)
404 nsCAutoString reverseDomain, scope;
405 scope = aScope;
406 scope.Left(reverseDomain, scope.FindChar(':')-1);
408 ReverseString(reverseDomain, aDomain);
409 return NS_OK;