зеркало из https://github.com/mozilla/gecko-dev.git
Bug 998863: Asynchronous Plugin Initialization, Part 8: Plugin process launch changes; r=josh
This commit is contained in:
Родитель
bd70e04b59
Коммит
46b61c4117
|
@ -12,6 +12,7 @@
|
|||
#include "mozilla/ipc/BrowserProcessSubThread.h"
|
||||
#include "mozilla/plugins/PluginMessageUtils.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
@ -30,7 +31,9 @@ struct RunnableMethodTraits<PluginProcessParent>
|
|||
|
||||
PluginProcessParent::PluginProcessParent(const std::string& aPluginFilePath) :
|
||||
GeckoChildProcessHost(GeckoProcessType_Plugin),
|
||||
mPluginFilePath(aPluginFilePath)
|
||||
mPluginFilePath(aPluginFilePath),
|
||||
mMainMsgLoop(MessageLoop::current()),
|
||||
mRunCompleteTaskImmediately(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -39,7 +42,7 @@ PluginProcessParent::~PluginProcessParent()
|
|||
}
|
||||
|
||||
bool
|
||||
PluginProcessParent::Launch(int32_t timeoutMs)
|
||||
PluginProcessParent::Launch(UniquePtr<LaunchCompleteTask> aLaunchCompleteTask)
|
||||
{
|
||||
ProcessArchitecture currentArchitecture = base::GetCurrentProcessArchitecture();
|
||||
uint32_t containerArchitectures = GetSupportedArchitecturesForProcessType(GeckoProcessType_Plugin);
|
||||
|
@ -74,10 +77,16 @@ PluginProcessParent::Launch(int32_t timeoutMs)
|
|||
}
|
||||
}
|
||||
|
||||
mLaunchCompleteTask = Move(aLaunchCompleteTask);
|
||||
|
||||
vector<string> args;
|
||||
args.push_back(MungePluginDsoPath(mPluginFilePath));
|
||||
Telemetry::AutoTimer<Telemetry::PLUGIN_STARTUP_MS> timer;
|
||||
return SyncLaunch(args, timeoutMs, selectedArchitecture);
|
||||
|
||||
bool result = AsyncLaunch(args, selectedArchitecture);
|
||||
if (!result) {
|
||||
mLaunchCompleteTask = nullptr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -94,3 +103,49 @@ PluginProcessParent::Delete()
|
|||
ioLoop->PostTask(FROM_HERE,
|
||||
NewRunnableMethod(this, &PluginProcessParent::Delete));
|
||||
}
|
||||
|
||||
void
|
||||
PluginProcessParent::SetCallRunnableImmediately(bool aCallImmediately)
|
||||
{
|
||||
mRunCompleteTaskImmediately = aCallImmediately;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginProcessParent::WaitUntilConnected(int32_t aTimeoutMs)
|
||||
{
|
||||
bool result = GeckoChildProcessHost::WaitUntilConnected(aTimeoutMs);
|
||||
if (mRunCompleteTaskImmediately && mLaunchCompleteTask) {
|
||||
if (result) {
|
||||
mLaunchCompleteTask->SetLaunchSucceeded();
|
||||
}
|
||||
mLaunchCompleteTask->Run();
|
||||
mLaunchCompleteTask = nullptr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
PluginProcessParent::OnChannelConnected(int32_t peer_pid)
|
||||
{
|
||||
GeckoChildProcessHost::OnChannelConnected(peer_pid);
|
||||
if (mLaunchCompleteTask && !mRunCompleteTaskImmediately) {
|
||||
mMainMsgLoop->PostTask(FROM_HERE, mLaunchCompleteTask.release());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginProcessParent::OnChannelError()
|
||||
{
|
||||
GeckoChildProcessHost::OnChannelError();
|
||||
if (mLaunchCompleteTask && !mRunCompleteTaskImmediately) {
|
||||
mMainMsgLoop->PostTask(FROM_HERE, mLaunchCompleteTask.release());
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PluginProcessParent::IsConnected()
|
||||
{
|
||||
mozilla::MonitorAutoLock lock(mMonitor);
|
||||
return mProcessState == PROCESS_CONNECTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,15 +11,32 @@
|
|||
#include "base/basictypes.h"
|
||||
|
||||
#include "base/file_path.h"
|
||||
#include "base/task.h"
|
||||
#include "base/thread.h"
|
||||
#include "base/waitable_event.h"
|
||||
#include "chrome/common/child_process_host.h"
|
||||
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIRunnable.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class LaunchCompleteTask : public Task
|
||||
{
|
||||
public:
|
||||
LaunchCompleteTask()
|
||||
: mLaunchSucceeded(false)
|
||||
{
|
||||
}
|
||||
|
||||
void SetLaunchSucceeded() { mLaunchSucceeded = true; }
|
||||
|
||||
protected:
|
||||
bool mLaunchSucceeded;
|
||||
};
|
||||
|
||||
class PluginProcessParent : public mozilla::ipc::GeckoChildProcessHost
|
||||
{
|
||||
|
@ -28,10 +45,13 @@ public:
|
|||
~PluginProcessParent();
|
||||
|
||||
/**
|
||||
* Synchronously launch the plugin process. If the process fails to launch
|
||||
* after timeoutMs, this method will return false.
|
||||
* Launch the plugin process. If the process fails to launch,
|
||||
* this method will return false.
|
||||
*
|
||||
* @param aLaunchCompleteTask Task that is executed on the main
|
||||
* thread once the asynchonous launch has completed.
|
||||
*/
|
||||
bool Launch(int32_t timeoutMs);
|
||||
bool Launch(UniquePtr<LaunchCompleteTask> aLaunchCompleteTask = UniquePtr<LaunchCompleteTask>());
|
||||
|
||||
void Delete();
|
||||
|
||||
|
@ -45,8 +65,19 @@ public:
|
|||
using mozilla::ipc::GeckoChildProcessHost::GetShutDownEvent;
|
||||
using mozilla::ipc::GeckoChildProcessHost::GetChannel;
|
||||
|
||||
void SetCallRunnableImmediately(bool aCallImmediately);
|
||||
virtual bool WaitUntilConnected(int32_t aTimeoutMs = 0) MOZ_OVERRIDE;
|
||||
|
||||
virtual void OnChannelConnected(int32_t peer_pid) MOZ_OVERRIDE;
|
||||
virtual void OnChannelError() MOZ_OVERRIDE;
|
||||
|
||||
bool IsConnected();
|
||||
|
||||
private:
|
||||
std::string mPluginFilePath;
|
||||
UniquePtr<LaunchCompleteTask> mLaunchCompleteTask;
|
||||
MessageLoop* mMainMsgLoop;
|
||||
bool mRunCompleteTaskImmediately;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(PluginProcessParent);
|
||||
};
|
||||
|
|
|
@ -315,8 +315,6 @@ GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts, int aTime
|
|||
{
|
||||
PrepareLaunch();
|
||||
|
||||
PRIntervalTime timeoutTicks = (aTimeoutMs > 0) ?
|
||||
PR_MillisecondsToInterval(aTimeoutMs) : PR_INTERVAL_NO_TIMEOUT;
|
||||
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
|
||||
NS_ASSERTION(MessageLoop::current() != ioLoop, "sync launch from the IO thread NYI");
|
||||
|
||||
|
@ -324,8 +322,40 @@ GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts, int aTime
|
|||
NewRunnableMethod(this,
|
||||
&GeckoChildProcessHost::RunPerformAsyncLaunch,
|
||||
aExtraOpts, arch));
|
||||
|
||||
return WaitUntilConnected(aTimeoutMs);
|
||||
}
|
||||
|
||||
bool
|
||||
GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts,
|
||||
base::ProcessArchitecture arch)
|
||||
{
|
||||
PrepareLaunch();
|
||||
|
||||
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
|
||||
ioLoop->PostTask(FROM_HERE,
|
||||
NewRunnableMethod(this,
|
||||
&GeckoChildProcessHost::RunPerformAsyncLaunch,
|
||||
aExtraOpts, arch));
|
||||
|
||||
// This may look like the sync launch wait, but we only delay as
|
||||
// long as it takes to create the channel.
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
while (mProcessState < CHANNEL_INITIALIZED) {
|
||||
lock.Wait();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GeckoChildProcessHost::WaitUntilConnected(int32_t aTimeoutMs)
|
||||
{
|
||||
// NB: this uses a different mechanism than the chromium parent
|
||||
// class.
|
||||
PRIntervalTime timeoutTicks = (aTimeoutMs > 0) ?
|
||||
PR_MillisecondsToInterval(aTimeoutMs) : PR_INTERVAL_NO_TIMEOUT;
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
PRIntervalTime waitStart = PR_IntervalNow();
|
||||
PRIntervalTime current;
|
||||
|
@ -354,27 +384,6 @@ GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts, int aTime
|
|||
return mProcessState == PROCESS_CONNECTED;
|
||||
}
|
||||
|
||||
bool
|
||||
GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts)
|
||||
{
|
||||
PrepareLaunch();
|
||||
|
||||
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
|
||||
ioLoop->PostTask(FROM_HERE,
|
||||
NewRunnableMethod(this,
|
||||
&GeckoChildProcessHost::RunPerformAsyncLaunch,
|
||||
aExtraOpts, base::GetCurrentProcessArchitecture()));
|
||||
|
||||
// This may look like the sync launch wait, but we only delay as
|
||||
// long as it takes to create the channel.
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
while (mProcessState < CHANNEL_INITIALIZED) {
|
||||
lock.Wait();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GeckoChildProcessHost::LaunchAndWaitForProcessHandle(StringVector aExtraOpts)
|
||||
{
|
||||
|
|
|
@ -52,7 +52,10 @@ public:
|
|||
// Block until the IPC channel for our subprocess is initialized,
|
||||
// but no longer. The child process may or may not have been
|
||||
// created when this method returns.
|
||||
bool AsyncLaunch(StringVector aExtraOpts=StringVector());
|
||||
bool AsyncLaunch(StringVector aExtraOpts=StringVector(),
|
||||
base::ProcessArchitecture arch=base::GetCurrentProcessArchitecture());
|
||||
|
||||
virtual bool WaitUntilConnected(int32_t aTimeoutMs = 0);
|
||||
|
||||
// Block until the IPC channel for our subprocess is initialized and
|
||||
// the OS process is created. The subprocess may or may not have
|
||||
|
|
Загрузка…
Ссылка в новой задаче