blob: 7a976e0e69826ad80dc774c59c8e37fde7ab08ee [file] [log] [blame]
[email protected]b39c9b22012-01-24 17:45:461// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]a0421732011-02-23 03:55:405#include "content/browser/plugin_process_host.h"
initial.commit09911bf2008-07-26 23:55:296
[email protected]7398dcc2011-09-06 21:40:327#if defined(OS_WIN) && !defined(USE_AURA)
initial.commit09911bf2008-07-26 23:55:298#include <windows.h>
[email protected]2456c572009-11-09 04:21:519#elif defined(OS_POSIX)
10#include <utility> // for pair<>
[email protected]6eaddcc2009-02-23 21:03:0411#endif
12
initial.commit09911bf2008-07-26 23:55:2913#include <vector>
14
[email protected]7c854372011-08-15 20:41:4615#include "base/base_switches.h"
[email protected]80751052011-11-12 17:10:5816#include "base/bind.h"
initial.commit09911bf2008-07-26 23:55:2917#include "base/command_line.h"
[email protected]6eaddcc2009-02-23 21:03:0418#include "base/file_path.h"
initial.commit09911bf2008-07-26 23:55:2919#include "base/file_util.h"
20#include "base/logging.h"
[email protected]a5f73fea2012-02-15 18:09:1721#include "base/metrics/histogram.h"
initial.commit09911bf2008-07-26 23:55:2922#include "base/path_service.h"
[email protected]d2f11962009-08-17 19:50:0423#include "base/string_util.h"
[email protected]386c73502010-09-15 17:38:4224#include "base/utf_string_conversions.h"
[email protected]4c01d4992012-01-23 23:33:0125#include "content/browser/browser_child_process_host_impl.h"
[email protected]e67385f2011-12-21 06:00:5626#include "content/browser/plugin_service_impl.h"
[email protected]4734d0b2011-12-03 07:10:4427#include "content/common/child_process_host_impl.h"
[email protected]105303e2011-03-14 22:16:1028#include "content/common/plugin_messages.h"
[email protected]94dc971d2011-03-05 19:08:3229#include "content/common/resource_messages.h"
[email protected]c38831a12011-10-28 12:44:4930#include "content/public/browser/browser_thread.h"
[email protected]87f3c082011-10-19 18:07:4431#include "content/public/browser/content_browser_client.h"
[email protected]10d861c52011-11-10 00:03:4132#include "content/public/browser/notification_types.h"
[email protected]47214d882012-02-29 06:28:4833#include "content/public/browser/plugin_service.h"
[email protected]c08950d22011-10-13 22:20:2934#include "content/public/common/content_switches.h"
[email protected]bd5d6cf2011-12-01 00:39:1235#include "content/public/common/process_type.h"
[email protected]979c7e42009-07-23 16:14:0936#include "ipc/ipc_switches.h"
[email protected]42ce29d2011-01-20 23:19:4637#include "ui/base/ui_base_switches.h"
[email protected]c38831a12011-10-28 12:44:4938#include "ui/gfx/native_widget_types.h"
[email protected]c9e2cbbb2012-05-12 21:17:2739#include "ui/gl/gl_switches.h"
[email protected]6eaddcc2009-02-23 21:03:0440
[email protected]631bb742011-11-02 11:29:3941using content::BrowserThread;
[email protected]4967f792012-01-20 22:14:4042using content::ChildProcessData;
[email protected]4734d0b2011-12-03 07:10:4443using content::ChildProcessHost;
[email protected]631bb742011-11-02 11:29:3944
[email protected]753efc42010-03-09 19:52:1645#if defined(USE_X11)
[email protected]08397d52011-02-05 01:53:3846#include "ui/gfx/gtk_native_view_id_manager.h"
[email protected]700d3d52009-07-07 17:40:4647#endif
48
[email protected]f3ef7b12009-08-07 22:03:1749#if defined(OS_MACOSX)
[email protected]0378bf42011-01-01 18:20:1450#include "base/mac/mac_util.h"
[email protected]d31081452011-03-15 21:04:0251#include "content/common/plugin_carbon_interpose_constants_mac.h"
[email protected]08397d52011-02-05 01:53:3852#include "ui/gfx/rect.h"
[email protected]f3ef7b12009-08-07 22:03:1753#endif
54
[email protected]7398dcc2011-09-06 21:40:3255#if defined(OS_WIN) && !defined(USE_AURA)
[email protected]ded09892011-08-16 01:44:3556#include "base/win/windows_version.h"
57#include "webkit/plugins/npapi/plugin_constants_win.h"
[email protected]e4486d3202011-06-07 01:42:0458#include "webkit/plugins/npapi/webplugin_delegate_impl.h"
59
[email protected]d0ec2422011-06-08 20:55:3160namespace {
61
62void ReparentPluginWindowHelper(HWND window, HWND parent) {
63 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
64
65 int window_style = WS_CHILD;
66 if (!webkit::npapi::WebPluginDelegateImpl::IsDummyActivationWindow(window))
67 window_style |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
68
69 ::SetWindowLongPtr(window, GWL_STYLE, window_style);
70 ::SetParent(window, parent);
[email protected]ded09892011-08-16 01:44:3571 // Allow the Flash plugin to forward some messages back to Chrome.
72 if (base::win::GetVersion() >= base::win::VERSION_WIN7)
73 ::SetPropW(parent, webkit::npapi::kNativeWindowClassFilterProp, HANDLE(-1));
[email protected]d0ec2422011-06-08 20:55:3174}
75
76} // namespace
77
[email protected]875d4892009-04-21 21:48:3678void PluginProcessHost::OnPluginWindowDestroyed(HWND window, HWND parent) {
79 // The window is destroyed at this point, we just care about its parent, which
80 // is the intermediate window we created.
[email protected]20b64d32009-03-05 02:07:1881 std::set<HWND>::iterator window_index =
[email protected]875d4892009-04-21 21:48:3682 plugin_parent_windows_set_.find(parent);
83 if (window_index == plugin_parent_windows_set_.end())
84 return;
[email protected]20b64d32009-03-05 02:07:1885
[email protected]875d4892009-04-21 21:48:3686 plugin_parent_windows_set_.erase(window_index);
87 PostMessage(parent, WM_CLOSE, 0, 0);
[email protected]20b64d32009-03-05 02:07:1888}
89
90void PluginProcessHost::AddWindow(HWND window) {
91 plugin_parent_windows_set_.insert(window);
[email protected]6eaddcc2009-02-23 21:03:0492}
93
[email protected]e4486d3202011-06-07 01:42:0494void PluginProcessHost::OnReparentPluginWindow(HWND window, HWND parent) {
[email protected]ded09892011-08-16 01:44:3595 // Reparent only from the plugin process to our process.
[email protected]e4486d3202011-06-07 01:42:0496 DWORD process_id = 0;
[email protected]ded09892011-08-16 01:44:3597 ::GetWindowThreadProcessId(window, &process_id);
[email protected]4967f792012-01-20 22:14:4098 if (process_id != ::GetProcessId(process_->GetHandle()))
[email protected]ded09892011-08-16 01:44:3599 return;
[email protected]e4486d3202011-06-07 01:42:04100 ::GetWindowThreadProcessId(parent, &process_id);
101 if (process_id != ::GetCurrentProcessId())
102 return;
103
[email protected]d0ec2422011-06-08 20:55:31104 BrowserThread::PostTask(
105 BrowserThread::UI, FROM_HERE,
[email protected]80751052011-11-12 17:10:58106 base::Bind(ReparentPluginWindowHelper, window, parent));
[email protected]e4486d3202011-06-07 01:42:04107}
[email protected]a5f73fea2012-02-15 18:09:17108
109void PluginProcessHost::OnReportExecutableMemory(size_t size) {
110 // TODO(jschuh): move this into the plugin process once it supports UMA.
111 UMA_HISTOGRAM_MEMORY_KB("Plugin.ExecPageSizeKB", size / 1024);
112}
[email protected]6eaddcc2009-02-23 21:03:04113#endif // defined(OS_WIN)
[email protected]d7f45952009-01-16 23:04:23114
[email protected]a13283cc2012-04-05 00:21:22115#if defined(TOOLKIT_GTK)
[email protected]700d3d52009-07-07 17:40:46116void PluginProcessHost::OnMapNativeViewId(gfx::NativeViewId id,
117 gfx::PluginWindowHandle* output) {
118 *output = 0;
[email protected]3fa441d2011-09-18 17:28:50119#if !defined(USE_AURA)
[email protected]687b9602010-12-08 10:43:08120 GtkNativeViewManager::GetInstance()->GetXIDForId(output, id);
[email protected]3fa441d2011-09-18 17:28:50121#endif
[email protected]700d3d52009-07-07 17:40:46122}
[email protected]a13283cc2012-04-05 00:21:22123#endif // defined(TOOLKIT_GTK)
[email protected]700d3d52009-07-07 17:40:46124
[email protected]dabe6072009-03-17 00:52:35125PluginProcessHost::PluginProcessHost()
[email protected]2db347232010-05-28 21:26:36126#if defined(OS_MACOSX)
[email protected]4967f792012-01-20 22:14:40127 : plugin_cursor_visible_(true)
[email protected]2db347232010-05-28 21:26:36128#endif
129{
[email protected]4c01d4992012-01-23 23:33:01130 process_.reset(
131 new BrowserChildProcessHostImpl(content::PROCESS_TYPE_PLUGIN, this));
initial.commit09911bf2008-07-26 23:55:29132}
133
134PluginProcessHost::~PluginProcessHost() {
[email protected]7398dcc2011-09-06 21:40:32135#if defined(OS_WIN) && !defined(USE_AURA)
[email protected]20b64d32009-03-05 02:07:18136 // We erase HWNDs from the plugin_parent_windows_set_ when we receive a
137 // notification that the window is being destroyed. If we don't receive this
138 // notification and the PluginProcessHost instance is being destroyed, it
139 // means that the plugin process crashed. We paint a sad face in this case in
140 // the renderer process. To ensure that the sad face shows up, and we don't
141 // leak HWNDs, we should destroy existing plugin parent windows.
142 std::set<HWND>::iterator window_index;
143 for (window_index = plugin_parent_windows_set_.begin();
144 window_index != plugin_parent_windows_set_.end();
145 window_index++) {
146 PostMessage(*window_index, WM_CLOSE, 0, 0);
147 }
[email protected]1d5ac662009-10-01 19:41:56148#elif defined(OS_MACOSX)
[email protected]b44dbd12009-10-11 19:02:15149 // If the plugin process crashed but had fullscreen windows open at the time,
150 // make sure that the menu bar is visible.
151 std::set<uint32>::iterator window_index;
152 for (window_index = plugin_fullscreen_windows_set_.begin();
153 window_index != plugin_fullscreen_windows_set_.end();
154 window_index++) {
[email protected]f8b3ef82010-10-11 02:45:52155 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
[email protected]0378bf42011-01-01 18:20:14156 base::mac::ReleaseFullScreen(base::mac::kFullScreenModeHideAll);
[email protected]b44dbd12009-10-11 19:02:15157 } else {
[email protected]80751052011-11-12 17:10:58158 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
159 base::Bind(base::mac::ReleaseFullScreen,
160 base::mac::kFullScreenModeHideAll));
[email protected]b44dbd12009-10-11 19:02:15161 }
[email protected]1d5ac662009-10-01 19:41:56162 }
[email protected]18db46182010-02-02 17:04:55163 // If the plugin hid the cursor, reset that.
164 if (!plugin_cursor_visible_) {
[email protected]f8b3ef82010-10-11 02:45:52165 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
[email protected]0378bf42011-01-01 18:20:14166 base::mac::SetCursorVisibility(true);
[email protected]18db46182010-02-02 17:04:55167 } else {
[email protected]80751052011-11-12 17:10:58168 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
169 base::Bind(base::mac::SetCursorVisibility, true));
[email protected]18db46182010-02-02 17:04:55170 }
171 }
[email protected]20b64d32009-03-05 02:07:18172#endif
[email protected]46b69e42010-11-02 12:26:39173 // Cancel all pending and sent requests.
174 CancelRequests();
initial.commit09911bf2008-07-26 23:55:29175}
176
[email protected]4967f792012-01-20 22:14:40177bool PluginProcessHost::Send(IPC::Message* message) {
178 return process_->Send(message);
179}
180
[email protected]99907362012-01-11 05:41:40181bool PluginProcessHost::Init(const webkit::WebPluginInfo& info) {
[email protected]a27a9382009-02-11 23:55:10182 info_ = info;
[email protected]4967f792012-01-20 22:14:40183 process_->SetName(info_.name);
[email protected]a27a9382009-02-11 23:55:10184
[email protected]4967f792012-01-20 22:14:40185 std::string channel_id = process_->GetHost()->CreateChannel();
[email protected]4734d0b2011-12-03 07:10:44186 if (channel_id.empty())
initial.commit09911bf2008-07-26 23:55:29187 return false;
188
[email protected]7c4ea142010-01-26 05:15:42189 // Build command line for plugin. When we have a plugin launcher, we can't
190 // allow "self" on linux and we need the real file path.
191 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
[email protected]13081fc2010-08-04 18:24:38192 CommandLine::StringType plugin_launcher =
193 browser_command_line.GetSwitchValueNative(switches::kPluginLauncher);
[email protected]8c40f322011-08-24 03:33:36194
195#if defined(OS_MACOSX)
196 // Run the plug-in process in a mode tolerant of heap execution without
197 // explicit mprotect calls. Some plug-ins still rely on this quaint and
198 // archaic "feature." See http://crbug.com/93551.
[email protected]4cb43102011-12-02 20:24:49199 int flags = ChildProcessHost::CHILD_ALLOW_HEAP_EXECUTION;
[email protected]8c40f322011-08-24 03:33:36200#elif defined(OS_LINUX)
[email protected]4cb43102011-12-02 20:24:49201 int flags = plugin_launcher.empty() ? ChildProcessHost::CHILD_ALLOW_SELF :
202 ChildProcessHost::CHILD_NORMAL;
[email protected]8c40f322011-08-24 03:33:36203#else
[email protected]4cb43102011-12-02 20:24:49204 int flags = ChildProcessHost::CHILD_NORMAL;
[email protected]8c40f322011-08-24 03:33:36205#endif
206
[email protected]4cb43102011-12-02 20:24:49207 FilePath exe_path = ChildProcessHost::GetChildPath(flags);
[email protected]ba4c78e2009-10-13 23:00:11208 if (exe_path.empty())
initial.commit09911bf2008-07-26 23:55:29209 return false;
210
[email protected]fb1277e82009-11-21 20:32:30211 CommandLine* cmd_line = new CommandLine(exe_path);
[email protected]588c54b02009-09-18 21:45:54212 // Put the process type and plugin path first so they're easier to see
213 // in process listings using native process management tools.
[email protected]05076ba22010-07-30 05:59:57214 cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kPluginProcess);
[email protected]4f08c83f2010-07-29 23:02:34215 cmd_line->AppendSwitchPath(switches::kPluginPath, info.path);
[email protected]588c54b02009-09-18 21:45:54216
[email protected]2735e3692009-09-25 18:19:39217 // Propagate the following switches to the plugin command line (along with
initial.commit09911bf2008-07-26 23:55:29218 // any associated values) if present in the browser command line
[email protected]4f08c83f2010-07-29 23:02:34219 static const char* const kSwitchNames[] = {
initial.commit09911bf2008-07-26 23:55:29220 switches::kDisableBreakpad,
[email protected]dc51d1c2011-11-30 04:42:21221#if defined(OS_MACOSX)
222 switches::kDisableCompositedCoreAnimationPlugins,
223#endif
initial.commit09911bf2008-07-26 23:55:29224 switches::kDisableLogging,
initial.commit09911bf2008-07-26 23:55:29225 switches::kEnableDCHECK,
[email protected]b1f172a72011-04-11 17:26:07226 switches::kEnableLogging,
[email protected]4500a722009-03-27 19:56:54227 switches::kEnableStatsTable,
[email protected]b1f172a72011-04-11 17:26:07228 switches::kFullMemoryCrashReport,
229 switches::kLoggingLevel,
[email protected]b1f172a72011-04-11 17:26:07230 switches::kLogPluginMessages,
[email protected]b1f172a72011-04-11 17:26:07231 switches::kNoSandbox,
232 switches::kPluginStartupDialog,
[email protected]b1f172a72011-04-11 17:26:07233 switches::kTestSandbox,
[email protected]50f38422011-11-09 19:21:33234 switches::kTraceStartup,
[email protected]b1f172a72011-04-11 17:26:07235 switches::kUseGL,
236 switches::kUserAgent,
[email protected]b1f172a72011-04-11 17:26:07237 switches::kV,
initial.commit09911bf2008-07-26 23:55:29238 };
239
[email protected]4f08c83f2010-07-29 23:02:34240 cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
241 arraysize(kSwitchNames));
initial.commit09911bf2008-07-26 23:55:29242
243 // If specified, prepend a launcher program to the command line.
[email protected]e5e19c32009-04-20 22:10:02244 if (!plugin_launcher.empty())
[email protected]fb1277e82009-11-21 20:32:30245 cmd_line->PrependWrapper(plugin_launcher);
initial.commit09911bf2008-07-26 23:55:29246
[email protected]99907362012-01-11 05:41:40247 std::string locale =
248 content::GetContentClient()->browser()->GetApplicationLocale();
initial.commit09911bf2008-07-26 23:55:29249 if (!locale.empty()) {
250 // Pass on the locale so the null plugin will use the right language in the
251 // prompt to install the desired plugin.
[email protected]f77d87622010-07-30 17:43:17252 cmd_line->AppendSwitchASCII(switches::kLang, locale);
initial.commit09911bf2008-07-26 23:55:29253 }
254
[email protected]4734d0b2011-12-03 07:10:44255 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
initial.commit09911bf2008-07-26 23:55:29256
[email protected]2456c572009-11-09 04:21:51257#if defined(OS_POSIX)
[email protected]a82af392012-02-24 04:40:20258 base::EnvironmentVector env;
[email protected]23563dc1e2010-02-16 16:11:00259#if defined(OS_MACOSX) && !defined(__LP64__)
[email protected]f3ef7b12009-08-07 22:03:17260 // Add our interposing library for Carbon. This is stripped back out in
261 // plugin_main.cc, so changes here should be reflected there.
262 std::string interpose_list(plugin_interpose_strings::kInterposeLibraryPath);
263 const char* existing_list =
264 getenv(plugin_interpose_strings::kDYLDInsertLibrariesKey);
265 if (existing_list) {
266 interpose_list.insert(0, ":");
267 interpose_list.insert(0, existing_list);
268 }
[email protected]3d2217d2009-11-23 21:26:47269 env.push_back(std::pair<std::string, std::string>(
[email protected]f3ef7b12009-08-07 22:03:17270 plugin_interpose_strings::kDYLDInsertLibrariesKey,
[email protected]3d2217d2009-11-23 21:26:47271 interpose_list));
[email protected]fb1277e82009-11-21 20:32:30272#endif
273#endif
274
[email protected]4967f792012-01-20 22:14:40275 process_->Launch(
[email protected]fb1277e82009-11-21 20:32:30276#if defined(OS_WIN)
277 FilePath(),
278#elif defined(OS_POSIX)
[email protected]7c4ea142010-01-26 05:15:42279 false,
[email protected]fb1277e82009-11-21 20:32:30280 env,
281#endif
282 cmd_line);
283
[email protected]358cb8e2011-05-25 02:12:45284 // The plugin needs to be shutdown gracefully, i.e. NP_Shutdown needs to be
285 // called on the plugin. The plugin process exits when it receives the
286 // OnChannelError notification indicating that the browser plugin channel has
287 // been destroyed.
[email protected]4967f792012-01-20 22:14:40288 process_->SetTerminateChildOnShutdown(false);
[email protected]358cb8e2011-05-25 02:12:45289
[email protected]fb1277e82009-11-21 20:32:30290 return true;
initial.commit09911bf2008-07-26 23:55:29291}
[email protected]fb1277e82009-11-21 20:32:30292
[email protected]4e59e812010-04-06 20:51:16293void PluginProcessHost::ForceShutdown() {
[email protected]f8b3ef82010-10-11 02:45:52294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]4e59e812010-04-06 20:51:16295 Send(new PluginProcessMsg_NotifyRenderersOfPendingShutdown());
[email protected]4967f792012-01-20 22:14:40296 process_->ForceShutdown();
[email protected]4e59e812010-04-06 20:51:16297}
298
[email protected]4cb43102011-12-02 20:24:49299void PluginProcessHost::AddFilter(IPC::ChannelProxy::MessageFilter* filter) {
[email protected]4967f792012-01-20 22:14:40300 process_->GetHost()->AddFilter(filter);
[email protected]4cb43102011-12-02 20:24:49301}
302
[email protected]a95986a82010-12-24 06:19:28303bool PluginProcessHost::OnMessageReceived(const IPC::Message& msg) {
304 bool handled = true;
initial.commit09911bf2008-07-26 23:55:29305 IPC_BEGIN_MESSAGE_MAP(PluginProcessHost, msg)
306 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ChannelCreated, OnChannelCreated)
[email protected]7398dcc2011-09-06 21:40:32307#if defined(OS_WIN) && !defined(USE_AURA)
[email protected]875d4892009-04-21 21:48:36308 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginWindowDestroyed,
309 OnPluginWindowDestroyed)
[email protected]e4486d3202011-06-07 01:42:04310 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ReparentPluginWindow,
311 OnReparentPluginWindow)
[email protected]a5f73fea2012-02-15 18:09:17312 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ReportExecutableMemory,
313 OnReportExecutableMemory)
[email protected]829c2842009-04-01 01:48:52314#endif
[email protected]a13283cc2012-04-05 00:21:22315#if defined(TOOLKIT_GTK)
[email protected]700d3d52009-07-07 17:40:46316 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_MapNativeViewId,
317 OnMapNativeViewId)
318#endif
[email protected]1d5ac662009-10-01 19:41:56319#if defined(OS_MACOSX)
320 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginSelectWindow,
321 OnPluginSelectWindow)
322 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginShowWindow,
323 OnPluginShowWindow)
324 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginHideWindow,
325 OnPluginHideWindow)
[email protected]18db46182010-02-02 17:04:55326 IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginSetCursorVisibility,
327 OnPluginSetCursorVisibility)
[email protected]1d5ac662009-10-01 19:41:56328#endif
[email protected]a95986a82010-12-24 06:19:28329 IPC_MESSAGE_UNHANDLED(handled = false)
initial.commit09911bf2008-07-26 23:55:29330 IPC_END_MESSAGE_MAP()
[email protected]a95986a82010-12-24 06:19:28331
332 DCHECK(handled);
333 return handled;
initial.commit09911bf2008-07-26 23:55:29334}
335
336void PluginProcessHost::OnChannelConnected(int32 peer_pid) {
initial.commit09911bf2008-07-26 23:55:29337 for (size_t i = 0; i < pending_requests_.size(); ++i) {
[email protected]46b69e42010-11-02 12:26:39338 RequestPluginChannel(pending_requests_[i]);
initial.commit09911bf2008-07-26 23:55:29339 }
340
341 pending_requests_.clear();
initial.commit09911bf2008-07-26 23:55:29342}
343
344void PluginProcessHost::OnChannelError() {
[email protected]46b69e42010-11-02 12:26:39345 CancelRequests();
346}
initial.commit09911bf2008-07-26 23:55:29347
[email protected]ddb1e5a2010-12-13 20:10:45348bool PluginProcessHost::CanShutdown() {
349 return sent_requests_.empty();
350}
351
[email protected]47214d882012-02-29 06:28:48352void PluginProcessHost::OnProcessCrashed(int exit_code) {
353 PluginServiceImpl::GetInstance()->RegisterPluginCrash(info_.path);
354}
355
[email protected]46b69e42010-11-02 12:26:39356void PluginProcessHost::CancelRequests() {
357 for (size_t i = 0; i < pending_requests_.size(); ++i)
358 pending_requests_[i]->OnError();
initial.commit09911bf2008-07-26 23:55:29359 pending_requests_.clear();
[email protected]a3a8fb6d2009-10-22 20:12:51360
361 while (!sent_requests_.empty()) {
[email protected]8d32d5f2011-09-15 02:22:32362 Client* client = sent_requests_.front();
363 if (client)
364 client->OnError();
[email protected]4befe7592011-09-14 22:49:09365 sent_requests_.pop_front();
[email protected]a3a8fb6d2009-10-22 20:12:51366 }
initial.commit09911bf2008-07-26 23:55:29367}
368
[email protected]1a5acea82011-09-12 11:00:21369// static
370void PluginProcessHost::CancelPendingRequestsForResourceContext(
[email protected]df02aca2012-02-09 21:03:20371 content::ResourceContext* context) {
[email protected]4967f792012-01-20 22:14:40372 for (PluginProcessHostIterator host_it; !host_it.Done(); ++host_it) {
373 PluginProcessHost* host = *host_it;
[email protected]1a5acea82011-09-12 11:00:21374 for (size_t i = 0; i < host->pending_requests_.size(); ++i) {
[email protected]df02aca2012-02-09 21:03:20375 if (host->pending_requests_[i]->GetResourceContext() == context) {
[email protected]1a5acea82011-09-12 11:00:21376 host->pending_requests_[i]->OnError();
377 host->pending_requests_.erase(host->pending_requests_.begin() + i);
378 --i;
379 }
380 }
381 }
382}
383
[email protected]46b69e42010-11-02 12:26:39384void PluginProcessHost::OpenChannelToPlugin(Client* client) {
[email protected]4967f792012-01-20 22:14:40385 process_->Notify(content::NOTIFICATION_CHILD_INSTANCE_CREATED);
[email protected]46b69e42010-11-02 12:26:39386 client->SetPluginInfo(info_);
[email protected]4967f792012-01-20 22:14:40387 if (process_->GetHost()->IsChannelOpening()) {
[email protected]d2e884d2009-06-22 20:37:52388 // The channel is already in the process of being opened. Put
389 // this "open channel" request into a queue of requests that will
390 // be run once the channel is open.
[email protected]46b69e42010-11-02 12:26:39391 pending_requests_.push_back(client);
initial.commit09911bf2008-07-26 23:55:29392 return;
393 }
394
initial.commit09911bf2008-07-26 23:55:29395 // We already have an open channel, send a request right away to plugin.
[email protected]46b69e42010-11-02 12:26:39396 RequestPluginChannel(client);
initial.commit09911bf2008-07-26 23:55:29397}
398
[email protected]4befe7592011-09-14 22:49:09399void PluginProcessHost::CancelPendingRequest(Client* client) {
400 std::vector<Client*>::iterator it = pending_requests_.begin();
401 while (it != pending_requests_.end()) {
402 if (client == *it) {
403 pending_requests_.erase(it);
404 return;
405 }
406 ++it;
407 }
408 DCHECK(it != pending_requests_.end());
409}
410
411void PluginProcessHost::CancelSentRequest(Client* client) {
412 std::list<Client*>::iterator it = sent_requests_.begin();
413 while (it != sent_requests_.end()) {
414 if (client == *it) {
415 *it = NULL;
416 return;
417 }
418 ++it;
419 }
420 DCHECK(it != sent_requests_.end());
421}
422
[email protected]46b69e42010-11-02 12:26:39423void PluginProcessHost::RequestPluginChannel(Client* client) {
initial.commit09911bf2008-07-26 23:55:29424 // We can't send any sync messages from the browser because it might lead to
425 // a hang. However this async messages must be answered right away by the
426 // plugin process (i.e. unblocks a Send() call like a sync message) otherwise
427 // a deadlock can occur if the plugin creation request from the renderer is
428 // a result of a sync message by the plugin process.
[email protected]46b69e42010-11-02 12:26:39429 PluginProcessMsg_CreateChannel* msg =
[email protected]d5a19162011-06-30 18:51:54430 new PluginProcessMsg_CreateChannel(
431 client->ID(),
432 client->OffTheRecord());
initial.commit09911bf2008-07-26 23:55:29433 msg->set_unblock(true);
434 if (Send(msg)) {
[email protected]4befe7592011-09-14 22:49:09435 sent_requests_.push_back(client);
436 client->OnSentPluginChannelRequest();
initial.commit09911bf2008-07-26 23:55:29437 } else {
[email protected]46b69e42010-11-02 12:26:39438 client->OnError();
initial.commit09911bf2008-07-26 23:55:29439 }
440}
441
[email protected]3dfc7a42009-06-27 01:43:51442void PluginProcessHost::OnChannelCreated(
443 const IPC::ChannelHandle& channel_handle) {
[email protected]46b69e42010-11-02 12:26:39444 Client* client = sent_requests_.front();
[email protected]3dfc7a42009-06-27 01:43:51445
[email protected]4befe7592011-09-14 22:49:09446 if (client)
447 client->OnChannelOpened(channel_handle);
448 sent_requests_.pop_front();
initial.commit09911bf2008-07-26 23:55:29449}