mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1268984 - Ensure GMPs are re-inserted in GMPServiceParent::mPlugins in the same order in ReAddOnGMPThread. r=gerald,jesup,a=ritu
The GMP which GeckoMediaPluginServiceParent::FindPluginForAPIFrom() returns depends on the order in which GMPs lie in GMPServiceParent::mPlugins. However when we shutdown a GMPParent we remove and then re-append the GMPParent to mPlugins. This means the order in which GMPs lie in the list changes. So when WebRTC requests an H.264 decoder, the first time it will get OpenH264, since that's first in the list. But once we dispose of that decoder, its GMPParent will be cloned and the clone will be appended to the end of the list. This means the next time WebRTC requests a decoder, it'll get whatever was next in the list. This could be the Adobe GMP, which seems to be able to handle whatever WebRTC is putting into it. However, if you do this enough times, you'll get the Widevine CDM, which can't handle whatever WebRTC is putting into it. So a quick hack to fix this is in ReAddOnGMPThread is to re-insert the clone of the GMP into the slot in mPlugins that the original occupied. Then WebRTC will always get OpenH264 whenever it requests for an H.264 decoder, as the order of the GMPParents in mPlugins won't change. MozReview-Commit-ID: Ii4AMqDqAo9
This commit is contained in:
parent
4eab9fb575
commit
ed8e6a58be
@ -908,7 +908,7 @@ GeckoMediaPluginServiceParent::GetPluginVersionForAPI(const nsACString& aAPI,
|
||||
double maxParsedVersion = -1.;
|
||||
|
||||
*aHasPlugin = false;
|
||||
while (GMPParent* gmp = FindPluginForAPIFrom(index, api, *aTags, &index)) {
|
||||
while (RefPtr<GMPParent> gmp = FindPluginForAPIFrom(index, api, *aTags, &index)) {
|
||||
*aHasPlugin = true;
|
||||
double parsedVersion = atof(gmp->GetVersion().get());
|
||||
if (maxParsedVersion < 0 || parsedVersion > maxParsedVersion) {
|
||||
@ -941,7 +941,7 @@ GeckoMediaPluginServiceParent::EnsurePluginsOnDiskScanned()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
GMPParent*
|
||||
already_AddRefed<GMPParent>
|
||||
GeckoMediaPluginServiceParent::FindPluginForAPIFrom(size_t aSearchStartIndex,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags,
|
||||
@ -949,7 +949,7 @@ GeckoMediaPluginServiceParent::FindPluginForAPIFrom(size_t aSearchStartIndex,
|
||||
{
|
||||
mMutex.AssertCurrentThreadOwns();
|
||||
for (size_t i = aSearchStartIndex; i < mPlugins.Length(); i++) {
|
||||
GMPParent* gmp = mPlugins[i];
|
||||
RefPtr<GMPParent> gmp = mPlugins[i];
|
||||
bool supportsAllTags = true;
|
||||
for (size_t t = 0; t < aTags.Length(); t++) {
|
||||
const nsCString& tag = aTags.ElementAt(t);
|
||||
@ -964,12 +964,12 @@ GeckoMediaPluginServiceParent::FindPluginForAPIFrom(size_t aSearchStartIndex,
|
||||
if (aOutPluginIndex) {
|
||||
*aOutPluginIndex = i;
|
||||
}
|
||||
return gmp;
|
||||
return gmp.forget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GMPParent*
|
||||
already_AddRefed<GMPParent>
|
||||
GeckoMediaPluginServiceParent::SelectPluginForAPI(const nsACString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags)
|
||||
@ -981,16 +981,16 @@ GeckoMediaPluginServiceParent::SelectPluginForAPI(const nsACString& aNodeId,
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
size_t index = 0;
|
||||
GMPParent* gmp = nullptr;
|
||||
RefPtr<GMPParent> gmp;
|
||||
while ((gmp = FindPluginForAPIFrom(index, aAPI, aTags, &index))) {
|
||||
if (aNodeId.IsEmpty()) {
|
||||
if (gmp->CanBeSharedCrossNodeIds()) {
|
||||
return gmp;
|
||||
return gmp.forget();
|
||||
}
|
||||
} else if (gmp->CanBeUsedFrom(aNodeId)) {
|
||||
MOZ_ASSERT(!aNodeId.IsEmpty());
|
||||
gmp->SetNodeId(aNodeId);
|
||||
return gmp;
|
||||
return gmp.forget();
|
||||
}
|
||||
|
||||
if (!gmpToClone ||
|
||||
@ -1012,11 +1012,15 @@ GeckoMediaPluginServiceParent::SelectPluginForAPI(const nsACString& aNodeId,
|
||||
// Plugin exists, but we can't use it due to cross-origin separation. Create a
|
||||
// new one.
|
||||
if (gmpToClone) {
|
||||
GMPParent* clone = ClonePlugin(gmpToClone);
|
||||
RefPtr<GMPParent> clone = ClonePlugin(gmpToClone);
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
mPlugins.AppendElement(clone);
|
||||
}
|
||||
if (!aNodeId.IsEmpty()) {
|
||||
clone->SetNodeId(aNodeId);
|
||||
}
|
||||
return clone;
|
||||
return clone.forget();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@ -1037,7 +1041,7 @@ CreateGMPParent()
|
||||
return new GMPParent();
|
||||
}
|
||||
|
||||
GMPParent*
|
||||
already_AddRefed<GMPParent>
|
||||
GeckoMediaPluginServiceParent::ClonePlugin(const GMPParent* aOriginal)
|
||||
{
|
||||
MOZ_ASSERT(aOriginal);
|
||||
@ -1050,10 +1054,7 @@ GeckoMediaPluginServiceParent::ClonePlugin(const GMPParent* aOriginal)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
mPlugins.AppendElement(gmp);
|
||||
|
||||
return gmp.get();
|
||||
return gmp.forget();
|
||||
}
|
||||
|
||||
RefPtr<GenericPromise>
|
||||
@ -1196,15 +1197,21 @@ GeckoMediaPluginServiceParent::ReAddOnGMPThread(const RefPtr<GMPParent>& aOld)
|
||||
|
||||
RefPtr<GMPParent> gmp;
|
||||
if (!mShuttingDownOnGMPThread) {
|
||||
// Don't re-add plugin if we're shutting down. Let the old plugin die.
|
||||
// We're not shutting down, so replace the old plugin in the list with a
|
||||
// clone which is in a pristine state. Note: We place the plugin in
|
||||
// the same slot in the array as a hack to ensure if we re-request with
|
||||
// the same capabilities we get an instance of the same plugin.
|
||||
gmp = ClonePlugin(aOld);
|
||||
MutexAutoLock lock(mMutex);
|
||||
MOZ_ASSERT(mPlugins.Contains(aOld));
|
||||
if (mPlugins.Contains(aOld)) {
|
||||
mPlugins[mPlugins.IndexOf(aOld)] = gmp;
|
||||
}
|
||||
} else {
|
||||
// We're shutting down; don't re-add plugin, let the old plugin die.
|
||||
MutexAutoLock lock(mMutex);
|
||||
mPlugins.RemoveElement(aOld);
|
||||
}
|
||||
// Note: both are now in the list
|
||||
// Until we give up the GMPThread, we're safe even if we unlock temporarily
|
||||
// since off-main-thread users just test for existance; they don't modify the list.
|
||||
MutexAutoLock lock(mMutex);
|
||||
mPlugins.RemoveElement(aOld);
|
||||
|
||||
// Schedule aOld to be destroyed. We can't destroy it from here since we
|
||||
// may be inside ActorDestroyed() for it.
|
||||
NS_DispatchToCurrentThread(WrapRunnableNM(&Dummy, aOld));
|
||||
|
@ -66,13 +66,14 @@ private:
|
||||
|
||||
void ClearStorage();
|
||||
|
||||
GMPParent* SelectPluginForAPI(const nsACString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags);
|
||||
GMPParent* FindPluginForAPIFrom(size_t aSearchStartIndex,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags,
|
||||
size_t* aOutPluginIndex);
|
||||
already_AddRefed<GMPParent> SelectPluginForAPI(const nsACString& aNodeId,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags);
|
||||
|
||||
already_AddRefed<GMPParent> FindPluginForAPIFrom(size_t aSearchStartIndex,
|
||||
const nsCString& aAPI,
|
||||
const nsTArray<nsCString>& aTags,
|
||||
size_t* aOutPluginIndex);
|
||||
|
||||
nsresult GetNodeId(const nsAString& aOrigin, const nsAString& aTopLevelOrigin,
|
||||
const nsAString& aGMPName,
|
||||
@ -114,7 +115,9 @@ protected:
|
||||
UniquePtr<GetGMPContentParentCallback>&& aCallback)
|
||||
override;
|
||||
private:
|
||||
GMPParent* ClonePlugin(const GMPParent* aOriginal);
|
||||
// Creates a copy of aOriginal. Note that the caller is responsible for
|
||||
// adding this to GeckoMediaPluginServiceParent::mPlugins.
|
||||
already_AddRefed<GMPParent> ClonePlugin(const GMPParent* aOriginal);
|
||||
nsresult EnsurePluginsOnDiskScanned();
|
||||
nsresult InitStorage();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user