diff options
Diffstat (limited to 'dom/plugins/ipc/PluginProcessParent.cpp')
-rw-r--r-- | dom/plugins/ipc/PluginProcessParent.cpp | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/dom/plugins/ipc/PluginProcessParent.cpp b/dom/plugins/ipc/PluginProcessParent.cpp new file mode 100644 index 000000000..444568135 --- /dev/null +++ b/dom/plugins/ipc/PluginProcessParent.cpp @@ -0,0 +1,163 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/plugins/PluginProcessParent.h" + +#include "base/string_util.h" +#include "base/process_util.h" + +#include "mozilla/ipc/BrowserProcessSubThread.h" +#include "mozilla/plugins/PluginMessageUtils.h" +#include "nsThreadUtils.h" + +using std::vector; +using std::string; + +using mozilla::ipc::BrowserProcessSubThread; +using mozilla::ipc::GeckoChildProcessHost; +using mozilla::plugins::LaunchCompleteTask; +using mozilla::plugins::PluginProcessParent; +using base::ProcessArchitecture; + +PluginProcessParent::PluginProcessParent(const std::string& aPluginFilePath) : + GeckoChildProcessHost(GeckoProcessType_Plugin), + mPluginFilePath(aPluginFilePath), + mTaskFactory(this), + mMainMsgLoop(MessageLoop::current()), + mRunCompleteTaskImmediately(false) +{ +} + +PluginProcessParent::~PluginProcessParent() +{ +} + +bool +PluginProcessParent::Launch(mozilla::UniquePtr<LaunchCompleteTask> aLaunchCompleteTask, + int32_t aSandboxLevel) +{ + if (aSandboxLevel != 0) { + MOZ_ASSERT(false, + "Can't enable an NPAPI process sandbox for platform/build."); + } + + ProcessArchitecture currentArchitecture = base::GetCurrentProcessArchitecture(); + uint32_t containerArchitectures = GetSupportedArchitecturesForProcessType(GeckoProcessType_Plugin); + + uint32_t pluginLibArchitectures = currentArchitecture; + + ProcessArchitecture selectedArchitecture = currentArchitecture; + if (!(pluginLibArchitectures & containerArchitectures & currentArchitecture)) { + // Prefererence in order: x86_64, i386, PPC. The only particularly important thing + // about this order is that we'll prefer 64-bit architectures first. + if (base::PROCESS_ARCH_X86_64 & pluginLibArchitectures & containerArchitectures) { + selectedArchitecture = base::PROCESS_ARCH_X86_64; + } + else if (base::PROCESS_ARCH_I386 & pluginLibArchitectures & containerArchitectures) { + selectedArchitecture = base::PROCESS_ARCH_I386; + } + else if (base::PROCESS_ARCH_PPC & pluginLibArchitectures & containerArchitectures) { + selectedArchitecture = base::PROCESS_ARCH_PPC; + } + else if (base::PROCESS_ARCH_ARM & pluginLibArchitectures & containerArchitectures) { + selectedArchitecture = base::PROCESS_ARCH_ARM; + } + else if (base::PROCESS_ARCH_MIPS & pluginLibArchitectures & containerArchitectures) { + selectedArchitecture = base::PROCESS_ARCH_MIPS; + } + else { + return false; + } + } + + mLaunchCompleteTask = mozilla::Move(aLaunchCompleteTask); + + vector<string> args; + args.push_back(MungePluginDsoPath(mPluginFilePath)); + + bool result = AsyncLaunch(args, selectedArchitecture); + if (!result) { + mLaunchCompleteTask = nullptr; + } + return result; +} + +void +PluginProcessParent::Delete() +{ + MessageLoop* currentLoop = MessageLoop::current(); + MessageLoop* ioLoop = XRE_GetIOMessageLoop(); + + if (currentLoop == ioLoop) { + delete this; + return; + } + + ioLoop->PostTask(NewNonOwningRunnableMethod(this, &PluginProcessParent::Delete)); +} + +void +PluginProcessParent::SetCallRunnableImmediately(bool aCallImmediately) +{ + mRunCompleteTaskImmediately = aCallImmediately; +} + +/** + * This function exists so that we may provide an additional level of + * indirection between the task being posted to main event loop (a + * RunnableMethod) and the launch complete task itself. This is needed + * for cases when both WaitUntilConnected or OnChannel* race to invoke the + * task. + */ +void +PluginProcessParent::RunLaunchCompleteTask() +{ + if (mLaunchCompleteTask) { + mLaunchCompleteTask->Run(); + mLaunchCompleteTask = nullptr; + } +} + +bool +PluginProcessParent::WaitUntilConnected(int32_t aTimeoutMs) +{ + bool result = GeckoChildProcessHost::WaitUntilConnected(aTimeoutMs); + if (mRunCompleteTaskImmediately && mLaunchCompleteTask) { + if (result) { + mLaunchCompleteTask->SetLaunchSucceeded(); + } + RunLaunchCompleteTask(); + } + return result; +} + +void +PluginProcessParent::OnChannelConnected(int32_t peer_pid) +{ + GeckoChildProcessHost::OnChannelConnected(peer_pid); + if (mLaunchCompleteTask && !mRunCompleteTaskImmediately) { + mLaunchCompleteTask->SetLaunchSucceeded(); + mMainMsgLoop->PostTask(mTaskFactory.NewRunnableMethod( + &PluginProcessParent::RunLaunchCompleteTask)); + } +} + +void +PluginProcessParent::OnChannelError() +{ + GeckoChildProcessHost::OnChannelError(); + if (mLaunchCompleteTask && !mRunCompleteTaskImmediately) { + mMainMsgLoop->PostTask(mTaskFactory.NewRunnableMethod( + &PluginProcessParent::RunLaunchCompleteTask)); + } +} + +bool +PluginProcessParent::IsConnected() +{ + mozilla::MonitorAutoLock lock(mMonitor); + return mProcessState == PROCESS_CONNECTED; +} + |