GMPParent* GeckoMediaPluginServiceParent::FindPluginForAPIFrom(size_t aSearchStartIndex, const nsCString& aAPI, const nsTArray<nsCString>& aTags, size_t* aOutPluginIndex) { mMutex.AssertCurrentThreadOwns(); for (size_t i = aSearchStartIndex; i < mPlugins.Length(); i++) { GMPParent* gmp = mPlugins[i]; bool supportsAllTags = true; for (size_t t = 0; t < aTags.Length(); t++) { const nsCString& tag = aTags.ElementAt(t); if (!gmp->SupportsAPI(aAPI, tag)) { supportsAllTags = false; break; } } if (!supportsAllTags) { continue; } if (aOutPluginIndex) { *aOutPluginIndex = i; } return gmp; } return nullptr; }
GMPParent* GeckoMediaPluginServiceParent::SelectPluginForAPI(const nsACString& aNodeId, const nsCString& aAPI, const nsTArray<nsCString>& aTags) { MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread, "Can't clone GMP plugins on non-GMP threads."); GMPParent* gmpToClone = nullptr; { MutexAutoLock lock(mMutex); size_t index = 0; GMPParent* gmp = nullptr; while ((gmp = FindPluginForAPIFrom(index, aAPI, aTags, &index))) { if (aNodeId.IsEmpty()) { if (gmp->CanBeSharedCrossNodeIds()) { return gmp; } } else if (gmp->CanBeUsedFrom(aNodeId)) { MOZ_ASSERT(!aNodeId.IsEmpty()); gmp->SetNodeId(aNodeId); return gmp; } if (!gmpToClone || (gmpToClone->IsMarkedForDeletion() && !gmp->IsMarkedForDeletion())) { // This GMP has the correct type but has the wrong nodeId; hold on to it // in case we need to clone it. // Prefer GMPs in-use for the case where an upgraded plugin version is // waiting for the old one to die. If the old plugin is in use, we // should continue using it so that any persistent state remains // consistent. Otherwise, just check that the plugin isn't scheduled // for deletion. gmpToClone = gmp; } // Loop around and try the next plugin; it may be usable from aNodeId. index++; } } // Plugin exists, but we can't use it due to cross-origin separation. Create a // new one. if (gmpToClone) { GMPParent* clone = ClonePlugin(gmpToClone); if (!aNodeId.IsEmpty()) { clone->SetNodeId(aNodeId); } return clone; } if (aAPI.EqualsLiteral(GMP_API_DECRYPTOR)) { // XXX to remove in bug 1147692 return SelectPluginForAPI(aNodeId, NS_LITERAL_CSTRING(GMP_API_DECRYPTOR_COMPAT), aTags); } return nullptr; }
GMPParent* GeckoMediaPluginServiceParent::SelectPluginForAPI(const nsACString& aNodeId, const nsCString& aAPI, const nsTArray<nsCString>& aTags) { MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread, "Can't clone GMP plugins on non-GMP threads."); GMPParent* gmpToClone = nullptr; { MutexAutoLock lock(mMutex); size_t index = 0; GMPParent* gmp = nullptr; while ((gmp = FindPluginForAPIFrom(index, aAPI, aTags, &index))) { if (aNodeId.IsEmpty()) { if (gmp->CanBeSharedCrossNodeIds()) { return gmp; } } else if (gmp->CanBeUsedFrom(aNodeId)) { MOZ_ASSERT(!aNodeId.IsEmpty()); gmp->SetNodeId(aNodeId); return gmp; } // This GMP has the correct type but has the wrong nodeId; hold on to it // in case we need to clone it. gmpToClone = gmp; // Loop around and try the next plugin; it may be usable from aNodeId. index++; } } // Plugin exists, but we can't use it due to cross-origin separation. Create a // new one. if (gmpToClone) { GMPParent* clone = ClonePlugin(gmpToClone); if (!aNodeId.IsEmpty()) { clone->SetNodeId(aNodeId); } return clone; } if (aAPI.EqualsLiteral(GMP_API_DECRYPTOR)) { // XXX to remove in bug 1147692 return SelectPluginForAPI(aNodeId, NS_LITERAL_CSTRING(GMP_API_DECRYPTOR_COMPAT), aTags); } return nullptr; }