Bug 1337058 - Remove FindPlugins IPC message; r=bsmedberg

This commit is contained in:
Kyle Machulis 2017-06-06 10:39:46 -07:00
parent 237aa3d58c
commit 13959a88ce
8 changed files with 140 additions and 111 deletions

View File

@ -128,6 +128,7 @@
#include "nsDirectoryServiceUtils.h"
#include "nsDirectoryServiceDefs.h"
#include "nsContentPermissionHelper.h"
#include "nsPluginHost.h"
#ifdef NS_PRINTING
#include "nsPrintingProxy.h"
#endif
@ -3384,5 +3385,15 @@ ContentChild::GetEventTargetFor(TabChild* aTabChild)
return IToplevelProtocol::GetActorEventTarget(aTabChild);
}
mozilla::ipc::IPCResult
ContentChild::RecvSetPluginList(const uint32_t& aPluginEpoch,
nsTArray<plugins::PluginTag>&& aPluginTags,
nsTArray<plugins::FakePluginTag>&& aFakePluginTags)
{
RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
host->SetPluginsInContent(aPluginEpoch, aPluginTags, aFakePluginTags);
return IPC_OK();
}
} // namespace dom
} // namespace mozilla

View File

@ -661,6 +661,9 @@ public:
virtual already_AddRefed<nsIEventTarget> GetEventTargetFor(TabChild* aTabChild) override;
mozilla::ipc::IPCResult
RecvSetPluginList(const uint32_t& aPluginEpoch, nsTArray<PluginTag>&& aPluginTags, nsTArray<FakePluginTag>&& aFakePluginTags) override;
private:
static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure);
void StartForceKillTimer();

View File

@ -1162,17 +1162,6 @@ ContentParent::RecvGetBlocklistState(const uint32_t& aPluginId,
return IPC_OK();
}
mozilla::ipc::IPCResult
ContentParent::RecvFindPlugins(const uint32_t& aPluginEpoch,
nsresult* aRv,
nsTArray<PluginTag>* aPlugins,
nsTArray<FakePluginTag>* aFakePlugins,
uint32_t* aNewPluginEpoch)
{
*aRv = mozilla::plugins::FindPluginsForContent(aPluginEpoch, aPlugins, aFakePlugins, aNewPluginEpoch);
return IPC_OK();
}
/*static*/ TabParent*
ContentParent::CreateBrowser(const TabContext& aContext,
Element* aFrameElement,
@ -2448,6 +2437,11 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
Unused << SendInitBlobURLs(registrations);
}
}
// Start up nsPluginHost and run FindPlugins to cache the plugin list.
// If this isn't our first content process, just send over cached list.
RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
pluginHost->SendPluginsToContent();
}
bool
@ -5297,3 +5291,11 @@ ContentParent::CanCommunicateWith(ContentParentId aOtherProcess)
}
return parentId == aOtherProcess;
}
mozilla::ipc::IPCResult
ContentParent::RecvMaybeReloadPlugins()
{
RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
pluginHost->ReloadPlugins();
return IPC_OK();
}

View File

@ -298,6 +298,8 @@ public:
uint32_t* aRunID,
Endpoint<PPluginModuleParent>* aEndpoint) override;
virtual mozilla::ipc::IPCResult RecvMaybeReloadPlugins() override;
virtual mozilla::ipc::IPCResult RecvConnectPluginBridge(const uint32_t& aPluginId,
nsresult* aRv,
Endpoint<PPluginModuleParent>* aEndpoint) override;
@ -305,12 +307,6 @@ public:
virtual mozilla::ipc::IPCResult RecvGetBlocklistState(const uint32_t& aPluginId,
uint32_t* aIsBlocklisted) override;
virtual mozilla::ipc::IPCResult RecvFindPlugins(const uint32_t& aPluginEpoch,
nsresult* aRv,
nsTArray<PluginTag>* aPlugins,
nsTArray<FakePluginTag>* aFakePlugins,
uint32_t* aNewPluginEpoch) override;
virtual mozilla::ipc::IPCResult RecvUngrabPointer(const uint32_t& aTime) override;
virtual mozilla::ipc::IPCResult RecvRemovePermission(const IPC::Principal& aPrincipal,

View File

@ -611,6 +611,17 @@ child:
async PIPCBlobInputStream(nsID aID, uint64_t aSize);
/**
* This call takes the set of plugins loaded in the chrome process, and
* sends them to the content process. However, in many cases this set will
* not have changed since the last SetPluginList message. To keep track of
* this, the chrome process increments an epoch number every time the set of
* plugins changes. The chrome process sends up the last epoch it observed.
* If the epoch last seen by the content process is the same, the content
* process ignores the update. Otherwise the content process updates its
* list and reloads its plugins.
**/
async SetPluginList(uint32_t pluginEpoch, PluginTag[] plugins, FakePluginTag[] fakePlugins);
parent:
async InitBackground(Endpoint<PBackgroundParent> aEndpoint);
@ -646,20 +657,6 @@ parent:
*/
sync GetBlocklistState(uint32_t aPluginId) returns (uint32_t aState);
/**
* This call returns the set of plugins loaded in the chrome
* process. However, in many cases this set will not have changed since the
* last FindPlugins message. Consequently, the chrome process increments an
* epoch number every time the set of plugins changes. The content process
* sends up the last epoch it observed. If the epochs are the same, the
* chrome process returns no plugins. Otherwise it returns a complete list.
*
* |pluginEpoch| is the epoch last observed by the content
* process. |newPluginEpoch| is the current epoch in the chrome process. If
* |pluginEpoch == newPluginEpoch|, then |plugins| will be left empty.
*/
sync FindPlugins(uint32_t pluginEpoch) returns (nsresult aResult, PluginTag[] plugins, FakePluginTag[] fakePlugins, uint32_t newPluginEpoch);
async PJavaScript();
async PRemoteSpellcheckEngine();
@ -1094,6 +1091,7 @@ parent:
async AddMemoryReport(MemoryReport aReport);
async FinishMemoryReport(uint32_t aGeneration);
async MaybeReloadPlugins();
both:
async AsyncMessage(nsString aMessage, CpowEntry[] aCpows,
Principal aPrincipal, ClonedMessageData aData);

View File

@ -51,6 +51,7 @@
#include "nsICategoryManager.h"
#include "nsPluginStreamListenerPeer.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/FakePluginTagInitBinding.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/plugins/PluginAsyncSurrogate.h"
@ -267,14 +268,6 @@ nsPluginHost::nsPluginHost()
, mPluginsDisabled(false)
, mPluginEpoch(0)
{
// Bump the pluginchanged epoch on startup. This insures content gets a
// good plugin list the first time it requests it. Normally we'd just
// init this to 1, but due to the unique nature of our ctor we need to do
// this manually.
if (XRE_IsParentProcess()) {
IncrementChromeEpoch();
}
// check to see if pref is set at startup to let plugins take over in
// full page mode for certain image mime types that we handle internally
mOverrideInternalTypes =
@ -303,6 +296,13 @@ nsPluginHost::nsPluginHost()
PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("nsPluginHost::ctor\n"));
PR_LogFlush();
#endif
// Load plugins on creation, as there's a good chance we'll need to send them
// to content processes directly after creation.
if (XRE_IsParentProcess())
{
LoadPlugins();
}
}
nsPluginHost::~nsPluginHost()
@ -360,8 +360,20 @@ nsresult nsPluginHost::ReloadPlugins()
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
("nsPluginHost::ReloadPlugins Begin\n"));
nsresult rv = NS_OK;
// If we're calling this from a content process, forward the reload request to
// the parent process. If plugins actually changed, it will notify us
// asynchronously later.
if (XRE_IsContentProcess())
{
Unused << mozilla::dom::ContentChild::GetSingleton()->SendMaybeReloadPlugins();
// In content processes, always signal that plugins have not changed. We
// will never know if they changed here unless we make slow synchronous
// calls. This information will hopefully only be wrong once, as if there
// has been a plugin update, we expect to have gotten notification from the
// parent process and everything should be updated by the next time this is
// called. See Bug 1337058 for more info.
return NS_ERROR_PLUGINS_PLUGINSNOTCHANGED;
}
// this will create the initial plugin list out of cache
// if it was not created yet
if (!mPluginsLoaded)
@ -382,6 +394,14 @@ nsresult nsPluginHost::ReloadPlugins()
if (!pluginschanged)
return NS_ERROR_PLUGINS_PLUGINSNOTCHANGED;
return ActuallyReloadPlugins();
}
nsresult
nsPluginHost::ActuallyReloadPlugins()
{
nsresult rv = NS_OK;
// shutdown plugins and kill the list if there are no running plugins
RefPtr<nsPluginTag> prev;
RefPtr<nsPluginTag> next;
@ -415,6 +435,13 @@ nsresult nsPluginHost::ReloadPlugins()
// load them again
rv = LoadPlugins();
if (XRE_IsParentProcess())
{
// If the plugin list changed, update content. If the plugin list changed
// for the content process, it will also reload plugins.
SendPluginsToContent();
}
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
("nsPluginHost::ReloadPlugins End\n"));
@ -2276,11 +2303,11 @@ WatchRegKey(uint32_t aRoot, nsCOMPtr<nsIWindowsRegKey>& aKey)
nsresult nsPluginHost::LoadPlugins()
{
#ifdef ANDROID
// This should only be run in the parent process. On plugin list change, we'll
// update observers in the content process as part of SetPluginsInContent
if (XRE_IsContentProcess()) {
return NS_OK;
}
#endif
// do not do anything if it is already done
// use ReloadPlugins() to enforce loading
if (mPluginsLoaded)
@ -2315,32 +2342,24 @@ nsresult nsPluginHost::LoadPlugins()
}
nsresult
nsPluginHost::FindPluginsInContent(bool aCreatePluginList, bool* aPluginsChanged)
nsPluginHost::SetPluginsInContent(uint32_t aPluginEpoch,
nsTArray<mozilla::plugins::PluginTag>& aPlugins,
nsTArray<mozilla::plugins::FakePluginTag>& aFakePlugins)
{
MOZ_ASSERT(XRE_IsContentProcess());
dom::ContentChild* cp = dom::ContentChild::GetSingleton();
nsresult rv;
nsTArray<PluginTag> plugins;
nsTArray<FakePluginTag> fakePlugins;
uint32_t parentEpoch;
if (!cp->SendFindPlugins(ChromeEpochForContent(), &rv, &plugins, &fakePlugins, &parentEpoch) ||
NS_FAILED(rv)) {
return NS_ERROR_NOT_AVAILABLE;
}
if (parentEpoch != ChromeEpochForContent()) {
*aPluginsChanged = true;
if (!aCreatePluginList) {
return NS_OK;
}
if (aPluginEpoch != ChromeEpochForContent()) {
// Since we know we're going to be repopulating the lists anyways, trigger a
// reload now to clear out all old entries.
ActuallyReloadPlugins();
// Don't do this if aCreatePluginList is false. Otherwise, when we actually
// want to create the list, we'll come back here and do nothing.
SetChromeEpochForContent(parentEpoch);
SetChromeEpochForContent(aPluginEpoch);
for (size_t i = 0; i < plugins.Length(); i++) {
PluginTag& tag = plugins[i];
for (auto tag : aPlugins) {
// Don't add the same plugin again.
if (nsPluginTag* existing = PluginWithId(tag.id())) {
@ -2367,7 +2386,7 @@ nsPluginHost::FindPluginsInContent(bool aCreatePluginList, bool* aPluginsChanged
AddPluginTag(pluginTag);
}
for (const auto& tag : fakePlugins) {
for (const auto& tag : aFakePlugins) {
// Don't add the same plugin again.
for (const auto& existingTag : mFakePlugins) {
if (existingTag->Id() == tag.id()) {
@ -2394,6 +2413,12 @@ nsPluginHost::FindPluginsInContent(bool aCreatePluginList, bool* aPluginsChanged
}
}
}
nsCOMPtr<nsIObserverService> obsService =
mozilla::services::GetObserverService();
if (obsService) {
obsService->NotifyObservers(nullptr, "plugins-list-updated", nullptr);
}
}
mPluginsLoaded = true;
@ -2411,8 +2436,10 @@ nsresult nsPluginHost::FindPlugins(bool aCreatePluginList, bool * aPluginsChange
*aPluginsChanged = false;
// If plugins are found or change, the content process will be notified by the
// parent process. Bail out early if this is called from the content process.
if (XRE_IsContentProcess()) {
return FindPluginsInContent(aCreatePluginList, aPluginsChanged);
return NS_OK;
}
nsresult rv;
@ -2541,35 +2568,19 @@ nsresult nsPluginHost::FindPlugins(bool aCreatePluginList, bool * aPluginsChange
}
nsresult
mozilla::plugins::FindPluginsForContent(uint32_t aPluginEpoch,
nsTArray<PluginTag>* aPlugins,
nsTArray<FakePluginTag>* aFakePlugins,
uint32_t* aNewPluginEpoch)
{
MOZ_ASSERT(XRE_IsParentProcess());
RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
return host->FindPluginsForContent(aPluginEpoch, aPlugins, aFakePlugins, aNewPluginEpoch);
}
nsresult
nsPluginHost::FindPluginsForContent(uint32_t aPluginEpoch,
nsTArray<PluginTag>* aPlugins,
nsTArray<FakePluginTag>* aFakePlugins,
uint32_t* aNewPluginEpoch)
nsPluginHost::SendPluginsToContent()
{
MOZ_ASSERT(XRE_IsParentProcess());
nsTArray<PluginTag> pluginTags;
nsTArray<FakePluginTag> fakePluginTags;
// Load plugins so that the epoch is correct.
nsresult rv = LoadPlugins();
if (NS_FAILED(rv)) {
return rv;
}
*aNewPluginEpoch = ChromeEpoch();
if (aPluginEpoch == ChromeEpoch()) {
return NS_OK;
}
uint32_t newPluginEpoch = ChromeEpoch();
nsTArray<nsCOMPtr<nsIInternalPluginTag>> plugins;
GetPlugins(plugins, true);
@ -2584,15 +2595,15 @@ nsPluginHost::FindPluginsForContent(uint32_t aPluginEpoch,
nsFakePluginTag* tag = static_cast<nsFakePluginTag*>(basetag.get());
mozilla::ipc::URIParams handlerURI;
SerializeURI(tag->HandlerURI(), handlerURI);
aFakePlugins->AppendElement(FakePluginTag(tag->Id(),
handlerURI,
tag->Name(),
tag->Description(),
tag->MimeTypes(),
tag->MimeDescriptions(),
tag->Extensions(),
tag->GetNiceFileName(),
tag->SandboxScript()));
fakePluginTags.AppendElement(FakePluginTag(tag->Id(),
handlerURI,
tag->Name(),
tag->Description(),
tag->MimeTypes(),
tag->MimeDescriptions(),
tag->Extensions(),
tag->GetNiceFileName(),
tag->SandboxScript()));
continue;
}
@ -2600,21 +2611,27 @@ nsPluginHost::FindPluginsForContent(uint32_t aPluginEpoch,
/// to be more sane and avoid this dance
nsPluginTag *tag = static_cast<nsPluginTag *>(basetag.get());
aPlugins->AppendElement(PluginTag(tag->mId,
tag->Name(),
tag->Description(),
tag->MimeTypes(),
tag->MimeDescriptions(),
tag->Extensions(),
tag->mIsJavaPlugin,
tag->mIsFlashPlugin,
tag->mSupportsAsyncInit,
tag->mSupportsAsyncRender,
tag->FileName(),
tag->Version(),
tag->mLastModifiedTime,
tag->IsFromExtension(),
tag->mSandboxLevel));
pluginTags.AppendElement(PluginTag(tag->mId,
tag->Name(),
tag->Description(),
tag->MimeTypes(),
tag->MimeDescriptions(),
tag->Extensions(),
tag->mIsJavaPlugin,
tag->mIsFlashPlugin,
tag->mSupportsAsyncInit,
tag->mSupportsAsyncRender,
tag->FileName(),
tag->Version(),
tag->mLastModifiedTime,
tag->IsFromExtension(),
tag->mSandboxLevel));
}
nsTArray<dom::ContentParent*> parents;
dom::ContentParent::GetAll(parents);
for (auto p : parents)
{
Unused << p->SendSetPluginList(newPluginEpoch, pluginTags, fakePluginTags);
}
return NS_OK;
}

View File

@ -252,6 +252,10 @@ public:
InfallibleTArray<nsCString>& result,
bool firstMatchOnly);
nsresult SendPluginsToContent();
nsresult SetPluginsInContent(uint32_t aPluginEpoch,
nsTArray<mozilla::plugins::PluginTag>& aPlugins,
nsTArray<mozilla::plugins::FakePluginTag>& aFakePlugins);
private:
friend class nsPluginUnloadRunnable;
@ -301,8 +305,6 @@ private:
nsresult
FindStoppedPluginForURL(nsIURI* aURL, nsIPluginInstanceOwner *aOwner);
nsresult FindPluginsInContent(bool aCreatePluginList, bool * aPluginsChanged);
nsresult
FindPlugins(bool aCreatePluginList, bool * aPluginsChanged);
@ -368,6 +370,8 @@ private:
void UpdateInMemoryPluginInfo(nsPluginTag* aPluginTag);
nsresult ActuallyReloadPlugins();
RefPtr<nsPluginTag> mPlugins;
RefPtr<nsPluginTag> mCachedPlugins;
RefPtr<nsInvalidPluginTag> mInvalidPlugins;

View File

@ -865,8 +865,6 @@ description =
description =
[PContent::GetBlocklistState]
description =
[PContent::FindPlugins]
description =
[PContent::NSSU2FTokenIsCompatibleVersion]
description =
[PContent::NSSU2FTokenIsRegistered]