Bug 1406818 - Introduce nsIToolkitProfile.removeInBackground to remove profile folder in a separate thread, r=ehsan
authorAndrea Marchesini <amarchesini@mozilla.com>
Fri, 13 Oct 2017 08:47:41 +0200
changeset 386120 eeb89284500e2756eec978be2d4233b3411aa4ca
parent 386119 4baaea004689e8f6f4a4d9feff99c98c5378c3ce
child 386121 322dbb6b6736339695b8be2f8043ba4c7ee9e140
push id32676
push userarchaeopteryx@coole-files.de
push dateFri, 13 Oct 2017 21:38:18 +0000
treeherdermozilla-central@a31334a65a1c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs1406818
milestone58.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 1406818 - Introduce nsIToolkitProfile.removeInBackground to remove profile folder in a separate thread, r=ehsan
toolkit/profile/nsIToolkitProfile.idl
toolkit/profile/nsToolkitProfileService.cpp
--- a/toolkit/profile/nsIToolkitProfile.idl
+++ b/toolkit/profile/nsIToolkitProfile.idl
@@ -70,16 +70,22 @@ interface nsIToolkitProfile : nsISupport
      *
      * @param removeFiles
      *        Indicates whether or not the profile directory should be
      *        removed in addition.
      */
     void remove(in boolean removeFiles);
 
     /**
+     * Removes the profile from the registry of profiles.
+     * The profile directory is removed in the stream transport thread.
+     */
+    void removeInBackground();
+
+    /**
      * Lock this profile using platform-specific locking methods.
      *
      * @param lockFile If locking fails, this may return a lockFile object
      *                 which can be used in platform-specific ways to
      *                 determine which process has the file locked. Null
      *                 may be passed.
      * @return An interface which holds a profile lock as long as you reference
      *         it.
--- a/toolkit/profile/nsToolkitProfileService.cpp
+++ b/toolkit/profile/nsToolkitProfileService.cpp
@@ -27,18 +27,21 @@
 #include "nsISimpleEnumerator.h"
 
 #ifdef XP_MACOSX
 #include <CoreFoundation/CoreFoundation.h>
 #include "nsILocalFileMac.h"
 #endif
 
 #include "nsAppDirectoryServiceDefs.h"
+#include "nsNetCID.h"
 #include "nsXULAppAPI.h"
+#include "nsThreadUtils.h"
 
+#include "nsIRunnable.h"
 #include "nsINIParser.h"
 #include "nsXREDirProvider.h"
 #include "nsAppRunner.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsNativeCharsetUtils.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Sprintf.h"
@@ -59,16 +62,19 @@ private:
     ~nsToolkitProfile() { }
 
     nsToolkitProfile(const nsACString& aName,
                      nsIFile* aRootDir,
                      nsIFile* aLocalDir,
                      nsToolkitProfile* aPrev,
                      bool aForExternalApp);
 
+    nsresult
+    RemoveInternal(bool aRemoveFiles, bool aInBackground);
+
     friend class nsToolkitProfileLock;
 
     nsCString                  mName;
     nsCOMPtr<nsIFile>          mRootDir;
     nsCOMPtr<nsIFile>          mLocalDir;
     nsIProfileLock*            mLock;
     bool                       mForExternalApp;
 };
@@ -218,42 +224,56 @@ nsToolkitProfile::SetName(const nsACStri
     NS_ENSURE_TRUE(!mForExternalApp, NS_ERROR_NOT_IMPLEMENTED);
 
     mName = aName;
     nsToolkitProfileService::gService->mDirty = true;
 
     return NS_OK;
 }
 
-NS_IMETHODIMP
-nsToolkitProfile::Remove(bool removeFiles)
+nsresult
+nsToolkitProfile::RemoveInternal(bool aRemoveFiles, bool aInBackground)
 {
     NS_ASSERTION(nsToolkitProfileService::gService,
                  "Whoa, my service is gone.");
 
     NS_ENSURE_TRUE(!mForExternalApp, NS_ERROR_NOT_IMPLEMENTED);
 
     if (mLock)
         return NS_ERROR_FILE_IS_LOCKED;
 
     if (!mPrev && !mNext && nsToolkitProfileService::gService->mFirst != this)
         return NS_ERROR_NOT_INITIALIZED;
 
-    if (removeFiles) {
-        bool equals;
-        nsresult rv = mRootDir->Equals(mLocalDir, &equals);
-        if (NS_FAILED(rv))
-            return rv;
+    if (aRemoveFiles) {
+        nsCOMPtr<nsIFile> rootDir(mRootDir);
+        nsCOMPtr<nsIFile> localDir(mLocalDir);
 
-        // The root dir might contain the temp dir, so remove
-        // the temp dir first.
-        if (!equals)
-            mLocalDir->Remove(true);
+        nsCOMPtr<nsIRunnable> runnable = NS_NewRunnableFunction(
+          "nsToolkitProfile::RemoveInternal",
+          [rootDir, localDir]() {
+              bool equals;
+              nsresult rv = rootDir->Equals(localDir, &equals);
+              // The root dir might contain the temp dir, so remove
+              // the temp dir first.
+              if (NS_SUCCEEDED(rv) && !equals) {
+                  localDir->Remove(true);
+              }
 
-        mRootDir->Remove(true);
+              rootDir->Remove(true);
+            }
+        );
+
+        if (aInBackground) {
+            nsCOMPtr<nsIEventTarget> target =
+                do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
+             target->Dispatch(runnable, NS_DISPATCH_NORMAL);
+        } else {
+          runnable->Run();
+        }
     }
 
     if (mPrev)
         mPrev->mNext = mNext;
     else
         nsToolkitProfileService::gService->mFirst = mNext;
 
     if (mNext)
@@ -266,16 +286,28 @@ nsToolkitProfile::Remove(bool removeFile
         nsToolkitProfileService::gService->mChosen = nullptr;
 
     nsToolkitProfileService::gService->mDirty = true;
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
+nsToolkitProfile::Remove(bool removeFiles)
+{
+    return RemoveInternal(removeFiles, false /* in background */);
+}
+
+NS_IMETHODIMP
+nsToolkitProfile::RemoveInBackground()
+{
+    return RemoveInternal(true /* remove Files */, true /* in background */);
+}
+
+NS_IMETHODIMP
 nsToolkitProfile::Lock(nsIProfileUnlocker* *aUnlocker, nsIProfileLock* *aResult)
 {
     if (mLock) {
         NS_ADDREF(*aResult = mLock);
         return NS_OK;
     }
 
     RefPtr<nsToolkitProfileLock> lock = new nsToolkitProfileLock();