LCOV - code coverage report
Current view: top level - dom/indexedDB - IDBDatabase.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 631 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 67 0.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 "IDBDatabase.h"
       8             : 
       9             : #include "FileInfo.h"
      10             : #include "IDBEvents.h"
      11             : #include "IDBFactory.h"
      12             : #include "IDBIndex.h"
      13             : #include "IDBMutableFile.h"
      14             : #include "IDBObjectStore.h"
      15             : #include "IDBRequest.h"
      16             : #include "IDBTransaction.h"
      17             : #include "IDBFactory.h"
      18             : #include "IndexedDatabaseManager.h"
      19             : #include "mozilla/ErrorResult.h"
      20             : #include "mozilla/EventDispatcher.h"
      21             : #include "MainThreadUtils.h"
      22             : #include "mozilla/Services.h"
      23             : #include "mozilla/storage.h"
      24             : #include "mozilla/dom/BindingDeclarations.h"
      25             : #include "mozilla/dom/DOMStringList.h"
      26             : #include "mozilla/dom/DOMStringListBinding.h"
      27             : #include "mozilla/dom/Exceptions.h"
      28             : #include "mozilla/dom/File.h"
      29             : #include "mozilla/dom/IDBDatabaseBinding.h"
      30             : #include "mozilla/dom/IDBObjectStoreBinding.h"
      31             : #include "mozilla/dom/indexedDB/PBackgroundIDBDatabaseFileChild.h"
      32             : #include "mozilla/dom/indexedDB/PBackgroundIDBSharedTypes.h"
      33             : #include "mozilla/dom/IPCBlobUtils.h"
      34             : #include "mozilla/dom/quota/QuotaManager.h"
      35             : #include "mozilla/ipc/BackgroundChild.h"
      36             : #include "mozilla/ipc/BackgroundUtils.h"
      37             : #include "mozilla/ipc/FileDescriptor.h"
      38             : #include "mozilla/ipc/InputStreamParams.h"
      39             : #include "mozilla/ipc/InputStreamUtils.h"
      40             : #include "nsAutoPtr.h"
      41             : #include "nsCOMPtr.h"
      42             : #include "nsIDocument.h"
      43             : #include "nsIObserver.h"
      44             : #include "nsIObserverService.h"
      45             : #include "nsIScriptError.h"
      46             : #include "nsISupportsPrimitives.h"
      47             : #include "nsThreadUtils.h"
      48             : #include "ProfilerHelpers.h"
      49             : #include "ReportInternalError.h"
      50             : #include "ScriptErrorHelper.h"
      51             : #include "nsQueryObject.h"
      52             : 
      53             : // Include this last to avoid path problems on Windows.
      54             : #include "ActorsChild.h"
      55             : 
      56             : namespace mozilla {
      57             : namespace dom {
      58             : 
      59             : using namespace mozilla::dom::indexedDB;
      60             : using namespace mozilla::dom::quota;
      61             : using namespace mozilla::ipc;
      62             : using namespace mozilla::services;
      63             : 
      64             : namespace {
      65             : 
      66             : const char kCycleCollectionObserverTopic[] = "cycle-collector-end";
      67             : const char kMemoryPressureObserverTopic[] = "memory-pressure";
      68             : const char kWindowObserverTopic[] = "inner-window-destroyed";
      69             : 
      70             : class CancelableRunnableWrapper final
      71             :   : public CancelableRunnable
      72             : {
      73             :   nsCOMPtr<nsIRunnable> mRunnable;
      74             : 
      75             : public:
      76           0 :   explicit CancelableRunnableWrapper(nsIRunnable* aRunnable)
      77           0 :     : CancelableRunnable("dom::CancelableRunnableWrapper")
      78           0 :     , mRunnable(aRunnable)
      79             :   {
      80           0 :     MOZ_ASSERT(aRunnable);
      81           0 :   }
      82             : 
      83             : private:
      84           0 :   ~CancelableRunnableWrapper()
      85           0 :   { }
      86             : 
      87             :   NS_DECL_NSIRUNNABLE
      88             :   nsresult Cancel() override;
      89             : };
      90             : 
      91             : class DatabaseFile final
      92             :   : public PBackgroundIDBDatabaseFileChild
      93             : {
      94             :   IDBDatabase* mDatabase;
      95             : 
      96             : public:
      97           0 :   explicit DatabaseFile(IDBDatabase* aDatabase)
      98           0 :     : mDatabase(aDatabase)
      99             :   {
     100           0 :     MOZ_ASSERT(aDatabase);
     101           0 :     aDatabase->AssertIsOnOwningThread();
     102             : 
     103           0 :     MOZ_COUNT_CTOR(DatabaseFile);
     104           0 :   }
     105             : 
     106             : private:
     107           0 :   ~DatabaseFile()
     108           0 :   {
     109           0 :     MOZ_ASSERT(!mDatabase);
     110             : 
     111           0 :     MOZ_COUNT_DTOR(DatabaseFile);
     112           0 :   }
     113             : 
     114             :   virtual void
     115           0 :   ActorDestroy(ActorDestroyReason aWhy) override
     116             :   {
     117           0 :     MOZ_ASSERT(mDatabase);
     118           0 :     mDatabase->AssertIsOnOwningThread();
     119             : 
     120           0 :     if (aWhy != Deletion) {
     121           0 :       RefPtr<IDBDatabase> database = mDatabase;
     122           0 :       database->NoteFinishedFileActor(this);
     123             :     }
     124             : 
     125             : #ifdef DEBUG
     126           0 :     mDatabase = nullptr;
     127             : #endif
     128           0 :   }
     129             : };
     130             : 
     131             : } // namespace
     132             : 
     133             : class IDBDatabase::Observer final
     134             :   : public nsIObserver
     135             : {
     136             :   IDBDatabase* mWeakDatabase;
     137             :   const uint64_t mWindowId;
     138             : 
     139             : public:
     140           0 :   Observer(IDBDatabase* aDatabase, uint64_t aWindowId)
     141           0 :     : mWeakDatabase(aDatabase)
     142           0 :     , mWindowId(aWindowId)
     143             :   {
     144           0 :     MOZ_ASSERT(NS_IsMainThread());
     145           0 :     MOZ_ASSERT(aDatabase);
     146           0 :   }
     147             : 
     148             :   void
     149           0 :   Revoke()
     150             :   {
     151           0 :     MOZ_ASSERT(NS_IsMainThread());
     152             : 
     153           0 :     mWeakDatabase = nullptr;
     154           0 :   }
     155             : 
     156             :   NS_DECL_ISUPPORTS
     157             : 
     158             : private:
     159           0 :   ~Observer()
     160           0 :   {
     161           0 :     MOZ_ASSERT(NS_IsMainThread());
     162           0 :     MOZ_ASSERT(!mWeakDatabase);
     163           0 :   }
     164             : 
     165             :   NS_DECL_NSIOBSERVER
     166             : };
     167             : 
     168           0 : IDBDatabase::IDBDatabase(IDBOpenDBRequest* aRequest,
     169             :                          IDBFactory* aFactory,
     170             :                          BackgroundDatabaseChild* aActor,
     171           0 :                          DatabaseSpec* aSpec)
     172             :   : IDBWrapperCache(aRequest)
     173             :   , mFactory(aFactory)
     174             :   , mSpec(aSpec)
     175             :   , mBackgroundActor(aActor)
     176           0 :   , mFileHandleDisabled(aRequest->IsFileHandleDisabled())
     177             :   , mClosed(false)
     178             :   , mInvalidated(false)
     179             :   , mQuotaExceeded(false)
     180           0 :   , mIncreasedActiveDatabaseCount(false)
     181             : {
     182           0 :   MOZ_ASSERT(aRequest);
     183           0 :   MOZ_ASSERT(aFactory);
     184           0 :   aFactory->AssertIsOnOwningThread();
     185           0 :   MOZ_ASSERT(aActor);
     186           0 :   MOZ_ASSERT(aSpec);
     187           0 : }
     188             : 
     189           0 : IDBDatabase::~IDBDatabase()
     190             : {
     191           0 :   AssertIsOnOwningThread();
     192           0 :   MOZ_ASSERT(!mBackgroundActor);
     193           0 :   MOZ_ASSERT(!mIncreasedActiveDatabaseCount);
     194           0 : }
     195             : 
     196             : // static
     197             : already_AddRefed<IDBDatabase>
     198           0 : IDBDatabase::Create(IDBOpenDBRequest* aRequest,
     199             :                     IDBFactory* aFactory,
     200             :                     BackgroundDatabaseChild* aActor,
     201             :                     DatabaseSpec* aSpec)
     202             : {
     203           0 :   MOZ_ASSERT(aRequest);
     204           0 :   MOZ_ASSERT(aFactory);
     205           0 :   aFactory->AssertIsOnOwningThread();
     206           0 :   MOZ_ASSERT(aActor);
     207           0 :   MOZ_ASSERT(aSpec);
     208             : 
     209             :   RefPtr<IDBDatabase> db =
     210           0 :     new IDBDatabase(aRequest, aFactory, aActor, aSpec);
     211             : 
     212           0 :   db->SetScriptOwner(aRequest->GetScriptOwner());
     213             : 
     214           0 :   if (NS_IsMainThread()) {
     215           0 :     if (nsPIDOMWindowInner* window = aFactory->GetParentObject()) {
     216           0 :       uint64_t windowId = window->WindowID();
     217             : 
     218           0 :       RefPtr<Observer> observer = new Observer(db, windowId);
     219             : 
     220           0 :       nsCOMPtr<nsIObserverService> obsSvc = GetObserverService();
     221           0 :       MOZ_ASSERT(obsSvc);
     222             : 
     223             :       // This topic must be successfully registered.
     224           0 :       MOZ_ALWAYS_SUCCEEDS(
     225             :         obsSvc->AddObserver(observer, kWindowObserverTopic, false));
     226             : 
     227             :       // These topics are not crucial.
     228           0 :       if (NS_FAILED(obsSvc->AddObserver(observer,
     229             :                                         kCycleCollectionObserverTopic,
     230           0 :                                         false)) ||
     231           0 :           NS_FAILED(obsSvc->AddObserver(observer,
     232             :                                         kMemoryPressureObserverTopic,
     233             :                                         false))) {
     234           0 :         NS_WARNING("Failed to add additional memory observers!");
     235             :       }
     236             : 
     237           0 :       db->mObserver.swap(observer);
     238             :     }
     239             :   }
     240             : 
     241           0 :   db->IncreaseActiveDatabaseCount();
     242             : 
     243           0 :   return db.forget();
     244             : }
     245             : 
     246             : #ifdef DEBUG
     247             : 
     248             : void
     249           0 : IDBDatabase::AssertIsOnOwningThread() const
     250             : {
     251           0 :   MOZ_ASSERT(mFactory);
     252           0 :   mFactory->AssertIsOnOwningThread();
     253           0 : }
     254             : 
     255             : #endif // DEBUG
     256             : 
     257             : nsIEventTarget*
     258           0 : IDBDatabase::EventTarget() const
     259             : {
     260           0 :   AssertIsOnOwningThread();
     261           0 :   return Factory()->EventTarget();
     262             : }
     263             : 
     264             : void
     265           0 : IDBDatabase::CloseInternal()
     266             : {
     267           0 :   AssertIsOnOwningThread();
     268             : 
     269           0 :   if (!mClosed) {
     270           0 :     mClosed = true;
     271             : 
     272           0 :     ExpireFileActors(/* aExpireAll */ true);
     273             : 
     274           0 :     if (mObserver) {
     275           0 :       mObserver->Revoke();
     276             : 
     277           0 :       nsCOMPtr<nsIObserverService> obsSvc = GetObserverService();
     278           0 :       if (obsSvc) {
     279             :         // These might not have been registered.
     280           0 :         obsSvc->RemoveObserver(mObserver, kCycleCollectionObserverTopic);
     281           0 :         obsSvc->RemoveObserver(mObserver, kMemoryPressureObserverTopic);
     282             : 
     283           0 :         MOZ_ALWAYS_SUCCEEDS(
     284             :           obsSvc->RemoveObserver(mObserver, kWindowObserverTopic));
     285             :       }
     286             : 
     287           0 :       mObserver = nullptr;
     288             :     }
     289             : 
     290           0 :     if (mBackgroundActor && !mInvalidated) {
     291           0 :       mBackgroundActor->SendClose();
     292             :     }
     293             : 
     294             :     // Decrease the number of active databases right after the database is
     295             :     // closed.
     296           0 :     MaybeDecreaseActiveDatabaseCount();
     297             :   }
     298           0 : }
     299             : 
     300             : void
     301           0 : IDBDatabase::InvalidateInternal()
     302             : {
     303           0 :   AssertIsOnOwningThread();
     304             : 
     305           0 :   InvalidateMutableFiles();
     306           0 :   AbortTransactions(/* aShouldWarn */ true);
     307             : 
     308           0 :   CloseInternal();
     309           0 : }
     310             : 
     311             : void
     312           0 : IDBDatabase::EnterSetVersionTransaction(uint64_t aNewVersion)
     313             : {
     314           0 :   AssertIsOnOwningThread();
     315           0 :   MOZ_ASSERT(aNewVersion);
     316           0 :   MOZ_ASSERT(!RunningVersionChangeTransaction());
     317           0 :   MOZ_ASSERT(mSpec);
     318           0 :   MOZ_ASSERT(!mPreviousSpec);
     319             : 
     320           0 :   mPreviousSpec = new DatabaseSpec(*mSpec);
     321             : 
     322           0 :   mSpec->metadata().version() = aNewVersion;
     323           0 : }
     324             : 
     325             : void
     326           0 : IDBDatabase::ExitSetVersionTransaction()
     327             : {
     328           0 :   AssertIsOnOwningThread();
     329             : 
     330           0 :   if (mPreviousSpec) {
     331           0 :     mPreviousSpec = nullptr;
     332             :   }
     333           0 : }
     334             : 
     335             : void
     336           0 : IDBDatabase::RevertToPreviousState()
     337             : {
     338           0 :   AssertIsOnOwningThread();
     339           0 :   MOZ_ASSERT(RunningVersionChangeTransaction());
     340           0 :   MOZ_ASSERT(mPreviousSpec);
     341             : 
     342             :   // Hold the current spec alive until RefreshTransactionsSpecEnumerator has
     343             :   // finished!
     344           0 :   nsAutoPtr<DatabaseSpec> currentSpec(mSpec.forget());
     345             : 
     346           0 :   mSpec = mPreviousSpec.forget();
     347             : 
     348           0 :   RefreshSpec(/* aMayDelete */ true);
     349           0 : }
     350             : 
     351             : void
     352           0 : IDBDatabase::RefreshSpec(bool aMayDelete)
     353             : {
     354           0 :   AssertIsOnOwningThread();
     355             : 
     356           0 :   for (auto iter = mTransactions.Iter(); !iter.Done(); iter.Next()) {
     357           0 :     RefPtr<IDBTransaction> transaction = iter.Get()->GetKey();
     358           0 :     MOZ_ASSERT(transaction);
     359           0 :     transaction->AssertIsOnOwningThread();
     360           0 :     transaction->RefreshSpec(aMayDelete);
     361             :   }
     362           0 : }
     363             : 
     364             : nsPIDOMWindowInner*
     365           0 : IDBDatabase::GetParentObject() const
     366             : {
     367           0 :   return mFactory->GetParentObject();
     368             : }
     369             : 
     370             : const nsString&
     371           0 : IDBDatabase::Name() const
     372             : {
     373           0 :   AssertIsOnOwningThread();
     374           0 :   MOZ_ASSERT(mSpec);
     375             : 
     376           0 :   return mSpec->metadata().name();
     377             : }
     378             : 
     379             : uint64_t
     380           0 : IDBDatabase::Version() const
     381             : {
     382           0 :   AssertIsOnOwningThread();
     383           0 :   MOZ_ASSERT(mSpec);
     384             : 
     385           0 :   return mSpec->metadata().version();
     386             : }
     387             : 
     388             : already_AddRefed<DOMStringList>
     389           0 : IDBDatabase::ObjectStoreNames() const
     390             : {
     391           0 :   AssertIsOnOwningThread();
     392           0 :   MOZ_ASSERT(mSpec);
     393             : 
     394           0 :   const nsTArray<ObjectStoreSpec>& objectStores = mSpec->objectStores();
     395             : 
     396           0 :   RefPtr<DOMStringList> list = new DOMStringList();
     397             : 
     398           0 :   if (!objectStores.IsEmpty()) {
     399           0 :     nsTArray<nsString>& listNames = list->StringArray();
     400           0 :     listNames.SetCapacity(objectStores.Length());
     401             : 
     402           0 :     for (uint32_t index = 0; index < objectStores.Length(); index++) {
     403           0 :       listNames.InsertElementSorted(objectStores[index].metadata().name());
     404             :     }
     405             :   }
     406             : 
     407           0 :   return list.forget();
     408             : }
     409             : 
     410             : already_AddRefed<nsIDocument>
     411           0 : IDBDatabase::GetOwnerDocument() const
     412             : {
     413           0 :   if (nsPIDOMWindowInner* window = GetOwner()) {
     414           0 :     nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
     415           0 :     return doc.forget();
     416             :   }
     417           0 :   return nullptr;
     418             : }
     419             : 
     420             : already_AddRefed<IDBObjectStore>
     421           0 : IDBDatabase::CreateObjectStore(
     422             :                             const nsAString& aName,
     423             :                             const IDBObjectStoreParameters& aOptionalParameters,
     424             :                             ErrorResult& aRv)
     425             : {
     426           0 :   AssertIsOnOwningThread();
     427             : 
     428           0 :   IDBTransaction* transaction = IDBTransaction::GetCurrent();
     429           0 :   if (!transaction ||
     430           0 :       transaction->Database() != this ||
     431           0 :       transaction->GetMode() != IDBTransaction::VERSION_CHANGE) {
     432           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     433           0 :     return nullptr;
     434             :   }
     435             : 
     436           0 :   if (!transaction->IsOpen()) {
     437           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     438           0 :     return nullptr;
     439             :   }
     440             : 
     441           0 :   KeyPath keyPath(0);
     442           0 :   if (NS_FAILED(KeyPath::Parse(aOptionalParameters.mKeyPath, &keyPath))) {
     443           0 :     aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
     444           0 :     return nullptr;
     445             :   }
     446             : 
     447           0 :   nsTArray<ObjectStoreSpec>& objectStores = mSpec->objectStores();
     448           0 :   for (uint32_t count = objectStores.Length(), index = 0;
     449           0 :        index < count;
     450             :        index++) {
     451           0 :     if (aName == objectStores[index].metadata().name()) {
     452           0 :       aRv.Throw(NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR);
     453           0 :       return nullptr;
     454             :     }
     455             :   }
     456             : 
     457           0 :   if (!keyPath.IsAllowedForObjectStore(aOptionalParameters.mAutoIncrement)) {
     458           0 :     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     459           0 :     return nullptr;
     460             :   }
     461             : 
     462             :   const ObjectStoreSpec* oldSpecElements =
     463           0 :     objectStores.IsEmpty() ? nullptr : objectStores.Elements();
     464             : 
     465           0 :   ObjectStoreSpec* newSpec = objectStores.AppendElement();
     466           0 :   newSpec->metadata() =
     467           0 :     ObjectStoreMetadata(transaction->NextObjectStoreId(), nsString(aName),
     468           0 :                         keyPath, aOptionalParameters.mAutoIncrement);
     469             : 
     470           0 :   if (oldSpecElements &&
     471           0 :       oldSpecElements != objectStores.Elements()) {
     472           0 :     MOZ_ASSERT(objectStores.Length() > 1);
     473             : 
     474             :     // Array got moved, update the spec pointers for all live objectStores and
     475             :     // indexes.
     476           0 :     RefreshSpec(/* aMayDelete */ false);
     477             :   }
     478             : 
     479             :   RefPtr<IDBObjectStore> objectStore =
     480           0 :     transaction->CreateObjectStore(*newSpec);
     481           0 :   MOZ_ASSERT(objectStore);
     482             : 
     483             :   // Don't do this in the macro because we always need to increment the serial
     484             :   // number to keep in sync with the parent.
     485           0 :   const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
     486             : 
     487           0 :   IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
     488             :                  "database(%s).transaction(%s).createObjectStore(%s)",
     489             :                "IndexedDB %s: C T[%lld] R[%llu]: "
     490             :                  "IDBDatabase.createObjectStore()",
     491             :                IDB_LOG_ID_STRING(),
     492             :                transaction->LoggingSerialNumber(),
     493             :                requestSerialNumber,
     494             :                IDB_LOG_STRINGIFY(this),
     495             :                IDB_LOG_STRINGIFY(transaction),
     496             :                IDB_LOG_STRINGIFY(objectStore));
     497             : 
     498           0 :   return objectStore.forget();
     499             : }
     500             : 
     501             : void
     502           0 : IDBDatabase::DeleteObjectStore(const nsAString& aName, ErrorResult& aRv)
     503             : {
     504           0 :   AssertIsOnOwningThread();
     505             : 
     506           0 :   IDBTransaction* transaction = IDBTransaction::GetCurrent();
     507           0 :   if (!transaction ||
     508           0 :       transaction->Database() != this ||
     509           0 :       transaction->GetMode() != IDBTransaction::VERSION_CHANGE) {
     510           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     511           0 :     return;
     512             :   }
     513             : 
     514           0 :   if (!transaction->IsOpen()) {
     515           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     516           0 :     return;
     517             :   }
     518             : 
     519           0 :   nsTArray<ObjectStoreSpec>& specArray = mSpec->objectStores();
     520             : 
     521           0 :   int64_t objectStoreId = 0;
     522             : 
     523           0 :   for (uint32_t specCount = specArray.Length(), specIndex = 0;
     524           0 :        specIndex < specCount;
     525             :        specIndex++) {
     526           0 :     const ObjectStoreMetadata& metadata = specArray[specIndex].metadata();
     527           0 :     MOZ_ASSERT(metadata.id());
     528             : 
     529           0 :     if (aName == metadata.name()) {
     530           0 :       objectStoreId = metadata.id();
     531             : 
     532             :       // Must do this before altering the metadata array!
     533           0 :       transaction->DeleteObjectStore(objectStoreId);
     534             : 
     535           0 :       specArray.RemoveElementAt(specIndex);
     536             : 
     537           0 :       RefreshSpec(/* aMayDelete */ false);
     538           0 :       break;
     539             :     }
     540             :   }
     541             : 
     542           0 :   if (!objectStoreId) {
     543           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR);
     544           0 :     return;
     545             :   }
     546             : 
     547             :   // Don't do this in the macro because we always need to increment the serial
     548             :   // number to keep in sync with the parent.
     549           0 :   const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber();
     550             : 
     551           0 :   IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld] Request[%llu]: "
     552             :                  "database(%s).transaction(%s).deleteObjectStore(\"%s\")",
     553             :                "IndexedDB %s: C T[%lld] R[%llu]: "
     554             :                  "IDBDatabase.deleteObjectStore()",
     555             :                IDB_LOG_ID_STRING(),
     556             :                transaction->LoggingSerialNumber(),
     557             :                requestSerialNumber,
     558             :                IDB_LOG_STRINGIFY(this),
     559             :                IDB_LOG_STRINGIFY(transaction),
     560             :                NS_ConvertUTF16toUTF8(aName).get());
     561             : }
     562             : 
     563             : already_AddRefed<IDBTransaction>
     564           0 : IDBDatabase::Transaction(JSContext* aCx,
     565             :                          const StringOrStringSequence& aStoreNames,
     566             :                          IDBTransactionMode aMode,
     567             :                          ErrorResult& aRv)
     568             : {
     569           0 :   AssertIsOnOwningThread();
     570             : 
     571           0 :   if ((aMode == IDBTransactionMode::Readwriteflush ||
     572           0 :        aMode == IDBTransactionMode::Cleanup) &&
     573           0 :       !IndexedDatabaseManager::ExperimentalFeaturesEnabled()) {
     574             :     // Pretend that this mode doesn't exist. We don't have a way to annotate
     575             :     // certain enum values as depending on preferences so we just duplicate the
     576             :     // normal exception generation here.
     577           0 :     aRv.ThrowTypeError<MSG_INVALID_ENUM_VALUE>(
     578           0 :       NS_LITERAL_STRING("Argument 2 of IDBDatabase.transaction"),
     579           0 :       NS_LITERAL_STRING("readwriteflush"),
     580           0 :       NS_LITERAL_STRING("IDBTransactionMode"));
     581           0 :     return nullptr;
     582             :   }
     583             : 
     584           0 :   RefPtr<IDBTransaction> transaction;
     585           0 :   aRv = Transaction(aCx, aStoreNames, aMode, getter_AddRefs(transaction));
     586           0 :   if (NS_WARN_IF(aRv.Failed())) {
     587           0 :     return nullptr;
     588             :   }
     589             : 
     590           0 :   return transaction.forget();
     591             : }
     592             : 
     593             : nsresult
     594           0 : IDBDatabase::Transaction(JSContext* aCx,
     595             :                          const StringOrStringSequence& aStoreNames,
     596             :                          IDBTransactionMode aMode,
     597             :                          IDBTransaction** aTransaction)
     598             : {
     599           0 :   AssertIsOnOwningThread();
     600             : 
     601           0 :   if (NS_WARN_IF((aMode == IDBTransactionMode::Readwriteflush ||
     602             :                   aMode == IDBTransactionMode::Cleanup) &&
     603             :                  !IndexedDatabaseManager::ExperimentalFeaturesEnabled())) {
     604           0 :     IDB_REPORT_INTERNAL_ERR();
     605           0 :     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     606             :   }
     607             : 
     608           0 :   if (QuotaManager::IsShuttingDown()) {
     609           0 :     IDB_REPORT_INTERNAL_ERR();
     610           0 :     return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     611             :   }
     612             : 
     613           0 :   if (mClosed || RunningVersionChangeTransaction()) {
     614           0 :     return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
     615             :   }
     616             : 
     617           0 :   AutoTArray<nsString, 1> stackSequence;
     618             : 
     619           0 :   if (aStoreNames.IsString()) {
     620           0 :     stackSequence.AppendElement(aStoreNames.GetAsString());
     621             :   } else {
     622           0 :     MOZ_ASSERT(aStoreNames.IsStringSequence());
     623           0 :     if (aStoreNames.GetAsStringSequence().IsEmpty()) {
     624           0 :       return NS_ERROR_DOM_INVALID_ACCESS_ERR;
     625             :     }
     626             :   }
     627             : 
     628             :   const nsTArray<nsString>& storeNames =
     629           0 :     aStoreNames.IsString() ?
     630             :     stackSequence :
     631           0 :     static_cast<const nsTArray<nsString>&>(aStoreNames.GetAsStringSequence());
     632           0 :   MOZ_ASSERT(!storeNames.IsEmpty());
     633             : 
     634           0 :   const nsTArray<ObjectStoreSpec>& objectStores = mSpec->objectStores();
     635           0 :   const uint32_t nameCount = storeNames.Length();
     636             : 
     637           0 :   nsTArray<nsString> sortedStoreNames;
     638           0 :   sortedStoreNames.SetCapacity(nameCount);
     639             : 
     640             :   // Check to make sure the object store names we collected actually exist.
     641           0 :   for (uint32_t nameIndex = 0; nameIndex < nameCount; nameIndex++) {
     642           0 :     const nsString& name = storeNames[nameIndex];
     643             : 
     644           0 :     bool found = false;
     645             : 
     646           0 :     for (uint32_t objCount = objectStores.Length(), objIndex = 0;
     647           0 :          objIndex < objCount;
     648             :          objIndex++) {
     649           0 :       if (objectStores[objIndex].metadata().name() == name) {
     650           0 :         found = true;
     651           0 :         break;
     652             :       }
     653             :     }
     654             : 
     655           0 :     if (!found) {
     656           0 :       return NS_ERROR_DOM_INDEXEDDB_NOT_FOUND_ERR;
     657             :     }
     658             : 
     659           0 :     sortedStoreNames.InsertElementSorted(name);
     660             :   }
     661             : 
     662             :   // Remove any duplicates.
     663           0 :   for (uint32_t nameIndex = nameCount - 1; nameIndex > 0; nameIndex--) {
     664           0 :     if (sortedStoreNames[nameIndex] == sortedStoreNames[nameIndex - 1]) {
     665           0 :       sortedStoreNames.RemoveElementAt(nameIndex);
     666             :     }
     667             :   }
     668             : 
     669             :   IDBTransaction::Mode mode;
     670           0 :   switch (aMode) {
     671             :     case IDBTransactionMode::Readonly:
     672           0 :       mode = IDBTransaction::READ_ONLY;
     673           0 :       break;
     674             :     case IDBTransactionMode::Readwrite:
     675           0 :       if (mQuotaExceeded) {
     676           0 :         mode = IDBTransaction::CLEANUP;
     677           0 :         mQuotaExceeded = false;
     678             :       } else {
     679           0 :         mode = IDBTransaction::READ_WRITE;
     680             :       }
     681           0 :       break;
     682             :     case IDBTransactionMode::Readwriteflush:
     683           0 :       mode = IDBTransaction::READ_WRITE_FLUSH;
     684           0 :       break;
     685             :     case IDBTransactionMode::Cleanup:
     686           0 :       mode = IDBTransaction::CLEANUP;
     687           0 :       mQuotaExceeded = false;
     688           0 :       break;
     689             :     case IDBTransactionMode::Versionchange:
     690           0 :       return NS_ERROR_DOM_TYPE_ERR;
     691             : 
     692             :     default:
     693           0 :       MOZ_CRASH("Unknown mode!");
     694             :   }
     695             : 
     696             :   RefPtr<IDBTransaction> transaction =
     697           0 :     IDBTransaction::Create(aCx, this, sortedStoreNames, mode);
     698           0 :   MOZ_ASSERT(transaction);
     699             : 
     700             :   BackgroundTransactionChild* actor =
     701           0 :     new BackgroundTransactionChild(transaction);
     702             : 
     703           0 :   IDB_LOG_MARK("IndexedDB %s: Child  Transaction[%lld]: "
     704             :                  "database(%s).transaction(%s)",
     705             :                "IndexedDB %s: C T[%lld]: IDBDatabase.transaction()",
     706             :                IDB_LOG_ID_STRING(),
     707             :                transaction->LoggingSerialNumber(),
     708             :                IDB_LOG_STRINGIFY(this),
     709             :                IDB_LOG_STRINGIFY(transaction));
     710             : 
     711           0 :   MOZ_ALWAYS_TRUE(
     712             :     mBackgroundActor->SendPBackgroundIDBTransactionConstructor(actor,
     713             :                                                                sortedStoreNames,
     714             :                                                                mode));
     715           0 :   MOZ_ASSERT(actor->GetActorEventTarget(),
     716             :     "The event target shall be inherited from it manager actor.");
     717             : 
     718           0 :   transaction->SetBackgroundActor(actor);
     719             : 
     720           0 :   if (mode == IDBTransaction::CLEANUP) {
     721           0 :     ExpireFileActors(/* aExpireAll */ true);
     722             :   }
     723             : 
     724           0 :   transaction.forget(aTransaction);
     725           0 :   return NS_OK;
     726             : }
     727             : 
     728             : StorageType
     729           0 : IDBDatabase::Storage() const
     730             : {
     731           0 :   AssertIsOnOwningThread();
     732           0 :   MOZ_ASSERT(mSpec);
     733             : 
     734           0 :   return PersistenceTypeToStorage(mSpec->metadata().persistenceType());
     735             : }
     736             : 
     737             : already_AddRefed<IDBRequest>
     738           0 : IDBDatabase::CreateMutableFile(JSContext* aCx,
     739             :                                const nsAString& aName,
     740             :                                const Optional<nsAString>& aType,
     741             :                                ErrorResult& aRv)
     742             : {
     743           0 :   AssertIsOnOwningThread();
     744             : 
     745           0 :   if (QuotaManager::IsShuttingDown()) {
     746           0 :     IDB_REPORT_INTERNAL_ERR();
     747           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     748           0 :     return nullptr;
     749             :   }
     750             : 
     751           0 :   if (mClosed || mFileHandleDisabled) {
     752           0 :     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
     753           0 :     return nullptr;
     754             :   }
     755             : 
     756           0 :   nsString type;
     757           0 :   if (aType.WasPassed()) {
     758           0 :     type = aType.Value();
     759             :   }
     760             : 
     761           0 :   CreateFileParams params(nsString(aName), type);
     762             : 
     763           0 :   RefPtr<IDBRequest> request = IDBRequest::Create(aCx, this, nullptr);
     764           0 :   MOZ_ASSERT(request);
     765             : 
     766             :   BackgroundDatabaseRequestChild* actor =
     767           0 :     new BackgroundDatabaseRequestChild(this, request);
     768             : 
     769           0 :   IDB_LOG_MARK("IndexedDB %s: Child  Request[%llu]: "
     770             :                  "database(%s).createMutableFile(%s)",
     771             :                "IndexedDB %s: C R[%llu]: IDBDatabase.createMutableFile()",
     772             :                IDB_LOG_ID_STRING(),
     773             :                request->LoggingSerialNumber(),
     774             :                IDB_LOG_STRINGIFY(this),
     775             :                NS_ConvertUTF16toUTF8(aName).get());
     776             : 
     777           0 :   mBackgroundActor->SendPBackgroundIDBDatabaseRequestConstructor(actor, params);
     778             : 
     779           0 :   MOZ_ASSERT(actor->GetActorEventTarget(),
     780             :     "The event target shall be inherited from its manager actor.");
     781             : 
     782           0 :   return request.forget();
     783             : }
     784             : 
     785             : void
     786           0 : IDBDatabase::RegisterTransaction(IDBTransaction* aTransaction)
     787             : {
     788           0 :   AssertIsOnOwningThread();
     789           0 :   MOZ_ASSERT(aTransaction);
     790           0 :   aTransaction->AssertIsOnOwningThread();
     791           0 :   MOZ_ASSERT(!mTransactions.Contains(aTransaction));
     792             : 
     793           0 :   mTransactions.PutEntry(aTransaction);
     794           0 : }
     795             : 
     796             : void
     797           0 : IDBDatabase::UnregisterTransaction(IDBTransaction* aTransaction)
     798             : {
     799           0 :   AssertIsOnOwningThread();
     800           0 :   MOZ_ASSERT(aTransaction);
     801           0 :   aTransaction->AssertIsOnOwningThread();
     802           0 :   MOZ_ASSERT(mTransactions.Contains(aTransaction));
     803             : 
     804           0 :   mTransactions.RemoveEntry(aTransaction);
     805           0 : }
     806             : 
     807             : void
     808           0 : IDBDatabase::AbortTransactions(bool aShouldWarn)
     809             : {
     810           0 :   AssertIsOnOwningThread();
     811             : 
     812             :   class MOZ_STACK_CLASS Helper final
     813             :   {
     814             :     typedef AutoTArray<RefPtr<IDBTransaction>, 20> StrongTransactionArray;
     815             :     typedef AutoTArray<IDBTransaction*, 20> WeakTransactionArray;
     816             : 
     817             :   public:
     818             :     static void
     819           0 :     AbortTransactions(IDBDatabase* aDatabase, const bool aShouldWarn)
     820             :     {
     821           0 :       MOZ_ASSERT(aDatabase);
     822           0 :       aDatabase->AssertIsOnOwningThread();
     823             : 
     824             :       nsTHashtable<nsPtrHashKey<IDBTransaction>>& transactionTable =
     825           0 :         aDatabase->mTransactions;
     826             : 
     827           0 :       if (!transactionTable.Count()) {
     828           0 :         return;
     829             :       }
     830             : 
     831           0 :       StrongTransactionArray transactionsToAbort;
     832           0 :       transactionsToAbort.SetCapacity(transactionTable.Count());
     833             : 
     834           0 :       for (auto iter = transactionTable.Iter(); !iter.Done(); iter.Next()) {
     835           0 :         IDBTransaction* transaction = iter.Get()->GetKey();
     836           0 :         MOZ_ASSERT(transaction);
     837             : 
     838           0 :         transaction->AssertIsOnOwningThread();
     839             : 
     840             :         // Transactions that are already done can simply be ignored. Otherwise
     841             :         // there is a race here and it's possible that the transaction has not
     842             :         // been successfully committed yet so we will warn the user.
     843           0 :         if (!transaction->IsDone()) {
     844           0 :           transactionsToAbort.AppendElement(transaction);
     845             :         }
     846             :       }
     847           0 :       MOZ_ASSERT(transactionsToAbort.Length() <= transactionTable.Count());
     848             : 
     849           0 :       if (transactionsToAbort.IsEmpty()) {
     850           0 :         return;
     851             :       }
     852             : 
     853             :       // We want to abort transactions as soon as possible so we iterate the
     854             :       // transactions once and abort them all first, collecting the transactions
     855             :       // that need to have a warning issued along the way. Those that need a
     856             :       // warning will be a subset of those that are aborted, so we don't need
     857             :       // additional strong references here.
     858           0 :       WeakTransactionArray transactionsThatNeedWarning;
     859             : 
     860           0 :       for (RefPtr<IDBTransaction>& transaction : transactionsToAbort) {
     861           0 :         MOZ_ASSERT(transaction);
     862           0 :         MOZ_ASSERT(!transaction->IsDone());
     863             : 
     864           0 :         if (aShouldWarn) {
     865           0 :           switch (transaction->GetMode()) {
     866             :             // We ignore transactions that could not have written any data.
     867             :             case IDBTransaction::READ_ONLY:
     868           0 :               break;
     869             : 
     870             :             // We warn for any transactions that could have written data.
     871             :             case IDBTransaction::READ_WRITE:
     872             :             case IDBTransaction::READ_WRITE_FLUSH:
     873             :             case IDBTransaction::CLEANUP:
     874             :             case IDBTransaction::VERSION_CHANGE:
     875           0 :               transactionsThatNeedWarning.AppendElement(transaction);
     876           0 :               break;
     877             : 
     878             :             default:
     879           0 :               MOZ_CRASH("Unknown mode!");
     880             :           }
     881             :         }
     882             : 
     883           0 :         transaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
     884             :       }
     885             : 
     886             :       static const char kWarningMessage[] =
     887             :         "IndexedDBTransactionAbortNavigation";
     888             : 
     889           0 :       for (IDBTransaction* transaction : transactionsThatNeedWarning) {
     890           0 :         MOZ_ASSERT(transaction);
     891             : 
     892           0 :         nsString filename;
     893             :         uint32_t lineNo, column;
     894           0 :         transaction->GetCallerLocation(filename, &lineNo, &column);
     895             : 
     896           0 :         aDatabase->LogWarning(kWarningMessage, filename, lineNo, column);
     897             :       }
     898             :     }
     899             :   };
     900             : 
     901           0 :   Helper::AbortTransactions(this, aShouldWarn);
     902           0 : }
     903             : 
     904             : PBackgroundIDBDatabaseFileChild*
     905           0 : IDBDatabase::GetOrCreateFileActorForBlob(Blob* aBlob)
     906             : {
     907           0 :   AssertIsOnOwningThread();
     908           0 :   MOZ_ASSERT(aBlob);
     909           0 :   MOZ_ASSERT(mBackgroundActor);
     910             : 
     911             :   // We use the File's nsIWeakReference as the key to the table because
     912             :   // a) it is unique per blob, b) it is reference-counted so that we can
     913             :   // guarantee that it stays alive, and c) it doesn't hold the actual File
     914             :   // alive.
     915           0 :   nsCOMPtr<nsIDOMBlob> blob = aBlob;
     916           0 :   nsCOMPtr<nsIWeakReference> weakRef = do_GetWeakReference(blob);
     917           0 :   MOZ_ASSERT(weakRef);
     918             : 
     919           0 :   PBackgroundIDBDatabaseFileChild* actor = nullptr;
     920             : 
     921           0 :   if (!mFileActors.Get(weakRef, &actor)) {
     922           0 :     BlobImpl* blobImpl = aBlob->Impl();
     923           0 :     MOZ_ASSERT(blobImpl);
     924             : 
     925             :     PBackgroundChild* backgroundManager =
     926           0 :       mBackgroundActor->Manager()->Manager();
     927           0 :     MOZ_ASSERT(backgroundManager);
     928             : 
     929           0 :     IPCBlob ipcBlob;
     930           0 :     nsresult rv = IPCBlobUtils::Serialize(blobImpl, backgroundManager, ipcBlob);
     931           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     932           0 :       return nullptr;
     933             :     }
     934             : 
     935           0 :     auto* dbFile = new DatabaseFile(this);
     936             : 
     937           0 :     actor =
     938           0 :       mBackgroundActor->SendPBackgroundIDBDatabaseFileConstructor(dbFile,
     939             :                                                                   ipcBlob);
     940           0 :     if (NS_WARN_IF(!actor)) {
     941           0 :       return nullptr;
     942             :     }
     943             : 
     944           0 :     MOZ_ASSERT(actor->GetActorEventTarget(),
     945             :      "The event target shall be inherited from its manager actor.");
     946           0 :     mFileActors.Put(weakRef, actor);
     947             :   }
     948             : 
     949           0 :   MOZ_ASSERT(actor);
     950             : 
     951           0 :   return actor;
     952             : }
     953             : 
     954             : void
     955           0 : IDBDatabase::NoteFinishedFileActor(PBackgroundIDBDatabaseFileChild* aFileActor)
     956             : {
     957           0 :   AssertIsOnOwningThread();
     958           0 :   MOZ_ASSERT(aFileActor);
     959             : 
     960           0 :   for (auto iter = mFileActors.Iter(); !iter.Done(); iter.Next()) {
     961           0 :     MOZ_ASSERT(iter.Key());
     962           0 :     PBackgroundIDBDatabaseFileChild* actor = iter.Data();
     963           0 :     MOZ_ASSERT(actor);
     964             : 
     965           0 :     if (actor == aFileActor) {
     966           0 :       iter.Remove();
     967             :     }
     968             :   }
     969           0 : }
     970             : 
     971             : void
     972           0 : IDBDatabase::NoteActiveTransaction()
     973             : {
     974           0 :   AssertIsOnOwningThread();
     975           0 :   MOZ_ASSERT(mFactory);
     976             : 
     977             :   // Increase the number of active transactions.
     978           0 :   mFactory->UpdateActiveTransactionCount(1);
     979           0 : }
     980             : 
     981             : void
     982           0 : IDBDatabase::NoteInactiveTransaction()
     983             : {
     984           0 :   AssertIsOnOwningThread();
     985             : 
     986           0 :   if (!mBackgroundActor || !mFileActors.Count()) {
     987           0 :     MOZ_ASSERT(mFactory);
     988           0 :     mFactory->UpdateActiveTransactionCount(-1);
     989           0 :     return;
     990             :   }
     991             : 
     992             :   RefPtr<Runnable> runnable =
     993           0 :     NewRunnableMethod("IDBDatabase::NoteInactiveTransactionDelayed",
     994             :                       this,
     995           0 :                       &IDBDatabase::NoteInactiveTransactionDelayed);
     996           0 :   MOZ_ASSERT(runnable);
     997             : 
     998           0 :   if (!NS_IsMainThread()) {
     999             :     // Wrap as a nsICancelableRunnable to make workers happy.
    1000           0 :     RefPtr<Runnable> cancelable = new CancelableRunnableWrapper(runnable);
    1001           0 :     cancelable.swap(runnable);
    1002             :   }
    1003             : 
    1004           0 :   MOZ_ALWAYS_SUCCEEDS(
    1005             :     EventTarget()->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL));
    1006             : }
    1007             : 
    1008             : nsresult
    1009           0 : IDBDatabase::GetQuotaInfo(nsACString& aOrigin,
    1010             :                           PersistenceType* aPersistenceType)
    1011             : {
    1012             :   using mozilla::dom::quota::QuotaManager;
    1013             : 
    1014           0 :   MOZ_ASSERT(NS_IsMainThread(), "This can't work off the main thread!");
    1015             : 
    1016           0 :   if (aPersistenceType) {
    1017           0 :     *aPersistenceType = mSpec->metadata().persistenceType();
    1018           0 :     MOZ_ASSERT(*aPersistenceType != PERSISTENCE_TYPE_INVALID);
    1019             :   }
    1020             : 
    1021           0 :   PrincipalInfo* principalInfo = mFactory->GetPrincipalInfo();
    1022           0 :   MOZ_ASSERT(principalInfo);
    1023             : 
    1024           0 :   switch (principalInfo->type()) {
    1025             :     case PrincipalInfo::TNullPrincipalInfo:
    1026           0 :       MOZ_CRASH("Is this needed?!");
    1027             : 
    1028             :     case PrincipalInfo::TSystemPrincipalInfo:
    1029           0 :       QuotaManager::GetInfoForChrome(nullptr, nullptr, &aOrigin);
    1030           0 :       return NS_OK;
    1031             : 
    1032             :     case PrincipalInfo::TContentPrincipalInfo: {
    1033             :       nsresult rv;
    1034             :       nsCOMPtr<nsIPrincipal> principal =
    1035           0 :         PrincipalInfoToPrincipal(*principalInfo, &rv);
    1036           0 :       if (NS_WARN_IF(NS_FAILED(rv))) {
    1037           0 :         return rv;
    1038             :       }
    1039             : 
    1040           0 :       rv = QuotaManager::GetInfoFromPrincipal(principal,
    1041             :                                               nullptr,
    1042             :                                               nullptr,
    1043             :                                               &aOrigin);
    1044           0 :       if (NS_WARN_IF(NS_FAILED(rv))) {
    1045           0 :         return rv;
    1046             :       }
    1047             : 
    1048           0 :       return NS_OK;
    1049             :     }
    1050             : 
    1051             :     default:
    1052           0 :       MOZ_CRASH("Unknown PrincipalInfo type!");
    1053             :   }
    1054             : 
    1055             :   MOZ_CRASH("Should never get here!");
    1056             : }
    1057             : 
    1058             : void
    1059           0 : IDBDatabase::ExpireFileActors(bool aExpireAll)
    1060             : {
    1061           0 :   AssertIsOnOwningThread();
    1062             : 
    1063           0 :   if (mBackgroundActor && mFileActors.Count()) {
    1064           0 :     for (auto iter = mFileActors.Iter(); !iter.Done(); iter.Next()) {
    1065           0 :       nsISupports* key = iter.Key();
    1066           0 :       PBackgroundIDBDatabaseFileChild* actor = iter.Data();
    1067           0 :       MOZ_ASSERT(key);
    1068           0 :       MOZ_ASSERT(actor);
    1069             : 
    1070           0 :       bool shouldExpire = aExpireAll;
    1071           0 :       if (!shouldExpire) {
    1072           0 :         nsCOMPtr<nsIWeakReference> weakRef = do_QueryInterface(key);
    1073           0 :         MOZ_ASSERT(weakRef);
    1074             : 
    1075           0 :         nsCOMPtr<nsISupports> referent = do_QueryReferent(weakRef);
    1076           0 :         shouldExpire = !referent;
    1077             :       }
    1078             : 
    1079           0 :       if (shouldExpire) {
    1080           0 :         PBackgroundIDBDatabaseFileChild::Send__delete__(actor);
    1081             : 
    1082           0 :         if (!aExpireAll) {
    1083           0 :           iter.Remove();
    1084             :         }
    1085             :       }
    1086             :     }
    1087           0 :     if (aExpireAll) {
    1088           0 :       mFileActors.Clear();
    1089             :     }
    1090             :   } else {
    1091           0 :     MOZ_ASSERT(!mFileActors.Count());
    1092             :   }
    1093           0 : }
    1094             : 
    1095             : void
    1096           0 : IDBDatabase::NoteLiveMutableFile(IDBMutableFile* aMutableFile)
    1097             : {
    1098           0 :   AssertIsOnOwningThread();
    1099           0 :   MOZ_ASSERT(aMutableFile);
    1100           0 :   aMutableFile->AssertIsOnOwningThread();
    1101           0 :   MOZ_ASSERT(!mLiveMutableFiles.Contains(aMutableFile));
    1102             : 
    1103           0 :   mLiveMutableFiles.AppendElement(aMutableFile);
    1104           0 : }
    1105             : 
    1106             : void
    1107           0 : IDBDatabase::NoteFinishedMutableFile(IDBMutableFile* aMutableFile)
    1108             : {
    1109           0 :   AssertIsOnOwningThread();
    1110           0 :   MOZ_ASSERT(aMutableFile);
    1111           0 :   aMutableFile->AssertIsOnOwningThread();
    1112             : 
    1113             :   // It's ok if this is called after we cleared the array, so don't assert that
    1114             :   // aMutableFile is in the list.
    1115             : 
    1116           0 :   mLiveMutableFiles.RemoveElement(aMutableFile);
    1117           0 : }
    1118             : 
    1119             : void
    1120           0 : IDBDatabase::InvalidateMutableFiles()
    1121             : {
    1122           0 :   AssertIsOnOwningThread();
    1123             : 
    1124           0 :   if (!mLiveMutableFiles.IsEmpty()) {
    1125           0 :     for (uint32_t count = mLiveMutableFiles.Length(), index = 0;
    1126           0 :          index < count;
    1127             :          index++) {
    1128           0 :       mLiveMutableFiles[index]->Invalidate();
    1129             :     }
    1130             : 
    1131           0 :     mLiveMutableFiles.Clear();
    1132             :   }
    1133           0 : }
    1134             : 
    1135             : void
    1136           0 : IDBDatabase::Invalidate()
    1137             : {
    1138           0 :   AssertIsOnOwningThread();
    1139             : 
    1140           0 :   if (!mInvalidated) {
    1141           0 :     mInvalidated = true;
    1142             : 
    1143           0 :     InvalidateInternal();
    1144             :   }
    1145           0 : }
    1146             : 
    1147             : void
    1148           0 : IDBDatabase::NoteInactiveTransactionDelayed()
    1149             : {
    1150           0 :   ExpireFileActors(/* aExpireAll */ false);
    1151             : 
    1152           0 :   MOZ_ASSERT(mFactory);
    1153           0 :   mFactory->UpdateActiveTransactionCount(-1);
    1154           0 : }
    1155             : 
    1156             : void
    1157           0 : IDBDatabase::LogWarning(const char* aMessageName,
    1158             :                         const nsAString& aFilename,
    1159             :                         uint32_t aLineNumber,
    1160             :                         uint32_t aColumnNumber)
    1161             : {
    1162           0 :   AssertIsOnOwningThread();
    1163           0 :   MOZ_ASSERT(aMessageName);
    1164             : 
    1165           0 :   ScriptErrorHelper::DumpLocalizedMessage(nsDependentCString(aMessageName),
    1166             :                                           aFilename,
    1167             :                                           aLineNumber,
    1168             :                                           aColumnNumber,
    1169             :                                           nsIScriptError::warningFlag,
    1170           0 :                                           mFactory->IsChrome(),
    1171           0 :                                           mFactory->InnerWindowID());
    1172           0 : }
    1173             : 
    1174           0 : NS_IMPL_ADDREF_INHERITED(IDBDatabase, IDBWrapperCache)
    1175           0 : NS_IMPL_RELEASE_INHERITED(IDBDatabase, IDBWrapperCache)
    1176             : 
    1177           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBDatabase)
    1178           0 : NS_INTERFACE_MAP_END_INHERITING(IDBWrapperCache)
    1179             : 
    1180             : NS_IMPL_CYCLE_COLLECTION_CLASS(IDBDatabase)
    1181             : 
    1182           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBDatabase, IDBWrapperCache)
    1183           0 :   tmp->AssertIsOnOwningThread();
    1184           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFactory)
    1185           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    1186             : 
    1187           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBDatabase, IDBWrapperCache)
    1188           0 :   tmp->AssertIsOnOwningThread();
    1189             : 
    1190             :   // Don't unlink mFactory!
    1191             : 
    1192             :   // We've been unlinked, at the very least we should be able to prevent further
    1193             :   // transactions from starting and unblock any other SetVersion callers.
    1194           0 :   tmp->CloseInternal();
    1195           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    1196             : 
    1197             : void
    1198           0 : IDBDatabase::LastRelease()
    1199             : {
    1200           0 :   AssertIsOnOwningThread();
    1201             : 
    1202           0 :   CloseInternal();
    1203             : 
    1204           0 :   if (mBackgroundActor) {
    1205           0 :     mBackgroundActor->SendDeleteMeInternal();
    1206           0 :     MOZ_ASSERT(!mBackgroundActor, "SendDeleteMeInternal should have cleared!");
    1207             :   }
    1208           0 : }
    1209             : 
    1210             : nsresult
    1211           0 : IDBDatabase::PostHandleEvent(EventChainPostVisitor& aVisitor)
    1212             : {
    1213             :   nsresult rv =
    1214           0 :     IndexedDatabaseManager::CommonPostHandleEvent(aVisitor, mFactory);
    1215           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
    1216           0 :     return rv;
    1217             :   }
    1218             : 
    1219           0 :   return NS_OK;
    1220             : }
    1221             : 
    1222             : JSObject*
    1223           0 : IDBDatabase::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
    1224             : {
    1225           0 :   return IDBDatabaseBinding::Wrap(aCx, this, aGivenProto);
    1226             : }
    1227             : 
    1228             : NS_IMETHODIMP
    1229           0 : CancelableRunnableWrapper::Run()
    1230             : {
    1231           0 :   nsCOMPtr<nsIRunnable> runnable;
    1232           0 :   mRunnable.swap(runnable);
    1233             : 
    1234           0 :   if (runnable) {
    1235           0 :     return runnable->Run();
    1236             :   }
    1237             : 
    1238           0 :   return NS_OK;
    1239             : }
    1240             : 
    1241             : nsresult
    1242           0 : CancelableRunnableWrapper::Cancel()
    1243             : {
    1244           0 :   if (mRunnable) {
    1245           0 :     mRunnable = nullptr;
    1246           0 :     return NS_OK;
    1247             :   }
    1248             : 
    1249           0 :   return NS_ERROR_UNEXPECTED;
    1250             : }
    1251             : 
    1252           0 : NS_IMPL_ISUPPORTS(IDBDatabase::Observer, nsIObserver)
    1253             : 
    1254             : NS_IMETHODIMP
    1255           0 : IDBDatabase::
    1256             : Observer::Observe(nsISupports* aSubject,
    1257             :                   const char* aTopic,
    1258             :                   const char16_t* aData)
    1259             : {
    1260           0 :   MOZ_ASSERT(NS_IsMainThread());
    1261           0 :   MOZ_ASSERT(aTopic);
    1262             : 
    1263           0 :   if (!strcmp(aTopic, kWindowObserverTopic)) {
    1264           0 :     if (mWeakDatabase) {
    1265           0 :       nsCOMPtr<nsISupportsPRUint64> supportsInt = do_QueryInterface(aSubject);
    1266           0 :       MOZ_ASSERT(supportsInt);
    1267             : 
    1268             :       uint64_t windowId;
    1269           0 :       MOZ_ALWAYS_SUCCEEDS(supportsInt->GetData(&windowId));
    1270             : 
    1271           0 :       if (windowId == mWindowId) {
    1272           0 :         RefPtr<IDBDatabase> database = mWeakDatabase;
    1273           0 :         mWeakDatabase = nullptr;
    1274             : 
    1275           0 :         database->InvalidateInternal();
    1276             :       }
    1277             :     }
    1278             : 
    1279           0 :     return NS_OK;
    1280             :   }
    1281             : 
    1282           0 :   if (!strcmp(aTopic, kCycleCollectionObserverTopic) ||
    1283           0 :       !strcmp(aTopic, kMemoryPressureObserverTopic)) {
    1284           0 :     if (mWeakDatabase) {
    1285           0 :       RefPtr<IDBDatabase> database = mWeakDatabase;
    1286             : 
    1287           0 :       database->ExpireFileActors(/* aExpireAll */ false);
    1288             :     }
    1289             : 
    1290           0 :     return NS_OK;
    1291             :   }
    1292             : 
    1293           0 :   NS_WARNING("Unknown observer topic!");
    1294           0 :   return NS_OK;
    1295             : }
    1296             : 
    1297             : nsresult
    1298           0 : IDBDatabase::RenameObjectStore(int64_t aObjectStoreId, const nsAString& aName)
    1299             : {
    1300           0 :   MOZ_ASSERT(mSpec);
    1301             : 
    1302           0 :   nsTArray<ObjectStoreSpec>& objectStores = mSpec->objectStores();
    1303             : 
    1304           0 :   ObjectStoreSpec* foundObjectStoreSpec = nullptr;
    1305             :   // Find the matched object store spec and check if 'aName' is already used by
    1306             :   // another object store.
    1307           0 :   for (uint32_t objCount = objectStores.Length(), objIndex = 0;
    1308           0 :        objIndex < objCount;
    1309             :        objIndex++) {
    1310           0 :     const ObjectStoreSpec& objSpec = objectStores[objIndex];
    1311           0 :     if (objSpec.metadata().id() == aObjectStoreId) {
    1312           0 :       MOZ_ASSERT(!foundObjectStoreSpec);
    1313           0 :       foundObjectStoreSpec = &objectStores[objIndex];
    1314           0 :       continue;
    1315             :     }
    1316           0 :     if (aName == objSpec.metadata().name()) {
    1317           0 :       return NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR;
    1318             :     }
    1319             :   }
    1320             : 
    1321           0 :   MOZ_ASSERT(foundObjectStoreSpec);
    1322             : 
    1323             :   // Update the name of the matched object store.
    1324           0 :   foundObjectStoreSpec->metadata().name() = nsString(aName);
    1325             : 
    1326           0 :   return NS_OK;
    1327             : }
    1328             : 
    1329             : nsresult
    1330           0 : IDBDatabase::RenameIndex(int64_t aObjectStoreId,
    1331             :                          int64_t aIndexId,
    1332             :                          const nsAString& aName)
    1333             : {
    1334           0 :   MOZ_ASSERT(mSpec);
    1335             : 
    1336           0 :   nsTArray<ObjectStoreSpec>& objectStores = mSpec->objectStores();
    1337             : 
    1338           0 :   ObjectStoreSpec* foundObjectStoreSpec = nullptr;
    1339             :   // Find the matched index metadata and check if 'aName' is already used by
    1340             :   // another index.
    1341           0 :   for (uint32_t objCount = objectStores.Length(), objIndex = 0;
    1342           0 :        objIndex < objCount;
    1343             :        objIndex++) {
    1344           0 :     const ObjectStoreSpec& objSpec = objectStores[objIndex];
    1345           0 :     if (objSpec.metadata().id() == aObjectStoreId) {
    1346           0 :       foundObjectStoreSpec = &objectStores[objIndex];
    1347           0 :       break;
    1348             :     }
    1349             :   }
    1350             : 
    1351           0 :   MOZ_ASSERT(foundObjectStoreSpec);
    1352             : 
    1353           0 :   nsTArray<IndexMetadata>& indexes = foundObjectStoreSpec->indexes();
    1354           0 :   IndexMetadata* foundIndexMetadata = nullptr;
    1355           0 :   for (uint32_t idxCount = indexes.Length(), idxIndex = 0;
    1356           0 :        idxIndex < idxCount;
    1357             :        idxIndex++) {
    1358           0 :     const IndexMetadata& metadata = indexes[idxIndex];
    1359           0 :     if (metadata.id() == aIndexId) {
    1360           0 :       MOZ_ASSERT(!foundIndexMetadata);
    1361           0 :       foundIndexMetadata = &indexes[idxIndex];
    1362           0 :       continue;
    1363             :     }
    1364           0 :     if (aName == metadata.name()) {
    1365           0 :       return NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR;
    1366             :     }
    1367             :   }
    1368             : 
    1369           0 :   MOZ_ASSERT(foundIndexMetadata);
    1370             : 
    1371             :   // Update the name of the matched object store.
    1372           0 :   foundIndexMetadata->name() = nsString(aName);
    1373             : 
    1374           0 :   return NS_OK;
    1375             : }
    1376             : 
    1377             : void
    1378           0 : IDBDatabase::IncreaseActiveDatabaseCount()
    1379             : {
    1380           0 :   AssertIsOnOwningThread();
    1381           0 :   MOZ_ASSERT(mFactory);
    1382           0 :   MOZ_ASSERT(!mIncreasedActiveDatabaseCount);
    1383             : 
    1384           0 :   mFactory->UpdateActiveDatabaseCount(1);
    1385           0 :   mIncreasedActiveDatabaseCount = true;
    1386           0 : }
    1387             : 
    1388             : void
    1389           0 : IDBDatabase::MaybeDecreaseActiveDatabaseCount()
    1390             : {
    1391           0 :   AssertIsOnOwningThread();
    1392             : 
    1393           0 :   if (mIncreasedActiveDatabaseCount) {
    1394             :     // Decrease the number of active databases.
    1395           0 :     MOZ_ASSERT(mFactory);
    1396           0 :     mFactory->UpdateActiveDatabaseCount(-1);
    1397           0 :     mIncreasedActiveDatabaseCount = false;
    1398             :   }
    1399           0 : }
    1400             : 
    1401             : } // namespace dom
    1402             : } // namespace mozilla

Generated by: LCOV version 1.13