Bug 1286798 - Part 41: Implement QuotaClient::AbortOperationsForProcess; r=asuth
authorJan Varga <jan.varga@gmail.com>
Thu, 29 Nov 2018 21:49:27 +0100
changeset 508039 270fc081f01f49ebc32dfc9cad99e937e2fba4a2
parent 508038 f2cdc8e4ef39643e4d3930544ecde4b690c3e326
child 508040 398f80b485a969faead8677260975d1b6e2f4606
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs1286798
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1286798 - Part 41: Implement QuotaClient::AbortOperationsForProcess; r=asuth Needed for snapshot reusing.
dom/localstorage/ActorsParent.cpp
--- a/dom/localstorage/ActorsParent.cpp
+++ b/dom/localstorage/ActorsParent.cpp
@@ -9,16 +9,17 @@
 #include "LocalStorageCommon.h"
 #include "LSObject.h"
 #include "mozIStorageConnection.h"
 #include "mozIStorageService.h"
 #include "mozStorageCID.h"
 #include "mozStorageHelper.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Unused.h"
+#include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/PBackgroundLSDatabaseParent.h"
 #include "mozilla/dom/PBackgroundLSObserverParent.h"
 #include "mozilla/dom/PBackgroundLSRequestParent.h"
 #include "mozilla/dom/PBackgroundLSSharedTypes.h"
 #include "mozilla/dom/PBackgroundLSSimpleRequestParent.h"
 #include "mozilla/dom/PBackgroundLSSnapshotParent.h"
 #include "mozilla/dom/StorageDBUpdater.h"
 #include "mozilla/dom/StorageUtils.h"
@@ -1587,30 +1588,33 @@ private:
                   const nsString& aOldValue,
                   const nsString& aNewValue);
 };
 
 class PreparedDatastore
 {
   RefPtr<Datastore> mDatastore;
   nsCOMPtr<nsITimer> mTimer;
+  const Maybe<ContentParentId> mContentParentId;
   // Strings share buffers if possible, so it's not a problem to duplicate the
   // origin here.
   const nsCString mOrigin;
   uint64_t mDatastoreId;
   bool mForPreload;
   bool mInvalidated;
 
 public:
   PreparedDatastore(Datastore* aDatastore,
+                    const Maybe<ContentParentId>& aContentParentId,
                     const nsACString& aOrigin,
                     uint64_t aDatastoreId,
                     bool aForPreload)
     : mDatastore(aDatastore)
     , mTimer(NS_NewTimer())
+    , mContentParentId(aContentParentId)
     , mOrigin(aOrigin)
     , mDatastoreId(aDatastoreId)
     , mForPreload(aForPreload)
     , mInvalidated(false)
   {
     AssertIsOnBackgroundThread();
     MOZ_ASSERT(aDatastore);
     MOZ_ASSERT(mTimer);
@@ -1639,16 +1643,22 @@ public:
   GetDatastore() const
   {
     AssertIsOnBackgroundThread();
     MOZ_ASSERT(mDatastore);
 
     return mDatastore;
   }
 
+  const Maybe<ContentParentId>&
+  GetContentParentId() const
+  {
+    return mContentParentId;
+  }
+
   const nsCString&
   Origin() const
   {
     return mOrigin;
   }
 
   void
   Invalidate()
@@ -1690,46 +1700,54 @@ private:
  ******************************************************************************/
 
 class Database final
   : public PBackgroundLSDatabaseParent
 {
   RefPtr<Datastore> mDatastore;
   Snapshot* mSnapshot;
   const PrincipalInfo mPrincipalInfo;
+  const Maybe<ContentParentId> mContentParentId;
   // Strings share buffers if possible, so it's not a problem to duplicate the
   // origin here.
   nsCString mOrigin;
   uint32_t mPrivateBrowsingId;
   bool mAllowedToClose;
   bool mActorDestroyed;
   bool mRequestedAllowToClose;
 #ifdef DEBUG
   bool mActorWasAlive;
 #endif
 
 public:
   // Created in AllocPBackgroundLSDatabaseParent.
   Database(const PrincipalInfo& aPrincipalInfo,
+           const Maybe<ContentParentId>& aContentParentId,
            const nsACString& aOrigin,
            uint32_t aPrivateBrowsingId);
 
   Datastore*
   GetDatastore() const
   {
     AssertIsOnBackgroundThread();
     return mDatastore;
   }
 
   const PrincipalInfo&
   GetPrincipalInfo() const
   {
     return mPrincipalInfo;
   }
 
+  bool
+  IsOwnedByProcess(ContentParentId aContentParentId) const
+  {
+    return mContentParentId && mContentParentId.value() == aContentParentId;
+  }
+
   uint32_t
   PrivateBrowsingId() const
   {
     return mPrivateBrowsingId;
   }
 
   const nsCString&
   Origin() const
@@ -2060,25 +2078,27 @@ class PrepareDatastoreOp
     // to SendingReadyMessage.
     DatabaseWorkLoadData,
 
     // The nesting has completed.
     AfterNesting
   };
 
   nsCOMPtr<nsIEventTarget> mMainEventTarget;
+  RefPtr<ContentParent> mContentParent;
   RefPtr<PrepareDatastoreOp> mDelayedOp;
   RefPtr<DirectoryLock> mDirectoryLock;
   RefPtr<Connection> mConnection;
   RefPtr<Datastore> mDatastore;
   nsAutoPtr<ArchivedOriginInfo> mArchivedOriginInfo;
   LoadDataOp* mLoadDataOp;
   nsDataHashtable<nsStringHashKey, nsString> mValues;
   nsTArray<LSItemInfo> mOrderedItems;
   const LSRequestPrepareDatastoreParams mParams;
+  Maybe<ContentParentId> mContentParentId;
   nsCString mSuffix;
   nsCString mGroup;
   nsCString mMainThreadOrigin;
   nsCString mOrigin;
   nsString mDatabaseFilePath;
   uint32_t mPrivateBrowsingId;
   int64_t mUsage;
   int64_t mSizeOfKeys;
@@ -2089,16 +2109,17 @@ class PrepareDatastoreOp
   bool mInvalidated;
 
 #ifdef DEBUG
   int64_t mDEBUGUsage;
 #endif
 
 public:
   PrepareDatastoreOp(nsIEventTarget* aMainEventTarget,
+                     already_AddRefed<ContentParent> aContentParent,
                      const LSRequestParams& aParams);
 
   bool
   OriginIsKnown() const
   {
     AssertIsOnOwningThread();
 
     return !mOrigin.IsEmpty();
@@ -2736,19 +2757,21 @@ AllocPBackgroundLSDatabaseParent(const P
   }
 
   // If we ever decide to return null from this point on, we need to make sure
   // that the datastore is closed and the prepared datastore is removed from the
   // gPreparedDatastores hashtable.
   // We also assume that IPDL must call RecvPBackgroundLSDatabaseConstructor
   // once we return a valid actor in this method.
 
-  RefPtr<Database> database = new Database(aPrincipalInfo,
-                                           preparedDatastore->Origin(),
-                                           aPrivateBrowsingId);
+  RefPtr<Database> database =
+    new Database(aPrincipalInfo,
+                 preparedDatastore->GetContentParentId(),
+                 preparedDatastore->Origin(),
+                 aPrivateBrowsingId);
 
   // Transfer ownership to IPDL.
   return database.forget().take();
 }
 
 bool
 RecvPBackgroundLSDatabaseConstructor(PBackgroundLSDatabaseParent* aActor,
                                      const PrincipalInfo& aPrincipalInfo,
@@ -2880,18 +2903,23 @@ AllocPBackgroundLSRequestParent(PBackgro
   if (!BackgroundParent::IsOtherProcessActor(aBackgroundActor)) {
     mainEventTarget = LSObject::GetSyncLoopEventTarget();
   }
 
   RefPtr<LSRequestBase> actor;
 
   switch (aParams.type()) {
     case LSRequestParams::TLSRequestPrepareDatastoreParams: {
+      RefPtr<ContentParent> contentParent =
+        BackgroundParent::GetContentParent(aBackgroundActor);
+
       RefPtr<PrepareDatastoreOp> prepareDatastoreOp =
-        new PrepareDatastoreOp(mainEventTarget, aParams);
+        new PrepareDatastoreOp(mainEventTarget,
+                               contentParent.forget(),
+                               aParams);
 
       if (!gPrepareDatastoreOps) {
         gPrepareDatastoreOps = new PrepareDatastoreOpArray();
       }
       gPrepareDatastoreOps->AppendElement(prepareDatastoreOp);
 
       actor = std::move(prepareDatastoreOp);
 
@@ -4510,20 +4538,22 @@ PreparedDatastore::TimerCallback(nsITime
   self->Destroy();
 }
 
 /*******************************************************************************
  * Database
  ******************************************************************************/
 
 Database::Database(const PrincipalInfo& aPrincipalInfo,
+                   const Maybe<ContentParentId>& aContentParentId,
                    const nsACString& aOrigin,
                    uint32_t aPrivateBrowsingId)
   : mSnapshot(nullptr)
   , mPrincipalInfo(aPrincipalInfo)
+  , mContentParentId(aContentParentId)
   , mOrigin(aOrigin)
   , mPrivateBrowsingId(aPrivateBrowsingId)
   , mAllowedToClose(false)
   , mActorDestroyed(false)
   , mRequestedAllowToClose(false)
 #ifdef DEBUG
   , mActorWasAlive(false)
 #endif
@@ -5312,36 +5342,43 @@ LSRequestBase::RecvFinish()
 
   return IPC_OK();
 }
 
 /*******************************************************************************
  * PrepareDatastoreOp
  ******************************************************************************/
 
-PrepareDatastoreOp::PrepareDatastoreOp(nsIEventTarget* aMainEventTarget,
-                                       const LSRequestParams& aParams)
+PrepareDatastoreOp::PrepareDatastoreOp(
+                                 nsIEventTarget* aMainEventTarget,
+                                 already_AddRefed<ContentParent> aContentParent,
+                                 const LSRequestParams& aParams)
   : LSRequestBase(aMainEventTarget)
   , mMainEventTarget(aMainEventTarget)
+  , mContentParent(std::move(aContentParent))
   , mLoadDataOp(nullptr)
   , mParams(aParams.get_LSRequestPrepareDatastoreParams())
   , mPrivateBrowsingId(0)
   , mUsage(0)
   , mSizeOfKeys(0)
   , mSizeOfItems(0)
   , mNestedState(NestedState::BeforeNesting)
   , mDatabaseNotAvailable(false)
   , mRequestedDirectoryLock(false)
   , mInvalidated(false)
 #ifdef DEBUG
   , mDEBUGUsage(0)
 #endif
 {
   MOZ_ASSERT(aParams.type() ==
                LSRequestParams::TLSRequestPrepareDatastoreParams);
+
+  if (mContentParent) {
+    mContentParentId = Some(mContentParent->ChildID());
+  }
 }
 
 PrepareDatastoreOp::~PrepareDatastoreOp()
 {
   MOZ_ASSERT(!mDirectoryLock);
   MOZ_ASSERT_IF(MayProceedOnNonOwningThread(),
                 mState == State::Initial || mState == State::Completed);
   MOZ_ASSERT(!mLoadDataOp);
@@ -5349,16 +5386,20 @@ PrepareDatastoreOp::~PrepareDatastoreOp(
 
 nsresult
 PrepareDatastoreOp::Open()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mState == State::Opening);
   MOZ_ASSERT(mNestedState == NestedState::BeforeNesting);
 
+  // Swap this to the stack now to ensure that we release it on this thread.
+  RefPtr<ContentParent> contentParent;
+  mContentParent.swap(contentParent);
+
   if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonBackgroundThread()) ||
       !MayProceedOnNonOwningThread()) {
     return NS_ERROR_FAILURE;
   }
 
   const PrincipalInfo& principalInfo = mParams.principalInfo();
 
   if (principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo) {
@@ -6154,16 +6195,17 @@ PrepareDatastoreOp::GetResponse(LSReques
     MOZ_ASSERT(!gDatastores->Get(mOrigin));
     gDatastores->Put(mOrigin, mDatastore);
   }
 
   uint64_t datastoreId = ++gLastDatastoreId;
 
   nsAutoPtr<PreparedDatastore> preparedDatastore(
     new PreparedDatastore(mDatastore,
+                          mContentParentId,
                           mOrigin,
                           datastoreId,
                           /* aForPreload */ !mParams.createIfNotExists()));
 
   if (!gPreparedDatastores) {
     gPreparedDatastores = new PreparedDatastoreHashtable();
   }
   gPreparedDatastores->Put(datastoreId, preparedDatastore);
@@ -7024,16 +7066,24 @@ QuotaClient::AbortOperations(const nsACS
     }
   }
 }
 
 void
 QuotaClient::AbortOperationsForProcess(ContentParentId aContentParentId)
 {
   AssertIsOnBackgroundThread();
+
+  if (gLiveDatabases) {
+    for (Database* database : *gLiveDatabases) {
+      if (database->IsOwnedByProcess(aContentParentId)) {
+        database->RequestAllowToClose();
+      }
+    }
+  }
 }
 
 void
 QuotaClient::StartIdleMaintenance()
 {
   AssertIsOnBackgroundThread();
 }