Bug 998863: Asynchronous Plugin Initialization, Part 8: Plugin process launch changes; r=josh

This commit is contained in:
Aaron Klotz 2014-12-24 17:56:53 -07:00
Родитель bd70e04b59
Коммит 46b61c4117
4 изменённых файлов: 130 добавлений и 32 удалений

Просмотреть файл

@ -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