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; }
void GeckoMediaPluginServiceParent::ReAddOnGMPThread(const nsRefPtr<GMPParent>& aOld) { MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread); LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, (void*) aOld)); nsRefPtr<GMPParent> gmp; if (!mShuttingDownOnGMPThread) { // Don't re-add plugin if we're shutting down. Let the old plugin die. gmp = ClonePlugin(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)); }