LCOV - code coverage report
Current view: top level - dom/storage - LocalStorage.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 10 108 9.3 %
Date: 2017-07-14 16:53:18 Functions: 4 21 19.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "LocalStorage.h"
       8             : #include "LocalStorageCache.h"
       9             : #include "LocalStorageManager.h"
      10             : #include "StorageUtils.h"
      11             : 
      12             : #include "nsIObserverService.h"
      13             : #include "nsIScriptSecurityManager.h"
      14             : #include "nsIPermissionManager.h"
      15             : #include "nsIPrincipal.h"
      16             : #include "nsICookiePermission.h"
      17             : 
      18             : #include "mozilla/dom/ContentChild.h"
      19             : #include "mozilla/dom/ContentParent.h"
      20             : #include "mozilla/dom/PermissionMessageUtils.h"
      21             : #include "mozilla/dom/StorageBinding.h"
      22             : #include "mozilla/dom/StorageEvent.h"
      23             : #include "mozilla/dom/StorageEventBinding.h"
      24             : #include "mozilla/Services.h"
      25             : #include "mozilla/Preferences.h"
      26             : #include "mozilla/EnumSet.h"
      27             : #include "nsThreadUtils.h"
      28             : #include "nsContentUtils.h"
      29             : #include "nsServiceManagerUtils.h"
      30             : 
      31             : namespace mozilla {
      32             : 
      33             : using namespace ipc;
      34             : 
      35             : namespace dom {
      36             : 
      37           0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(LocalStorage, Storage, mManager);
      38             : 
      39           3 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(LocalStorage)
      40           2 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
      41           2 : NS_INTERFACE_MAP_END_INHERITING(Storage)
      42             : 
      43           4 : NS_IMPL_ADDREF_INHERITED(LocalStorage, Storage)
      44           3 : NS_IMPL_RELEASE_INHERITED(LocalStorage, Storage)
      45             : 
      46           1 : LocalStorage::LocalStorage(nsPIDOMWindowInner* aWindow,
      47             :                            LocalStorageManager* aManager,
      48             :                            LocalStorageCache* aCache,
      49             :                            const nsAString& aDocumentURI,
      50             :                            nsIPrincipal* aPrincipal,
      51           1 :                            bool aIsPrivate)
      52             :   : Storage(aWindow, aPrincipal)
      53             :   , mManager(aManager)
      54             :   , mCache(aCache)
      55             :   , mDocumentURI(aDocumentURI)
      56           1 :   , mIsPrivate(aIsPrivate)
      57             : {
      58           1 :   mCache->Preload();
      59           1 : }
      60             : 
      61           0 : LocalStorage::~LocalStorage()
      62             : {
      63           0 : }
      64             : 
      65             : int64_t
      66           0 : LocalStorage::GetOriginQuotaUsage() const
      67             : {
      68           0 :   return mCache->GetOriginQuotaUsage(this);
      69             : }
      70             : 
      71             : uint32_t
      72           0 : LocalStorage::GetLength(nsIPrincipal& aSubjectPrincipal,
      73             :                         ErrorResult& aRv)
      74             : {
      75           0 :   if (!CanUseStorage(aSubjectPrincipal)) {
      76           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
      77           0 :     return 0;
      78             :   }
      79             : 
      80             :   uint32_t length;
      81           0 :   aRv = mCache->GetLength(this, &length);
      82           0 :   return length;
      83             : }
      84             : 
      85             : void
      86           0 : LocalStorage::Key(uint32_t aIndex, nsAString& aResult,
      87             :                   nsIPrincipal& aSubjectPrincipal,
      88             :                   ErrorResult& aRv)
      89             : {
      90           0 :   if (!CanUseStorage(aSubjectPrincipal)) {
      91           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
      92           0 :     return;
      93             :   }
      94             : 
      95           0 :   aRv = mCache->GetKey(this, aIndex, aResult);
      96             : }
      97             : 
      98             : void
      99           0 : LocalStorage::GetItem(const nsAString& aKey, nsAString& aResult,
     100             :                       nsIPrincipal& aSubjectPrincipal,
     101             :                       ErrorResult& aRv)
     102             : {
     103           0 :   if (!CanUseStorage(aSubjectPrincipal)) {
     104           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     105           0 :     return;
     106             :   }
     107             : 
     108           0 :   aRv = mCache->GetItem(this, aKey, aResult);
     109             : }
     110             : 
     111             : void
     112           0 : LocalStorage::SetItem(const nsAString& aKey, const nsAString& aData,
     113             :                       nsIPrincipal& aSubjectPrincipal,
     114             :                       ErrorResult& aRv)
     115             : {
     116           0 :   if (!CanUseStorage(aSubjectPrincipal)) {
     117           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     118           0 :     return;
     119             :   }
     120             : 
     121           0 :   nsString data;
     122           0 :   bool ok = data.Assign(aData, fallible);
     123           0 :   if (!ok) {
     124           0 :     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     125           0 :     return;
     126             :   }
     127             : 
     128           0 :   nsString old;
     129           0 :   aRv = mCache->SetItem(this, aKey, data, old);
     130           0 :   if (aRv.Failed()) {
     131           0 :     return;
     132             :   }
     133             : 
     134           0 :   if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) {
     135           0 :     BroadcastChangeNotification(aKey, old, aData);
     136             :   }
     137             : }
     138             : 
     139             : void
     140           0 : LocalStorage::RemoveItem(const nsAString& aKey, nsIPrincipal& aSubjectPrincipal,
     141             :                          ErrorResult& aRv)
     142             : {
     143           0 :   if (!CanUseStorage(aSubjectPrincipal)) {
     144           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     145           0 :     return;
     146             :   }
     147             : 
     148           0 :   nsAutoString old;
     149           0 :   aRv = mCache->RemoveItem(this, aKey, old);
     150           0 :   if (aRv.Failed()) {
     151           0 :     return;
     152             :   }
     153             : 
     154           0 :   if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) {
     155           0 :     BroadcastChangeNotification(aKey, old, NullString());
     156             :   }
     157             : }
     158             : 
     159             : void
     160           0 : LocalStorage::Clear(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv)
     161             : {
     162           0 :   if (!CanUseStorage(aSubjectPrincipal)) {
     163           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     164           0 :     return;
     165             :   }
     166             : 
     167           0 :   aRv = mCache->Clear(this);
     168           0 :   if (NS_WARN_IF(aRv.Failed())) {
     169           0 :     return;
     170             :   }
     171             : 
     172           0 :   if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) {
     173           0 :     BroadcastChangeNotification(NullString(), NullString(), NullString());
     174             :   }
     175             : }
     176             : 
     177             : void
     178           0 : LocalStorage::BroadcastChangeNotification(const nsAString& aKey,
     179             :                                           const nsAString& aOldValue,
     180             :                                           const nsAString& aNewValue)
     181             : {
     182           0 :   if (!XRE_IsParentProcess() && Principal()) {
     183             :     // If we are in a child process, we want to send a message to the parent in
     184             :     // order to broadcast the StorageEvent correctly to any child process.
     185           0 :     dom::ContentChild* cc = dom::ContentChild::GetSingleton();
     186           0 :     Unused << NS_WARN_IF(!cc->SendBroadcastLocalStorageChange(
     187             :       mDocumentURI, nsString(aKey), nsString(aOldValue), nsString(aNewValue),
     188             :       IPC::Principal(Principal()), mIsPrivate));
     189             :   }
     190             : 
     191           0 :   DispatchStorageEvent(mDocumentURI, aKey, aOldValue, aNewValue,
     192           0 :                        Principal(), mIsPrivate, this, false);
     193           0 : }
     194             : 
     195             : /* static */ void
     196           0 : LocalStorage::DispatchStorageEvent(const nsAString& aDocumentURI,
     197             :                                    const nsAString& aKey,
     198             :                                    const nsAString& aOldValue,
     199             :                                    const nsAString& aNewValue,
     200             :                                    nsIPrincipal* aPrincipal,
     201             :                                    bool aIsPrivate,
     202             :                                    Storage* aStorage,
     203             :                                    bool aImmediateDispatch)
     204             : {
     205           0 :   NotifyChange(aStorage, aPrincipal, aKey, aOldValue, aNewValue,
     206           0 :                u"localStorage", aDocumentURI, aIsPrivate, aImmediateDispatch);
     207             : 
     208             :   // If we are in the parent process and we have the principal, we want to
     209             :   // broadcast this event to every other process.
     210           0 :   if (XRE_IsParentProcess() && aPrincipal) {
     211           0 :     for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
     212           0 :       Unused << cp->SendDispatchLocalStorageChange(
     213           0 :         nsString(aDocumentURI), nsString(aKey), nsString(aOldValue),
     214           0 :         nsString(aNewValue), IPC::Principal(aPrincipal), aIsPrivate);
     215             :     }
     216             :   }
     217           0 : }
     218             : 
     219             : void
     220           0 : LocalStorage::ApplyEvent(StorageEvent* aStorageEvent)
     221             : {
     222           0 :   MOZ_ASSERT(aStorageEvent);
     223             : 
     224           0 :   nsAutoString key;
     225           0 :   nsAutoString old;
     226           0 :   nsAutoString value;
     227             : 
     228           0 :   aStorageEvent->GetKey(key);
     229           0 :   aStorageEvent->GetNewValue(value);
     230             : 
     231             :   // No key means clearing the full storage.
     232           0 :   if (key.IsVoid()) {
     233           0 :     MOZ_ASSERT(value.IsVoid());
     234           0 :     mCache->Clear(this, LocalStorageCache::E10sPropagated);
     235           0 :     return;
     236             :   }
     237             : 
     238             :   // No new value means removing the key.
     239           0 :   if (value.IsVoid()) {
     240           0 :     mCache->RemoveItem(this, key, old, LocalStorageCache::E10sPropagated);
     241           0 :     return;
     242             :   }
     243             : 
     244             :   // Otherwise, we set the new value.
     245           0 :   mCache->SetItem(this, key, value, old, LocalStorageCache::E10sPropagated);
     246             : }
     247             : 
     248             : static const char kPermissionType[] = "cookie";
     249             : static const char kStorageEnabled[] = "dom.storage.enabled";
     250             : 
     251             : bool
     252           0 : LocalStorage::PrincipalEquals(nsIPrincipal* aPrincipal)
     253             : {
     254           0 :   return StorageUtils::PrincipalsEqual(mPrincipal, aPrincipal);
     255             : }
     256             : 
     257             : void
     258           0 : LocalStorage::GetSupportedNames(nsTArray<nsString>& aKeys)
     259             : {
     260           0 :   if (!CanUseStorage(*nsContentUtils::SubjectPrincipal())) {
     261             :     // return just an empty array
     262           0 :     aKeys.Clear();
     263           0 :     return;
     264             :   }
     265             : 
     266           0 :   mCache->GetKeys(this, aKeys);
     267             : }
     268             : 
     269             : bool
     270           0 : LocalStorage::IsForkOf(const Storage* aOther) const
     271             : {
     272           0 :   MOZ_ASSERT(aOther);
     273           0 :   if (aOther->Type() != eLocalStorage) {
     274           0 :     return false;
     275             :   }
     276             : 
     277           0 :   return mCache == static_cast<const LocalStorage*>(aOther)->mCache;
     278             : }
     279             : 
     280             : } // namespace dom
     281             : } // namespace mozilla

Generated by: LCOV version 1.13