Bug 1286798 - Part 41: Implement QuotaClient::AbortOperationsForProcess; r=asuth draft
authorJan Varga <jan.varga@gmail.com>
Wed, 24 Oct 2018 06:59:08 +0200
changeset 481719 fb2a73c881f8990d814f5bba57f3c70423050dd4
parent 481718 0492574cd8ea95cf0022c71ed64469b96534fa52
child 481720 564e6a8da37f657c000ee3ab771874d1d7766b8e
push id10
push userbugmail@asutherland.org
push dateSun, 18 Nov 2018 18:57:42 +0000
reviewersasuth
bugs1286798
milestone65.0a1
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
@@ -8,16 +8,17 @@
 
 #include "LocalStorageCommon.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"
@@ -1568,30 +1569,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);
@@ -1620,16 +1624,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()
@@ -1671,46 +1681,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
@@ -2041,25 +2059,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;
@@ -2070,16 +2090,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();
@@ -2717,19 +2738,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,
@@ -2864,18 +2887,23 @@ AllocPBackgroundLSRequestParent(PBackgro
 
   nsCOMPtr<nsIEventTarget> mainEventTarget =
     reinterpret_cast<nsIEventTarget*>(aMainEventTarget);
 
   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);
 
@@ -4495,20 +4523,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
@@ -5297,36 +5327,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);
@@ -5334,16 +5371,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) {
@@ -6139,16 +6180,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);
@@ -7009,16 +7051,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();
 }