Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: sw=4 ts=4 et :
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "mozilla/plugins/PluginProcessParent.h"
8 :
9 : #include "base/string_util.h"
10 : #include "base/process_util.h"
11 :
12 : #include "mozilla/ipc/BrowserProcessSubThread.h"
13 : #include "mozilla/plugins/PluginMessageUtils.h"
14 : #include "mozilla/Telemetry.h"
15 : #include "nsThreadUtils.h"
16 :
17 : using std::vector;
18 : using std::string;
19 :
20 : using mozilla::ipc::BrowserProcessSubThread;
21 : using mozilla::ipc::GeckoChildProcessHost;
22 : using mozilla::plugins::LaunchCompleteTask;
23 : using mozilla::plugins::PluginProcessParent;
24 : using base::ProcessArchitecture;
25 :
26 : #ifdef XP_WIN
27 : PluginProcessParent::PidSet* PluginProcessParent::sPidSet = nullptr;
28 : #endif
29 :
30 0 : PluginProcessParent::PluginProcessParent(const std::string& aPluginFilePath) :
31 : GeckoChildProcessHost(GeckoProcessType_Plugin)
32 : , mPluginFilePath(aPluginFilePath)
33 : , mTaskFactory(this)
34 0 : , mMainMsgLoop(MessageLoop::current())
35 : #ifdef XP_WIN
36 : , mChildPid(0)
37 : #endif
38 : {
39 0 : }
40 :
41 0 : PluginProcessParent::~PluginProcessParent()
42 : {
43 : #ifdef XP_WIN
44 : if (sPidSet && mChildPid) {
45 : sPidSet->RemoveEntry(mChildPid);
46 : if (sPidSet->IsEmpty()) {
47 : delete sPidSet;
48 : sPidSet = nullptr;
49 : }
50 : }
51 : #endif
52 0 : }
53 :
54 : bool
55 0 : PluginProcessParent::Launch(mozilla::UniquePtr<LaunchCompleteTask> aLaunchCompleteTask,
56 : int32_t aSandboxLevel)
57 : {
58 : #if defined(XP_WIN) && defined(MOZ_SANDBOX)
59 : mSandboxLevel = aSandboxLevel;
60 : #else
61 0 : if (aSandboxLevel != 0) {
62 0 : MOZ_ASSERT(false,
63 : "Can't enable an NPAPI process sandbox for platform/build.");
64 : }
65 : #endif
66 :
67 0 : ProcessArchitecture currentArchitecture = base::GetCurrentProcessArchitecture();
68 0 : uint32_t containerArchitectures = GetSupportedArchitecturesForProcessType(GeckoProcessType_Plugin);
69 :
70 0 : uint32_t pluginLibArchitectures = currentArchitecture;
71 : #ifdef XP_MACOSX
72 : nsresult rv = GetArchitecturesForBinary(mPluginFilePath.c_str(), &pluginLibArchitectures);
73 : if (NS_FAILED(rv)) {
74 : // If the call failed just assume that we want the current architecture.
75 : pluginLibArchitectures = currentArchitecture;
76 : }
77 : #endif
78 :
79 0 : ProcessArchitecture selectedArchitecture = currentArchitecture;
80 0 : if (!(pluginLibArchitectures & containerArchitectures & currentArchitecture)) {
81 : // Prefererence in order: x86_64, i386, PPC. The only particularly important thing
82 : // about this order is that we'll prefer 64-bit architectures first.
83 0 : if (base::PROCESS_ARCH_X86_64 & pluginLibArchitectures & containerArchitectures) {
84 0 : selectedArchitecture = base::PROCESS_ARCH_X86_64;
85 : }
86 0 : else if (base::PROCESS_ARCH_I386 & pluginLibArchitectures & containerArchitectures) {
87 0 : selectedArchitecture = base::PROCESS_ARCH_I386;
88 : }
89 0 : else if (base::PROCESS_ARCH_PPC & pluginLibArchitectures & containerArchitectures) {
90 0 : selectedArchitecture = base::PROCESS_ARCH_PPC;
91 : }
92 0 : else if (base::PROCESS_ARCH_ARM & pluginLibArchitectures & containerArchitectures) {
93 0 : selectedArchitecture = base::PROCESS_ARCH_ARM;
94 : }
95 0 : else if (base::PROCESS_ARCH_MIPS & pluginLibArchitectures & containerArchitectures) {
96 0 : selectedArchitecture = base::PROCESS_ARCH_MIPS;
97 : }
98 : else {
99 0 : return false;
100 : }
101 : }
102 :
103 0 : mLaunchCompleteTask = mozilla::Move(aLaunchCompleteTask);
104 :
105 0 : vector<string> args;
106 0 : args.push_back(MungePluginDsoPath(mPluginFilePath));
107 :
108 0 : bool result = AsyncLaunch(args, selectedArchitecture);
109 0 : if (!result) {
110 0 : mLaunchCompleteTask = nullptr;
111 : }
112 0 : return result;
113 : }
114 :
115 : void
116 0 : PluginProcessParent::Delete()
117 : {
118 0 : MessageLoop* currentLoop = MessageLoop::current();
119 0 : MessageLoop* ioLoop = XRE_GetIOMessageLoop();
120 :
121 0 : if (currentLoop == ioLoop) {
122 0 : delete this;
123 0 : return;
124 : }
125 :
126 0 : ioLoop->PostTask(
127 0 : NewNonOwningRunnableMethod("plugins::PluginProcessParent::Delete",
128 : this,
129 0 : &PluginProcessParent::Delete));
130 : }
131 :
132 : /**
133 : * This function exists so that we may provide an additional level of
134 : * indirection between the task being posted to main event loop (a
135 : * RunnableMethod) and the launch complete task itself. This is needed
136 : * for cases when both WaitUntilConnected or OnChannel* race to invoke the
137 : * task.
138 : */
139 : void
140 0 : PluginProcessParent::RunLaunchCompleteTask()
141 : {
142 0 : if (mLaunchCompleteTask) {
143 0 : mLaunchCompleteTask->Run();
144 0 : mLaunchCompleteTask = nullptr;
145 : }
146 0 : }
147 :
148 : bool
149 0 : PluginProcessParent::WaitUntilConnected(int32_t aTimeoutMs)
150 : {
151 0 : bool result = GeckoChildProcessHost::WaitUntilConnected(aTimeoutMs);
152 0 : if (mLaunchCompleteTask) {
153 0 : if (result) {
154 0 : mLaunchCompleteTask->SetLaunchSucceeded();
155 : }
156 0 : RunLaunchCompleteTask();
157 : }
158 0 : return result;
159 : }
160 :
161 : void
162 0 : PluginProcessParent::OnChannelConnected(int32_t peer_pid)
163 : {
164 : #ifdef XP_WIN
165 : mChildPid = static_cast<uint32_t>(peer_pid);
166 : if (!sPidSet) {
167 : sPidSet = new PluginProcessParent::PidSet();
168 : }
169 : sPidSet->PutEntry(mChildPid);
170 : #endif
171 :
172 0 : GeckoChildProcessHost::OnChannelConnected(peer_pid);
173 0 : }
174 :
175 : void
176 0 : PluginProcessParent::OnChannelError()
177 : {
178 0 : GeckoChildProcessHost::OnChannelError();
179 0 : }
180 :
181 : bool
182 0 : PluginProcessParent::IsConnected()
183 : {
184 0 : mozilla::MonitorAutoLock lock(mMonitor);
185 0 : return mProcessState == PROCESS_CONNECTED;
186 : }
187 :
188 : bool
189 0 : PluginProcessParent::IsPluginProcessId(base::ProcessId procId) {
190 : #ifdef XP_WIN
191 : MOZ_ASSERT(XRE_IsParentProcess());
192 : return sPidSet && sPidSet->Contains(static_cast<uint32_t>(procId));
193 : #else
194 0 : NS_ERROR("IsPluginProcessId not available on this platform.");
195 0 : return false;
196 : #endif
197 : }
|