LCOV - code coverage report
Current view: top level - dom/storage - StorageIPC.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 107 317 33.8 %
Date: 2017-07-14 16:53:18 Functions: 30 71 42.3 %
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 "StorageIPC.h"
       8             : 
       9             : #include "LocalStorageManager.h"
      10             : 
      11             : #include "mozilla/dom/ContentChild.h"
      12             : #include "mozilla/dom/ContentParent.h"
      13             : #include "mozilla/Unused.h"
      14             : #include "nsIDiskSpaceWatcher.h"
      15             : #include "nsThreadUtils.h"
      16             : 
      17             : namespace mozilla {
      18             : namespace dom {
      19             : 
      20             : // ----------------------------------------------------------------------------
      21             : // Child
      22             : // ----------------------------------------------------------------------------
      23             : 
      24           2 : NS_IMPL_ADDREF(StorageDBChild)
      25             : 
      26           0 : NS_IMETHODIMP_(MozExternalRefCountType) StorageDBChild::Release(void)
      27             : {
      28           0 :   NS_PRECONDITION(0 != mRefCnt, "dup release");
      29           0 :   nsrefcnt count = --mRefCnt;
      30           0 :   NS_LOG_RELEASE(this, count, "StorageDBChild");
      31           0 :   if (count == 1 && mIPCOpen) {
      32           0 :     Send__delete__(this);
      33           0 :     return 0;
      34             :   }
      35           0 :   if (count == 0) {
      36           0 :     mRefCnt = 1;
      37           0 :     delete this;
      38           0 :     return 0;
      39             :   }
      40           0 :   return count;
      41             : }
      42             : 
      43             : void
      44           1 : StorageDBChild::AddIPDLReference()
      45             : {
      46           1 :   MOZ_ASSERT(!mIPCOpen, "Attempting to retain multiple IPDL references");
      47           1 :   mIPCOpen = true;
      48           1 :   AddRef();
      49           1 : }
      50             : 
      51             : void
      52           0 : StorageDBChild::ReleaseIPDLReference()
      53             : {
      54           0 :   MOZ_ASSERT(mIPCOpen, "Attempting to release non-existent IPDL reference");
      55           0 :   mIPCOpen = false;
      56           0 :   Release();
      57           0 : }
      58             : 
      59           1 : StorageDBChild::StorageDBChild(LocalStorageManager* aManager)
      60             :   : mManager(aManager)
      61             :   , mStatus(NS_OK)
      62           1 :   , mIPCOpen(false)
      63             : {
      64           1 : }
      65             : 
      66           0 : StorageDBChild::~StorageDBChild()
      67             : {
      68           0 : }
      69             : 
      70             : nsTHashtable<nsCStringHashKey>&
      71           0 : StorageDBChild::OriginsHavingData()
      72             : {
      73           0 :   if (!mOriginsHavingData) {
      74           0 :     mOriginsHavingData = new nsTHashtable<nsCStringHashKey>;
      75             :   }
      76             : 
      77           0 :   return *mOriginsHavingData;
      78             : }
      79             : 
      80             : nsresult
      81           1 : StorageDBChild::Init()
      82             : {
      83           1 :   ContentChild* child = ContentChild::GetSingleton();
      84           1 :   AddIPDLReference();
      85           1 :   child->SendPStorageConstructor(this);
      86           1 :   return NS_OK;
      87             : }
      88             : 
      89             : nsresult
      90           0 : StorageDBChild::Shutdown()
      91             : {
      92             :   // There is nothing to do here, IPC will release automatically and
      93             :   // the actual thread running on the parent process will also stop
      94             :   // automatically in profile-before-change topic observer.
      95           0 :   return NS_OK;
      96             : }
      97             : 
      98             : void
      99           2 : StorageDBChild::AsyncPreload(LocalStorageCacheBridge* aCache, bool aPriority)
     100             : {
     101           2 :   if (mIPCOpen) {
     102             :     // Adding ref to cache for the time of preload.  This ensures a reference to
     103             :     // to the cache and that all keys will load into this cache object.
     104           2 :     mLoadingCaches.PutEntry(aCache);
     105           2 :     SendAsyncPreload(aCache->OriginSuffix(), aCache->OriginNoSuffix(),
     106           2 :                      aPriority);
     107             :   } else {
     108             :     // No IPC, no love.  But the LoadDone call is expected.
     109           0 :     aCache->LoadDone(NS_ERROR_UNEXPECTED);
     110             :   }
     111           2 : }
     112             : 
     113             : void
     114           1 : StorageDBChild::AsyncGetUsage(StorageUsageBridge* aUsage)
     115             : {
     116           1 :   if (mIPCOpen) {
     117           1 :     SendAsyncGetUsage(aUsage->OriginScope());
     118             :   }
     119           1 : }
     120             : 
     121             : void
     122           0 : StorageDBChild::SyncPreload(LocalStorageCacheBridge* aCache, bool aForceSync)
     123             : {
     124           0 :   if (NS_FAILED(mStatus)) {
     125           0 :     aCache->LoadDone(mStatus);
     126           0 :     return;
     127             :   }
     128             : 
     129           0 :   if (!mIPCOpen) {
     130           0 :     aCache->LoadDone(NS_ERROR_UNEXPECTED);
     131           0 :     return;
     132             :   }
     133             : 
     134             :   // There is no way to put the child process to a wait state to receive all
     135             :   // incoming async responses from the parent, hence we have to do a sync
     136             :   // preload instead.  We are smart though, we only demand keys that are left to
     137             :   // load in case the async preload has already loaded some keys.
     138           0 :   InfallibleTArray<nsString> keys, values;
     139             :   nsresult rv;
     140           0 :   SendPreload(aCache->OriginSuffix(), aCache->OriginNoSuffix(),
     141           0 :               aCache->LoadedCount(), &keys, &values, &rv);
     142             : 
     143           0 :   for (uint32_t i = 0; i < keys.Length(); ++i) {
     144           0 :     aCache->LoadItem(keys[i], values[i]);
     145             :   }
     146             : 
     147           0 :   aCache->LoadDone(rv);
     148             : }
     149             : 
     150             : nsresult
     151           0 : StorageDBChild::AsyncAddItem(LocalStorageCacheBridge* aCache,
     152             :                              const nsAString& aKey,
     153             :                              const nsAString& aValue)
     154             : {
     155           0 :   if (NS_FAILED(mStatus) || !mIPCOpen) {
     156           0 :     return mStatus;
     157             :   }
     158             : 
     159           0 :   SendAsyncAddItem(aCache->OriginSuffix(), aCache->OriginNoSuffix(),
     160           0 :                    nsString(aKey), nsString(aValue));
     161           0 :   OriginsHavingData().PutEntry(aCache->Origin());
     162           0 :   return NS_OK;
     163             : }
     164             : 
     165             : nsresult
     166           0 : StorageDBChild::AsyncUpdateItem(LocalStorageCacheBridge* aCache,
     167             :                                 const nsAString& aKey,
     168             :                                 const nsAString& aValue)
     169             : {
     170           0 :   if (NS_FAILED(mStatus) || !mIPCOpen) {
     171           0 :     return mStatus;
     172             :   }
     173             : 
     174           0 :   SendAsyncUpdateItem(aCache->OriginSuffix(), aCache->OriginNoSuffix(),
     175           0 :                       nsString(aKey), nsString(aValue));
     176           0 :   OriginsHavingData().PutEntry(aCache->Origin());
     177           0 :   return NS_OK;
     178             : }
     179             : 
     180             : nsresult
     181           0 : StorageDBChild::AsyncRemoveItem(LocalStorageCacheBridge* aCache,
     182             :                                 const nsAString& aKey)
     183             : {
     184           0 :   if (NS_FAILED(mStatus) || !mIPCOpen) {
     185           0 :     return mStatus;
     186             :   }
     187             : 
     188           0 :   SendAsyncRemoveItem(aCache->OriginSuffix(), aCache->OriginNoSuffix(),
     189           0 :                       nsString(aKey));
     190           0 :   return NS_OK;
     191             : }
     192             : 
     193             : nsresult
     194           0 : StorageDBChild::AsyncClear(LocalStorageCacheBridge* aCache)
     195             : {
     196           0 :   if (NS_FAILED(mStatus) || !mIPCOpen) {
     197           0 :     return mStatus;
     198             :   }
     199             : 
     200           0 :   SendAsyncClear(aCache->OriginSuffix(), aCache->OriginNoSuffix());
     201           0 :   OriginsHavingData().RemoveEntry(aCache->Origin());
     202           0 :   return NS_OK;
     203             : }
     204             : 
     205             : bool
     206           1 : StorageDBChild::ShouldPreloadOrigin(const nsACString& aOrigin)
     207             : {
     208             :   // Return true if we didn't receive the origins list yet.
     209             :   // I tend to rather preserve a bit of early-after-start performance
     210             :   // than a bit of memory here.
     211           1 :   return !mOriginsHavingData || mOriginsHavingData->Contains(aOrigin);
     212             : }
     213             : 
     214             : mozilla::ipc::IPCResult
     215           0 : StorageDBChild::RecvObserve(const nsCString& aTopic,
     216             :                             const nsString& aOriginAttributesPattern,
     217             :                             const nsCString& aOriginScope)
     218             : {
     219           0 :   StorageObserver::Self()->Notify(
     220           0 :     aTopic.get(), aOriginAttributesPattern, aOriginScope);
     221           0 :   return IPC_OK();
     222             : }
     223             : 
     224             : mozilla::ipc::IPCResult
     225           0 : StorageDBChild::RecvOriginsHavingData(nsTArray<nsCString>&& aOrigins)
     226             : {
     227             :   // Force population of mOriginsHavingData even if there are no origins so that
     228             :   // ShouldPreloadOrigin does not generate false positives for all origins.
     229           0 :   if (!aOrigins.Length()) {
     230           0 :     Unused << OriginsHavingData();
     231             :   }
     232             : 
     233           0 :   for (uint32_t i = 0; i < aOrigins.Length(); ++i) {
     234           0 :     OriginsHavingData().PutEntry(aOrigins[i]);
     235             :   }
     236             : 
     237           0 :   return IPC_OK();
     238             : }
     239             : 
     240             : mozilla::ipc::IPCResult
     241           0 : StorageDBChild::RecvLoadItem(const nsCString& aOriginSuffix,
     242             :                              const nsCString& aOriginNoSuffix,
     243             :                              const nsString& aKey,
     244             :                              const nsString& aValue)
     245             : {
     246             :   LocalStorageCache* aCache =
     247           0 :     mManager->GetCache(aOriginSuffix, aOriginNoSuffix);
     248           0 :   if (aCache) {
     249           0 :     aCache->LoadItem(aKey, aValue);
     250             :   }
     251             : 
     252           0 :   return IPC_OK();
     253             : }
     254             : 
     255             : mozilla::ipc::IPCResult
     256           2 : StorageDBChild::RecvLoadDone(const nsCString& aOriginSuffix,
     257             :                              const nsCString& aOriginNoSuffix,
     258             :                              const nsresult& aRv)
     259             : {
     260             :   LocalStorageCache* aCache =
     261           2 :     mManager->GetCache(aOriginSuffix, aOriginNoSuffix);
     262           2 :   if (aCache) {
     263           2 :     aCache->LoadDone(aRv);
     264             : 
     265             :     // Just drop reference to this cache now since the load is done.
     266           2 :     mLoadingCaches.RemoveEntry(static_cast<LocalStorageCacheBridge*>(aCache));
     267             :   }
     268             : 
     269           2 :   return IPC_OK();
     270             : }
     271             : 
     272             : mozilla::ipc::IPCResult
     273           1 : StorageDBChild::RecvLoadUsage(const nsCString& aOriginNoSuffix,
     274             :                               const int64_t& aUsage)
     275             : {
     276             :   RefPtr<StorageUsageBridge> scopeUsage =
     277           2 :     mManager->GetOriginUsage(aOriginNoSuffix);
     278           1 :   scopeUsage->LoadUsage(aUsage);
     279           2 :   return IPC_OK();
     280             : }
     281             : 
     282             : mozilla::ipc::IPCResult
     283           0 : StorageDBChild::RecvError(const nsresult& aRv)
     284             : {
     285           0 :   mStatus = aRv;
     286           0 :   return IPC_OK();
     287             : }
     288             : 
     289             : // ----------------------------------------------------------------------------
     290             : // Parent
     291             : // ----------------------------------------------------------------------------
     292             : 
     293           8 : NS_IMPL_ADDREF(StorageDBParent)
     294           7 : NS_IMPL_RELEASE(StorageDBParent)
     295             : 
     296             : void
     297           1 : StorageDBParent::AddIPDLReference()
     298             : {
     299           1 :   MOZ_ASSERT(!mIPCOpen, "Attempting to retain multiple IPDL references");
     300           1 :   mIPCOpen = true;
     301           1 :   AddRef();
     302           1 : }
     303             : 
     304             : void
     305           0 : StorageDBParent::ReleaseIPDLReference()
     306             : {
     307           0 :   MOZ_ASSERT(mIPCOpen, "Attempting to release non-existent IPDL reference");
     308           0 :   mIPCOpen = false;
     309           0 :   Release();
     310           0 : }
     311             : 
     312             : namespace {
     313             : 
     314           3 : class SendInitialChildDataRunnable : public Runnable
     315             : {
     316             : public:
     317           1 :   explicit SendInitialChildDataRunnable(StorageDBParent* aParent)
     318           1 :     : Runnable("dom::SendInitialChildDataRunnable")
     319           1 :     , mParent(aParent)
     320           1 :   {}
     321             : 
     322             : private:
     323           1 :   NS_IMETHOD Run() override
     324             :   {
     325           1 :     if (!mParent->IPCOpen()) {
     326           0 :       return NS_OK;
     327             :     }
     328             : 
     329           1 :     StorageDBBridge* db = LocalStorageCache::GetDatabase();
     330           1 :     if (db) {
     331           0 :       InfallibleTArray<nsCString> scopes;
     332           0 :       db->GetOriginsHavingData(&scopes);
     333           0 :       mozilla::Unused << mParent->SendOriginsHavingData(scopes);
     334             :     }
     335             : 
     336             :     // We need to check if the device is in a low disk space situation, so
     337             :     // we can forbid in that case any write in localStorage.
     338             :     nsCOMPtr<nsIDiskSpaceWatcher> diskSpaceWatcher =
     339           2 :       do_GetService("@mozilla.org/toolkit/disk-space-watcher;1");
     340           1 :     if (!diskSpaceWatcher) {
     341           1 :       return NS_OK;
     342             :     }
     343             : 
     344           0 :     bool lowDiskSpace = false;
     345           0 :     diskSpaceWatcher->GetIsDiskFull(&lowDiskSpace);
     346             : 
     347           0 :     if (lowDiskSpace) {
     348           0 :       mozilla::Unused << mParent->SendObserve(
     349           0 :         nsDependentCString("low-disk-space"), EmptyString(), EmptyCString());
     350             :     }
     351             : 
     352           0 :     return NS_OK;
     353             :   }
     354             : 
     355             :   RefPtr<StorageDBParent> mParent;
     356             : };
     357             : 
     358             : } // namespace
     359             : 
     360           1 : StorageDBParent::StorageDBParent()
     361           1 : : mIPCOpen(false)
     362             : {
     363           1 :   StorageObserver* observer = StorageObserver::Self();
     364           1 :   if (observer) {
     365           1 :     observer->AddSink(this);
     366             :   }
     367             : 
     368             :   // We are always open by IPC only
     369           1 :   AddIPDLReference();
     370             : 
     371             :   // Cannot send directly from here since the channel
     372             :   // is not completely built at this moment.
     373             :   RefPtr<SendInitialChildDataRunnable> r =
     374           2 :     new SendInitialChildDataRunnable(this);
     375           1 :   NS_DispatchToCurrentThread(r);
     376           1 : }
     377             : 
     378           0 : StorageDBParent::~StorageDBParent()
     379             : {
     380           0 :   StorageObserver* observer = StorageObserver::Self();
     381           0 :   if (observer) {
     382           0 :     observer->RemoveSink(this);
     383             :   }
     384           0 : }
     385             : 
     386             : StorageDBParent::CacheParentBridge*
     387           2 : StorageDBParent::NewCache(const nsACString& aOriginSuffix,
     388             :                           const nsACString& aOriginNoSuffix)
     389             : {
     390           2 :   return new CacheParentBridge(this, aOriginSuffix, aOriginNoSuffix);
     391             : }
     392             : 
     393             : void
     394           0 : StorageDBParent::ActorDestroy(ActorDestroyReason aWhy)
     395             : {
     396             :   // Implement me! Bug 1005169
     397           0 : }
     398             : 
     399             : mozilla::ipc::IPCResult
     400           2 : StorageDBParent::RecvAsyncPreload(const nsCString& aOriginSuffix,
     401             :                                   const nsCString& aOriginNoSuffix,
     402             :                                   const bool& aPriority)
     403             : {
     404           2 :   StorageDBBridge* db = LocalStorageCache::StartDatabase();
     405           2 :   if (!db) {
     406           0 :     return IPC_FAIL_NO_REASON(this);
     407             :   }
     408             : 
     409           2 :   db->AsyncPreload(NewCache(aOriginSuffix, aOriginNoSuffix), aPriority);
     410           2 :   return IPC_OK();
     411             : }
     412             : 
     413             : mozilla::ipc::IPCResult
     414           1 : StorageDBParent::RecvAsyncGetUsage(const nsCString& aOriginNoSuffix)
     415             : {
     416           1 :   StorageDBBridge* db = LocalStorageCache::StartDatabase();
     417           1 :   if (!db) {
     418           0 :     return IPC_FAIL_NO_REASON(this);
     419             :   }
     420             : 
     421             :   // The object releases it self in LoadUsage method
     422             :   RefPtr<UsageParentBridge> usage =
     423           2 :     new UsageParentBridge(this, aOriginNoSuffix);
     424           1 :   db->AsyncGetUsage(usage);
     425           1 :   return IPC_OK();
     426             : }
     427             : 
     428             : namespace {
     429             : 
     430             : // We need another implementation of LocalStorageCacheBridge to do
     431             : // synchronous IPC preload.  This class just receives Load* notifications
     432             : // and fills the returning arguments of RecvPreload with the database
     433             : // values for us.
     434           0 : class SyncLoadCacheHelper : public LocalStorageCacheBridge
     435             : {
     436             : public:
     437           0 :   SyncLoadCacheHelper(const nsCString& aOriginSuffix,
     438             :                       const nsCString& aOriginNoSuffix,
     439             :                       uint32_t aAlreadyLoadedCount,
     440             :                       InfallibleTArray<nsString>* aKeys,
     441             :                       InfallibleTArray<nsString>* aValues,
     442             :                       nsresult* rv)
     443           0 :   : mMonitor("DOM Storage SyncLoad IPC")
     444             :   , mSuffix(aOriginSuffix)
     445             :   , mOrigin(aOriginNoSuffix)
     446             :   , mKeys(aKeys)
     447             :   , mValues(aValues)
     448             :   , mRv(rv)
     449             :   , mLoaded(false)
     450           0 :   , mLoadedCount(aAlreadyLoadedCount)
     451             :   {
     452             :     // Precaution
     453           0 :     *mRv = NS_ERROR_UNEXPECTED;
     454           0 :   }
     455             : 
     456           0 :   virtual const nsCString Origin() const
     457             :   {
     458           0 :     return LocalStorageManager::CreateOrigin(mSuffix, mOrigin);
     459             :   }
     460           0 :   virtual const nsCString& OriginNoSuffix() const { return mOrigin; }
     461           0 :   virtual const nsCString& OriginSuffix() const { return mSuffix; }
     462           0 :   virtual bool Loaded() { return mLoaded; }
     463           0 :   virtual uint32_t LoadedCount() { return mLoadedCount; }
     464           0 :   virtual bool LoadItem(const nsAString& aKey, const nsString& aValue)
     465             :   {
     466             :     // Called on the aCache background thread
     467           0 :     if (mLoaded) {
     468           0 :       return false;
     469             :     }
     470             : 
     471           0 :     ++mLoadedCount;
     472           0 :     mKeys->AppendElement(aKey);
     473           0 :     mValues->AppendElement(aValue);
     474           0 :     return true;
     475             :   }
     476             : 
     477           0 :   virtual void LoadDone(nsresult aRv)
     478             :   {
     479             :     // Called on the aCache background thread
     480           0 :     MonitorAutoLock monitor(mMonitor);
     481           0 :     mLoaded = true;
     482           0 :     *mRv = aRv;
     483           0 :     monitor.Notify();
     484           0 :   }
     485             : 
     486           0 :   virtual void LoadWait()
     487             :   {
     488             :     // Called on the main thread, exits after LoadDone() call
     489           0 :     MonitorAutoLock monitor(mMonitor);
     490           0 :     while (!mLoaded) {
     491           0 :       monitor.Wait();
     492             :     }
     493           0 :   }
     494             : 
     495             : private:
     496             :   Monitor mMonitor;
     497             :   nsCString mSuffix, mOrigin;
     498             :   InfallibleTArray<nsString>* mKeys;
     499             :   InfallibleTArray<nsString>* mValues;
     500             :   nsresult* mRv;
     501             :   bool mLoaded;
     502             :   uint32_t mLoadedCount;
     503             : };
     504             : 
     505             : } // namespace
     506             : 
     507             : mozilla::ipc::IPCResult
     508           0 : StorageDBParent::RecvPreload(const nsCString& aOriginSuffix,
     509             :                              const nsCString& aOriginNoSuffix,
     510             :                              const uint32_t& aAlreadyLoadedCount,
     511             :                              InfallibleTArray<nsString>* aKeys,
     512             :                              InfallibleTArray<nsString>* aValues,
     513             :                              nsresult* aRv)
     514             : {
     515           0 :   StorageDBBridge* db = LocalStorageCache::StartDatabase();
     516           0 :   if (!db) {
     517           0 :     return IPC_FAIL_NO_REASON(this);
     518             :   }
     519             : 
     520             :   RefPtr<SyncLoadCacheHelper> cache(
     521             :     new SyncLoadCacheHelper(aOriginSuffix, aOriginNoSuffix, aAlreadyLoadedCount,
     522           0 :                             aKeys, aValues, aRv));
     523             : 
     524           0 :   db->SyncPreload(cache, true);
     525           0 :   return IPC_OK();
     526             : }
     527             : 
     528             : mozilla::ipc::IPCResult
     529           0 : StorageDBParent::RecvAsyncAddItem(const nsCString& aOriginSuffix,
     530             :                                   const nsCString& aOriginNoSuffix,
     531             :                                   const nsString& aKey,
     532             :                                   const nsString& aValue)
     533             : {
     534           0 :   StorageDBBridge* db = LocalStorageCache::StartDatabase();
     535           0 :   if (!db) {
     536           0 :     return IPC_FAIL_NO_REASON(this);
     537             :   }
     538             : 
     539           0 :   nsresult rv = db->AsyncAddItem(NewCache(aOriginSuffix, aOriginNoSuffix), aKey,
     540           0 :                                  aValue);
     541           0 :   if (NS_FAILED(rv) && mIPCOpen) {
     542           0 :     mozilla::Unused << SendError(rv);
     543             :   }
     544             : 
     545           0 :   return IPC_OK();
     546             : }
     547             : 
     548             : mozilla::ipc::IPCResult
     549           0 : StorageDBParent::RecvAsyncUpdateItem(const nsCString& aOriginSuffix,
     550             :                                      const nsCString& aOriginNoSuffix,
     551             :                                      const nsString& aKey,
     552             :                                      const nsString& aValue)
     553             : {
     554           0 :   StorageDBBridge* db = LocalStorageCache::StartDatabase();
     555           0 :   if (!db) {
     556           0 :     return IPC_FAIL_NO_REASON(this);
     557             :   }
     558             : 
     559           0 :   nsresult rv = db->AsyncUpdateItem(NewCache(aOriginSuffix, aOriginNoSuffix),
     560           0 :                                     aKey, aValue);
     561           0 :   if (NS_FAILED(rv) && mIPCOpen) {
     562           0 :     mozilla::Unused << SendError(rv);
     563             :   }
     564             : 
     565           0 :   return IPC_OK();
     566             : }
     567             : 
     568             : mozilla::ipc::IPCResult
     569           0 : StorageDBParent::RecvAsyncRemoveItem(const nsCString& aOriginSuffix,
     570             :                                      const nsCString& aOriginNoSuffix,
     571             :                                      const nsString& aKey)
     572             : {
     573           0 :   StorageDBBridge* db = LocalStorageCache::StartDatabase();
     574           0 :   if (!db) {
     575           0 :     return IPC_FAIL_NO_REASON(this);
     576             :   }
     577             : 
     578           0 :   nsresult rv = db->AsyncRemoveItem(NewCache(aOriginSuffix, aOriginNoSuffix),
     579           0 :                                     aKey);
     580           0 :   if (NS_FAILED(rv) && mIPCOpen) {
     581           0 :     mozilla::Unused << SendError(rv);
     582             :   }
     583             : 
     584           0 :   return IPC_OK();
     585             : }
     586             : 
     587             : mozilla::ipc::IPCResult
     588           0 : StorageDBParent::RecvAsyncClear(const nsCString& aOriginSuffix,
     589             :                                 const nsCString& aOriginNoSuffix)
     590             : {
     591           0 :   StorageDBBridge* db = LocalStorageCache::StartDatabase();
     592           0 :   if (!db) {
     593           0 :     return IPC_FAIL_NO_REASON(this);
     594             :   }
     595             : 
     596           0 :   nsresult rv = db->AsyncClear(NewCache(aOriginSuffix, aOriginNoSuffix));
     597           0 :   if (NS_FAILED(rv) && mIPCOpen) {
     598           0 :     mozilla::Unused << SendError(rv);
     599             :   }
     600             : 
     601           0 :   return IPC_OK();
     602             : }
     603             : 
     604             : mozilla::ipc::IPCResult
     605           0 : StorageDBParent::RecvAsyncFlush()
     606             : {
     607           0 :   StorageDBBridge* db = LocalStorageCache::GetDatabase();
     608           0 :   if (!db) {
     609           0 :     return IPC_FAIL_NO_REASON(this);
     610             :   }
     611             : 
     612           0 :   db->AsyncFlush();
     613           0 :   return IPC_OK();
     614             : }
     615             : 
     616             : // StorageObserverSink
     617             : 
     618             : nsresult
     619           0 : StorageDBParent::Observe(const char* aTopic,
     620             :                          const nsAString& aOriginAttributesPattern,
     621             :                          const nsACString& aOriginScope)
     622             : {
     623           0 :   if (mIPCOpen) {
     624           0 :       mozilla::Unused << SendObserve(nsDependentCString(aTopic),
     625           0 :                                      nsString(aOriginAttributesPattern),
     626           0 :                                      nsCString(aOriginScope));
     627             :   }
     628             : 
     629           0 :   return NS_OK;
     630             : }
     631             : 
     632             : namespace {
     633             : 
     634             : // Results must be sent back on the main thread
     635           6 : class LoadRunnable : public Runnable
     636             : {
     637             : public:
     638             :   enum TaskType {
     639             :     loadItem,
     640             :     loadDone
     641             :   };
     642             : 
     643           0 :   LoadRunnable(StorageDBParent* aParent,
     644             :                TaskType aType,
     645             :                const nsACString& aOriginSuffix,
     646             :                const nsACString& aOriginNoSuffix,
     647             :                const nsAString& aKey = EmptyString(),
     648             :                const nsAString& aValue = EmptyString())
     649           0 :     : Runnable("dom::LoadRunnable")
     650             :     , mParent(aParent)
     651             :     , mType(aType)
     652             :     , mSuffix(aOriginSuffix)
     653             :     , mOrigin(aOriginNoSuffix)
     654             :     , mKey(aKey)
     655           0 :     , mValue(aValue)
     656           0 :   { }
     657             : 
     658           2 :   LoadRunnable(StorageDBParent* aParent,
     659             :                TaskType aType,
     660             :                const nsACString& aOriginSuffix,
     661             :                const nsACString& aOriginNoSuffix,
     662             :                nsresult aRv)
     663           2 :     : Runnable("dom::LoadRunnable")
     664             :     , mParent(aParent)
     665             :     , mType(aType)
     666             :     , mSuffix(aOriginSuffix)
     667             :     , mOrigin(aOriginNoSuffix)
     668           2 :     , mRv(aRv)
     669           2 :   { }
     670             : 
     671             : private:
     672             :   RefPtr<StorageDBParent> mParent;
     673             :   TaskType mType;
     674             :   nsCString mSuffix, mOrigin;
     675             :   nsString mKey;
     676             :   nsString mValue;
     677             :   nsresult mRv;
     678             : 
     679           2 :   NS_IMETHOD Run() override
     680             :   {
     681           2 :     if (!mParent->IPCOpen()) {
     682           0 :       return NS_OK;
     683             :     }
     684             : 
     685           2 :     switch (mType)
     686             :     {
     687             :     case loadItem:
     688           0 :       mozilla::Unused << mParent->SendLoadItem(mSuffix, mOrigin, mKey, mValue);
     689           0 :       break;
     690             :     case loadDone:
     691           2 :       mozilla::Unused << mParent->SendLoadDone(mSuffix, mOrigin, mRv);
     692           2 :       break;
     693             :     }
     694             : 
     695           2 :     return NS_OK;
     696             :   }
     697             : };
     698             : 
     699             : } // namespace
     700             : 
     701             : // StorageDBParent::CacheParentBridge
     702             : 
     703             : const nsCString
     704           0 : StorageDBParent::CacheParentBridge::Origin() const
     705             : {
     706           0 :   return LocalStorageManager::CreateOrigin(mOriginSuffix, mOriginNoSuffix);
     707             : }
     708             : 
     709             : bool
     710           0 : StorageDBParent::CacheParentBridge::LoadItem(const nsAString& aKey,
     711             :                                              const nsString& aValue)
     712             : {
     713           0 :   if (mLoaded) {
     714           0 :     return false;
     715             :   }
     716             : 
     717           0 :   ++mLoadedCount;
     718             : 
     719             :   RefPtr<LoadRunnable> r =
     720             :     new LoadRunnable(mParent, LoadRunnable::loadItem, mOriginSuffix,
     721           0 :                      mOriginNoSuffix, aKey, aValue);
     722           0 :   NS_DispatchToMainThread(r);
     723           0 :   return true;
     724             : }
     725             : 
     726             : void
     727           4 : StorageDBParent::CacheParentBridge::LoadDone(nsresult aRv)
     728             : {
     729             :   // Prevent send of duplicate LoadDone.
     730           4 :   if (mLoaded) {
     731           2 :     return;
     732             :   }
     733             : 
     734           2 :   mLoaded = true;
     735             : 
     736             :   RefPtr<LoadRunnable> r =
     737             :     new LoadRunnable(mParent, LoadRunnable::loadDone, mOriginSuffix,
     738           6 :                      mOriginNoSuffix, aRv);
     739           2 :   NS_DispatchToMainThread(r);
     740             : }
     741             : 
     742             : void
     743           0 : StorageDBParent::CacheParentBridge::LoadWait()
     744             : {
     745             :   // Should never be called on this implementation
     746           0 :   MOZ_ASSERT(false);
     747             : }
     748             : 
     749             : // StorageDBParent::UsageParentBridge
     750             : 
     751             : namespace {
     752             : 
     753           3 : class UsageRunnable : public Runnable
     754             : {
     755             : public:
     756           1 :   UsageRunnable(StorageDBParent* aParent,
     757             :                 const nsACString& aOriginScope,
     758             :                 const int64_t& aUsage)
     759           1 :     : Runnable("dom::UsageRunnable")
     760             :     , mParent(aParent)
     761             :     , mOriginScope(aOriginScope)
     762           1 :     , mUsage(aUsage)
     763           1 :   {}
     764             : 
     765             : private:
     766           1 :   NS_IMETHOD Run() override
     767             :   {
     768           1 :     if (!mParent->IPCOpen()) {
     769           0 :       return NS_OK;
     770             :     }
     771             : 
     772           1 :     mozilla::Unused << mParent->SendLoadUsage(mOriginScope, mUsage);
     773           1 :     return NS_OK;
     774             :   }
     775             : 
     776             :   RefPtr<StorageDBParent> mParent;
     777             :   nsCString mOriginScope;
     778             :   int64_t mUsage;
     779             : };
     780             : 
     781             : } // namespace
     782             : 
     783             : void
     784           1 : StorageDBParent::UsageParentBridge::LoadUsage(const int64_t aUsage)
     785             : {
     786           3 :   RefPtr<UsageRunnable> r = new UsageRunnable(mParent, mOriginScope, aUsage);
     787           1 :   NS_DispatchToMainThread(r);
     788           1 : }
     789             : 
     790             : } // namespace dom
     791             : } // namespace mozilla

Generated by: LCOV version 1.13