Bug 980447 - Add persistenceType argument to nsIQuotaManager.clearStoragesForURI (r=janv)
authorLuke Wagner <luke@mozilla.com>
Mon, 14 Apr 2014 15:48:49 -0500
changeset 196917 e28142a94b74006685c5644df83cc7d7c6965967
parent 196916 6f5a918051d532a569fbbfe06839a872dd156548
child 196918 d1f1725198dae6c350b00537fefa08f817da85ae
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjanv
bugs980447
milestone31.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 980447 - Add persistenceType argument to nsIQuotaManager.clearStoragesForURI (r=janv)
dom/indexedDB/IndexedDatabaseManager.cpp
dom/indexedDB/OpenDatabaseHelper.cpp
dom/quota/PersistenceType.h
dom/quota/QuotaManager.cpp
dom/quota/QuotaManager.h
dom/quota/nsIQuotaManager.idl
js/xpconnect/src/XPCQuickStubs.h
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -603,17 +603,19 @@ IndexedDatabaseManager::AsyncDeleteFile(
 
   NS_ENSURE_ARG_POINTER(aFileManager);
 
   QuotaManager* quotaManager = QuotaManager::Get();
   NS_ASSERTION(quotaManager, "Shouldn't be null!");
 
   // See if we're currently clearing the storages for this origin. If so then
   // we pretend that we've already deleted everything.
-  if (quotaManager->IsClearOriginPending(aFileManager->Origin())) {
+  if (quotaManager->IsClearOriginPending(
+                             aFileManager->Origin(),
+                             Nullable<PersistenceType>(aFileManager->Type()))) {
     return NS_OK;
   }
 
   nsRefPtr<AsyncDeleteFileRunnable> runnable =
     new AsyncDeleteFileRunnable(aFileManager, aFileId);
 
   nsresult rv =
     quotaManager->IOThread()->Dispatch(runnable, NS_DISPATCH_NORMAL);
--- a/dom/indexedDB/OpenDatabaseHelper.cpp
+++ b/dom/indexedDB/OpenDatabaseHelper.cpp
@@ -2141,17 +2141,18 @@ OpenDatabaseHelper::StartSetVersion()
   nsRefPtr<SetVersionHelper> helper =
     new SetVersionHelper(transaction, mOpenDBRequest, this, mRequestedVersion,
                          mCurrentVersion);
 
   QuotaManager* quotaManager = QuotaManager::Get();
   NS_ASSERTION(quotaManager, "This should never be null!");
 
   rv = quotaManager->AcquireExclusiveAccess(
-             mDatabase, mDatabase->Origin(), helper,
+             mDatabase, mDatabase->Origin(),
+             Nullable<PersistenceType>(mDatabase->Type()), helper,
              &VersionChangeEventsRunnable::QueueVersionChange<SetVersionHelper>,
              helper);
   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   // The SetVersionHelper is responsible for dispatching us back to the
   // main thread again and changing the state to eSetVersionCompleted.
   mState = eSetVersionPending;
   return NS_OK;
@@ -2171,17 +2172,18 @@ OpenDatabaseHelper::StartDelete()
   nsRefPtr<DeleteDatabaseHelper> helper =
     new DeleteDatabaseHelper(mOpenDBRequest, this, mCurrentVersion, mName,
                              mGroup, mASCIIOrigin, mPersistenceType);
 
   QuotaManager* quotaManager = QuotaManager::Get();
   NS_ASSERTION(quotaManager, "This should never be null!");
 
   rv = quotaManager->AcquireExclusiveAccess(
-         mDatabase, mDatabase->Origin(), helper,
+         mDatabase, mDatabase->Origin(),
+         Nullable<PersistenceType>(mDatabase->Type()), helper,
          &VersionChangeEventsRunnable::QueueVersionChange<DeleteDatabaseHelper>,
          helper);
   IDB_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   // The DeleteDatabaseHelper is responsible for dispatching us back to the
   // main thread again and changing the state to eDeleteCompleted.
   mState = eDeletePending;
   return NS_OK;
--- a/dom/quota/PersistenceType.h
+++ b/dom/quota/PersistenceType.h
@@ -50,16 +50,38 @@ PersistenceTypeFromText(const nsACString
 
   if (aText.EqualsLiteral("temporary")) {
     return PERSISTENCE_TYPE_TEMPORARY;
   }
 
   MOZ_ASSUME_UNREACHABLE("Should never get here!");
 }
 
+inline nsresult
+NullablePersistenceTypeFromText(const nsACString& aText,
+                                Nullable<PersistenceType> *aPersistenceType)
+{
+  if (aText.IsVoid()) {
+    *aPersistenceType = Nullable<PersistenceType>();
+    return NS_OK;
+  }
+
+  if (aText.EqualsLiteral("persistent")) {
+    *aPersistenceType = Nullable<PersistenceType>(PERSISTENCE_TYPE_PERSISTENT);
+    return NS_OK;
+  }
+
+  if (aText.EqualsLiteral("temporary")) {
+    *aPersistenceType = Nullable<PersistenceType>(PERSISTENCE_TYPE_TEMPORARY);
+    return NS_OK;
+  }
+
+  return NS_ERROR_UNEXPECTED;
+}
+
 inline mozilla::dom::StorageType
 PersistenceTypeToStorage(PersistenceType aPersistenceType)
 {
   return mozilla::dom::StorageType(static_cast<int>(aPersistenceType));
 }
 
 inline PersistenceType
 PersistenceTypeFromStorage(const Optional<mozilla::dom::StorageType>& aStorage,
--- a/dom/quota/QuotaManager.cpp
+++ b/dom/quota/QuotaManager.cpp
@@ -183,18 +183,20 @@ class OriginClearRunnable MOZ_FINAL : pu
 
     // Running on the main thread after all work is done.
     Complete
   };
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
-  OriginClearRunnable(const OriginOrPatternString& aOriginOrPattern)
+  OriginClearRunnable(const OriginOrPatternString& aOriginOrPattern,
+                      Nullable<PersistenceType> aPersistenceType)
   : mOriginOrPattern(aOriginOrPattern),
+    mPersistenceType(aPersistenceType),
     mCallbackState(Pending)
   { }
 
   NS_IMETHOD
   Run();
 
   // AcquireListener override
   virtual nsresult
@@ -223,16 +225,17 @@ public:
                            void* aClosure);
 
   void
   DeleteFiles(QuotaManager* aQuotaManager,
               PersistenceType aPersistenceType);
 
 private:
   OriginOrPatternString mOriginOrPattern;
+  Nullable<PersistenceType> mPersistenceType;
   CallbackState mCallbackState;
 };
 
 // Responsible for calculating the amount of space taken up by storages of a
 // certain origin. Created when nsIQuotaManager::GetUsageForURI is called.
 // May be canceled with nsIQuotaRequest::Cancel. Runs three times, first
 // on the main thread, next on the IO thread, and then finally again on the main
 // thread. While on the IO thread the runnable will calculate the size of all
@@ -2275,16 +2278,17 @@ QuotaManager::Clear()
   // the end of the event queue.
   return NS_OK;
 }
 
 NS_IMETHODIMP
 QuotaManager::ClearStoragesForURI(nsIURI* aURI,
                                   uint32_t aAppId,
                                   bool aInMozBrowserOnly,
+                                  const nsACString& aPersistenceType,
                                   uint8_t aOptionalArgCount)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   NS_ENSURE_ARG_POINTER(aURI);
 
   // This only works from the main process.
   NS_ENSURE_TRUE(IsMainProcess(), NS_ERROR_NOT_AVAILABLE);
@@ -2297,42 +2301,49 @@ QuotaManager::ClearStoragesForURI(nsIURI
   nsCString origin;
   nsresult rv = GetInfoFromURI(aURI, aAppId, aInMozBrowserOnly, nullptr, &origin,
                                nullptr, nullptr);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString pattern;
   GetOriginPatternString(aAppId, aInMozBrowserOnly, origin, pattern);
 
+  Nullable<PersistenceType> persistenceType;
+  rv = NullablePersistenceTypeFromText(aPersistenceType, &persistenceType);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   // If there is a pending or running clear operation for this origin, return
   // immediately.
-  if (IsClearOriginPending(pattern)) {
+  if (IsClearOriginPending(pattern, persistenceType)) {
     return NS_OK;
   }
 
   OriginOrPatternString oops = OriginOrPatternString::FromPattern(pattern);
 
   // Queue up the origin clear runnable.
-  nsRefPtr<OriginClearRunnable> runnable = new OriginClearRunnable(oops);
-
-  rv = WaitForOpenAllowed(oops, Nullable<PersistenceType>(), EmptyCString(),
-                          runnable);
+  nsRefPtr<OriginClearRunnable> runnable =
+    new OriginClearRunnable(oops, persistenceType);
+
+  rv = WaitForOpenAllowed(oops, persistenceType, EmptyCString(), runnable);
   NS_ENSURE_SUCCESS(rv, rv);
 
   runnable->AdvanceState();
 
   // Give the runnable some help by invalidating any storages in the way.
   StorageMatcher<nsAutoTArray<nsIOfflineStorage*, 20> > matches;
   matches.Find(mLiveStorages, pattern);
 
   for (uint32_t index = 0; index < matches.Length(); index++) {
-    // We need to grab references to any live storages here to prevent them
-    // from dying while we invalidate them.
-    nsCOMPtr<nsIOfflineStorage> storage = matches[index];
-    storage->Invalidate();
+    if (persistenceType.IsNull() ||
+        matches[index]->Type() == persistenceType.Value()) {
+      // We need to grab references to any live storages here to prevent them
+      // from dying while we invalidate them.
+      nsCOMPtr<nsIOfflineStorage> storage = matches[index];
+      storage->Invalidate();
+    }
   }
 
   // After everything has been invalidated the helper should be dispatched to
   // the end of the event queue.
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -2635,35 +2646,29 @@ QuotaManager::LockedRemoveQuotaForOrigin
         mGroupInfoPairs.Remove(aGroup);
       }
     }
   }
 }
 
 nsresult
 QuotaManager::AcquireExclusiveAccess(const nsACString& aPattern,
+                                     Nullable<PersistenceType> aPersistenceType,
                                      nsIOfflineStorage* aStorage,
                                      AcquireListener* aListener,
                                      WaitingOnStoragesCallback aCallback,
                                      void* aClosure)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(aListener, "Need a listener!");
 
   // Find the right SynchronizedOp.
-  SynchronizedOp* op;
-  if (aStorage) {
-    op = FindSynchronizedOp(aPattern,
-                            Nullable<PersistenceType>(aStorage->Type()),
-                            aStorage->Id());
-  }
-  else {
-    op = FindSynchronizedOp(aPattern, Nullable<PersistenceType>(),
-                            EmptyCString());
-  }
+  SynchronizedOp* op =
+    FindSynchronizedOp(aPattern, aPersistenceType,
+                       aStorage ? aStorage->Id() : EmptyCString());
 
   NS_ASSERTION(op, "We didn't find a SynchronizedOp?");
   NS_ASSERTION(!op->mListener, "SynchronizedOp already has a listener?!?");
 
   nsTArray<nsCOMPtr<nsIOfflineStorage> > liveStorages;
 
   if (aStorage) {
     // We need to wait for the storages to go away.
@@ -2835,30 +2840,33 @@ QuotaManager::ClearStoragesForApp(uint32
                "Bad appId!");
 
   // This only works from the main process.
   NS_ENSURE_TRUE(IsMainProcess(), NS_ERROR_NOT_AVAILABLE);
 
   nsAutoCString pattern;
   GetOriginPatternStringMaybeIgnoreBrowser(aAppId, aBrowserOnly, pattern);
 
+  // Clear both temporary and persistent storages.
+  Nullable<PersistenceType> persistenceType;
+
   // If there is a pending or running clear operation for this app, return
   // immediately.
-  if (IsClearOriginPending(pattern)) {
+  if (IsClearOriginPending(pattern, persistenceType)) {
     return NS_OK;
   }
 
   OriginOrPatternString oops = OriginOrPatternString::FromPattern(pattern);
 
   // Queue up the origin clear runnable.
-  nsRefPtr<OriginClearRunnable> runnable = new OriginClearRunnable(oops);
+  nsRefPtr<OriginClearRunnable> runnable =
+    new OriginClearRunnable(oops, persistenceType);
 
   nsresult rv =
-    WaitForOpenAllowed(oops, Nullable<PersistenceType>(), EmptyCString(),
-                       runnable);
+    WaitForOpenAllowed(oops, persistenceType, EmptyCString(), runnable);
   NS_ENSURE_SUCCESS(rv, rv);
 
   runnable->AdvanceState();
 
   // Give the runnable some help by invalidating any storages in the way.
   StorageMatcher<nsAutoTArray<nsIOfflineStorage*, 20> > matches;
   matches.Find(mLiveStorages, pattern);
 
@@ -3502,47 +3510,50 @@ OriginClearRunnable::Run()
     case OpenAllowed: {
       NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
       AdvanceState();
 
       // Now we have to wait until the thread pool is done with all of the
       // storages we care about.
       nsresult rv =
-        quotaManager->AcquireExclusiveAccess(mOriginOrPattern, this,
-                                             InvalidateOpenedStorages, nullptr);
+        quotaManager->AcquireExclusiveAccess(mOriginOrPattern, mPersistenceType,
+                                             this, InvalidateOpenedStorages,
+                                             nullptr);
       NS_ENSURE_SUCCESS(rv, rv);
 
       return NS_OK;
     }
 
     case IO: {
       AssertIsOnIOThread();
 
       AdvanceState();
 
-      DeleteFiles(quotaManager, PERSISTENCE_TYPE_PERSISTENT);
-
-      DeleteFiles(quotaManager, PERSISTENCE_TYPE_TEMPORARY);
+      if (mPersistenceType.IsNull()) {
+        DeleteFiles(quotaManager, PERSISTENCE_TYPE_PERSISTENT);
+        DeleteFiles(quotaManager, PERSISTENCE_TYPE_TEMPORARY);
+      } else {
+        DeleteFiles(quotaManager, mPersistenceType.Value());
+      }
 
       // Now dispatch back to the main thread.
       if (NS_FAILED(NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL))) {
         NS_WARNING("Failed to dispatch to main thread!");
         return NS_ERROR_FAILURE;
       }
 
       return NS_OK;
     }
 
     case Complete: {
       NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
       // Tell the QuotaManager that we're done.
-      quotaManager->AllowNextSynchronizedOp(mOriginOrPattern,
-                                            Nullable<PersistenceType>(),
+      quotaManager->AllowNextSynchronizedOp(mOriginOrPattern, mPersistenceType,
                                             EmptyCString());
 
       return NS_OK;
     }
 
     default:
       NS_ERROR("Unknown state value!");
       return NS_ERROR_UNEXPECTED;
@@ -3858,17 +3869,18 @@ ResetOrClearRunnable::Run()
     case OpenAllowed: {
       NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
       AdvanceState();
 
       // Now we have to wait until the thread pool is done with all of the
       // storages we care about.
       nsresult rv =
-        quotaManager->AcquireExclusiveAccess(NullCString(), this,
+        quotaManager->AcquireExclusiveAccess(NullCString(),
+                                             Nullable<PersistenceType>(), this,
                                              InvalidateOpenedStorages, nullptr);
       NS_ENSURE_SUCCESS(rv, rv);
 
       return NS_OK;
     }
 
     case IO: {
       AssertIsOnIOThread();
--- a/dom/quota/QuotaManager.h
+++ b/dom/quota/QuotaManager.h
@@ -193,45 +193,47 @@ public:
                      const nsACString& aId, nsIRunnable* aRunnable);
 
   // Acquire exclusive access to the storage given (waits for all others to
   // close).  If storages need to close first, the callback will be invoked
   // with an array of said storages.
   nsresult
   AcquireExclusiveAccess(nsIOfflineStorage* aStorage,
                          const nsACString& aOrigin,
+                         Nullable<PersistenceType> aPersistenceType,
                          AcquireListener* aListener,
                          WaitingOnStoragesCallback aCallback,
                          void* aClosure)
   {
     NS_ASSERTION(aStorage, "Need a storage here!");
-    return AcquireExclusiveAccess(aOrigin, aStorage, aListener, aCallback,
-                                  aClosure);
+    return AcquireExclusiveAccess(aOrigin, aPersistenceType, aStorage,
+                                  aListener, aCallback, aClosure);
   }
 
   nsresult
   AcquireExclusiveAccess(const nsACString& aOrigin,
+                         Nullable<PersistenceType> aPersistenceType,
                          AcquireListener* aListener,
                          WaitingOnStoragesCallback aCallback,
                          void* aClosure)
   {
-    return AcquireExclusiveAccess(aOrigin, nullptr, aListener, aCallback,
-                                  aClosure);
+    return AcquireExclusiveAccess(aOrigin, aPersistenceType, nullptr,
+                                  aListener, aCallback, aClosure);
   }
 
   void
   AllowNextSynchronizedOp(const OriginOrPatternString& aOriginOrPattern,
                           Nullable<PersistenceType> aPersistenceType,
                           const nsACString& aId);
 
   bool
-  IsClearOriginPending(const nsACString& aPattern)
+  IsClearOriginPending(const nsACString& aPattern,
+                       Nullable<PersistenceType> aPersistenceType)
   {
-    return !!FindSynchronizedOp(aPattern, Nullable<PersistenceType>(),
-                                EmptyCString());
+    return !!FindSynchronizedOp(aPattern, aPersistenceType, EmptyCString());
   }
 
   nsresult
   GetDirectoryForOrigin(PersistenceType aPersistenceType,
                         const nsACString& aASCIIOrigin,
                         nsIFile** aDirectory) const;
 
   nsresult
@@ -364,16 +366,17 @@ private:
 
   void
   LockedRemoveQuotaForOrigin(PersistenceType aPersistenceType,
                              const nsACString& aGroup,
                              const nsACString& aOrigin);
 
   nsresult
   AcquireExclusiveAccess(const nsACString& aOrigin,
+                         Nullable<PersistenceType> aPersistenceType,
                          nsIOfflineStorage* aStorage,
                          AcquireListener* aListener,
                          WaitingOnStoragesCallback aCallback,
                          void* aClosure);
 
   void
   AddSynchronizedOp(const OriginOrPatternString& aOriginOrPattern,
                     Nullable<PersistenceType> aPersistenceType);
--- a/dom/quota/nsIQuotaManager.idl
+++ b/dom/quota/nsIQuotaManager.idl
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIQuotaRequest;
 interface nsIURI;
 interface nsIUsageCallback;
 
-[scriptable, builtinclass, uuid(f19a03ae-e97d-41e9-95dd-681b910c4093)]
+[scriptable, builtinclass, uuid(2968fcd5-1872-4ddc-8c16-62b27e357f31)]
 interface nsIQuotaManager : nsISupports
 {
   /**
    * Schedules an asynchronous callback that will return the total amount of
    * disk space being used by storages for the given origin.
    *
    * @param aURI
    *        The URI whose usage is being queried.
@@ -46,17 +46,18 @@ interface nsIQuotaManager : nsISupports
    *
    * @param aURI
    *        The URI whose storages are to be cleared.
    */
   [optional_argc]
   void
   clearStoragesForURI(in nsIURI aURI,
                       [optional] in unsigned long aAppId,
-                      [optional] in boolean aInMozBrowserOnly);
+                      [optional] in boolean aInMozBrowserOnly,
+                      [optional] in ACString aPersistenceType);
 
   /**
    * Resets quota and storage management. This can be used to force
    * reinitialization of the temp storage, for example when the pref for
    * overriding the temp storage limit has changed.
    * Be carefull, this invalidates all live storages!
    *
    * If the dom.quotaManager.testing preference is not true the call will be
--- a/js/xpconnect/src/XPCQuickStubs.h
+++ b/js/xpconnect/src/XPCQuickStubs.h
@@ -307,18 +307,18 @@ public:
  * Like xpc_qsDOMString and xpc_qsAString, but for XPIDL native types annotated
  * with [cstring] rather than [domstring] or [astring].
  */
 class xpc_qsACString : public xpc_qsBasicString<nsACString, nsCString>
 {
 public:
     xpc_qsACString(JSContext *cx, JS::HandleValue v,
                    JS::MutableHandleValue pval, bool notpassed,
-                   StringificationBehavior nullBehavior,
-                   StringificationBehavior undefinedBehavior);
+                   StringificationBehavior nullBehavior = eNull,
+                   StringificationBehavior undefinedBehavior = eNull);
 };
 
 /**
  * And similar for AUTF8String.
  */
 class xpc_qsAUTF8String :
   public xpc_qsBasicString<nsACString, NS_ConvertUTF16toUTF8>
 {