☠☠ backed out by bf3916efc0bf ☠ ☠ | |
author | Benjamin Smedberg <benjamin@smedbergs.us> |
Thu, 10 Jul 2014 10:32:59 -0400 | |
changeset 193400 | 91f25a63dea90712cd525597cc64b257c4a83b4f |
parent 193399 | 1a4c6cb3174310e15f0e42bf343c9caa5ac2ff6d |
child 193401 | 31ac9fc7c6684d84e52f28288cb9352eb6af4995 |
push id | 27117 |
push user | ryanvm@gmail.com |
push date | Thu, 10 Jul 2014 22:23:14 +0000 |
treeherder | mozilla-central@e1a037c085d1 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | josh, jesup |
bugs | 1032814 |
milestone | 33.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
|
--- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -162,16 +162,17 @@ @BINPATH@/components/chrome.xpt @BINPATH@/components/commandhandler.xpt @BINPATH@/components/commandlines.xpt @BINPATH@/components/composer.xpt @BINPATH@/components/content_base.xpt @BINPATH@/components/content_events.xpt @BINPATH@/components/content_htmldoc.xpt @BINPATH@/components/content_html.xpt +@BINPATH@/components/content_geckomediaplugins.xpt #ifdef MOZ_WEBRTC @BINPATH@/components/content_webrtc.xpt #endif @BINPATH@/components/content_xslt.xpt @BINPATH@/components/cookie.xpt @BINPATH@/components/directory.xpt @BINPATH@/components/docshell.xpt @BINPATH@/components/dom.xpt
--- a/content/media/gmp/GMPParent.h +++ b/content/media/gmp/GMPParent.h @@ -10,20 +10,20 @@ #include "GMPVideoDecoderParent.h" #include "GMPVideoEncoderParent.h" #include "mozilla/gmp/PGMPParent.h" #include "nsCOMPtr.h" #include "nscore.h" #include "nsISupports.h" #include "nsString.h" #include "nsTArray.h" +#include "nsIFile.h" class nsILineInputStream; class nsIThread; -class nsIFile; namespace mozilla { namespace gmp { class GMPCapability { public: nsCString mAPIName; @@ -72,16 +72,20 @@ public: // Returns true if a plugin can be or is being used across multiple origins. bool CanBeSharedCrossOrigin() const; // A GMP can be used from an origin if it's already been set to work with // that origin, or if it's not been set to work with any origin and has // not yet been loaded (i.e. it's not shared across origins). bool CanBeUsedFrom(const nsAString& aOrigin) const; + already_AddRefed<nsIFile> GetDirectory() { + return nsCOMPtr<nsIFile>(mDirectory).forget(); + } + private: ~GMPParent(); bool EnsureProcessLoaded(); nsresult ReadGMPMetaData(); virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; virtual PGMPVideoDecoderParent* AllocPGMPVideoDecoderParent() MOZ_OVERRIDE; virtual bool DeallocPGMPVideoDecoderParent(PGMPVideoDecoderParent* aActor) MOZ_OVERRIDE; virtual PGMPVideoEncoderParent* AllocPGMPVideoEncoderParent() MOZ_OVERRIDE;
--- a/content/media/gmp/GMPService.cpp +++ b/content/media/gmp/GMPService.cpp @@ -3,26 +3,22 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "GMPService.h" #include "GMPParent.h" #include "GMPVideoDecoderParent.h" #include "nsIObserverService.h" #include "GeckoChildProcessHost.h" -#if defined(XP_WIN) -#include "nsIWindowsRegKey.h" -#endif #include "mozilla/ClearOnShutdown.h" #include "mozilla/SyncRunnable.h" -#include "nsDirectoryServiceUtils.h" -#include "nsDirectoryServiceDefs.h" #include "nsXPCOMPrivate.h" -#include "nsISimpleEnumerator.h" #include "mozilla/Services.h" +#include "nsNativeCharsetUtils.h" +#include "nsIConsoleService.h" namespace mozilla { namespace gmp { static StaticRefPtr<GeckoMediaPluginService> sSingletonService; class GMPServiceCreateHelper MOZ_FINAL : public nsRunnable { @@ -108,26 +104,16 @@ GeckoMediaPluginService::~GeckoMediaPlug MOZ_ASSERT(mPlugins.IsEmpty()); } void GeckoMediaPluginService::Init() { MOZ_ASSERT(NS_IsMainThread()); - // Cache user directory while we're on the main thread. We do this because - // if we try to use "~" in a path during plugin lookup on a non-main thread, - // the nsIFile code will try to resolve it using NS_GetSpecialDirectory, which - // doesn't work on non-main threads. - nsCOMPtr<nsIFile> homeDir; - NS_GetSpecialDirectory(NS_OS_HOME_DIR, getter_AddRefs(homeDir)); - if (homeDir) { - homeDir->GetPath(mHomePath); - } - nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService(); MOZ_ASSERT(obsService); MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false))); MOZ_ALWAYS_TRUE(NS_SUCCEEDED(obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false))); } NS_IMETHODIMP GeckoMediaPluginService::Observe(nsISupports* aSubject, @@ -177,16 +163,19 @@ GeckoMediaPluginService::GetThread(nsITh if (mShuttingDown) { return NS_ERROR_FAILURE; } nsresult rv = NS_NewNamedThread("GMPThread", getter_AddRefs(mGMPThread)); if (NS_FAILED(rv)) { return rv; } + + // Tell the thread to initialize plugins + mGMPThread->Dispatch(NS_NewRunnableMethod(this, &GeckoMediaPluginService::LoadFromEnvironment), NS_DISPATCH_NORMAL); } NS_ADDREF(mGMPThread); *aThread = mGMPThread; return NS_OK; } @@ -267,40 +256,92 @@ GeckoMediaPluginService::UnloadPlugins() mShuttingDownOnGMPThread = true; for (uint32_t i = 0; i < mPlugins.Length(); i++) { mPlugins[i]->UnloadProcess(); } mPlugins.Clear(); } +void +GeckoMediaPluginService::LoadFromEnvironment() +{ + MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); + + const char* env = PR_GetEnv("MOZ_GMP_PATH"); + if (!env || !*env) { + return; + } + + nsString allpaths; + if (NS_WARN_IF(NS_FAILED(NS_CopyNativeToUnicode(nsDependentCString(env), allpaths)))) { + return; + } + + uint32_t pos = 0; + while (pos < allpaths.Length()) { + // Loop over multiple path entries separated by colons (*nix) or + // semicolons (Windows) + int32_t next = allpaths.FindChar(XPCOM_ENV_PATH_SEPARATOR[0], pos); + if (next == -1) { + AddOnGMPThread(nsDependentSubstring(allpaths, pos)); + break; + } else { + AddOnGMPThread(nsDependentSubstring(allpaths, pos, next - pos)); + pos = next + 1; + } + } +} + +NS_IMETHODIMP +GeckoMediaPluginService::PathRunnable::Run() +{ + if (mAdd) { + mService->AddOnGMPThread(mPath); + } else { + mService->RemoveOnGMPThread(mPath); + } + return NS_OK; +} + +NS_IMETHODIMP +GeckoMediaPluginService::AddPluginDirectory(const nsAString& aDirectory) +{ + MOZ_ASSERT(NS_IsMainThread()); + nsCOMPtr<nsIThread> thread; + nsresult rv = GetThread(getter_AddRefs(thread)); + if (NS_FAILED(rv)) { + return rv; + } + nsCOMPtr<nsIRunnable> r = new PathRunnable(this, aDirectory, true); + thread->Dispatch(r, NS_DISPATCH_NORMAL); + return NS_OK; +} + +NS_IMETHODIMP +GeckoMediaPluginService::RemovePluginDirectory(const nsAString& aDirectory) +{ + MOZ_ASSERT(NS_IsMainThread()); + nsCOMPtr<nsIThread> thread; + nsresult rv = GetThread(getter_AddRefs(thread)); + if (NS_FAILED(rv)) { + return rv; + } + nsCOMPtr<nsIRunnable> r = new PathRunnable(this, aDirectory, false); + thread->Dispatch(r, NS_DISPATCH_NORMAL); + return NS_OK; +} + GMPParent* GeckoMediaPluginService::SelectPluginForAPI(const nsAString& aOrigin, const nsCString& aAPI, const nsTArray<nsCString>& aTags) { MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - GMPParent* gmp = SelectPluginFromListForAPI(aOrigin, aAPI, aTags); - if (gmp) { - return gmp; - } - - RefreshPluginList(); - - return SelectPluginFromListForAPI(aOrigin, aAPI, aTags); -} - -GMPParent* -GeckoMediaPluginService::SelectPluginFromListForAPI(const nsAString& aOrigin, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - for (uint32_t i = 0; i < mPlugins.Length(); i++) { GMPParent* gmp = mPlugins[i]; bool supportsAllTags = true; for (uint32_t t = 0; t < aTags.Length(); t++) { const nsCString& tag = aTags[t]; if (!gmp->SupportsAPI(aAPI, tag)) { supportsAllTags = false; break; @@ -318,202 +359,56 @@ GeckoMediaPluginService::SelectPluginFro gmp->SetOrigin(aOrigin); } return gmp; } } return nullptr; } -nsresult -GeckoMediaPluginService::GetDirectoriesToSearch(nsTArray<nsCOMPtr<nsIFile>> &aDirs) + +void +GeckoMediaPluginService::AddOnGMPThread(const nsAString& aDirectory) { MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); -#if defined(XP_MACOSX) - nsCOMPtr<nsIFile> searchDir = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID); - MOZ_ASSERT(!mHomePath.IsEmpty()); - nsresult rv = searchDir->InitWithPath(mHomePath + NS_LITERAL_STRING("/Library/Internet Plug-Ins/")); - if (NS_FAILED(rv)) { - return rv; - } - aDirs.AppendElement(searchDir); - searchDir = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID); - rv = searchDir->InitWithPath(NS_LITERAL_STRING("/Library/Internet Plug-Ins/")); - if (NS_FAILED(rv)) { - return rv; - } - aDirs.AppendElement(searchDir); -#elif defined(OS_POSIX) - nsCOMPtr<nsIFile> searchDir = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID); - nsresult rv = searchDir->InitWithPath(NS_LITERAL_STRING("/usr/lib/mozilla/plugins/")); - if (NS_FAILED(rv)) { - return rv; - } - aDirs.AppendElement(searchDir); -#endif - return NS_OK; -} - -#if defined(XP_WIN) -static nsresult -GetPossiblePluginsForRegRoot(uint32_t aKey, nsTArray<nsCOMPtr<nsIFile>>& aDirs) -{ - nsCOMPtr<nsIWindowsRegKey> regKey = do_CreateInstance("@mozilla.org/windows-registry-key;1"); - if (!regKey) { - return NS_ERROR_FAILURE; - } - - nsresult rv = regKey->Open(aKey, - NS_LITERAL_STRING("Software\\MozillaPlugins"), - nsIWindowsRegKey::ACCESS_READ); - if (NS_FAILED(rv)) { - return rv; - } - - uint32_t childCount = 0; - MOZ_ALWAYS_TRUE(NS_SUCCEEDED(regKey->GetChildCount(&childCount))); - for (uint32_t index = 0; index < childCount; index++) { - nsAutoString childName; - rv = regKey->GetChildName(index, childName); - if (NS_FAILED(rv)) { - continue; - } - - nsCOMPtr<nsIWindowsRegKey> childKey; - rv = regKey->OpenChild(childName, nsIWindowsRegKey::ACCESS_QUERY_VALUE, - getter_AddRefs(childKey)); - if (NS_FAILED(rv) || !childKey) { - continue; - } - - nsAutoString path; - rv = childKey->ReadStringValue(NS_LITERAL_STRING("Path"), path); - if (NS_FAILED(rv)) { - continue; - } - - nsCOMPtr<nsIFile> localFile; - if (NS_SUCCEEDED(NS_NewLocalFile(path, true, getter_AddRefs(localFile))) && - localFile) { - bool isFileThere = false; - if (NS_SUCCEEDED(localFile->Exists(&isFileThere)) && isFileThere) { - aDirs.AppendElement(localFile); - } - } - } - - regKey->Close(); - - return NS_OK; -} -#endif - -nsresult -GeckoMediaPluginService::GetPossiblePlugins(nsTArray<nsCOMPtr<nsIFile>>& aDirs) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - -#if defined(XP_WIN) - // The ROOT_KEY_CURRENT_USER entry typically fails to open, causing this call to - // fail. Don't check any return values because if we find nothing we don't care. - GetPossiblePluginsForRegRoot(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, aDirs); - GetPossiblePluginsForRegRoot(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, aDirs); -#endif - return NS_OK; -} - -nsresult -GeckoMediaPluginService::SearchDirectory(nsIFile* aSearchDir) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - MOZ_ASSERT(aSearchDir); - - nsCOMPtr<nsISimpleEnumerator> iter; - nsresult rv = aSearchDir->GetDirectoryEntries(getter_AddRefs(iter)); - if (NS_FAILED(rv)) { - return rv; - } - - bool hasMore; - while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) { - nsCOMPtr<nsISupports> supports; - rv = iter->GetNext(getter_AddRefs(supports)); - if (NS_FAILED(rv)) { - continue; - } - nsCOMPtr<nsIFile> dirEntry(do_QueryInterface(supports, &rv)); - if (NS_FAILED(rv)) { - continue; - } - ProcessPossiblePlugin(dirEntry); - } - - return NS_OK; -} - -void -GeckoMediaPluginService::ProcessPossiblePlugin(nsIFile* aDir) -{ - MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - MOZ_ASSERT(aDir); - - bool isDirectory = false; - nsresult rv = aDir->IsDirectory(&isDirectory); - if (NS_FAILED(rv) || !isDirectory) { - return; - } - - nsAutoString leafName; - rv = aDir->GetLeafName(leafName); - if (NS_FAILED(rv)) { - return; - } - - NS_NAMED_LITERAL_STRING(prefix, "gmp-"); - if (leafName.Length() <= prefix.Length() || - !Substring(leafName, 0, prefix.Length()).Equals(prefix)) { + nsCOMPtr<nsIFile> directory; + nsresult rv = NS_NewLocalFile(aDirectory, false, getter_AddRefs(directory)); + if (NS_WARN_IF(NS_FAILED(rv))) { return; } nsRefPtr<GMPParent> gmp = new GMPParent(); - rv = gmp->Init(aDir); + rv = gmp->Init(directory); if (NS_FAILED(rv)) { return; } mPlugins.AppendElement(gmp); } void -GeckoMediaPluginService::RefreshPluginList() +GeckoMediaPluginService::RemoveOnGMPThread(const nsAString& aDirectory) { MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); - for (uint32_t iPlusOne = mPlugins.Length(); iPlusOne > 0; iPlusOne--) { - if (mPlugins[iPlusOne - 1]->State() == GMPStateNotLoaded) { - mPlugins.RemoveElementAt(iPlusOne - 1); - } - } - - nsTArray<nsCOMPtr<nsIFile>> searchDirs; - nsresult rv = GetDirectoriesToSearch(searchDirs); - if (NS_FAILED(rv)) { + nsCOMPtr<nsIFile> directory; + nsresult rv = NS_NewLocalFile(aDirectory, false, getter_AddRefs(directory)); + if (NS_WARN_IF(NS_FAILED(rv))) { return; } - for (uint32_t i = 0; i < searchDirs.Length(); i++) { - SearchDirectory(searchDirs[i]); + for (uint32_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]->UnloadProcess(); + mPlugins.RemoveElementAt(i); + return; + } } - - nsTArray<nsCOMPtr<nsIFile>> possiblePlugins; - rv = GetPossiblePlugins(possiblePlugins); - if (NS_FAILED(rv)) { - return; - } - - for (uint32_t i = 0; i < possiblePlugins.Length(); i++) { - ProcessPossiblePlugin(possiblePlugins[i]); - } + 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.")); } } // namespace gmp } // namespace mozilla
--- a/content/media/gmp/GMPService.h +++ b/content/media/gmp/GMPService.h @@ -9,17 +9,16 @@ #include "mozIGeckoMediaPluginService.h" #include "nsIObserver.h" #include "nsTArray.h" #include "mozilla/Mutex.h" #include "nsString.h" #include "nsCOMPtr.h" #include "nsIThread.h" -class nsIFile; template <class> struct already_AddRefed; namespace mozilla { namespace gmp { class GMPParent; class GeckoMediaPluginService MOZ_FINAL : public mozIGeckoMediaPluginService @@ -33,34 +32,49 @@ public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_MOZIGECKOMEDIAPLUGINSERVICE NS_DECL_NSIOBSERVER private: ~GeckoMediaPluginService(); - GMPParent* SelectPluginFromListForAPI(const nsAString& aOrigin, - const nsCString& aAPI, - const nsTArray<nsCString>& aTags); GMPParent* SelectPluginForAPI(const nsAString& aOrigin, const nsCString& aAPI, const nsTArray<nsCString>& aTags); + void UnloadPlugins(); - void RefreshPluginList(); + void LoadFromEnvironment(); void ProcessPossiblePlugin(nsIFile* aDir); - nsresult SearchDirectory(nsIFile* aSearchDir); - nsresult GetPossiblePlugins(nsTArray<nsCOMPtr<nsIFile>>& aDirs); - nsresult GetDirectoriesToSearch(nsTArray<nsCOMPtr<nsIFile>>& aDirs); + + void AddOnGMPThread(const nsAString& aSearchDir); + void RemoveOnGMPThread(const nsAString& aSearchDir); + + class PathRunnable : public nsRunnable + { + public: + PathRunnable(GeckoMediaPluginService* service, const nsAString& path, + bool add) + : mService(service) + , mPath(path) + , mAdd(add) + { } + + NS_DECL_NSIRUNNABLE + + private: + nsRefPtr<GeckoMediaPluginService> mService; + nsString mPath; + bool mAdd; + }; nsTArray<nsRefPtr<GMPParent>> mPlugins; Mutex mMutex; // Protects mGMPThread and mShuttingDown nsCOMPtr<nsIThread> mGMPThread; bool mShuttingDown; bool mShuttingDownOnGMPThread; - nsString mHomePath; }; } // namespace gmp } // namespace mozilla #endif // GMPService_h_
--- a/content/media/gmp/mozIGeckoMediaPluginService.idl +++ b/content/media/gmp/mozIGeckoMediaPluginService.idl @@ -16,31 +16,50 @@ class GMPVideoHost; %} [ptr] native GMPVideoDecoder(GMPVideoDecoder); [ptr] native GMPVideoEncoder(GMPVideoEncoder); [ptr] native GMPVideoHost(GMPVideoHost); [ptr] native MessageLoop(MessageLoop); [ptr] native TagArray(nsTArray<nsCString>); -[uuid(BF5A9086-70F5-4D38-832D-1609BBF963CD)] +[scriptable, uuid(63fc797f-9d01-43f4-8b93-5b1fe713c2f8)] interface mozIGeckoMediaPluginService : nsISupports { - // Returns the GMP thread. - // Callable from any thread. + /** + * The GMP thread. Callable from any thread. + */ readonly attribute nsIThread thread; - // Returns a video decoder that supports the specified tags. - // The array of tags should at least contain a codec tag, and optionally - // other tags such as for EME keysystem. - // Callable only on GMP thread. + /** + * Get a video decoder that supports the specified tags. + * The array of tags should at least contain a codec tag, and optionally + * other tags such as for EME keysystem. + * Callable only on GMP thread. + */ + [noscript] GMPVideoDecoder getGMPVideoDecoder(in TagArray tags, [optional] in AString origin, out GMPVideoHost outVideoHost); - // Returns a video encoder that supports the specified tags. - // The array of tags should at least contain a codec tag, and optionally - // other tags. - // Callable only on GMP thread. + /** + * Get a video encoder that supports the specified tags. + * The array of tags should at least contain a codec tag, and optionally + * other tags. + * Callable only on GMP thread. + */ + [noscript] GMPVideoEncoder getGMPVideoEncoder(in TagArray tags, [optional] in AString origin, out GMPVideoHost outVideoHost); + + /** + * Add a directory to scan for gecko media plugins. + * @note Main-thread API. + */ + void addPluginDirectory(in AString directory); + + /** + * Remove a directory for gecko media plugins. + * @note Main-thread API. + */ + void removePluginDirectory(in AString directory); };