Bug 1099410 - [e10s] Fix re-entrant plugin loading (r=bsmedberg)

This commit is contained in:
Bill McCloskey 2014-11-21 14:00:55 -08:00
parent 94a3194d6b
commit c822973e54
2 changed files with 62 additions and 12 deletions

View File

@ -97,29 +97,82 @@ mozilla::plugins::SetupBridge(uint32_t aPluginId, dom::ContentParent* aContentPa
return PPluginModule::Bridge(aContentParent, chromeParent); return PPluginModule::Bridge(aContentParent, chromeParent);
} }
PluginModuleContentParent* PluginModuleContentParent::sSavedModuleParent; // A linked list used to fetch newly created PluginModuleContentParent instances
// for LoadModule. Each pending LoadModule call owns an element in this list.
// The element's mModule field is filled in when the new
// PluginModuleContentParent arrives from chrome.
struct MOZ_STACK_CLASS SavedPluginModule
{
SavedPluginModule() : mModule(nullptr), mNext(sSavedModuleStack)
{
sSavedModuleStack = this;
}
~SavedPluginModule()
{
MOZ_ASSERT(sSavedModuleStack == this);
sSavedModuleStack = mNext;
}
PluginModuleContentParent* GetModule() { return mModule; }
// LoadModule can be on the stack multiple times since the intr message it
// sends will dispatch arbitrary incoming messages from the chrome process,
// which can include new HTTP data. This makes it somewhat tricky to match
// up the object created in PluginModuleContentParent::Create with the
// LoadModule call that asked for it.
//
// Each invocation of LoadModule pushes a new SavedPluginModule object on
// the sSavedModuleStack stack, with the most recent invocation at the
// front. LoadModule messages are always processed by the chrome process in
// order, and PluginModuleContentParent allocation messages will also be
// received in order. Therefore, we need to match up the first received
// PluginModuleContentParent creation message with the first sent LoadModule
// call. This call will be the last one in the list that doesn't already
// have a module attached to it.
static void SaveModule(PluginModuleContentParent* module)
{
SavedPluginModule* saved = sSavedModuleStack;
SavedPluginModule* prev = nullptr;
while (saved && !saved->mModule) {
prev = saved;
saved = saved->mNext;
}
MOZ_ASSERT(prev);
MOZ_ASSERT(!prev->mModule);
prev->mModule = module;
}
private:
PluginModuleContentParent* mModule;
SavedPluginModule* mNext;
static SavedPluginModule* sSavedModuleStack;
};
SavedPluginModule* SavedPluginModule::sSavedModuleStack;
/* static */ PluginLibrary* /* static */ PluginLibrary*
PluginModuleContentParent::LoadModule(uint32_t aPluginId) PluginModuleContentParent::LoadModule(uint32_t aPluginId)
{ {
MOZ_ASSERT(!sSavedModuleParent); SavedPluginModule saved;
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Content); MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Content);
/* /*
* We send a LoadPlugin message to the chrome process using an intr * We send a LoadPlugin message to the chrome process using an intr
* message. Before it sends its response, it sends a message to create * message. Before it sends its response, it sends a message to create a
* PluginModuleParent instance. That message is handled by * PluginModuleContentParent instance. That message is handled by
* PluginModuleContentParent::Create, which saves the instance in * PluginModuleContentParent::Create. See SavedPluginModule for details
* sSavedModuleParent. We fetch it from there after LoadPlugin finishes. * about how we match up the result of PluginModuleContentParent::Create
* with the LoadModule call that requested it.
*/ */
dom::ContentChild* cp = dom::ContentChild::GetSingleton(); dom::ContentChild* cp = dom::ContentChild::GetSingleton();
if (!cp->CallLoadPlugin(aPluginId)) { if (!cp->CallLoadPlugin(aPluginId)) {
return nullptr; return nullptr;
} }
PluginModuleContentParent* parent = sSavedModuleParent; PluginModuleContentParent* parent = saved.GetModule();
MOZ_ASSERT(parent); MOZ_ASSERT(parent);
sSavedModuleParent = nullptr;
return parent; return parent;
} }
@ -135,8 +188,7 @@ PluginModuleContentParent::Create(mozilla::ipc::Transport* aTransport,
return nullptr; return nullptr;
} }
MOZ_ASSERT(!sSavedModuleParent); SavedPluginModule::SaveModule(parent);
sSavedModuleParent = parent;
DebugOnly<bool> ok = parent->Open(aTransport, handle, XRE_GetIOMessageLoop(), DebugOnly<bool> ok = parent->Open(aTransport, handle, XRE_GetIOMessageLoop(),
mozilla::ipc::ParentSide); mozilla::ipc::ParentSide);

View File

@ -274,8 +274,6 @@ class PluginModuleContentParent : public PluginModuleParent
#ifdef MOZ_CRASHREPORTER_INJECTOR #ifdef MOZ_CRASHREPORTER_INJECTOR
void OnCrash(DWORD processID) MOZ_OVERRIDE {} void OnCrash(DWORD processID) MOZ_OVERRIDE {}
#endif #endif
static PluginModuleContentParent* sSavedModuleParent;
}; };
class PluginModuleChromeParent class PluginModuleChromeParent