Bug 1145336: Remove old GMPs during updates. r=jwwang
authorStephen Pohl <spohl.mozilla.bugs@gmail.com>
Sun, 22 Mar 2015 23:12:03 -0400
changeset 251182 a23240479b9b1fb428def556bcedf7045b31da68
parent 251181 56f07a799bd170e3ad0b48f338bd8b2351809c59
child 251183 181e52c05fe0e8b1f057a999a367d9db36803036
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-esr52@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwwang
bugs1145336
milestone39.0a1
Bug 1145336: Remove old GMPs during updates. r=jwwang
dom/media/gmp/GMPService.cpp
dom/media/gmp/GMPService.h
dom/media/gmp/mozIGeckoMediaPluginService.idl
toolkit/mozapps/extensions/internal/GMPProvider.jsm
--- a/dom/media/gmp/GMPService.cpp
+++ b/dom/media/gmp/GMPService.cpp
@@ -660,36 +660,49 @@ GeckoMediaPluginService::LoadFromEnviron
   }
 
   mScannedPluginOnDisk = true;
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginService::PathRunnable::Run()
 {
-  if (mAdd) {
+  if (mOperation == ADD) {
     mService->AddOnGMPThread(mPath);
   } else {
-    mService->RemoveOnGMPThread(mPath);
+    mService->RemoveOnGMPThread(mPath,
+                                mOperation == REMOVE_AND_DELETE_FROM_DISK);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginService::AddPluginDirectory(const nsAString& aDirectory)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  return GMPDispatch(new PathRunnable(this, aDirectory, true));
+  return GMPDispatch(new PathRunnable(this, aDirectory,
+                                      PathRunnable::EOperation::ADD));
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginService::RemovePluginDirectory(const nsAString& aDirectory)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  return GMPDispatch(new PathRunnable(this, aDirectory, false));
+  return GMPDispatch(new PathRunnable(this, aDirectory,
+                                      PathRunnable::EOperation::REMOVE));
+}
+
+NS_IMETHODIMP
+GeckoMediaPluginService::RemoveAndDeletePluginDirectory(
+  const nsAString& aDirectory)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  return GMPDispatch(
+    new PathRunnable(this, aDirectory,
+                     PathRunnable::EOperation::REMOVE_AND_DELETE_FROM_DISK));
 }
 
 class DummyRunnable : public nsRunnable {
 public:
   NS_IMETHOD Run() { return NS_OK; }
 };
 
 NS_IMETHODIMP
@@ -910,33 +923,38 @@ GeckoMediaPluginService::AddOnGMPThread(
     return;
   }
 
   MutexAutoLock lock(mMutex);
   mPlugins.AppendElement(gmp);
 }
 
 void
-GeckoMediaPluginService::RemoveOnGMPThread(const nsAString& aDirectory)
+GeckoMediaPluginService::RemoveOnGMPThread(const nsAString& aDirectory,
+                                           const bool aDeleteFromDisk)
 {
   MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
   LOGD(("%s::%s: %s", __CLASS__, __FUNCTION__, NS_LossyConvertUTF16toASCII(aDirectory).get()));
 
   nsCOMPtr<nsIFile> directory;
   nsresult rv = NS_NewLocalFile(aDirectory, false, getter_AddRefs(directory));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   MutexAutoLock lock(mMutex);
   for (size_t i = 0; i < mPlugins.Length(); ++i) {
     nsCOMPtr<nsIFile> pluginpath = mPlugins[i]->GetDirectory();
     bool equals;
     if (NS_SUCCEEDED(directory->Equals(pluginpath, &equals)) && equals) {
+      mPlugins[i]->AbortAsyncShutdown();
       mPlugins[i]->CloseActive(true);
+      if (aDeleteFromDisk) {
+        pluginpath->Remove(true);
+      }
       mPlugins.RemoveElementAt(i);
       return;
     }
   }
   NS_WARNING("Removing GMP which was never added.");
   nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
   cs->LogStringMessage(MOZ_UTF16("Removing GMP which was never added."));
 }
--- a/dom/media/gmp/GMPService.h
+++ b/dom/media/gmp/GMPService.h
@@ -66,18 +66,19 @@ private:
 
   void UnloadPlugins();
   void CrashPlugins();
   void SetAsyncShutdownComplete();
 
   void LoadFromEnvironment();
   void ProcessPossiblePlugin(nsIFile* aDir);
 
-  void AddOnGMPThread(const nsAString& aSearchDir);
-  void RemoveOnGMPThread(const nsAString& aSearchDir);
+  void AddOnGMPThread(const nsAString& aDirectory);
+  void RemoveOnGMPThread(const nsAString& aDirectory,
+                         const bool aDeleteFromDisk);
 
   nsresult SetAsyncShutdownTimeout();
 
   struct DirectoryFilter {
     virtual bool operator()(nsIFile* aPath) = 0;
     ~DirectoryFilter() {}
   };
   void ClearNodeIdAndPlugin(DirectoryFilter& aFilter);
@@ -91,29 +92,35 @@ protected:
 private:
   GMPParent* ClonePlugin(const GMPParent* aOriginal);
   nsresult EnsurePluginsOnDiskScanned();
   nsresult InitStorage();
 
   class PathRunnable : public nsRunnable
   {
   public:
-    PathRunnable(GeckoMediaPluginService* service, const nsAString& path,
-                 bool add)
-      : mService(service)
-      , mPath(path)
-      , mAdd(add)
+    enum EOperation {
+      ADD,
+      REMOVE,
+      REMOVE_AND_DELETE_FROM_DISK,
+    };
+
+    PathRunnable(GeckoMediaPluginService* aService, const nsAString& aPath,
+                 EOperation aOperation)
+      : mService(aService)
+      , mPath(aPath)
+      , mOperation(aOperation)
     { }
 
     NS_DECL_NSIRUNNABLE
 
   private:
     nsRefPtr<GeckoMediaPluginService> mService;
     nsString mPath;
-    bool mAdd;
+    EOperation mOperation;
   };
 
   Mutex mMutex; // Protects mGMPThread and mShuttingDown and mPlugins
   nsTArray<nsRefPtr<GMPParent>> mPlugins;
   nsCOMPtr<nsIThread> mGMPThread;
   bool mShuttingDown;
   bool mShuttingDownOnGMPThread;
 
--- a/dom/media/gmp/mozIGeckoMediaPluginService.idl
+++ b/dom/media/gmp/mozIGeckoMediaPluginService.idl
@@ -21,17 +21,17 @@ class GMPVideoHost;
 [ptr] native GMPVideoDecoderProxy(GMPVideoDecoderProxy);
 [ptr] native GMPVideoEncoderProxy(GMPVideoEncoderProxy);
 [ptr] native GMPVideoHost(GMPVideoHost);
 [ptr] native MessageLoop(MessageLoop);
 [ptr] native TagArray(nsTArray<nsCString>);
 [ptr] native GMPDecryptorProxy(GMPDecryptorProxy);
 [ptr] native GMPAudioDecoderProxy(GMPAudioDecoderProxy);
 
-[scriptable, uuid(56cc105f-dd27-4752-83e0-371908edba04)]
+[scriptable, uuid(f71e6e57-5175-4cf3-8cc2-629273a75b67)]
 interface mozIGeckoMediaPluginService : nsISupports
 {
 
   /**
    * The GMP thread. Callable from any thread.
    */
   readonly attribute nsIThread thread;
 
@@ -93,16 +93,22 @@ interface mozIGeckoMediaPluginService : 
 
   /**
    * Remove a directory for gecko media plugins.
    * @note Main-thread API.
    */
   void removePluginDirectory(in AString directory);
 
   /**
+   * Remove a directory for gecko media plugins and delete it from disk.
+   * @note Main-thread API.
+   */
+  void removeAndDeletePluginDirectory(in AString directory);
+
+  /**
    * Gets the NodeId for a (origin, urlbarOrigin, isInprivateBrowsing) tuple.
    */
   ACString getNodeId(in AString origin,
                      in AString topLevelOrigin,
                      in bool inPrivateBrowsingMode);
 
   /**
    * Clears storage data associated with the origin.
--- a/toolkit/mozapps/extensions/internal/GMPProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/GMPProvider.jsm
@@ -362,17 +362,17 @@ GMPWrapper.prototype = {
     }
   },
 
   onPrefVersionChanged: function() {
     AddonManagerPrivate.callAddonListeners("onUninstalling", this, false);
     if (this._gmpPath) {
       this._log.info("onPrefVersionChanged() - unregistering gmp directory " +
                      this._gmpPath);
-      gmpService.removePluginDirectory(this._gmpPath);
+      gmpService.removeAndDeletePluginDirectory(this._gmpPath);
     }
     AddonManagerPrivate.callAddonListeners("onUninstalled", this);
 
     AddonManagerPrivate.callInstallListeners("onExternalInstall", null, this,
                                              null, false);
     AddonManagerPrivate.callAddonListeners("onInstalling", this, false);
     this._gmpPath = null;
     if (this.isInstalled) {