LCOV - code coverage report
Current view: directory - dom/src/storage - nsDOMStorage.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1164 588 50.5 %
Date: 2012-07-07 Functions: 182 108 59.3 %

       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
       4                 :  *
       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/
       9                 :  *
      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.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Mozilla Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2006
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Neil Deakin <enndeakin@sympatico.ca>
      24                 :  *   Johnny Stenback <jst@mozilla.com>
      25                 :  *   Ehsan Akhgari <ehsan.akhgari@gmail.com>
      26                 :  *   Honza Bambas <honzab@firemni.cz>
      27                 :  *   Josh Matthews <josh@joshmatthews.net>
      28                 :  *
      29                 :  * Alternatively, the contents of this file may be used under the terms of
      30                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      31                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      32                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      33                 :  * of those above. If you wish to allow use of your version of this file only
      34                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      35                 :  * use your version of this file under the terms of the MPL, indicate your
      36                 :  * decision by deleting the provisions above and replace them with the notice
      37                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      38                 :  * the provisions above, a recipient may use your version of this file under
      39                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      40                 :  *
      41                 :  * ***** END LICENSE BLOCK ***** */
      42                 : 
      43                 : #include "StorageChild.h"
      44                 : #include "StorageParent.h"
      45                 : #include "nsXULAppAPI.h"
      46                 : using mozilla::dom::StorageChild;
      47                 : 
      48                 : #include "prnetdb.h"
      49                 : #include "nsCOMPtr.h"
      50                 : #include "nsDOMError.h"
      51                 : #include "nsDOMClassInfoID.h"
      52                 : #include "nsDOMJSUtils.h"
      53                 : #include "nsUnicharUtils.h"
      54                 : #include "nsIDocument.h"
      55                 : #include "nsDOMStorage.h"
      56                 : #include "nsEscape.h"
      57                 : #include "nsContentUtils.h"
      58                 : #include "nsIScriptSecurityManager.h"
      59                 : #include "nsIPrincipal.h"
      60                 : #include "nsIURI.h"
      61                 : #include "nsReadableUtils.h"
      62                 : #include "nsIObserverService.h"
      63                 : #include "nsNetUtil.h"
      64                 : #include "nsIPrefBranch.h"
      65                 : #include "nsICookiePermission.h"
      66                 : #include "nsIPermission.h"
      67                 : #include "nsIPermissionManager.h"
      68                 : #include "nsCycleCollectionParticipant.h"
      69                 : #include "nsIOfflineCacheUpdate.h"
      70                 : #include "nsIJSContextStack.h"
      71                 : #include "nsIPrivateBrowsingService.h"
      72                 : #include "nsDOMString.h"
      73                 : #include "nsNetCID.h"
      74                 : #include "mozilla/Preferences.h"
      75                 : #include "nsThreadUtils.h"
      76                 : #include "mozilla/Telemetry.h"
      77                 : #include "DictionaryHelpers.h"
      78                 : 
      79                 : // calls FlushAndDeleteTemporaryTables(false)
      80                 : #define NS_DOMSTORAGE_FLUSH_TIMER_TOPIC "domstorage-flush-timer"
      81                 : 
      82                 : // calls FlushAndDeleteTemporaryTables(true)
      83                 : #define NS_DOMSTORAGE_FLUSH_FORCE_TOPIC "domstorage-flush-force"
      84                 : 
      85                 : using namespace mozilla;
      86                 : 
      87                 : static const PRUint32 ASK_BEFORE_ACCEPT = 1;
      88                 : static const PRUint32 ACCEPT_SESSION = 2;
      89                 : static const PRUint32 BEHAVIOR_REJECT = 2;
      90                 : 
      91                 : static const PRUint32 DEFAULT_QUOTA = 5 * 1024;
      92                 : // Be generous with offline apps by default...
      93                 : static const PRUint32 DEFAULT_OFFLINE_APP_QUOTA = 200 * 1024;
      94                 : // ... but warn if it goes over this amount
      95                 : static const PRUint32 DEFAULT_OFFLINE_WARN_QUOTA = 50 * 1024;
      96                 : 
      97                 : // Intervals to flush the temporary table after in seconds
      98                 : #define NS_DOMSTORAGE_MAXIMUM_TEMPTABLE_INACTIVITY_TIME (5)
      99                 : #define NS_DOMSTORAGE_MAXIMUM_TEMPTABLE_AGE (30)
     100                 : 
     101                 : static const char kPermissionType[] = "cookie";
     102                 : static const char kStorageEnabled[] = "dom.storage.enabled";
     103                 : static const char kDefaultQuota[] = "dom.storage.default_quota";
     104                 : static const char kCookiesBehavior[] = "network.cookie.cookieBehavior";
     105                 : static const char kCookiesLifetimePolicy[] = "network.cookie.lifetimePolicy";
     106                 : static const char kOfflineAppWarnQuota[] = "offline-apps.quota.warn";
     107                 : static const char kOfflineAppQuota[] = "offline-apps.quota.max";
     108                 : 
     109                 : // The URI returned is the innermost URI that should be used for
     110                 : // security-check-like stuff.  aHost is its hostname, correctly canonicalized.
     111                 : static nsresult
     112               0 : GetPrincipalURIAndHost(nsIPrincipal* aPrincipal, nsIURI** aURI, nsCString& aHost)
     113                 : {
     114               0 :   nsresult rv = aPrincipal->GetDomain(aURI);
     115               0 :   NS_ENSURE_SUCCESS(rv, rv);
     116                 : 
     117               0 :   if (!*aURI) {
     118               0 :     rv = aPrincipal->GetURI(aURI);
     119               0 :     NS_ENSURE_SUCCESS(rv, rv);
     120                 :   }
     121                 : 
     122               0 :   if (!*aURI) {
     123               0 :     return NS_OK;
     124                 :   }
     125                 : 
     126               0 :   nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(*aURI);
     127               0 :   if (!innerURI) {
     128               0 :     return NS_ERROR_UNEXPECTED;
     129                 :   }
     130                 : 
     131               0 :   rv = innerURI->GetAsciiHost(aHost);
     132               0 :   if (NS_FAILED(rv)) {
     133               0 :     return NS_ERROR_DOM_SECURITY_ERR;
     134                 :   }
     135                 :   
     136               0 :   innerURI.swap(*aURI);
     137                 : 
     138               0 :   return NS_OK;
     139                 : }
     140                 : 
     141                 : //
     142                 : // Helper that tells us whether the caller is secure or not.
     143                 : //
     144                 : 
     145                 : static bool
     146             168 : IsCallerSecure()
     147                 : {
     148             336 :   nsCOMPtr<nsIPrincipal> subjectPrincipal;
     149             168 :   nsresult rv = nsContentUtils::GetSecurityManager()->
     150             168 :                   GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
     151             168 :   NS_ENSURE_SUCCESS(rv, false);
     152                 : 
     153             168 :   if (!subjectPrincipal) {
     154                 :     // No subject principal means no code is running. Default to not
     155                 :     // being secure in that case.
     156                 : 
     157               0 :     return false;
     158                 :   }
     159                 : 
     160             336 :   nsCOMPtr<nsIURI> codebase;
     161             168 :   subjectPrincipal->GetURI(getter_AddRefs(codebase));
     162                 : 
     163             168 :   if (!codebase) {
     164             168 :     return false;
     165                 :   }
     166                 : 
     167               0 :   nsCOMPtr<nsIURI> innerUri = NS_GetInnermostURI(codebase);
     168                 : 
     169               0 :   if (!innerUri) {
     170               0 :     return false;
     171                 :   }
     172                 : 
     173               0 :   bool isHttps = false;
     174               0 :   rv = innerUri->SchemeIs("https", &isHttps);
     175                 : 
     176               0 :   return NS_SUCCEEDED(rv) && isHttps;
     177                 : }
     178                 : 
     179                 : PRUint32
     180              24 : GetOfflinePermission(const nsACString &aDomain)
     181                 : {
     182                 :   // Fake a URI for the permission manager
     183              48 :   nsCOMPtr<nsIURI> uri;
     184              24 :   NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + aDomain);
     185                 : 
     186                 :   PRUint32 perm;
     187              24 :   if (uri) {
     188                 :     nsCOMPtr<nsIPermissionManager> permissionManager =
     189              48 :       do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
     190                 : 
     191              48 :     if (permissionManager &&
     192              48 :         NS_SUCCEEDED(permissionManager->TestPermission(uri, "offline-app", &perm)))
     193              24 :         return perm;
     194                 :   }
     195                 : 
     196               0 :   return nsIPermissionManager::UNKNOWN_ACTION;
     197                 : }
     198                 : 
     199                 : bool
     200               6 : IsOfflineAllowed(const nsACString &aDomain)
     201                 : {
     202               6 :   PRInt32 perm = GetOfflinePermission(aDomain);
     203               6 :   return IS_PERMISSION_ALLOWED(perm);
     204                 : }
     205                 : 
     206                 : // Returns two quotas - A hard limit for which adding data will be an error,
     207                 : // and a limit after which a warning event will be sent to the observer
     208                 : // service.  The warn limit may be -1, in which case there will be no warning.
     209                 : // If aOverrideQuota is set, the larger offline apps quota is used and no
     210                 : // warning is sent.
     211                 : static PRUint32
     212              18 : GetQuota(const nsACString &aDomain, PRInt32 *aQuota, PRInt32 *aWarnQuota,
     213                 :          bool aOverrideQuota)
     214                 : {
     215              18 :   PRUint32 perm = GetOfflinePermission(aDomain);
     216              18 :   if (IS_PERMISSION_ALLOWED(perm) || aOverrideQuota) {
     217                 :     // This is an offline app, give more space by default.
     218                 :     *aQuota = Preferences::GetInt(kOfflineAppQuota,
     219              12 :                                   DEFAULT_OFFLINE_APP_QUOTA) * 1024;
     220                 : 
     221              12 :     if (perm == nsIOfflineCacheUpdateService::ALLOW_NO_WARN ||
     222                 :         aOverrideQuota) {
     223              12 :       *aWarnQuota = -1;
     224                 :     } else {
     225                 :       *aWarnQuota = Preferences::GetInt(kOfflineAppWarnQuota,
     226               0 :                                         DEFAULT_OFFLINE_WARN_QUOTA) * 1024;
     227                 :     }
     228              12 :     return perm;
     229                 :   }
     230                 : 
     231                 :   // FIXME: per-domain quotas?
     232               6 :   *aQuota = Preferences::GetInt(kDefaultQuota, DEFAULT_QUOTA) * 1024;
     233               6 :   *aWarnQuota = -1;
     234                 : 
     235               6 :   return perm;
     236                 : }
     237                 : 
     238              34 : nsSessionStorageEntry::nsSessionStorageEntry(KeyTypePointer aStr)
     239              34 :   : nsStringHashKey(aStr), mItem(nsnull)
     240                 : {
     241              34 : }
     242                 : 
     243               0 : nsSessionStorageEntry::nsSessionStorageEntry(const nsSessionStorageEntry& aToCopy)
     244               0 :   : nsStringHashKey(aToCopy), mItem(nsnull)
     245                 : {
     246               0 :   NS_ERROR("We're horked.");
     247               0 : }
     248                 : 
     249              34 : nsSessionStorageEntry::~nsSessionStorageEntry()
     250                 : {
     251              34 : }
     252                 : 
     253                 : //
     254                 : // nsDOMStorageManager
     255                 : //
     256                 : 
     257                 : nsDOMStorageManager* nsDOMStorageManager::gStorageManager;
     258                 : 
     259            1404 : nsDOMStorageManager::nsDOMStorageManager()
     260            1404 :   : mInPrivateBrowsing(false)
     261                 : {
     262            1404 : }
     263                 : 
     264          182619 : NS_IMPL_ISUPPORTS3(nsDOMStorageManager,
     265                 :                    nsIDOMStorageManager,
     266                 :                    nsIObserver,
     267                 :                    nsISupportsWeakReference)
     268                 : 
     269                 : //static
     270                 : nsresult
     271            1404 : nsDOMStorageManager::Initialize()
     272                 : {
     273            1404 :   gStorageManager = new nsDOMStorageManager();
     274            1404 :   if (!gStorageManager)
     275               0 :     return NS_ERROR_OUT_OF_MEMORY;
     276                 : 
     277            1404 :   if (!gStorageManager->mStorages.Init()) {
     278               0 :     delete gStorageManager;
     279               0 :     gStorageManager = nsnull;
     280               0 :     return NS_ERROR_OUT_OF_MEMORY;
     281                 :   }
     282                 : 
     283            1404 :   NS_ADDREF(gStorageManager);
     284                 : 
     285                 :   // No observers needed in non-chrome
     286            1404 :   if (XRE_GetProcessType() != GeckoProcessType_Default)
     287               0 :     return NS_OK;
     288                 : 
     289            2808 :   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     290            1404 :   if (!os)
     291               0 :     return NS_OK;
     292                 : 
     293                 :   nsresult rv;
     294            1404 :   rv = os->AddObserver(gStorageManager, "cookie-changed", true);
     295            1404 :   NS_ENSURE_SUCCESS(rv, rv);
     296            1404 :   rv = os->AddObserver(gStorageManager, "offline-app-removed", true);
     297            1404 :   NS_ENSURE_SUCCESS(rv, rv);
     298            1404 :   rv = os->AddObserver(gStorageManager, NS_PRIVATE_BROWSING_SWITCH_TOPIC, true);
     299            1404 :   NS_ENSURE_SUCCESS(rv, rv);
     300            1404 :   rv = os->AddObserver(gStorageManager, "profile-after-change", true);
     301            1404 :   NS_ENSURE_SUCCESS(rv, rv);
     302            1404 :   rv = os->AddObserver(gStorageManager, "perm-changed", true);
     303            1404 :   NS_ENSURE_SUCCESS(rv, rv);
     304            1404 :   rv = os->AddObserver(gStorageManager, "browser:purge-domain-data", true);
     305            1404 :   NS_ENSURE_SUCCESS(rv, rv);
     306                 :   // Used for temporary table flushing
     307            1404 :   rv = os->AddObserver(gStorageManager, "profile-before-change", true);
     308            1404 :   NS_ENSURE_SUCCESS(rv, rv);
     309            1404 :   rv = os->AddObserver(gStorageManager, NS_DOMSTORAGE_FLUSH_TIMER_TOPIC, true);
     310            1404 :   NS_ENSURE_SUCCESS(rv, rv);
     311                 : 
     312            1404 :   return NS_OK;
     313                 : }
     314                 : 
     315                 : //static
     316                 : nsDOMStorageManager*
     317               4 : nsDOMStorageManager::GetInstance()
     318                 : {
     319               4 :   NS_ASSERTION(gStorageManager,
     320                 :                "nsDOMStorageManager::GetInstance() called before Initialize()");
     321               4 :   NS_IF_ADDREF(gStorageManager);
     322               4 :   return gStorageManager;
     323                 : }
     324                 : 
     325                 : //static
     326                 : void
     327            1403 : nsDOMStorageManager::Shutdown()
     328                 : {
     329            1403 :   NS_IF_RELEASE(gStorageManager);
     330            1403 :   gStorageManager = nsnull;
     331                 : 
     332            1403 :   ShutdownDB();
     333            1403 : }
     334                 : 
     335                 : //static
     336                 : void
     337            1440 : nsDOMStorageManager::ShutdownDB()
     338                 : {
     339            1440 :   delete DOMStorageImpl::gStorageDB;
     340            1440 :   DOMStorageImpl::gStorageDB = nsnull;
     341            1440 : }
     342                 : 
     343                 : static PLDHashOperator
     344              10 : ClearStorage(nsDOMStorageEntry* aEntry, void* userArg)
     345                 : {
     346              10 :   aEntry->mStorage->ClearAll();
     347              10 :   return PL_DHASH_REMOVE;
     348                 : }
     349                 : 
     350                 : static PLDHashOperator
     351               6 : ClearStorageIfDomainMatches(nsDOMStorageEntry* aEntry, void* userArg)
     352                 : {
     353               6 :   nsCAutoString* aKey = static_cast<nsCAutoString*> (userArg);
     354               6 :   if (StringBeginsWith(aEntry->mStorage->GetScopeDBKey(), *aKey)) {
     355               4 :     aEntry->mStorage->ClearAll();
     356                 :   }
     357               6 :   return PL_DHASH_REMOVE;
     358                 : }
     359                 : 
     360                 : static nsresult
     361              13 : GetOfflineDomains(nsTArray<nsString>& aDomains)
     362                 : {
     363                 :   nsCOMPtr<nsIPermissionManager> permissionManager =
     364              26 :     do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
     365              13 :   if (permissionManager) {
     366              26 :     nsCOMPtr<nsISimpleEnumerator> enumerator;
     367              13 :     nsresult rv = permissionManager->GetEnumerator(getter_AddRefs(enumerator));
     368              13 :     NS_ENSURE_SUCCESS(rv, rv);
     369                 : 
     370                 :     bool hasMore;
     371              26 :     while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore) {
     372               0 :       nsCOMPtr<nsISupports> supp;
     373               0 :       rv = enumerator->GetNext(getter_AddRefs(supp));
     374               0 :       NS_ENSURE_SUCCESS(rv, rv);
     375                 : 
     376               0 :       nsCOMPtr<nsIPermission> perm(do_QueryInterface(supp, &rv));
     377               0 :       NS_ENSURE_SUCCESS(rv, rv);
     378                 : 
     379                 :       PRUint32 capability;
     380               0 :       rv = perm->GetCapability(&capability);
     381               0 :       NS_ENSURE_SUCCESS(rv, rv);
     382               0 :       if (capability != nsIPermissionManager::DENY_ACTION) {
     383               0 :         nsCAutoString type;
     384               0 :         rv = perm->GetType(type);
     385               0 :         NS_ENSURE_SUCCESS(rv, rv);
     386                 : 
     387               0 :         if (type.EqualsLiteral("offline-app")) {
     388               0 :           nsCAutoString host;
     389               0 :           rv = perm->GetHost(host);
     390               0 :           NS_ENSURE_SUCCESS(rv, rv);
     391                 : 
     392               0 :           aDomains.AppendElement(NS_ConvertUTF8toUTF16(host));
     393                 :         }
     394                 :       }
     395                 :     }
     396                 :   }
     397                 : 
     398              13 :   return NS_OK;
     399                 : }
     400                 : 
     401                 : nsresult
     402           18058 : nsDOMStorageManager::Observe(nsISupports *aSubject,
     403                 :                              const char *aTopic,
     404                 :                              const PRUnichar *aData)
     405                 : {
     406           18058 :   if (!strcmp(aTopic, "profile-after-change")) {
     407                 :     nsCOMPtr<nsIPrivateBrowsingService> pbs =
     408               0 :       do_GetService(NS_PRIVATE_BROWSING_SERVICE_CONTRACTID);
     409               0 :     if (pbs)
     410               0 :       pbs->GetPrivateBrowsingEnabled(&gStorageManager->mInPrivateBrowsing);
     411                 :   }
     412           18058 :   else if (!strcmp(aTopic, "offline-app-removed")) {
     413               0 :     nsresult rv = DOMStorageImpl::InitDB();
     414               0 :     NS_ENSURE_SUCCESS(rv, rv);
     415               0 :     return DOMStorageImpl::gStorageDB->RemoveOwner(NS_ConvertUTF16toUTF8(aData),
     416               0 :                                                    true);
     417           69246 :   } else if (!strcmp(aTopic, "cookie-changed") &&
     418           51188 :              !nsCRT::strcmp(aData, NS_LITERAL_STRING("cleared").get())) {
     419              46 :     mStorages.EnumerateEntries(ClearStorage, nsnull);
     420                 : 
     421              46 :     nsresult rv = DOMStorageImpl::InitDB();
     422              46 :     NS_ENSURE_SUCCESS(rv, rv);
     423                 : 
     424                 :     // Remove global storage for domains that aren't marked for offline use.
     425              24 :     nsTArray<nsString> domains;
     426              12 :     rv = GetOfflineDomains(domains);
     427              12 :     NS_ENSURE_SUCCESS(rv, rv);
     428              12 :     return DOMStorageImpl::gStorageDB->RemoveOwners(domains, true, false);
     429           18012 :   } else if (!strcmp(aTopic, NS_PRIVATE_BROWSING_SWITCH_TOPIC)) {
     430             141 :     mStorages.EnumerateEntries(ClearStorage, nsnull);
     431             141 :     if (!nsCRT::strcmp(aData, NS_LITERAL_STRING(NS_PRIVATE_BROWSING_ENTER).get()))
     432              74 :       mInPrivateBrowsing = true;
     433              67 :     else if (!nsCRT::strcmp(aData, NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).get()))
     434              67 :       mInPrivateBrowsing = false;
     435             141 :     nsresult rv = DOMStorageImpl::InitDB();
     436             141 :     NS_ENSURE_SUCCESS(rv, rv);
     437                 : 
     438             137 :     return DOMStorageImpl::gStorageDB->DropPrivateBrowsingStorages();
     439           17871 :   } else if (!strcmp(aTopic, "perm-changed")) {
     440                 :     // Check for cookie permission change
     441            1008 :     nsCOMPtr<nsIPermission> perm(do_QueryInterface(aSubject));
     442             504 :     if (perm) {
     443             992 :       nsCAutoString type;
     444             496 :       perm->GetType(type);
     445             496 :       if (type != NS_LITERAL_CSTRING("cookie"))
     446             487 :         return NS_OK;
     447                 : 
     448               9 :       PRUint32 cap = 0;
     449               9 :       perm->GetCapability(&cap);
     450              18 :       if (!(cap & nsICookiePermission::ACCESS_SESSION) ||
     451               9 :           nsDependentString(aData) != NS_LITERAL_STRING("deleted"))
     452               9 :         return NS_OK;
     453                 : 
     454               0 :       nsCAutoString host;
     455               0 :       perm->GetHost(host);
     456               0 :       if (host.IsEmpty())
     457               0 :         return NS_OK;
     458                 : 
     459               0 :       nsresult rv = DOMStorageImpl::InitDB();
     460               0 :       NS_ENSURE_SUCCESS(rv, rv);
     461                 : 
     462               0 :       return DOMStorageImpl::gStorageDB->DropSessionOnlyStoragesForHost(host);
     463                 :     }
     464           17367 :   } else if (!strcmp(aTopic, "timer-callback")) {
     465               0 :     nsCOMPtr<nsIObserverService> obsserv = mozilla::services::GetObserverService();
     466               0 :     if (obsserv)
     467               0 :       obsserv->NotifyObservers(nsnull, NS_DOMSTORAGE_FLUSH_TIMER_TOPIC, nsnull);
     468           17367 :   } else if (!strcmp(aTopic, "browser:purge-domain-data")) {
     469                 :     // Convert the domain name to the ACE format
     470              96 :     nsCAutoString aceDomain;
     471                 :     nsresult rv;
     472              96 :     nsCOMPtr<nsIIDNService> converter = do_GetService(NS_IDNSERVICE_CONTRACTID);
     473              48 :     if (converter) {
     474              48 :       rv = converter->ConvertUTF8toACE(NS_ConvertUTF16toUTF8(aData), aceDomain);
     475              48 :       NS_ENSURE_SUCCESS(rv, rv);
     476                 :     } else {
     477                 :       // In case the IDN service is not available, this is the best we can come up with!
     478               0 :       NS_EscapeURL(NS_ConvertUTF16toUTF8(aData),
     479                 :                    esc_OnlyNonASCII | esc_AlwaysCopy,
     480               0 :                    aceDomain);
     481                 :     }
     482                 : 
     483              96 :     nsCAutoString key;
     484              48 :     rv = nsDOMStorageDBWrapper::CreateDomainScopeDBKey(aceDomain, key);
     485              48 :     NS_ENSURE_SUCCESS(rv, rv);
     486                 : 
     487                 :     // Clear the storage entries for matching domains
     488              48 :     mStorages.EnumerateEntries(ClearStorageIfDomainMatches, &key);
     489                 : 
     490              48 :     rv = DOMStorageImpl::InitDB();
     491              48 :     NS_ENSURE_SUCCESS(rv, rv);
     492                 : 
     493              96 :     DOMStorageImpl::gStorageDB->RemoveOwner(aceDomain, true);
     494           17319 :   } else if (!strcmp(aTopic, "profile-before-change")) {
     495             800 :     if (DOMStorageImpl::gStorageDB) {
     496                 :       DebugOnly<nsresult> rv =
     497              74 :         DOMStorageImpl::gStorageDB->FlushAndDeleteTemporaryTables(true);
     498              37 :       NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
     499                 :                        "DOMStorage: temporary table commit failed");
     500              37 :       DOMStorageImpl::gStorageDB->Close();
     501              37 :       nsDOMStorageManager::ShutdownDB();
     502                 :     }
     503           16519 :   } else if (!strcmp(aTopic, NS_DOMSTORAGE_FLUSH_TIMER_TOPIC)) {
     504               0 :     if (DOMStorageImpl::gStorageDB) {
     505                 :       DebugOnly<nsresult> rv =
     506               0 :         DOMStorageImpl::gStorageDB->FlushAndDeleteTemporaryTables(false);
     507               0 :       NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
     508                 :                        "DOMStorage: temporary table commit failed");
     509                 :     }
     510           16519 :   } else if (!strcmp(aTopic, NS_DOMSTORAGE_FLUSH_FORCE_TOPIC)) {
     511               0 :     if (DOMStorageImpl::gStorageDB) {
     512                 :       DebugOnly<nsresult> rv =
     513               0 :         DOMStorageImpl::gStorageDB->FlushAndDeleteTemporaryTables(true);
     514               0 :       NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
     515                 :                        "DOMStorage: temporary table commit failed");
     516                 :     }
     517                 :   }
     518                 : 
     519           17375 :   return NS_OK;
     520                 : }
     521                 : 
     522                 : NS_IMETHODIMP
     523               0 : nsDOMStorageManager::GetUsage(const nsAString& aDomain,
     524                 :                               PRInt32 *aUsage)
     525                 : {
     526               0 :   nsresult rv = DOMStorageImpl::InitDB();
     527               0 :   NS_ENSURE_SUCCESS(rv, rv);
     528                 : 
     529               0 :   return DOMStorageImpl::gStorageDB->GetUsage(NS_ConvertUTF16toUTF8(aDomain),
     530               0 :                                               false, aUsage);
     531                 : }
     532                 : 
     533                 : NS_IMETHODIMP
     534               1 : nsDOMStorageManager::ClearOfflineApps()
     535                 : {
     536               1 :     nsresult rv = DOMStorageImpl::InitDB();
     537               1 :     NS_ENSURE_SUCCESS(rv, rv);
     538                 : 
     539               2 :     nsTArray<nsString> domains;
     540               1 :     rv = GetOfflineDomains(domains);
     541               1 :     NS_ENSURE_SUCCESS(rv, rv);
     542               1 :     return DOMStorageImpl::gStorageDB->RemoveOwners(domains, true, true);
     543                 : }
     544                 : 
     545                 : NS_IMETHODIMP
     546              20 : nsDOMStorageManager::GetLocalStorageForPrincipal(nsIPrincipal *aPrincipal,
     547                 :                                                  const nsSubstring &aDocumentURI,
     548                 :                                                  nsIDOMStorage **aResult)
     549                 : {
     550              20 :   NS_ENSURE_ARG_POINTER(aPrincipal);
     551              20 :   *aResult = nsnull;
     552                 : 
     553                 :   nsresult rv;
     554                 : 
     555              40 :   nsRefPtr<nsDOMStorage2> storage = new nsDOMStorage2();
     556              20 :   if (!storage)
     557               0 :     return NS_ERROR_OUT_OF_MEMORY;
     558                 : 
     559              20 :   rv = storage->InitAsLocalStorage(aPrincipal, aDocumentURI);
     560              20 :   if (NS_FAILED(rv))
     561               0 :     return rv;
     562                 : 
     563              20 :   *aResult = storage.get();
     564              20 :   storage.forget();
     565                 : 
     566              20 :   return NS_OK;
     567                 : }
     568                 : 
     569                 : void
     570              20 : nsDOMStorageManager::AddToStoragesHash(DOMStorageImpl* aStorage)
     571                 : {
     572              20 :   nsDOMStorageEntry* entry = mStorages.PutEntry(aStorage);
     573              20 :   if (entry)
     574              20 :     entry->mStorage = aStorage;
     575              20 : }
     576                 : 
     577                 : void
     578              18 : nsDOMStorageManager::RemoveFromStoragesHash(DOMStorageImpl* aStorage)
     579                 : {
     580              18 :   nsDOMStorageEntry* entry = mStorages.GetEntry(aStorage);
     581              18 :   if (entry)
     582               3 :     mStorages.RemoveEntry(aStorage);
     583              18 : }
     584                 : 
     585                 : //
     586                 : // nsDOMStorage
     587                 : //
     588                 : 
     589                 : nsDOMStorageDBWrapper* DOMStorageImpl::gStorageDB = nsnull;
     590                 : 
     591              20 : nsDOMStorageEntry::nsDOMStorageEntry(KeyTypePointer aStr)
     592              20 :   : nsVoidPtrHashKey(aStr), mStorage(nsnull)
     593                 : {
     594              20 : }
     595                 : 
     596               0 : nsDOMStorageEntry::nsDOMStorageEntry(const nsDOMStorageEntry& aToCopy)
     597               0 :   : nsVoidPtrHashKey(aToCopy), mStorage(nsnull)
     598                 : {
     599               0 :   NS_ERROR("DOMStorage horked.");
     600               0 : }
     601                 : 
     602              20 : nsDOMStorageEntry::~nsDOMStorageEntry()
     603                 : {
     604              20 : }
     605                 : 
     606            1464 : NS_IMPL_CYCLE_COLLECTION_1(nsDOMStorage, mStorageImpl)
     607                 : 
     608                 : DOMCI_DATA(StorageObsolete, nsDOMStorage)
     609                 : 
     610              20 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMStorage)
     611              20 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMStorage)
     612               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMStorage)
     613               0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMStorageObsolete)
     614               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMStorageObsolete)
     615               0 :   NS_INTERFACE_MAP_ENTRY(nsPIDOMStorage)
     616               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(StorageObsolete)
     617               0 : NS_INTERFACE_MAP_END
     618                 : 
     619                 : nsresult
     620               0 : NS_NewDOMStorage(nsISupports* aOuter, REFNSIID aIID, void** aResult)
     621                 : {
     622               0 :   nsDOMStorage* storage = new nsDOMStorage();
     623               0 :   if (!storage)
     624               0 :     return NS_ERROR_OUT_OF_MEMORY;
     625                 : 
     626               0 :   return storage->QueryInterface(aIID, aResult);
     627                 : }
     628                 : 
     629                 : nsresult
     630               0 : NS_NewDOMStorage2(nsISupports* aOuter, REFNSIID aIID, void** aResult)
     631                 : {
     632               0 :   nsDOMStorage2* storage = new nsDOMStorage2();
     633               0 :   if (!storage)
     634               0 :     return NS_ERROR_OUT_OF_MEMORY;
     635                 : 
     636               0 :   return storage->QueryInterface(aIID, aResult);
     637                 : }
     638                 : 
     639              20 : DOMStorageBase::DOMStorageBase()
     640                 :   : mStorageType(nsPIDOMStorage::Unknown)
     641                 :   , mUseDB(false)
     642                 :   , mSessionOnly(true)
     643              20 :   , mCanUseChromePersist(false)
     644                 : {
     645              20 : }
     646                 : 
     647               0 : DOMStorageBase::DOMStorageBase(DOMStorageBase& aThat)
     648                 :   : mStorageType(aThat.mStorageType)
     649                 :   , mUseDB(false) // Clones don't use the DB
     650                 :   , mSessionOnly(true)
     651                 :   , mDomain(aThat.mDomain)
     652                 :   , mScopeDBKey(aThat.mScopeDBKey)
     653                 :   , mQuotaETLDplus1DomainDBKey(aThat.mQuotaETLDplus1DomainDBKey)
     654                 :   , mQuotaDomainDBKey(aThat.mQuotaDomainDBKey)
     655               0 :   , mCanUseChromePersist(aThat.mCanUseChromePersist)
     656                 : {
     657               0 : }
     658                 : 
     659                 : void
     660               0 : DOMStorageBase::InitAsSessionStorage(nsIURI* aDomainURI)
     661                 : {
     662                 :   // No need to check for a return value. If this would fail we would not get
     663                 :   // here as we call GetPrincipalURIAndHost (nsDOMStorage.cpp:88) from
     664                 :   // nsDOMStorage::CanUseStorage before we query the storage manager for a new
     665                 :   // sessionStorage. It calls GetAsciiHost on innermost URI. If it fails, we
     666                 :   // won't get to InitAsSessionStorage.
     667               0 :   aDomainURI->GetAsciiHost(mDomain);
     668                 : 
     669               0 :   mUseDB = false;
     670               0 :   mScopeDBKey.Truncate();
     671               0 :   mQuotaDomainDBKey.Truncate();
     672               0 :   mStorageType = nsPIDOMStorage::SessionStorage;
     673               0 : }
     674                 : 
     675                 : void
     676              20 : DOMStorageBase::InitAsLocalStorage(nsIURI* aDomainURI,
     677                 :                                    bool aCanUseChromePersist)
     678                 : {
     679                 :   // No need to check for a return value. If this would fail we would not get
     680                 :   // here as we call GetPrincipalURIAndHost (nsDOMStorage.cpp:88) from
     681                 :   // nsDOMStorage::CanUseStorage before we query the storage manager for a new
     682                 :   // localStorage. It calls GetAsciiHost on innermost URI. If it fails, we won't
     683                 :   // get to InitAsLocalStorage. Actually, mDomain will get replaced with
     684                 :   // mPrincipal in bug 455070. It is not even used for localStorage.
     685              20 :   aDomainURI->GetAsciiHost(mDomain);
     686                 : 
     687              20 :   nsDOMStorageDBWrapper::CreateOriginScopeDBKey(aDomainURI, mScopeDBKey);
     688                 : 
     689                 :   // XXX Bug 357323, we have to solve the issue how to define
     690                 :   // origin for file URLs. In that case CreateOriginScopeDBKey
     691                 :   // fails (the result is empty) and we must avoid database use
     692                 :   // in that case because it produces broken entries w/o owner.
     693              20 :   mUseDB = !mScopeDBKey.IsEmpty();
     694                 : 
     695                 :   nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(mDomain,
     696              20 :                                                 true, false, mQuotaDomainDBKey);
     697                 :   nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(mDomain,
     698              20 :                                                 true, true, mQuotaETLDplus1DomainDBKey);
     699              20 :   mCanUseChromePersist = aCanUseChromePersist;
     700              20 :   mStorageType = nsPIDOMStorage::LocalStorage;
     701              20 : }
     702                 : 
     703                 : void
     704               0 : DOMStorageBase::InitAsGlobalStorage(const nsACString& aDomainDemanded)
     705                 : {
     706               0 :   mDomain = aDomainDemanded;
     707                 : 
     708               0 :   nsDOMStorageDBWrapper::CreateDomainScopeDBKey(aDomainDemanded, mScopeDBKey);
     709                 : 
     710                 :   // XXX Bug 357323, we have to solve the issue how to define
     711                 :   // origin for file URLs. In that case CreateOriginScopeDBKey
     712                 :   // fails (the result is empty) and we must avoid database use
     713                 :   // in that case because it produces broken entries w/o owner.
     714               0 :   if (!(mUseDB = !mScopeDBKey.IsEmpty()))
     715               0 :     mScopeDBKey.AppendLiteral(":");
     716                 : 
     717                 :   nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(aDomainDemanded,
     718               0 :                                                 true, false, mQuotaDomainDBKey);
     719                 :   nsDOMStorageDBWrapper::CreateQuotaDomainDBKey(aDomainDemanded,
     720               0 :                                                 true, true, mQuotaETLDplus1DomainDBKey);
     721               0 :   mStorageType = nsPIDOMStorage::GlobalStorage;
     722               0 : }
     723                 : 
     724                 : PLDHashOperator
     725               4 : SessionStorageTraverser(nsSessionStorageEntry* aEntry, void* userArg) {
     726                 :   nsCycleCollectionTraversalCallback *cb = 
     727               4 :       static_cast<nsCycleCollectionTraversalCallback*>(userArg);
     728                 : 
     729               4 :   cb->NoteXPCOMChild((nsIDOMStorageItem *) aEntry->mItem);
     730                 : 
     731               4 :   return PL_DHASH_NEXT;
     732                 : }
     733                 : 
     734            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(DOMStorageImpl)
     735               4 : NS_IMPL_CYCLE_COLLECTION_UNLINK_0(DOMStorageImpl)
     736               4 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMStorageImpl)
     737                 : {
     738               4 :   if (tmp->mItems.IsInitialized()) {
     739               4 :     tmp->mItems.EnumerateEntries(SessionStorageTraverser, &cb);
     740                 :   }
     741                 : }
     742               4 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     743                 : 
     744              58 : NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMStorageImpl)
     745              78 : NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMStorageImpl)
     746              62 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMStorageImpl)
     747               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
     748               0 : NS_INTERFACE_MAP_END
     749                 : 
     750              20 : DOMStorageImpl::DOMStorageImpl(nsDOMStorage* aStorage)
     751                 : {
     752              20 :   Init(aStorage);
     753              20 : }
     754                 : 
     755               0 : DOMStorageImpl::DOMStorageImpl(nsDOMStorage* aStorage, DOMStorageImpl& aThat)
     756               0 :   : DOMStorageBase(aThat)
     757                 : {
     758               0 :   Init(aStorage);
     759               0 : }
     760                 : 
     761                 : void
     762              20 : DOMStorageImpl::Init(nsDOMStorage* aStorage)
     763                 : {
     764              20 :   mItemsCachedVersion = 0;
     765              20 :   mItems.Init(8);
     766              20 :   mOwner = aStorage;
     767              20 :   if (nsDOMStorageManager::gStorageManager)
     768              20 :     nsDOMStorageManager::gStorageManager->AddToStoragesHash(this);
     769              20 : }
     770                 : 
     771              40 : DOMStorageImpl::~DOMStorageImpl()
     772                 : {
     773              20 :   if (nsDOMStorageManager::gStorageManager)
     774              18 :     nsDOMStorageManager::gStorageManager->RemoveFromStoragesHash(this);
     775              20 : }
     776                 : 
     777                 : nsresult
     778             354 : DOMStorageImpl::InitDB()
     779                 : {
     780             354 :   if (!gStorageDB) {
     781              77 :     gStorageDB = new nsDOMStorageDBWrapper();
     782              77 :     if (!gStorageDB)
     783               0 :       return NS_ERROR_OUT_OF_MEMORY;
     784                 : 
     785              77 :     nsresult rv = gStorageDB->Init();
     786              77 :     if (NS_FAILED(rv)) {
     787                 :       // Failed to initialize the DB, delete it and null out the
     788                 :       // pointer so we don't end up attempting to use an
     789                 :       // un-initialized DB later on.
     790                 : 
     791              38 :       delete gStorageDB;
     792              38 :       gStorageDB = nsnull;
     793                 : 
     794              38 :       return rv;
     795                 :     }
     796                 :   }
     797                 : 
     798             316 :   return NS_OK;
     799                 : }
     800                 : 
     801                 : void
     802               0 : DOMStorageImpl::InitFromChild(bool aUseDB, bool aCanUseChromePersist,
     803                 :                               bool aSessionOnly, const nsACString& aDomain,
     804                 :                               const nsACString& aScopeDBKey,
     805                 :                               const nsACString& aQuotaDomainDBKey,
     806                 :                               const nsACString& aQuotaETLDplus1DomainDBKey,
     807                 :                               PRUint32 aStorageType)
     808                 : {
     809               0 :   mUseDB = aUseDB;
     810               0 :   mCanUseChromePersist = aCanUseChromePersist;
     811               0 :   mSessionOnly = aSessionOnly;
     812               0 :   mDomain = aDomain;
     813               0 :   mScopeDBKey = aScopeDBKey;
     814               0 :   mQuotaDomainDBKey = aQuotaDomainDBKey;
     815               0 :   mQuotaETLDplus1DomainDBKey = aQuotaETLDplus1DomainDBKey;
     816               0 :   mStorageType = static_cast<nsPIDOMStorage::nsDOMStorageType>(aStorageType);
     817               0 : }
     818                 : 
     819                 : void
     820               0 : DOMStorageImpl::SetSessionOnly(bool aSessionOnly)
     821                 : {
     822               0 :   mSessionOnly = aSessionOnly;
     823               0 : }
     824                 : 
     825                 : void
     826               0 : DOMStorageImpl::InitAsSessionStorage(nsIURI* aDomainURI)
     827                 : {
     828               0 :   DOMStorageBase::InitAsSessionStorage(aDomainURI);
     829               0 : }
     830                 : 
     831                 : void
     832              20 : DOMStorageImpl::InitAsLocalStorage(nsIURI* aDomainURI,
     833                 :                                    bool aCanUseChromePersist)
     834                 : {
     835              20 :   DOMStorageBase::InitAsLocalStorage(aDomainURI, aCanUseChromePersist);
     836              20 : }
     837                 : 
     838                 : void
     839               0 : DOMStorageImpl::InitAsGlobalStorage(const nsACString& aDomainDemanded)
     840                 : {
     841               0 :   DOMStorageBase::InitAsGlobalStorage(aDomainDemanded);
     842               0 : }
     843                 : 
     844                 : bool
     845              30 : DOMStorageImpl::CacheStoragePermissions()
     846                 : {
     847                 :   // If this is a cross-process situation, we don't have a real storage owner.
     848                 :   // All the correct checks have been done on the child, so we just need to
     849                 :   // make sure that our session-only status is correctly updated.
     850              30 :   if (!mOwner)
     851               0 :     return nsDOMStorage::CanUseStorage(&mSessionOnly);
     852                 :   
     853              30 :   return mOwner->CacheStoragePermissions();
     854                 : }
     855                 : 
     856                 : bool
     857             266 : DOMStorageImpl::CanUseChromePersist()
     858                 : {
     859             266 :   return mCanUseChromePersist;
     860                 : }
     861                 : 
     862                 : nsresult
     863              18 : DOMStorageImpl::GetCachedValue(const nsAString& aKey, nsAString& aValue,
     864                 :                                bool* aSecure)
     865                 : {
     866              18 :   aValue.Truncate();
     867              18 :   *aSecure = false;
     868                 : 
     869              18 :   nsSessionStorageEntry *entry = mItems.GetEntry(aKey);
     870              18 :   if (!entry)
     871              18 :     return NS_ERROR_NOT_AVAILABLE;
     872                 : 
     873               0 :   aValue = entry->mItem->GetValueInternal();
     874               0 :   *aSecure = entry->mItem->IsSecure();
     875                 : 
     876               0 :   return NS_OK;
     877                 : }
     878                 : 
     879                 : nsresult
     880              50 : DOMStorageImpl::GetDBValue(const nsAString& aKey, nsAString& aValue,
     881                 :                            bool* aSecure)
     882                 : {
     883              50 :   aValue.Truncate();
     884                 : 
     885              50 :   if (!UseDB())
     886               0 :     return NS_OK;
     887                 : 
     888              50 :   nsresult rv = InitDB();
     889              50 :   NS_ENSURE_SUCCESS(rv, rv);
     890                 : 
     891             100 :   nsAutoString value;
     892              50 :   rv = gStorageDB->GetKeyValue(this, aKey, value, aSecure);
     893                 : 
     894              50 :   if (rv == NS_ERROR_DOM_NOT_FOUND_ERR &&
     895                 :       mStorageType != nsPIDOMStorage::GlobalStorage) {
     896              18 :     SetDOMStringToNull(aValue);
     897                 :   }
     898                 : 
     899              50 :   if (NS_FAILED(rv))
     900              18 :     return rv;
     901                 : 
     902              32 :   aValue.Assign(value);
     903                 : 
     904              32 :   return NS_OK;
     905                 : }
     906                 : 
     907                 : nsresult
     908              18 : DOMStorageImpl::SetDBValue(const nsAString& aKey,
     909                 :                            const nsAString& aValue,
     910                 :                            bool aSecure)
     911                 : {
     912              18 :   if (!UseDB())
     913               0 :     return NS_OK;
     914                 : 
     915              18 :   nsresult rv = InitDB();
     916              18 :   NS_ENSURE_SUCCESS(rv, rv);
     917                 : 
     918                 :   PRInt32 offlineAppPermission;
     919                 :   PRInt32 quota;
     920                 :   PRInt32 warnQuota;
     921                 :   offlineAppPermission = GetQuota(mDomain, &quota, &warnQuota,
     922              18 :                                   CanUseChromePersist());
     923                 : 
     924              18 :   CacheKeysFromDB();
     925                 : 
     926                 :   PRInt32 usage;
     927                 :   rv = gStorageDB->SetKey(this, aKey, aValue, aSecure, quota,
     928               0 :                          !IS_PERMISSION_ALLOWED(offlineAppPermission),
     929              36 :                          &usage);
     930              18 :   NS_ENSURE_SUCCESS(rv, rv);
     931                 : 
     932              18 :   if (warnQuota >= 0 && usage > warnQuota) {
     933                 :     // try to include the window that exceeded the warn quota
     934               0 :     nsCOMPtr<nsIDOMWindow> window;
     935                 :     JSContext *cx;
     936                 :     nsCOMPtr<nsIJSContextStack> stack =
     937               0 :         do_GetService("@mozilla.org/js/xpc/ContextStack;1");
     938               0 :     if (stack && NS_SUCCEEDED(stack->Peek(&cx)) && cx) {
     939               0 :       nsCOMPtr<nsIScriptContext> scriptContext;
     940               0 :       scriptContext = GetScriptContextFromJSContext(cx);
     941               0 :       if (scriptContext) {
     942               0 :         window = do_QueryInterface(scriptContext->GetGlobalObject());
     943                 :       }
     944                 :     }
     945                 : 
     946               0 :     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     947               0 :     os->NotifyObservers(window, "dom-storage-warn-quota-exceeded",
     948               0 :                        NS_ConvertUTF8toUTF16(mDomain).get());
     949                 :   }
     950                 : 
     951              18 :   return NS_OK;
     952                 : }
     953                 : 
     954                 : nsresult
     955               0 : DOMStorageImpl::SetSecure(const nsAString& aKey, bool aSecure)
     956                 : {
     957               0 :   if (UseDB()) {
     958               0 :     nsresult rv = InitDB();
     959               0 :     NS_ENSURE_SUCCESS(rv, rv);
     960                 : 
     961               0 :     return gStorageDB->SetSecure(this, aKey, aSecure);
     962                 :   }
     963                 : 
     964               0 :   nsSessionStorageEntry *entry = mItems.GetEntry(aKey);
     965               0 :   NS_ASSERTION(entry, "Don't use SetSecure() with nonexistent keys!");
     966                 : 
     967               0 :   if (entry) {
     968               0 :     entry->mItem->SetSecureInternal(aSecure);
     969                 :   }  
     970                 : 
     971               0 :   return NS_OK;
     972                 : }
     973                 : 
     974                 : static PLDHashOperator
     975               9 : ClearStorageItem(nsSessionStorageEntry* aEntry, void* userArg)
     976                 : {
     977               9 :   aEntry->mItem->SetValueInternal(EmptyString());
     978               9 :   return PL_DHASH_NEXT;
     979                 : }
     980                 : 
     981                 : void
     982              14 : DOMStorageImpl::ClearAll()
     983                 : {
     984              14 :   mItems.EnumerateEntries(ClearStorageItem, nsnull);
     985              14 :   mItemsCachedVersion = 0;
     986              14 : }
     987                 : 
     988                 : struct CopyArgs {
     989                 :   DOMStorageImpl* storage;
     990                 :   bool callerSecure;
     991                 : };
     992                 : 
     993                 : static PLDHashOperator
     994               0 : CopyStorageItems(nsSessionStorageEntry* aEntry, void* userArg)
     995                 : {
     996                 :   // When copying items from one impl to another, we may not
     997                 :   // have an mOwner that we can call SetItem on. Therefore we need
     998                 :   // to replicate its behaviour.
     999                 :   
    1000               0 :   CopyArgs* args = static_cast<CopyArgs*>(userArg);
    1001                 : 
    1002               0 :   nsAutoString unused;
    1003               0 :   nsresult rv = args->storage->SetValue(args->callerSecure, aEntry->GetKey(),
    1004               0 :                                         aEntry->mItem->GetValueInternal(), unused);
    1005               0 :   if (NS_FAILED(rv))
    1006               0 :     return PL_DHASH_NEXT;
    1007                 : 
    1008               0 :   if (aEntry->mItem->IsSecure()) {
    1009               0 :     args->storage->SetSecure(aEntry->GetKey(), true);
    1010                 :   }
    1011                 : 
    1012               0 :   return PL_DHASH_NEXT;
    1013                 : }
    1014                 : 
    1015                 : nsresult
    1016               0 : DOMStorageImpl::CloneFrom(bool aCallerSecure, DOMStorageBase* aThat)
    1017                 : {
    1018                 :   // For various reasons, we no longer call SetItem in CopyStorageItems,
    1019                 :   // so we need to ensure that the storage permissions are correct.
    1020               0 :   if (!CacheStoragePermissions())
    1021               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    1022                 :   
    1023               0 :   DOMStorageImpl* that = static_cast<DOMStorageImpl*>(aThat);
    1024               0 :   CopyArgs args = { this, aCallerSecure };
    1025               0 :   that->mItems.EnumerateEntries(CopyStorageItems, &args);
    1026               0 :   return NS_OK;
    1027                 : }
    1028                 : 
    1029                 : nsresult
    1030              92 : DOMStorageImpl::CacheKeysFromDB()
    1031                 : {
    1032                 :   // cache all the keys in the hash. This is used by the Length and Key methods
    1033                 :   // use this cache for better performance. The disadvantage is that the
    1034                 :   // order may break if someone changes the keys in the database directly.
    1035              92 :   if (gStorageDB->IsScopeDirty(this)) {
    1036              38 :     nsresult rv = InitDB();
    1037              38 :     NS_ENSURE_SUCCESS(rv, rv);
    1038                 : 
    1039              38 :     mItems.Clear();
    1040                 : 
    1041              38 :     rv = gStorageDB->GetAllKeys(this, &mItems);
    1042              38 :     NS_ENSURE_SUCCESS(rv, rv);
    1043                 : 
    1044              38 :     gStorageDB->MarkScopeCached(this);
    1045                 :   }
    1046                 : 
    1047              92 :   return NS_OK;
    1048                 : }
    1049                 : 
    1050                 : struct KeysArrayBuilderStruct
    1051                 : {
    1052                 :   bool callerIsSecure;
    1053                 :   nsTArray<nsString> *keys;
    1054                 : };
    1055                 : 
    1056                 : static PLDHashOperator
    1057               0 : KeysArrayBuilder(nsSessionStorageEntry* aEntry, void* userArg)
    1058                 : {
    1059               0 :   KeysArrayBuilderStruct *keystruct = (KeysArrayBuilderStruct *)userArg;
    1060                 :   
    1061               0 :   if (keystruct->callerIsSecure || !aEntry->mItem->IsSecure())
    1062               0 :     keystruct->keys->AppendElement(aEntry->GetKey());
    1063                 : 
    1064               0 :   return PL_DHASH_NEXT;
    1065                 : }
    1066                 : 
    1067                 : nsTArray<nsString>*
    1068               0 : DOMStorageImpl::GetKeys(bool aCallerSecure)
    1069                 : {
    1070               0 :   if (UseDB())
    1071               0 :     CacheKeysFromDB();
    1072                 : 
    1073                 :   KeysArrayBuilderStruct keystruct;
    1074               0 :   keystruct.callerIsSecure = aCallerSecure;
    1075               0 :   keystruct.keys = new nsTArray<nsString>();
    1076               0 :   if (keystruct.keys)
    1077               0 :     mItems.EnumerateEntries(KeysArrayBuilder, &keystruct);
    1078                 :  
    1079               0 :   return keystruct.keys;
    1080                 : }
    1081                 : 
    1082                 : class ItemCounterState
    1083                 : {
    1084                 :  public:
    1085              44 :   ItemCounterState(bool aIsCallerSecure)
    1086              44 :   : mIsCallerSecure(aIsCallerSecure), mCount(0)
    1087                 :   {
    1088              44 :   }
    1089                 : 
    1090                 :   bool mIsCallerSecure;
    1091                 :   PRUint32 mCount;
    1092                 :  private:
    1093                 :   ItemCounterState(); // Not to be implemented
    1094                 : };
    1095                 : 
    1096                 : static PLDHashOperator
    1097              26 : ItemCounter(nsSessionStorageEntry* aEntry, void* userArg)
    1098                 : {
    1099              26 :   ItemCounterState *state = (ItemCounterState *)userArg;
    1100                 : 
    1101              26 :   if (state->mIsCallerSecure || !aEntry->mItem->IsSecure()) {
    1102              26 :     ++state->mCount;
    1103                 :   }
    1104                 : 
    1105              26 :   return PL_DHASH_NEXT;
    1106                 : }
    1107                 : 
    1108                 : nsresult
    1109              44 : DOMStorageImpl::GetLength(bool aCallerSecure, PRUint32* aLength)
    1110                 : {
    1111                 :   // Force reload of items from database.  This ensures sync localStorages for
    1112                 :   // same origins among different windows.
    1113              44 :   if (UseDB())
    1114              44 :     CacheKeysFromDB();
    1115                 : 
    1116              44 :   ItemCounterState state(aCallerSecure);
    1117                 : 
    1118              44 :   mItems.EnumerateEntries(ItemCounter, &state);
    1119                 : 
    1120              44 :   *aLength = state.mCount;
    1121              44 :   return NS_OK;
    1122                 : }
    1123                 : 
    1124                 : class IndexFinderData
    1125                 : {
    1126                 :  public:
    1127              24 :   IndexFinderData(bool aIsCallerSecure, PRUint32 aWantedIndex)
    1128                 :   : mIsCallerSecure(aIsCallerSecure), mIndex(0), mWantedIndex(aWantedIndex),
    1129              24 :     mItem(nsnull)
    1130                 :   {
    1131              24 :   }
    1132                 : 
    1133                 :   bool mIsCallerSecure;
    1134                 :   PRUint32 mIndex;
    1135                 :   PRUint32 mWantedIndex;
    1136                 :   nsSessionStorageEntry *mItem;
    1137                 : 
    1138                 :  private:
    1139                 :   IndexFinderData(); // Not to be implemented
    1140                 : };
    1141                 : 
    1142                 : static PLDHashOperator
    1143              24 : IndexFinder(nsSessionStorageEntry* aEntry, void* userArg)
    1144                 : {
    1145              24 :   IndexFinderData *data = (IndexFinderData *)userArg;
    1146                 : 
    1147              48 :   if (data->mIndex == data->mWantedIndex &&
    1148              24 :       (data->mIsCallerSecure || !aEntry->mItem->IsSecure())) {
    1149              24 :     data->mItem = aEntry;
    1150                 : 
    1151              24 :     return PL_DHASH_STOP;
    1152                 :   }
    1153                 : 
    1154               0 :   ++data->mIndex;
    1155                 : 
    1156               0 :   return PL_DHASH_NEXT;
    1157                 : }
    1158                 : 
    1159                 : nsresult
    1160              24 : DOMStorageImpl::GetKey(bool aCallerSecure, PRUint32 aIndex, nsAString& aKey)
    1161                 : {
    1162                 :   // XXXjst: This is as retarded as the DOM spec is, takes an unsigned
    1163                 :   // int, but the spec talks about what to do if a negative value is
    1164                 :   // passed in.
    1165                 : 
    1166                 :   // XXX: This does a linear search for the key at index, which would
    1167                 :   // suck if there's a large numer of indexes. Do we care? If so,
    1168                 :   // maybe we need to have a lazily populated key array here or
    1169                 :   // something?
    1170                 : 
    1171              24 :   if (UseDB()) {
    1172              24 :     CacheKeysFromDB();
    1173                 :   }
    1174                 : 
    1175              24 :   IndexFinderData data(aCallerSecure, aIndex);
    1176              24 :   mItems.EnumerateEntries(IndexFinder, &data);
    1177                 : 
    1178              24 :   if (!data.mItem) {
    1179                 :     // aIndex was larger than the number of accessible keys. Throw.
    1180               0 :     return NS_ERROR_DOM_INDEX_SIZE_ERR;
    1181                 :   }
    1182                 : 
    1183              24 :   aKey = data.mItem->GetKey();
    1184              24 :   return NS_OK;
    1185                 : }
    1186                 : 
    1187                 : // The behaviour of this function must be kept in sync with StorageChild::GetValue.
    1188                 : // See the explanatory comment there for more details.
    1189                 : nsIDOMStorageItem*
    1190              44 : DOMStorageImpl::GetValue(bool aCallerSecure, const nsAString& aKey,
    1191                 :                          nsresult* aResult)
    1192                 : {
    1193              44 :   nsSessionStorageEntry *entry = mItems.GetEntry(aKey);
    1194              44 :   nsIDOMStorageItem* item = nsnull;
    1195              44 :   if (entry) {
    1196              30 :     if (aCallerSecure || !entry->mItem->IsSecure()) {
    1197              30 :       item = entry->mItem;
    1198                 :     }
    1199                 :   }
    1200              14 :   else if (UseDB()) {
    1201                 :     bool secure;
    1202              28 :     nsAutoString value;
    1203              14 :     nsresult rv = GetDBValue(aKey, value, &secure);
    1204                 :     // return null if access isn't allowed or the key wasn't found
    1205              14 :     if (rv == NS_ERROR_DOM_SECURITY_ERR || rv == NS_ERROR_DOM_NOT_FOUND_ERR ||
    1206               0 :         (!aCallerSecure && secure))
    1207              14 :       return nsnull;
    1208                 : 
    1209               0 :     *aResult = rv;
    1210               0 :     NS_ENSURE_SUCCESS(rv, nsnull);
    1211                 : 
    1212                 :     nsRefPtr<nsDOMStorageItem> newitem =
    1213              14 :         new nsDOMStorageItem(this, aKey, value, secure);
    1214               0 :     if (newitem && (entry = mItems.PutEntry(aKey))) {
    1215               0 :       item = entry->mItem = newitem;
    1216                 :     }
    1217                 :     else {
    1218               0 :       *aResult = NS_ERROR_OUT_OF_MEMORY;
    1219                 :     }
    1220                 :   }
    1221              30 :   return item;
    1222                 : }
    1223                 : 
    1224                 : nsresult
    1225              18 : DOMStorageImpl::SetValue(bool aIsCallerSecure, const nsAString& aKey,
    1226                 :                          const nsAString& aData, nsAString& aOldValue)
    1227                 : {
    1228              18 :   if (aKey.IsEmpty())
    1229               0 :     return NS_OK;
    1230                 : 
    1231                 :   nsresult rv;
    1232              36 :   nsString oldValue;
    1233              18 :   SetDOMStringToNull(oldValue);
    1234                 : 
    1235                 :   // First store the value to the database, we need to do this before we update
    1236                 :   // the mItems cache.  SetDBValue is using the old cached value to decide
    1237                 :   // on quota checking.
    1238              18 :   if (UseDB()) {
    1239              18 :     rv = SetDBValue(aKey, aData, aIsCallerSecure);
    1240              18 :     NS_ENSURE_SUCCESS(rv, rv);
    1241                 :   }
    1242                 : 
    1243              18 :   nsSessionStorageEntry *entry = mItems.GetEntry(aKey);
    1244              18 :   if (entry) {
    1245               0 :     if (entry->mItem->IsSecure() && !aIsCallerSecure) {
    1246               0 :       return NS_ERROR_DOM_SECURITY_ERR;
    1247                 :     }
    1248               0 :     oldValue = entry->mItem->GetValueInternal();
    1249               0 :     entry->mItem->SetValueInternal(aData);
    1250                 :   }
    1251                 :   else {
    1252                 :     nsRefPtr<nsDOMStorageItem> newitem =
    1253              36 :         new nsDOMStorageItem(this, aKey, aData, aIsCallerSecure);
    1254              18 :     if (!newitem)
    1255               0 :       return NS_ERROR_OUT_OF_MEMORY;
    1256              18 :     entry = mItems.PutEntry(aKey);
    1257              18 :     NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
    1258              36 :     entry->mItem = newitem;
    1259                 :   }
    1260              18 :   aOldValue = oldValue;
    1261              18 :   return NS_OK;
    1262                 : }
    1263                 : 
    1264                 : nsresult
    1265               6 : DOMStorageImpl::RemoveValue(bool aCallerSecure, const nsAString& aKey,
    1266                 :                             nsAString& aOldValue)
    1267                 : {
    1268              12 :   nsString oldValue;
    1269               6 :   nsSessionStorageEntry *entry = mItems.GetEntry(aKey);
    1270                 : 
    1271               6 :   if (entry && entry->mItem->IsSecure() && !aCallerSecure) {
    1272               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    1273                 :   }
    1274                 : 
    1275               6 :   if (UseDB()) {
    1276               6 :     nsresult rv = InitDB();
    1277               6 :     NS_ENSURE_SUCCESS(rv, rv);
    1278                 : 
    1279              12 :     nsAutoString value;
    1280                 :     bool secureItem;
    1281               6 :     rv = GetDBValue(aKey, value, &secureItem);
    1282               6 :     NS_ENSURE_SUCCESS(rv, rv);
    1283               6 :     if (!aCallerSecure && secureItem)
    1284               0 :       return NS_ERROR_DOM_SECURITY_ERR;
    1285                 : 
    1286               6 :     oldValue = value;
    1287                 : 
    1288               6 :     rv = gStorageDB->RemoveKey(this, aKey, !IsOfflineAllowed(mDomain),
    1289              12 :                                aKey.Length() + value.Length());
    1290               6 :     NS_ENSURE_SUCCESS(rv, rv);
    1291                 :   }
    1292               0 :   else if (entry) {
    1293                 :     // clear string as StorageItems may be referencing this item
    1294               0 :     oldValue = entry->mItem->GetValueInternal();
    1295               0 :     entry->mItem->ClearValue();
    1296                 :   }
    1297                 : 
    1298               6 :   if (entry) {
    1299               6 :     mItems.RawRemoveEntry(entry);
    1300                 :   }
    1301               6 :   aOldValue = oldValue;
    1302               6 :   return NS_OK;
    1303                 : }
    1304                 : 
    1305                 : PR_STATIC_CALLBACK(PLDHashOperator)
    1306               6 : CheckSecure(nsSessionStorageEntry* aEntry, void* userArg)
    1307                 : {
    1308               6 :   bool* secure = (bool*)userArg;
    1309               6 :   if (aEntry->mItem->IsSecure()) {
    1310               0 :     *secure = true;
    1311               0 :     return PL_DHASH_STOP;
    1312                 :   }
    1313                 : 
    1314               6 :   return PL_DHASH_NEXT;
    1315                 : }
    1316                 : 
    1317                 : nsresult
    1318               6 : DOMStorageImpl::Clear(bool aCallerSecure, PRInt32* aOldCount)
    1319                 : {
    1320               6 :   if (UseDB())
    1321               6 :     CacheKeysFromDB();
    1322                 : 
    1323               6 :   PRInt32 oldCount = mItems.Count();
    1324                 : 
    1325               6 :   bool foundSecureItem = false;
    1326               6 :   mItems.EnumerateEntries(CheckSecure, &foundSecureItem);
    1327                 : 
    1328               6 :   if (foundSecureItem && !aCallerSecure) {
    1329               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    1330                 :   }
    1331                 : 
    1332               6 :   if (UseDB()) {
    1333               6 :     nsresult rv = InitDB();
    1334               6 :     NS_ENSURE_SUCCESS(rv, rv);
    1335                 : 
    1336               6 :     rv = gStorageDB->ClearStorage(this);
    1337               6 :     NS_ENSURE_SUCCESS(rv, rv);
    1338                 :   }
    1339                 : 
    1340               6 :   *aOldCount = oldCount;
    1341               6 :   mItems.Clear();
    1342               6 :   return NS_OK;
    1343                 : }
    1344                 : 
    1345              20 : nsDOMStorage::nsDOMStorage()
    1346                 :   : mStorageType(nsPIDOMStorage::Unknown)
    1347              20 :   , mEventBroadcaster(nsnull)
    1348                 : {
    1349              20 :   if (XRE_GetProcessType() != GeckoProcessType_Default)
    1350               0 :     mStorageImpl = new StorageChild(this);
    1351                 :   else
    1352              20 :     mStorageImpl = new DOMStorageImpl(this);
    1353              20 : }
    1354                 : 
    1355               0 : nsDOMStorage::nsDOMStorage(nsDOMStorage& aThat)
    1356                 :   : mStorageType(aThat.mStorageType)
    1357                 :   , mPrincipal(aThat.mPrincipal)
    1358               0 :   , mEventBroadcaster(nsnull)
    1359                 : {
    1360               0 :   if (XRE_GetProcessType() != GeckoProcessType_Default) {
    1361               0 :     StorageChild* other = static_cast<StorageChild*>(aThat.mStorageImpl.get());
    1362               0 :     mStorageImpl = new StorageChild(this, *other);
    1363                 :   } else {
    1364               0 :     DOMStorageImpl* other = static_cast<DOMStorageImpl*>(aThat.mStorageImpl.get());
    1365               0 :     mStorageImpl = new DOMStorageImpl(this, *other);
    1366                 :   }
    1367               0 : }
    1368                 : 
    1369              40 : nsDOMStorage::~nsDOMStorage()
    1370                 : {
    1371              80 : }
    1372                 : 
    1373                 : static
    1374                 : nsresult
    1375              20 : GetDomainURI(nsIPrincipal *aPrincipal, bool aIncludeDomain, nsIURI **_domain)
    1376                 : {
    1377              40 :   nsCOMPtr<nsIURI> uri;
    1378                 : 
    1379              20 :   if (aIncludeDomain) {
    1380               0 :     nsresult rv = aPrincipal->GetDomain(getter_AddRefs(uri));
    1381               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1382                 :   }
    1383                 : 
    1384              20 :   if (!uri) {
    1385              20 :     nsresult rv = aPrincipal->GetURI(getter_AddRefs(uri));
    1386              20 :     NS_ENSURE_SUCCESS(rv, rv);
    1387                 :   }
    1388                 : 
    1389                 :   // Check if we really got any URI. System principal doesn't return a URI
    1390                 :   // instance and we would crash in NS_GetInnermostURI below.
    1391              20 :   if (!uri)
    1392               0 :     return NS_ERROR_NOT_AVAILABLE;
    1393                 : 
    1394              40 :   nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(uri);
    1395              20 :   if (!innerURI)
    1396               0 :     return NS_ERROR_UNEXPECTED;
    1397              20 :   innerURI.forget(_domain);
    1398                 : 
    1399              20 :   return NS_OK;
    1400                 : }
    1401                 : 
    1402                 : nsresult
    1403               0 : nsDOMStorage::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI)
    1404                 : {
    1405               0 :   nsCOMPtr<nsIURI> domainURI;
    1406               0 :   nsresult rv = GetDomainURI(aPrincipal, true, getter_AddRefs(domainURI));
    1407               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1408                 : 
    1409               0 :   mDocumentURI = aDocumentURI;
    1410               0 :   mPrincipal = aPrincipal;
    1411                 : 
    1412               0 :   mStorageType = SessionStorage;
    1413                 : 
    1414               0 :   mStorageImpl->InitAsSessionStorage(domainURI);
    1415               0 :   return NS_OK;
    1416                 : }
    1417                 : 
    1418                 : nsresult
    1419              20 : nsDOMStorage::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI)
    1420                 : {
    1421              40 :   nsCOMPtr<nsIURI> domainURI;
    1422              20 :   nsresult rv = GetDomainURI(aPrincipal, false, getter_AddRefs(domainURI));
    1423              20 :   NS_ENSURE_SUCCESS(rv, rv);
    1424                 : 
    1425              20 :   mDocumentURI = aDocumentURI;
    1426              20 :   mPrincipal = aPrincipal;
    1427                 : 
    1428              20 :   mStorageType = LocalStorage;
    1429                 : 
    1430              20 :   bool canUseChromePersist = false;
    1431              40 :   nsCOMPtr<nsIURI> URI;
    1432              20 :   if (NS_SUCCEEDED(aPrincipal->GetURI(getter_AddRefs(URI))) && URI) {
    1433              20 :     canUseChromePersist = URICanUseChromePersist(URI);
    1434                 :   }
    1435                 :   
    1436              20 :   mStorageImpl->InitAsLocalStorage(domainURI, canUseChromePersist);
    1437              20 :   return NS_OK;
    1438                 : }
    1439                 : 
    1440                 : nsresult
    1441               0 : nsDOMStorage::InitAsGlobalStorage(const nsACString &aDomainDemanded)
    1442                 : {
    1443               0 :   mStorageType = GlobalStorage;
    1444               0 :   mEventBroadcaster = this;
    1445               0 :   mStorageImpl->InitAsGlobalStorage(aDomainDemanded);
    1446               0 :   return NS_OK;
    1447                 : }
    1448                 : 
    1449                 : //static
    1450                 : bool
    1451             172 : nsDOMStorage::CanUseStorage(bool* aSessionOnly)
    1452                 : {
    1453                 :   // check if the calling domain can use storage. Downgrade to session
    1454                 :   // only if only session storage may be used.
    1455             172 :   NS_ASSERTION(aSessionOnly, "null session flag");
    1456             172 :   *aSessionOnly = false;
    1457                 : 
    1458             172 :   if (!Preferences::GetBool(kStorageEnabled)) {
    1459               0 :     return false;
    1460                 :   }
    1461                 : 
    1462                 :   // chrome can always use storage regardless of permission preferences
    1463             172 :   if (nsContentUtils::IsCallerChrome())
    1464             172 :     return true;
    1465                 : 
    1466               0 :   nsCOMPtr<nsIPrincipal> subjectPrincipal;
    1467               0 :   nsresult rv = nsContentUtils::GetSecurityManager()->
    1468               0 :                   GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
    1469               0 :   NS_ENSURE_SUCCESS(rv, false);
    1470                 : 
    1471                 :   // if subjectPrincipal were null we'd have returned after
    1472                 :   // IsCallerChrome().
    1473                 : 
    1474               0 :   nsCOMPtr<nsIURI> subjectURI;
    1475               0 :   nsCAutoString unused;
    1476               0 :   if (NS_FAILED(GetPrincipalURIAndHost(subjectPrincipal,
    1477                 :                                        getter_AddRefs(subjectURI),
    1478                 :                                        unused))) {
    1479               0 :     return false;
    1480                 :   }
    1481                 : 
    1482                 :   nsCOMPtr<nsIPermissionManager> permissionManager =
    1483               0 :     do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
    1484               0 :   if (!permissionManager)
    1485               0 :     return false;
    1486                 : 
    1487                 :   PRUint32 perm;
    1488               0 :   permissionManager->TestPermission(subjectURI, kPermissionType, &perm);
    1489                 : 
    1490               0 :   if (perm == nsIPermissionManager::DENY_ACTION)
    1491               0 :     return false;
    1492                 : 
    1493                 :   // In private browsing mode we ougth to behave as in session-only cookies
    1494                 :   // mode to prevent detection of being in private browsing mode and ensuring
    1495                 :   // that there will be no traces left.
    1496               0 :   if (perm == nsICookiePermission::ACCESS_SESSION ||
    1497               0 :       nsDOMStorageManager::gStorageManager->InPrivateBrowsingMode()) {
    1498               0 :     *aSessionOnly = true;
    1499                 :   }
    1500               0 :   else if (perm != nsIPermissionManager::ALLOW_ACTION) {
    1501               0 :     PRUint32 cookieBehavior = Preferences::GetUint(kCookiesBehavior);
    1502               0 :     PRUint32 lifetimePolicy = Preferences::GetUint(kCookiesLifetimePolicy);
    1503                 : 
    1504                 :     // Treat "ask every time" as "reject always".
    1505                 :     // Chrome persistent pages can bypass this check.
    1506               0 :     if ((cookieBehavior == BEHAVIOR_REJECT || lifetimePolicy == ASK_BEFORE_ACCEPT) &&
    1507               0 :         !URICanUseChromePersist(subjectURI))
    1508               0 :       return false;
    1509                 : 
    1510               0 :     if (lifetimePolicy == ACCEPT_SESSION)
    1511               0 :       *aSessionOnly = true;
    1512                 :   }
    1513                 : 
    1514               0 :   return true;
    1515                 : }
    1516                 : 
    1517                 : bool
    1518             172 : nsDOMStorage::CacheStoragePermissions()
    1519                 : {
    1520                 :   // Bug 488446, disallowing storage use when in session only mode.
    1521                 :   // This is temporary fix before we find complete solution for storage
    1522                 :   // behavior in private browsing mode or session-only cookies mode.
    1523             172 :   if (!CanUseStorage(&mStorageImpl->mSessionOnly))
    1524               0 :     return false;
    1525                 : 
    1526             172 :   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
    1527             172 :   if (!ssm)
    1528               0 :     return false;
    1529                 : 
    1530             344 :   nsCOMPtr<nsIPrincipal> subjectPrincipal;
    1531             172 :   nsresult rv = ssm->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
    1532             172 :   NS_ENSURE_SUCCESS(rv, false);
    1533                 : 
    1534             172 :   return CanAccess(subjectPrincipal);
    1535                 : }
    1536                 : 
    1537                 : // static
    1538                 : bool
    1539              20 : nsDOMStorage::URICanUseChromePersist(nsIURI* aURI) {
    1540                 :   bool isAbout;
    1541                 :   return
    1542              20 :     (NS_SUCCEEDED(aURI->SchemeIs("moz-safe-about", &isAbout)) && isAbout) ||
    1543              20 :     (NS_SUCCEEDED(aURI->SchemeIs("about", &isAbout)) && isAbout);
    1544                 : }
    1545                 : 
    1546                 : NS_IMETHODIMP
    1547              44 : nsDOMStorage::GetLength(PRUint32 *aLength)
    1548                 : {
    1549              44 :   if (!CacheStoragePermissions())
    1550               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    1551                 :   
    1552              44 :   return mStorageImpl->GetLength(IsCallerSecure(), aLength);
    1553                 : }
    1554                 : 
    1555                 : NS_IMETHODIMP
    1556              24 : nsDOMStorage::Key(PRUint32 aIndex, nsAString& aKey)
    1557                 : {
    1558              24 :   if (!CacheStoragePermissions())
    1559               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    1560                 : 
    1561              24 :   return mStorageImpl->GetKey(IsCallerSecure(), aIndex, aKey);
    1562                 : }
    1563                 : 
    1564                 : nsIDOMStorageItem*
    1565              44 : nsDOMStorage::GetNamedItem(const nsAString& aKey, nsresult* aResult)
    1566                 : {
    1567              44 :   if (!CacheStoragePermissions()) {
    1568               0 :     *aResult = NS_ERROR_DOM_SECURITY_ERR;
    1569               0 :     return nsnull;
    1570                 :   }
    1571                 : 
    1572              44 :   *aResult = NS_OK;
    1573              44 :   if (aKey.IsEmpty())
    1574               0 :     return nsnull;
    1575                 :   
    1576              44 :   return mStorageImpl->GetValue(IsCallerSecure(), aKey, aResult);
    1577                 : }
    1578                 : 
    1579                 : nsresult
    1580              44 : nsDOMStorage::GetItem(const nsAString& aKey, nsAString &aData)
    1581                 : {
    1582                 :   nsresult rv;
    1583                 : 
    1584                 :   // IMPORTANT:
    1585                 :   // CacheStoragePermissions() is called inside of
    1586                 :   // GetItem(nsAString, nsIDOMStorageItem)
    1587                 :   // To call it particularly in this method would just duplicate
    1588                 :   // the call. If the code changes, make sure that call to
    1589                 :   // CacheStoragePermissions() is put here!
    1590                 : 
    1591              88 :   nsCOMPtr<nsIDOMStorageItem> item;
    1592              44 :   rv = GetItem(aKey, getter_AddRefs(item));
    1593              44 :   if (NS_FAILED(rv))
    1594               0 :     return rv;
    1595                 : 
    1596              44 :   if (item) {
    1597              30 :     rv = item->GetValue(aData);
    1598              30 :     NS_ENSURE_SUCCESS(rv, rv);
    1599                 :   }
    1600                 :   else
    1601              14 :     SetDOMStringToNull(aData);
    1602                 : 
    1603              44 :   return NS_OK;
    1604                 : }
    1605                 : 
    1606                 : static Telemetry::ID
    1607              18 : TelemetryIDForKey(nsPIDOMStorage::nsDOMStorageType type)
    1608                 : {
    1609              18 :   switch (type) {
    1610                 :   default:
    1611               0 :     MOZ_ASSERT(false);
    1612                 :     // We need to return something to satisfy the compiler.
    1613                 :     // Fallthrough.
    1614                 :   case nsPIDOMStorage::GlobalStorage:
    1615               0 :     return Telemetry::GLOBALDOMSTORAGE_KEY_SIZE_BYTES;
    1616                 :   case nsPIDOMStorage::LocalStorage:
    1617              18 :     return Telemetry::LOCALDOMSTORAGE_KEY_SIZE_BYTES;
    1618                 :   case nsPIDOMStorage::SessionStorage:
    1619               0 :     return Telemetry::SESSIONDOMSTORAGE_KEY_SIZE_BYTES;
    1620                 :   }
    1621                 : }
    1622                 : 
    1623                 : static Telemetry::ID
    1624              18 : TelemetryIDForValue(nsPIDOMStorage::nsDOMStorageType type)
    1625                 : {
    1626              18 :   switch (type) {
    1627                 :   default:
    1628               0 :     MOZ_ASSERT(false);
    1629                 :     // We need to return something to satisfy the compiler.
    1630                 :     // Fallthrough.
    1631                 :   case nsPIDOMStorage::GlobalStorage:
    1632               0 :     return Telemetry::GLOBALDOMSTORAGE_VALUE_SIZE_BYTES;
    1633                 :   case nsPIDOMStorage::LocalStorage:
    1634              18 :     return Telemetry::LOCALDOMSTORAGE_VALUE_SIZE_BYTES;
    1635                 :   case nsPIDOMStorage::SessionStorage:
    1636               0 :     return Telemetry::SESSIONDOMSTORAGE_VALUE_SIZE_BYTES;
    1637                 :   }
    1638                 : }
    1639                 : 
    1640                 : NS_IMETHODIMP
    1641              44 : nsDOMStorage::GetItem(const nsAString& aKey, nsIDOMStorageItem **aItem)
    1642                 : {
    1643                 :   nsresult rv;
    1644                 : 
    1645              44 :   NS_IF_ADDREF(*aItem = GetNamedItem(aKey, &rv));
    1646                 : 
    1647              44 :   return rv;
    1648                 : }
    1649                 : 
    1650                 : NS_IMETHODIMP
    1651              18 : nsDOMStorage::SetItem(const nsAString& aKey, const nsAString& aData)
    1652                 : {
    1653              18 :   if (!CacheStoragePermissions())
    1654               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    1655                 : 
    1656              18 :   Telemetry::Accumulate(TelemetryIDForKey(mStorageType), aKey.Length());
    1657              18 :   Telemetry::Accumulate(TelemetryIDForValue(mStorageType), aData.Length());
    1658                 : 
    1659              36 :   nsString oldValue;
    1660              18 :   nsresult rv = mStorageImpl->SetValue(IsCallerSecure(), aKey, aData, oldValue);
    1661              18 :   if (NS_FAILED(rv))
    1662               0 :     return rv;
    1663                 : 
    1664              18 :   if ((oldValue != aData || mStorageType == GlobalStorage) && mEventBroadcaster)
    1665              18 :     mEventBroadcaster->BroadcastChangeNotification(aKey, oldValue, aData);
    1666                 : 
    1667              18 :   return NS_OK;
    1668                 : }
    1669                 : 
    1670               6 : NS_IMETHODIMP nsDOMStorage::RemoveItem(const nsAString& aKey)
    1671                 : {
    1672               6 :   if (!CacheStoragePermissions())
    1673               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    1674                 : 
    1675               6 :   if (aKey.IsEmpty())
    1676               0 :     return NS_OK;
    1677                 : 
    1678              12 :   nsString oldValue;
    1679               6 :   nsresult rv = mStorageImpl->RemoveValue(IsCallerSecure(), aKey, oldValue);
    1680               6 :   if (rv == NS_ERROR_DOM_NOT_FOUND_ERR)
    1681               0 :     return NS_OK;
    1682               6 :   if (NS_FAILED(rv))
    1683               0 :     return rv;
    1684                 : 
    1685               6 :   if ((!oldValue.IsEmpty() && mStorageType != GlobalStorage) && mEventBroadcaster) {
    1686              12 :     nsAutoString nullString;
    1687               6 :     SetDOMStringToNull(nullString);
    1688               6 :     mEventBroadcaster->BroadcastChangeNotification(aKey, oldValue, nullString);
    1689                 :   }
    1690                 : 
    1691               6 :   return NS_OK;
    1692                 : }
    1693                 : 
    1694                 : nsresult
    1695               6 : nsDOMStorage::Clear()
    1696                 : {
    1697               6 :   if (!CacheStoragePermissions())
    1698               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    1699                 : 
    1700                 :   PRInt32 oldCount;
    1701               6 :   nsresult rv = mStorageImpl->Clear(IsCallerSecure(), &oldCount);
    1702               6 :   if (NS_FAILED(rv))
    1703               0 :     return rv;
    1704                 :   
    1705               6 :   if (oldCount && mEventBroadcaster) {
    1706              12 :     nsAutoString nullString;
    1707               6 :     SetDOMStringToNull(nullString);
    1708               6 :     mEventBroadcaster->BroadcastChangeNotification(nullString, nullString, nullString);
    1709                 :   }
    1710                 : 
    1711               6 :   return NS_OK;
    1712                 : }
    1713                 : 
    1714                 : already_AddRefed<nsIDOMStorage>
    1715               0 : nsDOMStorage::Clone()
    1716                 : {
    1717               0 :   NS_ASSERTION(false, "Old DOMStorage doesn't implement cloning");
    1718               0 :   return nsnull;
    1719                 : }
    1720                 : 
    1721                 : already_AddRefed<nsIDOMStorage>
    1722               0 : nsDOMStorage::Fork(const nsSubstring &aDocumentURI)
    1723                 : {
    1724               0 :   NS_ASSERTION(false, "Old DOMStorage doesn't implement forking");
    1725               0 :   return nsnull;
    1726                 : }
    1727                 : 
    1728               0 : bool nsDOMStorage::IsForkOf(nsIDOMStorage* aThat)
    1729                 : {
    1730               0 :   NS_ASSERTION(false, "Old DOMStorage doesn't implement forking");
    1731               0 :   return false;
    1732                 : }
    1733                 : 
    1734                 : nsresult
    1735               0 : nsDOMStorage::CloneFrom(nsDOMStorage* aThat)
    1736                 : {
    1737               0 :   return mStorageImpl->CloneFrom(IsCallerSecure(), aThat->mStorageImpl);
    1738                 : }
    1739                 : 
    1740                 : nsTArray<nsString> *
    1741               0 : nsDOMStorage::GetKeys()
    1742                 : {
    1743               0 :   return mStorageImpl->GetKeys(IsCallerSecure());
    1744                 : }
    1745                 : 
    1746                 : nsIPrincipal*
    1747               0 : nsDOMStorage::Principal()
    1748                 : {
    1749               0 :   return nsnull;
    1750                 : }
    1751                 : 
    1752                 : bool
    1753               0 : nsDOMStorage::CanAccessSystem(nsIPrincipal *aPrincipal)
    1754                 : {
    1755               0 :   if (!aPrincipal)
    1756               0 :     return true;
    1757                 : 
    1758               0 :   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
    1759               0 :   if (!ssm)
    1760               0 :     return false;
    1761                 : 
    1762                 :   bool isSystem;
    1763               0 :   nsresult rv = ssm->IsSystemPrincipal(aPrincipal, &isSystem);
    1764                 : 
    1765               0 :   return NS_SUCCEEDED(rv) && isSystem;
    1766                 : }
    1767                 : 
    1768                 : bool
    1769             172 : nsDOMStorage::CanAccess(nsIPrincipal *aPrincipal)
    1770                 : {
    1771             172 :   switch (mStorageType) {
    1772                 :   case nsPIDOMStorage::LocalStorage:
    1773                 :   case nsPIDOMStorage::SessionStorage:
    1774                 :     {
    1775                 :       // Allow C++ callers to access the storage
    1776             172 :       if (!aPrincipal)
    1777               0 :         return true;
    1778                 : 
    1779                 :       // Allow more powerful principals (e.g. system) to access the storage
    1780                 :       bool subsumes;
    1781             172 :       nsresult rv = aPrincipal->SubsumesIgnoringDomain(mPrincipal, &subsumes);
    1782             172 :       if (NS_FAILED(rv))
    1783               0 :         return false;
    1784                 : 
    1785             172 :       return subsumes;
    1786                 :     }
    1787                 : 
    1788                 :   case nsPIDOMStorage::GlobalStorage:
    1789                 :     {
    1790                 :       // Allow C++/system callers to access the storage
    1791               0 :       if (CanAccessSystem(aPrincipal))
    1792               0 :         return true;
    1793                 : 
    1794               0 :       nsCAutoString domain;
    1795               0 :       nsCOMPtr<nsIURI> unused;
    1796                 :       nsresult rv = GetPrincipalURIAndHost(aPrincipal,
    1797               0 :                                            getter_AddRefs(unused), domain);
    1798               0 :       NS_ENSURE_SUCCESS(rv, false);
    1799                 : 
    1800               0 :       return domain.Equals(mStorageImpl->mDomain);
    1801                 :     }
    1802                 : 
    1803                 :   default:
    1804               0 :     return false;
    1805                 :   }
    1806                 : 
    1807                 :   return false;
    1808                 : }
    1809                 : 
    1810                 : nsPIDOMStorage::nsDOMStorageType
    1811               0 : nsDOMStorage::StorageType()
    1812                 : {
    1813               0 :   return mStorageType;
    1814                 : }
    1815                 : 
    1816                 : void
    1817               0 : nsDOMStorage::BroadcastChangeNotification(const nsSubstring &aKey,
    1818                 :                                           const nsSubstring &aOldValue,
    1819                 :                                           const nsSubstring &aNewValue)
    1820                 : {
    1821                 :   nsCOMPtr<nsIObserverService> observerService =
    1822               0 :     mozilla::services::GetObserverService();
    1823               0 :   if (!observerService) {
    1824                 :     return;
    1825                 :   }
    1826                 : 
    1827                 :   // Fire off a notification that a storage object changed. If the
    1828                 :   // storage object is a session storage object, we don't pass a
    1829                 :   // domain, but if it's a global storage object we do.
    1830               0 :   observerService->NotifyObservers((nsIDOMStorageObsolete *)this,
    1831                 :                                    "dom-storage-changed",
    1832               0 :                                    NS_ConvertUTF8toUTF16(mStorageImpl->mDomain).get());
    1833                 : }
    1834                 : 
    1835                 : //
    1836                 : // nsDOMStorage2
    1837                 : //
    1838                 : 
    1839            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMStorage2)
    1840               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMStorage2)
    1841               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mStorage)
    1842               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    1843               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMStorage2)
    1844               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mStorage, nsIDOMStorageObsolete)
    1845               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    1846                 : 
    1847                 : DOMCI_DATA(Storage, nsDOMStorage2)
    1848                 : 
    1849             262 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMStorage2)
    1850             282 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMStorage2)
    1851             596 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMStorage2)
    1852             434 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMStorage)
    1853             414 :   NS_INTERFACE_MAP_ENTRY(nsIDOMStorage)
    1854             222 :   NS_INTERFACE_MAP_ENTRY(nsPIDOMStorage)
    1855             222 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Storage)
    1856             202 : NS_INTERFACE_MAP_END
    1857                 : 
    1858              20 : nsDOMStorage2::nsDOMStorage2()
    1859                 : {
    1860              20 : }
    1861                 : 
    1862               0 : nsDOMStorage2::nsDOMStorage2(nsDOMStorage2& aThat)
    1863                 : {
    1864               0 :   mStorage = new nsDOMStorage(*aThat.mStorage.get());
    1865               0 :   mPrincipal = aThat.mPrincipal;
    1866               0 : }
    1867                 : 
    1868                 : nsresult
    1869               0 : nsDOMStorage2::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI)
    1870                 : {
    1871               0 :   mStorage = new nsDOMStorage();
    1872               0 :   if (!mStorage)
    1873               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1874                 : 
    1875               0 :   mPrincipal = aPrincipal;
    1876               0 :   mDocumentURI = aDocumentURI;
    1877                 : 
    1878               0 :   return mStorage->InitAsSessionStorage(aPrincipal, aDocumentURI);
    1879                 : }
    1880                 : 
    1881                 : nsresult
    1882              20 : nsDOMStorage2::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI)
    1883                 : {
    1884              20 :   mStorage = new nsDOMStorage();
    1885              20 :   if (!mStorage)
    1886               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1887                 : 
    1888              20 :   mPrincipal = aPrincipal;
    1889              20 :   mDocumentURI = aDocumentURI;
    1890                 : 
    1891              20 :   return mStorage->InitAsLocalStorage(aPrincipal, aDocumentURI);
    1892                 : }
    1893                 : 
    1894                 : nsresult
    1895               0 : nsDOMStorage2::InitAsGlobalStorage(const nsACString &aDomainDemanded)
    1896                 : {
    1897               0 :   NS_ASSERTION(false, "Should not initialize nsDOMStorage2 as global storage.");
    1898               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    1899                 : }
    1900                 : 
    1901                 : already_AddRefed<nsIDOMStorage>
    1902               0 : nsDOMStorage2::Clone()
    1903                 : {
    1904               0 :   nsDOMStorage2* storage = new nsDOMStorage2(*this);
    1905               0 :   if (!storage)
    1906               0 :     return nsnull;
    1907                 : 
    1908               0 :   storage->mStorage->CloneFrom(mStorage);
    1909               0 :   NS_ADDREF(storage);
    1910                 : 
    1911               0 :   return storage;
    1912                 : }
    1913                 : 
    1914                 : already_AddRefed<nsIDOMStorage>
    1915               0 : nsDOMStorage2::Fork(const nsSubstring &aDocumentURI)
    1916                 : {
    1917               0 :   nsRefPtr<nsDOMStorage2> storage = new nsDOMStorage2();
    1918               0 :   if (!storage)
    1919               0 :     return nsnull;
    1920                 : 
    1921               0 :   nsresult rv = storage->InitAsSessionStorageFork(mPrincipal, aDocumentURI, mStorage);
    1922               0 :   if (NS_FAILED(rv))
    1923               0 :     return nsnull;
    1924                 : 
    1925               0 :   nsIDOMStorage* result = static_cast<nsIDOMStorage*>(storage.get());
    1926               0 :   storage.forget();
    1927               0 :   return result;
    1928                 : }
    1929                 : 
    1930               0 : bool nsDOMStorage2::IsForkOf(nsIDOMStorage* aThat)
    1931                 : {
    1932               0 :   if (!aThat)
    1933               0 :     return false;
    1934                 : 
    1935               0 :   nsDOMStorage2* storage = static_cast<nsDOMStorage2*>(aThat);
    1936               0 :   return mStorage == storage->mStorage;
    1937                 : }
    1938                 : 
    1939                 : nsresult
    1940               0 : nsDOMStorage2::InitAsSessionStorageFork(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI, nsIDOMStorageObsolete* aStorage)
    1941                 : {
    1942               0 :   mPrincipal = aPrincipal;
    1943               0 :   mDocumentURI = aDocumentURI;
    1944               0 :   mStorage = static_cast<nsDOMStorage*>(aStorage);
    1945                 : 
    1946               0 :   return NS_OK;
    1947                 : }
    1948                 : 
    1949                 : nsTArray<nsString> *
    1950               0 : nsDOMStorage2::GetKeys()
    1951                 : {
    1952               0 :   return mStorage->GetKeys();
    1953                 : }
    1954                 : 
    1955                 : nsIPrincipal*
    1956               0 : nsDOMStorage2::Principal()
    1957                 : {
    1958               0 :   return mPrincipal;
    1959                 : }
    1960                 : 
    1961                 : bool
    1962               0 : nsDOMStorage2::CanAccess(nsIPrincipal *aPrincipal)
    1963                 : {
    1964               0 :   return mStorage->CanAccess(aPrincipal);
    1965                 : }
    1966                 : 
    1967                 : nsPIDOMStorage::nsDOMStorageType
    1968               0 : nsDOMStorage2::StorageType()
    1969                 : {
    1970               0 :   if (mStorage)
    1971               0 :     return mStorage->StorageType();
    1972                 : 
    1973               0 :   return nsPIDOMStorage::Unknown;
    1974                 : }
    1975                 : 
    1976                 : namespace {
    1977                 : 
    1978                 : class StorageNotifierRunnable : public nsRunnable
    1979             120 : {
    1980                 : public:
    1981              30 :   StorageNotifierRunnable(nsISupports* aSubject)
    1982              30 :     : mSubject(aSubject)
    1983              30 :   { }
    1984                 : 
    1985                 :   NS_DECL_NSIRUNNABLE
    1986                 : 
    1987                 : private:
    1988                 :   nsCOMPtr<nsISupports> mSubject;
    1989                 : };
    1990                 : 
    1991                 : NS_IMETHODIMP
    1992              30 : StorageNotifierRunnable::Run()
    1993                 : {
    1994                 :   nsCOMPtr<nsIObserverService> observerService =
    1995              60 :     mozilla::services::GetObserverService();
    1996              30 :   if (observerService) {
    1997              30 :     observerService->NotifyObservers(mSubject, "dom-storage2-changed", nsnull);
    1998                 :   }
    1999              30 :   return NS_OK;
    2000                 : }
    2001                 : 
    2002                 : } // anonymous namespace
    2003                 : 
    2004                 : void
    2005              30 : nsDOMStorage2::BroadcastChangeNotification(const nsSubstring &aKey,
    2006                 :                                           const nsSubstring &aOldValue,
    2007                 :                                           const nsSubstring &aNewValue)
    2008                 : {
    2009                 :   nsresult rv;
    2010              60 :   nsCOMPtr<nsIDOMStorageEvent> event = new nsDOMStorageEvent();
    2011              60 :   rv = event->InitStorageEvent(NS_LITERAL_STRING("storage"),
    2012                 :                                false,
    2013                 :                                false,
    2014                 :                                aKey,
    2015                 :                                aOldValue,
    2016                 :                                aNewValue,
    2017                 :                                mDocumentURI,
    2018              30 :                                static_cast<nsIDOMStorage*>(this));
    2019              30 :   if (NS_FAILED(rv)) {
    2020                 :     return;
    2021                 :   }
    2022                 : 
    2023              90 :   nsRefPtr<StorageNotifierRunnable> r = new StorageNotifierRunnable(event);
    2024              30 :   NS_DispatchToMainThread(r);
    2025                 : }
    2026                 : 
    2027                 : NS_IMETHODIMP
    2028              44 : nsDOMStorage2::GetLength(PRUint32 *aLength)
    2029                 : {
    2030              44 :   return mStorage->GetLength(aLength);
    2031                 : }
    2032                 : 
    2033                 : NS_IMETHODIMP
    2034              24 : nsDOMStorage2::Key(PRUint32 aIndex, nsAString& aKey)
    2035                 : {
    2036              24 :   return mStorage->Key(aIndex, aKey);
    2037                 : }
    2038                 : 
    2039                 : NS_IMETHODIMP
    2040              44 : nsDOMStorage2::GetItem(const nsAString& aKey, nsAString &aData)
    2041                 : {
    2042              44 :   return mStorage->GetItem(aKey, aData);
    2043                 : }
    2044                 : 
    2045                 : NS_IMETHODIMP
    2046              18 : nsDOMStorage2::SetItem(const nsAString& aKey, const nsAString& aData)
    2047                 : {
    2048              18 :   mStorage->mEventBroadcaster = this;
    2049              18 :   return mStorage->SetItem(aKey, aData);
    2050                 : }
    2051                 : 
    2052                 : NS_IMETHODIMP
    2053               6 : nsDOMStorage2::RemoveItem(const nsAString& aKey)
    2054                 : {
    2055               6 :   mStorage->mEventBroadcaster = this;
    2056               6 :   return mStorage->RemoveItem(aKey);
    2057                 : }
    2058                 : 
    2059                 : NS_IMETHODIMP
    2060               6 : nsDOMStorage2::Clear()
    2061                 : {
    2062               6 :   mStorage->mEventBroadcaster = this;
    2063               6 :   return mStorage->Clear();
    2064                 : }
    2065                 : 
    2066                 : //
    2067                 : // nsDOMStorageList
    2068                 : //
    2069                 : 
    2070                 : DOMCI_DATA(StorageList, nsDOMStorageList)
    2071                 : 
    2072               0 : NS_INTERFACE_MAP_BEGIN(nsDOMStorageList)
    2073               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
    2074               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMStorageList)
    2075               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(StorageList)
    2076               0 : NS_INTERFACE_MAP_END
    2077                 : 
    2078               0 : NS_IMPL_ADDREF(nsDOMStorageList)
    2079               0 : NS_IMPL_RELEASE(nsDOMStorageList)
    2080                 : 
    2081                 : nsIDOMStorageObsolete*
    2082               0 : nsDOMStorageList::GetNamedItem(const nsAString& aDomain, nsresult* aResult)
    2083                 : {
    2084               0 :   nsCAutoString requestedDomain;
    2085                 : 
    2086                 :   // Normalize the requested domain
    2087               0 :   nsCOMPtr<nsIIDNService> idn = do_GetService(NS_IDNSERVICE_CONTRACTID);
    2088               0 :   if (idn) {
    2089               0 :     *aResult = idn->ConvertUTF8toACE(NS_ConvertUTF16toUTF8(aDomain),
    2090               0 :                                      requestedDomain);
    2091               0 :     NS_ENSURE_SUCCESS(*aResult, nsnull);
    2092                 :   } else {
    2093                 :     // Don't have the IDN service, best we can do is URL escape.
    2094               0 :     NS_EscapeURL(NS_ConvertUTF16toUTF8(aDomain),
    2095                 :                  esc_OnlyNonASCII | esc_AlwaysCopy,
    2096               0 :                  requestedDomain);
    2097                 :   }
    2098               0 :   ToLowerCase(requestedDomain);
    2099                 : 
    2100               0 :   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
    2101               0 :   if (!ssm) {
    2102               0 :     *aResult = NS_ERROR_FAILURE;
    2103               0 :     return nsnull;
    2104                 :   }
    2105                 : 
    2106               0 :   nsCOMPtr<nsIPrincipal> subjectPrincipal;
    2107               0 :   *aResult = ssm->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
    2108               0 :   NS_ENSURE_SUCCESS(*aResult, nsnull);
    2109                 : 
    2110               0 :   nsCAutoString currentDomain;
    2111               0 :   if (subjectPrincipal) {
    2112               0 :     nsCOMPtr<nsIURI> unused;
    2113               0 :     *aResult = GetPrincipalURIAndHost(subjectPrincipal, getter_AddRefs(unused),
    2114               0 :                                       currentDomain);
    2115               0 :     NS_ENSURE_SUCCESS(*aResult, nsnull);
    2116                 : 
    2117                 :     bool sessionOnly;
    2118               0 :     if (!nsDOMStorage::CanUseStorage(&sessionOnly)) {
    2119               0 :       *aResult = NS_ERROR_DOM_SECURITY_ERR;
    2120               0 :       return nsnull;
    2121                 :     }
    2122                 :   }
    2123                 : 
    2124               0 :   bool isSystem = nsContentUtils::IsCallerTrustedForRead();
    2125               0 :   if (currentDomain.IsEmpty() && !isSystem) {
    2126               0 :     *aResult = NS_ERROR_DOM_SECURITY_ERR;
    2127               0 :     return nsnull;
    2128                 :   }
    2129                 : 
    2130                 :   return GetStorageForDomain(requestedDomain,
    2131               0 :                              currentDomain, isSystem, aResult);
    2132                 : }
    2133                 : 
    2134                 : NS_IMETHODIMP
    2135               0 : nsDOMStorageList::NamedItem(const nsAString& aDomain,
    2136                 :                             nsIDOMStorageObsolete** aStorage)
    2137                 : {
    2138                 :   nsresult rv;
    2139               0 :   NS_IF_ADDREF(*aStorage = GetNamedItem(aDomain, &rv));
    2140               0 :   return rv;
    2141                 : }
    2142                 : 
    2143                 : // static
    2144                 : bool
    2145               0 : nsDOMStorageList::CanAccessDomain(const nsACString& aRequestedDomain,
    2146                 :                                   const nsACString& aCurrentDomain)
    2147                 : {
    2148               0 :   return aRequestedDomain.Equals(aCurrentDomain);
    2149                 : }
    2150                 : 
    2151                 : nsIDOMStorageObsolete*
    2152               0 : nsDOMStorageList::GetStorageForDomain(const nsACString& aRequestedDomain,
    2153                 :                                       const nsACString& aCurrentDomain,
    2154                 :                                       bool aNoCurrentDomainCheck,
    2155                 :                                       nsresult* aResult)
    2156                 : {
    2157               0 :   nsTArray<nsCString> requestedDomainArray;
    2158               0 :   if ((!aNoCurrentDomainCheck &&
    2159               0 :        !CanAccessDomain(aRequestedDomain, aCurrentDomain)) ||
    2160               0 :     !ConvertDomainToArray(aRequestedDomain, &requestedDomainArray)) {
    2161               0 :     *aResult = NS_ERROR_DOM_SECURITY_ERR;
    2162                 : 
    2163               0 :     return nsnull;
    2164                 :   }
    2165                 : 
    2166                 :   // now rebuild a string for the domain.
    2167               0 :   nsCAutoString usedDomain;
    2168               0 :   PRUint32 requestedPos = 0;
    2169               0 :   for (requestedPos = 0; requestedPos < requestedDomainArray.Length();
    2170                 :        requestedPos++) {
    2171               0 :     if (!usedDomain.IsEmpty())
    2172               0 :       usedDomain.Append('.');
    2173               0 :     usedDomain.Append(requestedDomainArray[requestedPos]);
    2174                 :   }
    2175                 : 
    2176               0 :   *aResult = NS_OK;
    2177                 : 
    2178                 :   // now have a valid domain, so look it up in the storage table
    2179               0 :   nsIDOMStorageObsolete* storage = mStorages.GetWeak(usedDomain);
    2180               0 :   if (!storage) {
    2181               0 :     nsRefPtr<nsDOMStorage> newstorage;
    2182               0 :     newstorage = new nsDOMStorage();
    2183               0 :     if (newstorage && mStorages.Put(usedDomain, newstorage)) {
    2184               0 :       *aResult = newstorage->InitAsGlobalStorage(usedDomain);
    2185               0 :       if (NS_FAILED(*aResult)) {
    2186               0 :         mStorages.Remove(usedDomain);
    2187               0 :         return nsnull;
    2188                 :       }
    2189               0 :       storage = newstorage;
    2190                 :     }
    2191                 :     else {
    2192               0 :       *aResult = NS_ERROR_OUT_OF_MEMORY;
    2193                 :     }
    2194                 :   }
    2195                 : 
    2196               0 :   return storage;
    2197                 : }
    2198                 : 
    2199                 : // static
    2200                 : bool
    2201               0 : nsDOMStorageList::ConvertDomainToArray(const nsACString& aDomain,
    2202                 :                                        nsTArray<nsCString> *aArray)
    2203                 : {
    2204               0 :   PRInt32 length = aDomain.Length();
    2205               0 :   PRInt32 n = 0;
    2206               0 :   while (n < length) {
    2207               0 :     PRInt32 dotpos = aDomain.FindChar('.', n);
    2208               0 :     nsCAutoString domain;
    2209                 : 
    2210               0 :     if (dotpos == -1) // no more dots
    2211               0 :       domain.Assign(Substring(aDomain, n));
    2212               0 :     else if (dotpos - n == 0) // no point continuing in this case
    2213               0 :       return false;
    2214               0 :     else if (dotpos >= 0)
    2215               0 :       domain.Assign(Substring(aDomain, n, dotpos - n));
    2216                 : 
    2217               0 :     ToLowerCase(domain);
    2218               0 :     aArray->AppendElement(domain);
    2219                 : 
    2220               0 :     if (dotpos == -1)
    2221                 :       break;
    2222                 : 
    2223               0 :     n = dotpos + 1;
    2224                 :   }
    2225                 : 
    2226                 :   // if n equals the length, there is a dot at the end, so treat it as invalid
    2227               0 :   return (n != length);
    2228                 : }
    2229                 : 
    2230                 : nsresult
    2231               0 : NS_NewDOMStorageList(nsIDOMStorageList** aResult)
    2232                 : {
    2233               0 :   *aResult = new nsDOMStorageList();
    2234               0 :   if (!*aResult)
    2235               0 :     return NS_ERROR_OUT_OF_MEMORY;
    2236                 : 
    2237               0 :   NS_ADDREF(*aResult);
    2238               0 :   return NS_OK;
    2239                 : }
    2240                 : 
    2241                 : //
    2242                 : // nsDOMStorageItem
    2243                 : //
    2244                 : 
    2245            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMStorageItem)
    2246               4 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMStorageItem)
    2247                 :   {
    2248               4 :     tmp->mStorage = nsnull;
    2249                 :   }
    2250               4 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    2251               4 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMStorageItem)
    2252                 :   {
    2253               4 :     cb.NoteXPCOMChild((nsISupports*) tmp->mStorage);
    2254                 :   }
    2255               4 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    2256                 : 
    2257             116 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMStorageItem)
    2258             116 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMStorageItem)
    2259                 : 
    2260                 : DOMCI_DATA(StorageItem, nsDOMStorageItem)
    2261                 : 
    2262             102 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMStorageItem)
    2263              30 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMStorageItem)
    2264              30 :   NS_INTERFACE_MAP_ENTRY(nsIDOMStorageItem)
    2265               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMToString)
    2266               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(StorageItem)
    2267               0 : NS_INTERFACE_MAP_END
    2268                 : 
    2269              34 : nsDOMStorageItem::nsDOMStorageItem(DOMStorageBase* aStorage,
    2270                 :                                    const nsAString& aKey,
    2271                 :                                    const nsAString& aValue,
    2272                 :                                    bool aSecure)
    2273                 :   : mSecure(aSecure),
    2274                 :     mKey(aKey),
    2275                 :     mValue(aValue),
    2276              34 :     mStorage(aStorage)
    2277                 : {
    2278              34 : }
    2279                 : 
    2280              68 : nsDOMStorageItem::~nsDOMStorageItem()
    2281                 : {
    2282             136 : }
    2283                 : 
    2284                 : NS_IMETHODIMP
    2285               0 : nsDOMStorageItem::GetSecure(bool* aSecure)
    2286                 : {
    2287               0 :   if (!mStorage->CacheStoragePermissions() || !IsCallerSecure()) {
    2288               0 :     return NS_ERROR_DOM_INVALID_ACCESS_ERR;
    2289                 :   }
    2290                 : 
    2291               0 :   if (mStorage->UseDB()) {
    2292               0 :     nsAutoString value;
    2293               0 :     return mStorage->GetDBValue(mKey, value, aSecure);
    2294                 :   }
    2295                 : 
    2296               0 :   *aSecure = IsSecure();
    2297               0 :   return NS_OK;
    2298                 : }
    2299                 : 
    2300                 : NS_IMETHODIMP
    2301               0 : nsDOMStorageItem::SetSecure(bool aSecure)
    2302                 : {
    2303               0 :   if (!mStorage->CacheStoragePermissions() || !IsCallerSecure()) {
    2304               0 :     return NS_ERROR_DOM_INVALID_ACCESS_ERR;
    2305                 :   }
    2306                 : 
    2307               0 :   if (mStorage->UseDB()) {
    2308               0 :     nsresult rv = mStorage->SetSecure(mKey, aSecure);
    2309               0 :     NS_ENSURE_SUCCESS(rv, rv);
    2310                 :   }
    2311                 : 
    2312               0 :   mSecure = aSecure;
    2313               0 :   return NS_OK;
    2314                 : }
    2315                 : 
    2316                 : NS_IMETHODIMP
    2317              30 : nsDOMStorageItem::GetValue(nsAString& aValue)
    2318                 : {
    2319              30 :   if (!mStorage->CacheStoragePermissions())
    2320               0 :     return NS_ERROR_DOM_INVALID_ACCESS_ERR;
    2321                 : 
    2322              30 :   if (mStorage->UseDB()) {
    2323                 :     bool secure;
    2324              30 :     nsresult rv = mStorage->GetDBValue(mKey, aValue, &secure);
    2325              30 :     if (rv == NS_ERROR_DOM_NOT_FOUND_ERR)
    2326               4 :       return NS_OK;
    2327              26 :     if (NS_SUCCEEDED(rv) && !IsCallerSecure() && secure)
    2328               0 :       return NS_ERROR_DOM_SECURITY_ERR;
    2329              26 :     return rv;
    2330                 :   }
    2331                 : 
    2332               0 :   if (IsSecure() && !IsCallerSecure()) {
    2333               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    2334                 :   }
    2335                 : 
    2336               0 :   aValue = mValue;
    2337               0 :   return NS_OK;
    2338                 : }
    2339                 : 
    2340                 : NS_IMETHODIMP
    2341               0 : nsDOMStorageItem::SetValue(const nsAString& aValue)
    2342                 : {
    2343               0 :   if (!mStorage->CacheStoragePermissions())
    2344               0 :     return NS_ERROR_DOM_INVALID_ACCESS_ERR;
    2345                 : 
    2346               0 :   bool secureCaller = IsCallerSecure();
    2347                 : 
    2348               0 :   if (mStorage->UseDB()) {
    2349                 :     // SetDBValue() does the security checks for us.
    2350               0 :     return mStorage->SetDBValue(mKey, aValue, secureCaller);
    2351                 :   }
    2352                 : 
    2353               0 :   bool secureItem = IsSecure();
    2354                 : 
    2355               0 :   if (!secureCaller && secureItem) {
    2356                 :     // The item is secure, but the caller isn't. Throw.
    2357               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    2358                 :   }
    2359                 : 
    2360               0 :   mValue = aValue;
    2361               0 :   mSecure = secureCaller;
    2362               0 :   return NS_OK;
    2363                 : }
    2364                 : 
    2365                 : NS_IMETHODIMP
    2366               0 : nsDOMStorageItem::ToString(nsAString& aStr)
    2367                 : {
    2368               0 :   return GetValue(aStr);
    2369                 : }
    2370                 : 
    2371                 : // Cycle collection implementation for nsDOMStorageEvent
    2372            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMStorageEvent)
    2373                 : 
    2374               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMStorageEvent, nsDOMEvent)
    2375               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mStorageArea)
    2376               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    2377                 : 
    2378               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMStorageEvent, nsDOMEvent)
    2379               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mStorageArea)
    2380               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    2381                 : 
    2382              90 : NS_IMPL_ADDREF_INHERITED(nsDOMStorageEvent, nsDOMEvent)
    2383              90 : NS_IMPL_RELEASE_INHERITED(nsDOMStorageEvent, nsDOMEvent)
    2384                 : 
    2385                 : DOMCI_DATA(StorageEvent, nsDOMStorageEvent)
    2386                 : 
    2387                 : // QueryInterface implementation for nsDOMStorageEvent
    2388              90 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMStorageEvent)
    2389              30 :   NS_INTERFACE_MAP_ENTRY(nsIDOMStorageEvent)
    2390               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(StorageEvent)
    2391               0 : NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
    2392                 : 
    2393                 : 
    2394                 : /* readonly attribute DOMString key; */
    2395               0 : NS_IMETHODIMP nsDOMStorageEvent::GetKey(nsAString & aKey)
    2396                 : {
    2397               0 :   aKey = mKey;
    2398               0 :   return NS_OK;
    2399                 : }
    2400                 : 
    2401                 : /* readonly attribute DOMString oldValue; */
    2402               0 : NS_IMETHODIMP nsDOMStorageEvent::GetOldValue(nsAString & aOldValue)
    2403                 : {
    2404               0 :   aOldValue = mOldValue;
    2405               0 :   return NS_OK;
    2406                 : }
    2407                 : 
    2408                 : /* readonly attribute DOMString newValue; */
    2409               0 : NS_IMETHODIMP nsDOMStorageEvent::GetNewValue(nsAString & aNewValue)
    2410                 : {
    2411               0 :   aNewValue = mNewValue;
    2412               0 :   return NS_OK;
    2413                 : }
    2414                 : 
    2415                 : /* readonly attribute DOMString url; */
    2416               0 : NS_IMETHODIMP nsDOMStorageEvent::GetUrl(nsAString & aUrl)
    2417                 : {
    2418               0 :   aUrl = mUrl;
    2419               0 :   return NS_OK;
    2420                 : }
    2421                 : 
    2422                 : /* readonly attribute nsIDOMStorage storageArea; */
    2423               0 : NS_IMETHODIMP nsDOMStorageEvent::GetStorageArea(nsIDOMStorage * *aStorageArea)
    2424                 : {
    2425               0 :   NS_ENSURE_ARG_POINTER(aStorageArea);
    2426                 : 
    2427               0 :   NS_IF_ADDREF(*aStorageArea = mStorageArea);
    2428               0 :   return NS_OK;
    2429                 : }
    2430                 : 
    2431                 : /* void initStorageEvent (in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString keyArg, in DOMString oldValueArg, in DOMString newValueArg, in DOMString urlArg, in nsIDOMStorage storageAreaArg); */
    2432              30 : NS_IMETHODIMP nsDOMStorageEvent::InitStorageEvent(const nsAString & typeArg,
    2433                 :                                                   bool canBubbleArg,
    2434                 :                                                   bool cancelableArg,
    2435                 :                                                   const nsAString & keyArg,
    2436                 :                                                   const nsAString & oldValueArg,
    2437                 :                                                   const nsAString & newValueArg,
    2438                 :                                                   const nsAString & urlArg,
    2439                 :                                                   nsIDOMStorage *storageAreaArg)
    2440                 : {
    2441                 :   nsresult rv;
    2442                 : 
    2443              30 :   rv = InitEvent(typeArg, canBubbleArg, cancelableArg);
    2444              30 :   NS_ENSURE_SUCCESS(rv, rv);
    2445                 : 
    2446              30 :   mKey = keyArg;
    2447              30 :   mOldValue = oldValueArg;
    2448              30 :   mNewValue = newValueArg;
    2449              30 :   mUrl = urlArg;
    2450              30 :   mStorageArea = storageAreaArg;
    2451                 : 
    2452              30 :   return NS_OK;
    2453                 : }
    2454                 : 
    2455                 : nsresult
    2456               0 : nsDOMStorageEvent::InitFromCtor(const nsAString& aType,
    2457                 :                                 JSContext* aCx, jsval* aVal)
    2458                 : {
    2459               0 :   mozilla::dom::StorageEventInit d;
    2460               0 :   nsresult rv = d.Init(aCx, aVal);
    2461               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2462                 :   return InitStorageEvent(aType, d.bubbles, d.cancelable, d.key, d.oldValue,
    2463               0 :                           d.newValue, d.url, d.storageArea);
    2464                 : }
    2465                 : 
    2466                 : // Obsolete globalStorage event
    2467                 : 
    2468                 : DOMCI_DATA(StorageEventObsolete, nsDOMStorageEventObsolete)
    2469                 : 
    2470                 : // QueryInterface implementation for nsDOMStorageEventObsolete
    2471               0 : NS_INTERFACE_MAP_BEGIN(nsDOMStorageEventObsolete)
    2472               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMStorageEventObsolete)
    2473               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(StorageEventObsolete)
    2474               0 : NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
    2475                 : 
    2476               0 : NS_IMPL_ADDREF_INHERITED(nsDOMStorageEventObsolete, nsDOMEvent)
    2477               0 : NS_IMPL_RELEASE_INHERITED(nsDOMStorageEventObsolete, nsDOMEvent)
    2478                 : 
    2479                 : 
    2480                 : NS_IMETHODIMP
    2481               0 : nsDOMStorageEventObsolete::GetDomain(nsAString& aDomain)
    2482                 : {
    2483                 :   // mDomain will be #session for session storage for events that fire
    2484                 :   // due to a change in a session storage object.
    2485               0 :   aDomain = mDomain;
    2486                 : 
    2487               0 :   return NS_OK;
    2488                 : }
    2489                 : 
    2490                 : NS_IMETHODIMP
    2491               0 : nsDOMStorageEventObsolete::InitStorageEvent(const nsAString& aTypeArg,
    2492                 :                                     bool aCanBubbleArg,
    2493                 :                                     bool aCancelableArg,
    2494                 :                                     const nsAString& aDomainArg)
    2495                 : {
    2496               0 :   nsresult rv = InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
    2497               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2498                 : 
    2499               0 :   mDomain = aDomainArg;
    2500                 : 
    2501               0 :   return NS_OK;
    2502            4392 : }

Generated by: LCOV version 1.7