Bug 1148012 - Add a run ID for plugins to differentiate subsequent runs of the same plugins. r=jimm.

Normally, this could be served by the process ID of a plugin, however, run ID is meant
to be consumed by multi-process browser chrome code for telling different runs of a
plugin apart (for example, for searching the DOM for a crashed instance of a plugin,
while ensuring that we don't accidentally find newly spawned instances that have not
crashed). Exposing something as low-level as the process ID to browser chrome code
seemed like Too Much Information. Also, there is the extremely unlikely chance that
a process ID might be re-used immediately after the original process shuts down. This
run ID avoids that case, regardless of how unlikely.
This commit is contained in:
Mike Conley 2015-03-17 13:42:34 -04:00
parent 4d921e1afe
commit 5ba86fbe43
6 changed files with 42 additions and 8 deletions

View File

@ -1022,17 +1022,21 @@ ContentParent::RecvGetGMPPluginVersionForAPI(const nsCString& aAPI,
}
bool
ContentParent::RecvLoadPlugin(const uint32_t& aPluginId, nsresult* aRv)
ContentParent::RecvLoadPlugin(const uint32_t& aPluginId, nsresult* aRv, uint32_t* aRunID)
{
*aRv = NS_OK;
return mozilla::plugins::SetupBridge(aPluginId, this, false, aRv);
return mozilla::plugins::SetupBridge(aPluginId, this, false, aRv, aRunID);
}
bool
ContentParent::RecvConnectPluginBridge(const uint32_t& aPluginId, nsresult* aRv)
{
*aRv = NS_OK;
return mozilla::plugins::SetupBridge(aPluginId, this, true, aRv);
// We don't need to get the run ID for the plugin, since we already got it
// in the first call to SetupBridge in RecvLoadPlugin, so we pass in a dummy
// pointer and just throw it away.
uint32_t dummy = 0;
return mozilla::plugins::SetupBridge(aPluginId, this, true, aRv, &dummy);
}
bool

View File

@ -174,7 +174,7 @@ public:
bool* aHasPlugin,
nsCString* aVersion) override;
virtual bool RecvLoadPlugin(const uint32_t& aPluginId, nsresult* aRv) override;
virtual bool RecvLoadPlugin(const uint32_t& aPluginId, nsresult* aRv, uint32_t* aRunID) override;
virtual bool RecvConnectPluginBridge(const uint32_t& aPluginId, nsresult* aRv) override;
virtual bool RecvFindPlugins(const uint32_t& aPluginEpoch,
nsTArray<PluginTag>* aPlugins,

View File

@ -633,7 +633,7 @@ parent:
* via bridging. The corresponding PluginModuleChild will live in the plugin
* process.
*/
sync LoadPlugin(uint32_t pluginId) returns (nsresult rv);
sync LoadPlugin(uint32_t aPluginId) returns (nsresult aResult, uint32_t aRunID);
/**
* This call is used by asynchronous plugin instantiation to notify the

View File

@ -17,7 +17,7 @@ namespace plugins {
bool
SetupBridge(uint32_t aPluginId, dom::ContentParent* aContentParent,
bool aForceBridgeNow, nsresult* rv);
bool aForceBridgeNow, nsresult* aResult, uint32_t* aRunID);
bool
FindPluginsForContent(uint32_t aPluginEpoch,

View File

@ -96,8 +96,13 @@ bool
mozilla::plugins::SetupBridge(uint32_t aPluginId,
dom::ContentParent* aContentParent,
bool aForceBridgeNow,
nsresult* rv)
nsresult* rv,
uint32_t* runID)
{
if (NS_WARN_IF(!rv) || NS_WARN_IF(!runID)) {
return false;
}
PluginModuleChromeParent::ClearInstantiationFlag();
nsRefPtr<nsPluginHost> host = nsPluginHost::GetInst();
nsRefPtr<nsNPAPIPlugin> plugin;
@ -106,6 +111,10 @@ mozilla::plugins::SetupBridge(uint32_t aPluginId,
return true;
}
PluginModuleChromeParent* chromeParent = static_cast<PluginModuleChromeParent*>(plugin->GetLibrary());
*rv = chromeParent->GetRunID(runID);
if (NS_FAILED(*rv)) {
return true;
}
chromeParent->SetContentParent(aContentParent);
if (!aForceBridgeNow && chromeParent->IsStartingAsync() &&
PluginModuleChromeParent::DidInstantiate()) {
@ -365,7 +374,8 @@ PluginModuleContentParent::LoadModule(uint32_t aPluginId)
*/
dom::ContentChild* cp = dom::ContentChild::GetSingleton();
nsresult rv;
if (!cp->SendLoadPlugin(aPluginId, &rv) ||
uint32_t runID;
if (!cp->SendLoadPlugin(aPluginId, &rv, &runID) ||
NS_FAILED(rv)) {
return nullptr;
}
@ -381,6 +391,7 @@ PluginModuleContentParent::LoadModule(uint32_t aPluginId)
}
parent->mPluginId = aPluginId;
parent->mRunID = runID;
return parent;
}
@ -644,6 +655,10 @@ PluginModuleContentParent::~PluginModuleContentParent()
Preferences::UnregisterCallback(TimeoutChanged, kContentTimeoutPref, this);
}
// We start the Run IDs at 1 so that we can use 0 as a way of detecting
// errors in retrieving the run ID.
uint32_t PluginModuleChromeParent::sNextRunID = 1;
bool PluginModuleChromeParent::sInstantiated = false;
PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId)
@ -675,6 +690,7 @@ PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32
{
NS_ASSERTION(mSubprocess, "Out of memory!");
sInstantiated = true;
mRunID = sNextRunID++;
RegisterSettingsCallbacks();
@ -1499,6 +1515,16 @@ PluginModuleParent::ActorDestroy(ActorDestroyReason why)
}
}
nsresult
PluginModuleParent::GetRunID(uint32_t* aRunID)
{
if (NS_WARN_IF(!aRunID)) {
return NS_ERROR_INVALID_POINTER;
}
*aRunID = mRunID;
return NS_OK;
}
void
PluginModuleChromeParent::ActorDestroy(ActorDestroyReason why)
{

View File

@ -128,6 +128,8 @@ public:
return mPluginName + mPluginVersion;
}
nsresult GetRunID(uint32_t* aRunID);
protected:
virtual mozilla::ipc::RacyInterruptPolicy
MediateInterruptRace(const Message& parent, const Message& child) override
@ -305,6 +307,7 @@ protected:
bool mNPInitialized;
nsTArray<nsRefPtr<PluginAsyncSurrogate>> mSurrogateInstances;
nsresult mAsyncNewRv;
uint32_t mRunID;
};
class PluginModuleContentParent : public PluginModuleParent
@ -551,6 +554,7 @@ private:
dom::ContentParent* mContentParent;
nsCOMPtr<nsIObserver> mOfflineObserver;
bool mIsBlocklisted;
static uint32_t sNextRunID;
static bool sInstantiated;
};