[email protected] | b39c9b2 | 2012-01-24 17:45:46 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
license.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 4 | |
[email protected] | a042173 | 2011-02-23 03:55:40 | [diff] [blame] | 5 | #include "content/browser/plugin_process_host.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 6 | |
[email protected] | 7398dcc | 2011-09-06 21:40:32 | [diff] [blame] | 7 | #if defined(OS_WIN) && !defined(USE_AURA) |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 8 | #include <windows.h> |
[email protected] | 2456c57 | 2009-11-09 04:21:51 | [diff] [blame] | 9 | #elif defined(OS_POSIX) |
| 10 | #include <utility> // for pair<> |
[email protected] | 6eaddcc | 2009-02-23 21:03:04 | [diff] [blame] | 11 | #endif |
| 12 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 13 | #include <vector> |
| 14 | |
[email protected] | 7c85437 | 2011-08-15 20:41:46 | [diff] [blame] | 15 | #include "base/base_switches.h" |
[email protected] | 8075105 | 2011-11-12 17:10:58 | [diff] [blame] | 16 | #include "base/bind.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 17 | #include "base/command_line.h" |
[email protected] | 6eaddcc | 2009-02-23 21:03:04 | [diff] [blame] | 18 | #include "base/file_path.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 19 | #include "base/file_util.h" |
| 20 | #include "base/logging.h" |
[email protected] | a5f73fea | 2012-02-15 18:09:17 | [diff] [blame] | 21 | #include "base/metrics/histogram.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 22 | #include "base/path_service.h" |
[email protected] | d2f1196 | 2009-08-17 19:50:04 | [diff] [blame] | 23 | #include "base/string_util.h" |
[email protected] | 386c7350 | 2010-09-15 17:38:42 | [diff] [blame] | 24 | #include "base/utf_string_conversions.h" |
[email protected] | 4c01d499 | 2012-01-23 23:33:01 | [diff] [blame] | 25 | #include "content/browser/browser_child_process_host_impl.h" |
[email protected] | e67385f | 2011-12-21 06:00:56 | [diff] [blame] | 26 | #include "content/browser/plugin_service_impl.h" |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 27 | #include "content/common/child_process_host_impl.h" |
[email protected] | 105303e | 2011-03-14 22:16:10 | [diff] [blame] | 28 | #include "content/common/plugin_messages.h" |
[email protected] | 94dc971d | 2011-03-05 19:08:32 | [diff] [blame] | 29 | #include "content/common/resource_messages.h" |
[email protected] | c38831a1 | 2011-10-28 12:44:49 | [diff] [blame] | 30 | #include "content/public/browser/browser_thread.h" |
[email protected] | 87f3c08 | 2011-10-19 18:07:44 | [diff] [blame] | 31 | #include "content/public/browser/content_browser_client.h" |
[email protected] | 10d861c5 | 2011-11-10 00:03:41 | [diff] [blame] | 32 | #include "content/public/browser/notification_types.h" |
[email protected] | 47214d88 | 2012-02-29 06:28:48 | [diff] [blame] | 33 | #include "content/public/browser/plugin_service.h" |
[email protected] | c08950d2 | 2011-10-13 22:20:29 | [diff] [blame] | 34 | #include "content/public/common/content_switches.h" |
[email protected] | bd5d6cf | 2011-12-01 00:39:12 | [diff] [blame] | 35 | #include "content/public/common/process_type.h" |
[email protected] | 979c7e4 | 2009-07-23 16:14:09 | [diff] [blame] | 36 | #include "ipc/ipc_switches.h" |
[email protected] | 42ce29d | 2011-01-20 23:19:46 | [diff] [blame] | 37 | #include "ui/base/ui_base_switches.h" |
[email protected] | c38831a1 | 2011-10-28 12:44:49 | [diff] [blame] | 38 | #include "ui/gfx/native_widget_types.h" |
[email protected] | c9e2cbbb | 2012-05-12 21:17:27 | [diff] [blame] | 39 | #include "ui/gl/gl_switches.h" |
[email protected] | 6eaddcc | 2009-02-23 21:03:04 | [diff] [blame] | 40 | |
[email protected] | 631bb74 | 2011-11-02 11:29:39 | [diff] [blame] | 41 | using content::BrowserThread; |
[email protected] | 4967f79 | 2012-01-20 22:14:40 | [diff] [blame] | 42 | using content::ChildProcessData; |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 43 | using content::ChildProcessHost; |
[email protected] | 631bb74 | 2011-11-02 11:29:39 | [diff] [blame] | 44 | |
[email protected] | 753efc4 | 2010-03-09 19:52:16 | [diff] [blame] | 45 | #if defined(USE_X11) |
[email protected] | 08397d5 | 2011-02-05 01:53:38 | [diff] [blame] | 46 | #include "ui/gfx/gtk_native_view_id_manager.h" |
[email protected] | 700d3d5 | 2009-07-07 17:40:46 | [diff] [blame] | 47 | #endif |
| 48 | |
[email protected] | f3ef7b1 | 2009-08-07 22:03:17 | [diff] [blame] | 49 | #if defined(OS_MACOSX) |
[email protected] | 0378bf4 | 2011-01-01 18:20:14 | [diff] [blame] | 50 | #include "base/mac/mac_util.h" |
[email protected] | d3108145 | 2011-03-15 21:04:02 | [diff] [blame] | 51 | #include "content/common/plugin_carbon_interpose_constants_mac.h" |
[email protected] | 08397d5 | 2011-02-05 01:53:38 | [diff] [blame] | 52 | #include "ui/gfx/rect.h" |
[email protected] | f3ef7b1 | 2009-08-07 22:03:17 | [diff] [blame] | 53 | #endif |
| 54 | |
[email protected] | 7398dcc | 2011-09-06 21:40:32 | [diff] [blame] | 55 | #if defined(OS_WIN) && !defined(USE_AURA) |
[email protected] | ded0989 | 2011-08-16 01:44:35 | [diff] [blame] | 56 | #include "base/win/windows_version.h" |
| 57 | #include "webkit/plugins/npapi/plugin_constants_win.h" |
[email protected] | e4486d320 | 2011-06-07 01:42:04 | [diff] [blame] | 58 | #include "webkit/plugins/npapi/webplugin_delegate_impl.h" |
| 59 | |
[email protected] | d0ec242 | 2011-06-08 20:55:31 | [diff] [blame] | 60 | namespace { |
| 61 | |
| 62 | void 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] | ded0989 | 2011-08-16 01:44:35 | [diff] [blame] | 71 | // 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] | d0ec242 | 2011-06-08 20:55:31 | [diff] [blame] | 74 | } |
| 75 | |
| 76 | } // namespace |
| 77 | |
[email protected] | 875d489 | 2009-04-21 21:48:36 | [diff] [blame] | 78 | void 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] | 20b64d3 | 2009-03-05 02:07:18 | [diff] [blame] | 81 | std::set<HWND>::iterator window_index = |
[email protected] | 875d489 | 2009-04-21 21:48:36 | [diff] [blame] | 82 | plugin_parent_windows_set_.find(parent); |
| 83 | if (window_index == plugin_parent_windows_set_.end()) |
| 84 | return; |
[email protected] | 20b64d3 | 2009-03-05 02:07:18 | [diff] [blame] | 85 | |
[email protected] | 875d489 | 2009-04-21 21:48:36 | [diff] [blame] | 86 | plugin_parent_windows_set_.erase(window_index); |
| 87 | PostMessage(parent, WM_CLOSE, 0, 0); |
[email protected] | 20b64d3 | 2009-03-05 02:07:18 | [diff] [blame] | 88 | } |
| 89 | |
| 90 | void PluginProcessHost::AddWindow(HWND window) { |
| 91 | plugin_parent_windows_set_.insert(window); |
[email protected] | 6eaddcc | 2009-02-23 21:03:04 | [diff] [blame] | 92 | } |
| 93 | |
[email protected] | e4486d320 | 2011-06-07 01:42:04 | [diff] [blame] | 94 | void PluginProcessHost::OnReparentPluginWindow(HWND window, HWND parent) { |
[email protected] | ded0989 | 2011-08-16 01:44:35 | [diff] [blame] | 95 | // Reparent only from the plugin process to our process. |
[email protected] | e4486d320 | 2011-06-07 01:42:04 | [diff] [blame] | 96 | DWORD process_id = 0; |
[email protected] | ded0989 | 2011-08-16 01:44:35 | [diff] [blame] | 97 | ::GetWindowThreadProcessId(window, &process_id); |
[email protected] | 4967f79 | 2012-01-20 22:14:40 | [diff] [blame] | 98 | if (process_id != ::GetProcessId(process_->GetHandle())) |
[email protected] | ded0989 | 2011-08-16 01:44:35 | [diff] [blame] | 99 | return; |
[email protected] | e4486d320 | 2011-06-07 01:42:04 | [diff] [blame] | 100 | ::GetWindowThreadProcessId(parent, &process_id); |
| 101 | if (process_id != ::GetCurrentProcessId()) |
| 102 | return; |
| 103 | |
[email protected] | d0ec242 | 2011-06-08 20:55:31 | [diff] [blame] | 104 | BrowserThread::PostTask( |
| 105 | BrowserThread::UI, FROM_HERE, |
[email protected] | 8075105 | 2011-11-12 17:10:58 | [diff] [blame] | 106 | base::Bind(ReparentPluginWindowHelper, window, parent)); |
[email protected] | e4486d320 | 2011-06-07 01:42:04 | [diff] [blame] | 107 | } |
[email protected] | a5f73fea | 2012-02-15 18:09:17 | [diff] [blame] | 108 | |
| 109 | void 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] | 6eaddcc | 2009-02-23 21:03:04 | [diff] [blame] | 113 | #endif // defined(OS_WIN) |
[email protected] | d7f4595 | 2009-01-16 23:04:23 | [diff] [blame] | 114 | |
[email protected] | a13283cc | 2012-04-05 00:21:22 | [diff] [blame] | 115 | #if defined(TOOLKIT_GTK) |
[email protected] | 700d3d5 | 2009-07-07 17:40:46 | [diff] [blame] | 116 | void PluginProcessHost::OnMapNativeViewId(gfx::NativeViewId id, |
| 117 | gfx::PluginWindowHandle* output) { |
| 118 | *output = 0; |
[email protected] | 3fa441d | 2011-09-18 17:28:50 | [diff] [blame] | 119 | #if !defined(USE_AURA) |
[email protected] | 687b960 | 2010-12-08 10:43:08 | [diff] [blame] | 120 | GtkNativeViewManager::GetInstance()->GetXIDForId(output, id); |
[email protected] | 3fa441d | 2011-09-18 17:28:50 | [diff] [blame] | 121 | #endif |
[email protected] | 700d3d5 | 2009-07-07 17:40:46 | [diff] [blame] | 122 | } |
[email protected] | a13283cc | 2012-04-05 00:21:22 | [diff] [blame] | 123 | #endif // defined(TOOLKIT_GTK) |
[email protected] | 700d3d5 | 2009-07-07 17:40:46 | [diff] [blame] | 124 | |
[email protected] | dabe607 | 2009-03-17 00:52:35 | [diff] [blame] | 125 | PluginProcessHost::PluginProcessHost() |
[email protected] | 2db34723 | 2010-05-28 21:26:36 | [diff] [blame] | 126 | #if defined(OS_MACOSX) |
[email protected] | 4967f79 | 2012-01-20 22:14:40 | [diff] [blame] | 127 | : plugin_cursor_visible_(true) |
[email protected] | 2db34723 | 2010-05-28 21:26:36 | [diff] [blame] | 128 | #endif |
| 129 | { |
[email protected] | 4c01d499 | 2012-01-23 23:33:01 | [diff] [blame] | 130 | process_.reset( |
| 131 | new BrowserChildProcessHostImpl(content::PROCESS_TYPE_PLUGIN, this)); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 132 | } |
| 133 | |
| 134 | PluginProcessHost::~PluginProcessHost() { |
[email protected] | 7398dcc | 2011-09-06 21:40:32 | [diff] [blame] | 135 | #if defined(OS_WIN) && !defined(USE_AURA) |
[email protected] | 20b64d3 | 2009-03-05 02:07:18 | [diff] [blame] | 136 | // 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] | 1d5ac66 | 2009-10-01 19:41:56 | [diff] [blame] | 148 | #elif defined(OS_MACOSX) |
[email protected] | b44dbd1 | 2009-10-11 19:02:15 | [diff] [blame] | 149 | // 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] | f8b3ef8 | 2010-10-11 02:45:52 | [diff] [blame] | 155 | if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
[email protected] | 0378bf4 | 2011-01-01 18:20:14 | [diff] [blame] | 156 | base::mac::ReleaseFullScreen(base::mac::kFullScreenModeHideAll); |
[email protected] | b44dbd1 | 2009-10-11 19:02:15 | [diff] [blame] | 157 | } else { |
[email protected] | 8075105 | 2011-11-12 17:10:58 | [diff] [blame] | 158 | BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 159 | base::Bind(base::mac::ReleaseFullScreen, |
| 160 | base::mac::kFullScreenModeHideAll)); |
[email protected] | b44dbd1 | 2009-10-11 19:02:15 | [diff] [blame] | 161 | } |
[email protected] | 1d5ac66 | 2009-10-01 19:41:56 | [diff] [blame] | 162 | } |
[email protected] | 18db4618 | 2010-02-02 17:04:55 | [diff] [blame] | 163 | // If the plugin hid the cursor, reset that. |
| 164 | if (!plugin_cursor_visible_) { |
[email protected] | f8b3ef8 | 2010-10-11 02:45:52 | [diff] [blame] | 165 | if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
[email protected] | 0378bf4 | 2011-01-01 18:20:14 | [diff] [blame] | 166 | base::mac::SetCursorVisibility(true); |
[email protected] | 18db4618 | 2010-02-02 17:04:55 | [diff] [blame] | 167 | } else { |
[email protected] | 8075105 | 2011-11-12 17:10:58 | [diff] [blame] | 168 | BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 169 | base::Bind(base::mac::SetCursorVisibility, true)); |
[email protected] | 18db4618 | 2010-02-02 17:04:55 | [diff] [blame] | 170 | } |
| 171 | } |
[email protected] | 20b64d3 | 2009-03-05 02:07:18 | [diff] [blame] | 172 | #endif |
[email protected] | 46b69e4 | 2010-11-02 12:26:39 | [diff] [blame] | 173 | // Cancel all pending and sent requests. |
| 174 | CancelRequests(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 175 | } |
| 176 | |
[email protected] | 4967f79 | 2012-01-20 22:14:40 | [diff] [blame] | 177 | bool PluginProcessHost::Send(IPC::Message* message) { |
| 178 | return process_->Send(message); |
| 179 | } |
| 180 | |
[email protected] | 9990736 | 2012-01-11 05:41:40 | [diff] [blame] | 181 | bool PluginProcessHost::Init(const webkit::WebPluginInfo& info) { |
[email protected] | a27a938 | 2009-02-11 23:55:10 | [diff] [blame] | 182 | info_ = info; |
[email protected] | 4967f79 | 2012-01-20 22:14:40 | [diff] [blame] | 183 | process_->SetName(info_.name); |
[email protected] | a27a938 | 2009-02-11 23:55:10 | [diff] [blame] | 184 | |
[email protected] | 4967f79 | 2012-01-20 22:14:40 | [diff] [blame] | 185 | std::string channel_id = process_->GetHost()->CreateChannel(); |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 186 | if (channel_id.empty()) |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 187 | return false; |
| 188 | |
[email protected] | 7c4ea14 | 2010-01-26 05:15:42 | [diff] [blame] | 189 | // 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] | 13081fc | 2010-08-04 18:24:38 | [diff] [blame] | 192 | CommandLine::StringType plugin_launcher = |
| 193 | browser_command_line.GetSwitchValueNative(switches::kPluginLauncher); |
[email protected] | 8c40f32 | 2011-08-24 03:33:36 | [diff] [blame] | 194 | |
| 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] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 199 | int flags = ChildProcessHost::CHILD_ALLOW_HEAP_EXECUTION; |
[email protected] | 8c40f32 | 2011-08-24 03:33:36 | [diff] [blame] | 200 | #elif defined(OS_LINUX) |
[email protected] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 201 | int flags = plugin_launcher.empty() ? ChildProcessHost::CHILD_ALLOW_SELF : |
| 202 | ChildProcessHost::CHILD_NORMAL; |
[email protected] | 8c40f32 | 2011-08-24 03:33:36 | [diff] [blame] | 203 | #else |
[email protected] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 204 | int flags = ChildProcessHost::CHILD_NORMAL; |
[email protected] | 8c40f32 | 2011-08-24 03:33:36 | [diff] [blame] | 205 | #endif |
| 206 | |
[email protected] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 207 | FilePath exe_path = ChildProcessHost::GetChildPath(flags); |
[email protected] | ba4c78e | 2009-10-13 23:00:11 | [diff] [blame] | 208 | if (exe_path.empty()) |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 209 | return false; |
| 210 | |
[email protected] | fb1277e8 | 2009-11-21 20:32:30 | [diff] [blame] | 211 | CommandLine* cmd_line = new CommandLine(exe_path); |
[email protected] | 588c54b0 | 2009-09-18 21:45:54 | [diff] [blame] | 212 | // 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] | 05076ba2 | 2010-07-30 05:59:57 | [diff] [blame] | 214 | cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kPluginProcess); |
[email protected] | 4f08c83f | 2010-07-29 23:02:34 | [diff] [blame] | 215 | cmd_line->AppendSwitchPath(switches::kPluginPath, info.path); |
[email protected] | 588c54b0 | 2009-09-18 21:45:54 | [diff] [blame] | 216 | |
[email protected] | 2735e369 | 2009-09-25 18:19:39 | [diff] [blame] | 217 | // Propagate the following switches to the plugin command line (along with |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 218 | // any associated values) if present in the browser command line |
[email protected] | 4f08c83f | 2010-07-29 23:02:34 | [diff] [blame] | 219 | static const char* const kSwitchNames[] = { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 220 | switches::kDisableBreakpad, |
[email protected] | dc51d1c | 2011-11-30 04:42:21 | [diff] [blame] | 221 | #if defined(OS_MACOSX) |
| 222 | switches::kDisableCompositedCoreAnimationPlugins, |
| 223 | #endif |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 224 | switches::kDisableLogging, |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 225 | switches::kEnableDCHECK, |
[email protected] | b1f172a7 | 2011-04-11 17:26:07 | [diff] [blame] | 226 | switches::kEnableLogging, |
[email protected] | 4500a72 | 2009-03-27 19:56:54 | [diff] [blame] | 227 | switches::kEnableStatsTable, |
[email protected] | b1f172a7 | 2011-04-11 17:26:07 | [diff] [blame] | 228 | switches::kFullMemoryCrashReport, |
| 229 | switches::kLoggingLevel, |
[email protected] | b1f172a7 | 2011-04-11 17:26:07 | [diff] [blame] | 230 | switches::kLogPluginMessages, |
[email protected] | b1f172a7 | 2011-04-11 17:26:07 | [diff] [blame] | 231 | switches::kNoSandbox, |
| 232 | switches::kPluginStartupDialog, |
[email protected] | b1f172a7 | 2011-04-11 17:26:07 | [diff] [blame] | 233 | switches::kTestSandbox, |
[email protected] | 50f3842 | 2011-11-09 19:21:33 | [diff] [blame] | 234 | switches::kTraceStartup, |
[email protected] | b1f172a7 | 2011-04-11 17:26:07 | [diff] [blame] | 235 | switches::kUseGL, |
| 236 | switches::kUserAgent, |
[email protected] | b1f172a7 | 2011-04-11 17:26:07 | [diff] [blame] | 237 | switches::kV, |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 238 | }; |
| 239 | |
[email protected] | 4f08c83f | 2010-07-29 23:02:34 | [diff] [blame] | 240 | cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames, |
| 241 | arraysize(kSwitchNames)); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 242 | |
| 243 | // If specified, prepend a launcher program to the command line. |
[email protected] | e5e19c3 | 2009-04-20 22:10:02 | [diff] [blame] | 244 | if (!plugin_launcher.empty()) |
[email protected] | fb1277e8 | 2009-11-21 20:32:30 | [diff] [blame] | 245 | cmd_line->PrependWrapper(plugin_launcher); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 246 | |
[email protected] | 9990736 | 2012-01-11 05:41:40 | [diff] [blame] | 247 | std::string locale = |
| 248 | content::GetContentClient()->browser()->GetApplicationLocale(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 249 | 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] | f77d8762 | 2010-07-30 17:43:17 | [diff] [blame] | 252 | cmd_line->AppendSwitchASCII(switches::kLang, locale); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 253 | } |
| 254 | |
[email protected] | 4734d0b | 2011-12-03 07:10:44 | [diff] [blame] | 255 | cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 256 | |
[email protected] | 2456c57 | 2009-11-09 04:21:51 | [diff] [blame] | 257 | #if defined(OS_POSIX) |
[email protected] | a82af39 | 2012-02-24 04:40:20 | [diff] [blame] | 258 | base::EnvironmentVector env; |
[email protected] | 23563dc1e | 2010-02-16 16:11:00 | [diff] [blame] | 259 | #if defined(OS_MACOSX) && !defined(__LP64__) |
[email protected] | f3ef7b1 | 2009-08-07 22:03:17 | [diff] [blame] | 260 | // 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] | 3d2217d | 2009-11-23 21:26:47 | [diff] [blame] | 269 | env.push_back(std::pair<std::string, std::string>( |
[email protected] | f3ef7b1 | 2009-08-07 22:03:17 | [diff] [blame] | 270 | plugin_interpose_strings::kDYLDInsertLibrariesKey, |
[email protected] | 3d2217d | 2009-11-23 21:26:47 | [diff] [blame] | 271 | interpose_list)); |
[email protected] | fb1277e8 | 2009-11-21 20:32:30 | [diff] [blame] | 272 | #endif |
| 273 | #endif |
| 274 | |
[email protected] | 4967f79 | 2012-01-20 22:14:40 | [diff] [blame] | 275 | process_->Launch( |
[email protected] | fb1277e8 | 2009-11-21 20:32:30 | [diff] [blame] | 276 | #if defined(OS_WIN) |
| 277 | FilePath(), |
| 278 | #elif defined(OS_POSIX) |
[email protected] | 7c4ea14 | 2010-01-26 05:15:42 | [diff] [blame] | 279 | false, |
[email protected] | fb1277e8 | 2009-11-21 20:32:30 | [diff] [blame] | 280 | env, |
| 281 | #endif |
| 282 | cmd_line); |
| 283 | |
[email protected] | 358cb8e | 2011-05-25 02:12:45 | [diff] [blame] | 284 | // 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] | 4967f79 | 2012-01-20 22:14:40 | [diff] [blame] | 288 | process_->SetTerminateChildOnShutdown(false); |
[email protected] | 358cb8e | 2011-05-25 02:12:45 | [diff] [blame] | 289 | |
[email protected] | fb1277e8 | 2009-11-21 20:32:30 | [diff] [blame] | 290 | return true; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 291 | } |
[email protected] | fb1277e8 | 2009-11-21 20:32:30 | [diff] [blame] | 292 | |
[email protected] | 4e59e81 | 2010-04-06 20:51:16 | [diff] [blame] | 293 | void PluginProcessHost::ForceShutdown() { |
[email protected] | f8b3ef8 | 2010-10-11 02:45:52 | [diff] [blame] | 294 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
[email protected] | 4e59e81 | 2010-04-06 20:51:16 | [diff] [blame] | 295 | Send(new PluginProcessMsg_NotifyRenderersOfPendingShutdown()); |
[email protected] | 4967f79 | 2012-01-20 22:14:40 | [diff] [blame] | 296 | process_->ForceShutdown(); |
[email protected] | 4e59e81 | 2010-04-06 20:51:16 | [diff] [blame] | 297 | } |
| 298 | |
[email protected] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 299 | void PluginProcessHost::AddFilter(IPC::ChannelProxy::MessageFilter* filter) { |
[email protected] | 4967f79 | 2012-01-20 22:14:40 | [diff] [blame] | 300 | process_->GetHost()->AddFilter(filter); |
[email protected] | 4cb4310 | 2011-12-02 20:24:49 | [diff] [blame] | 301 | } |
| 302 | |
[email protected] | a95986a8 | 2010-12-24 06:19:28 | [diff] [blame] | 303 | bool PluginProcessHost::OnMessageReceived(const IPC::Message& msg) { |
| 304 | bool handled = true; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 305 | IPC_BEGIN_MESSAGE_MAP(PluginProcessHost, msg) |
| 306 | IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ChannelCreated, OnChannelCreated) |
[email protected] | 7398dcc | 2011-09-06 21:40:32 | [diff] [blame] | 307 | #if defined(OS_WIN) && !defined(USE_AURA) |
[email protected] | 875d489 | 2009-04-21 21:48:36 | [diff] [blame] | 308 | IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginWindowDestroyed, |
| 309 | OnPluginWindowDestroyed) |
[email protected] | e4486d320 | 2011-06-07 01:42:04 | [diff] [blame] | 310 | IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ReparentPluginWindow, |
| 311 | OnReparentPluginWindow) |
[email protected] | a5f73fea | 2012-02-15 18:09:17 | [diff] [blame] | 312 | IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ReportExecutableMemory, |
| 313 | OnReportExecutableMemory) |
[email protected] | 829c284 | 2009-04-01 01:48:52 | [diff] [blame] | 314 | #endif |
[email protected] | a13283cc | 2012-04-05 00:21:22 | [diff] [blame] | 315 | #if defined(TOOLKIT_GTK) |
[email protected] | 700d3d5 | 2009-07-07 17:40:46 | [diff] [blame] | 316 | IPC_MESSAGE_HANDLER(PluginProcessHostMsg_MapNativeViewId, |
| 317 | OnMapNativeViewId) |
| 318 | #endif |
[email protected] | 1d5ac66 | 2009-10-01 19:41:56 | [diff] [blame] | 319 | #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] | 18db4618 | 2010-02-02 17:04:55 | [diff] [blame] | 326 | IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginSetCursorVisibility, |
| 327 | OnPluginSetCursorVisibility) |
[email protected] | 1d5ac66 | 2009-10-01 19:41:56 | [diff] [blame] | 328 | #endif |
[email protected] | a95986a8 | 2010-12-24 06:19:28 | [diff] [blame] | 329 | IPC_MESSAGE_UNHANDLED(handled = false) |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 330 | IPC_END_MESSAGE_MAP() |
[email protected] | a95986a8 | 2010-12-24 06:19:28 | [diff] [blame] | 331 | |
| 332 | DCHECK(handled); |
| 333 | return handled; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 334 | } |
| 335 | |
| 336 | void PluginProcessHost::OnChannelConnected(int32 peer_pid) { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 337 | for (size_t i = 0; i < pending_requests_.size(); ++i) { |
[email protected] | 46b69e4 | 2010-11-02 12:26:39 | [diff] [blame] | 338 | RequestPluginChannel(pending_requests_[i]); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 339 | } |
| 340 | |
| 341 | pending_requests_.clear(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 342 | } |
| 343 | |
| 344 | void PluginProcessHost::OnChannelError() { |
[email protected] | 46b69e4 | 2010-11-02 12:26:39 | [diff] [blame] | 345 | CancelRequests(); |
| 346 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 347 | |
[email protected] | ddb1e5a | 2010-12-13 20:10:45 | [diff] [blame] | 348 | bool PluginProcessHost::CanShutdown() { |
| 349 | return sent_requests_.empty(); |
| 350 | } |
| 351 | |
[email protected] | 47214d88 | 2012-02-29 06:28:48 | [diff] [blame] | 352 | void PluginProcessHost::OnProcessCrashed(int exit_code) { |
| 353 | PluginServiceImpl::GetInstance()->RegisterPluginCrash(info_.path); |
| 354 | } |
| 355 | |
[email protected] | 46b69e4 | 2010-11-02 12:26:39 | [diff] [blame] | 356 | void PluginProcessHost::CancelRequests() { |
| 357 | for (size_t i = 0; i < pending_requests_.size(); ++i) |
| 358 | pending_requests_[i]->OnError(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 359 | pending_requests_.clear(); |
[email protected] | a3a8fb6d | 2009-10-22 20:12:51 | [diff] [blame] | 360 | |
| 361 | while (!sent_requests_.empty()) { |
[email protected] | 8d32d5f | 2011-09-15 02:22:32 | [diff] [blame] | 362 | Client* client = sent_requests_.front(); |
| 363 | if (client) |
| 364 | client->OnError(); |
[email protected] | 4befe759 | 2011-09-14 22:49:09 | [diff] [blame] | 365 | sent_requests_.pop_front(); |
[email protected] | a3a8fb6d | 2009-10-22 20:12:51 | [diff] [blame] | 366 | } |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 367 | } |
| 368 | |
[email protected] | 1a5acea8 | 2011-09-12 11:00:21 | [diff] [blame] | 369 | // static |
| 370 | void PluginProcessHost::CancelPendingRequestsForResourceContext( |
[email protected] | df02aca | 2012-02-09 21:03:20 | [diff] [blame] | 371 | content::ResourceContext* context) { |
[email protected] | 4967f79 | 2012-01-20 22:14:40 | [diff] [blame] | 372 | for (PluginProcessHostIterator host_it; !host_it.Done(); ++host_it) { |
| 373 | PluginProcessHost* host = *host_it; |
[email protected] | 1a5acea8 | 2011-09-12 11:00:21 | [diff] [blame] | 374 | for (size_t i = 0; i < host->pending_requests_.size(); ++i) { |
[email protected] | df02aca | 2012-02-09 21:03:20 | [diff] [blame] | 375 | if (host->pending_requests_[i]->GetResourceContext() == context) { |
[email protected] | 1a5acea8 | 2011-09-12 11:00:21 | [diff] [blame] | 376 | host->pending_requests_[i]->OnError(); |
| 377 | host->pending_requests_.erase(host->pending_requests_.begin() + i); |
| 378 | --i; |
| 379 | } |
| 380 | } |
| 381 | } |
| 382 | } |
| 383 | |
[email protected] | 46b69e4 | 2010-11-02 12:26:39 | [diff] [blame] | 384 | void PluginProcessHost::OpenChannelToPlugin(Client* client) { |
[email protected] | 4967f79 | 2012-01-20 22:14:40 | [diff] [blame] | 385 | process_->Notify(content::NOTIFICATION_CHILD_INSTANCE_CREATED); |
[email protected] | 46b69e4 | 2010-11-02 12:26:39 | [diff] [blame] | 386 | client->SetPluginInfo(info_); |
[email protected] | 4967f79 | 2012-01-20 22:14:40 | [diff] [blame] | 387 | if (process_->GetHost()->IsChannelOpening()) { |
[email protected] | d2e884d | 2009-06-22 20:37:52 | [diff] [blame] | 388 | // 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] | 46b69e4 | 2010-11-02 12:26:39 | [diff] [blame] | 391 | pending_requests_.push_back(client); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 392 | return; |
| 393 | } |
| 394 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 395 | // We already have an open channel, send a request right away to plugin. |
[email protected] | 46b69e4 | 2010-11-02 12:26:39 | [diff] [blame] | 396 | RequestPluginChannel(client); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 397 | } |
| 398 | |
[email protected] | 4befe759 | 2011-09-14 22:49:09 | [diff] [blame] | 399 | void 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 | |
| 411 | void 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] | 46b69e4 | 2010-11-02 12:26:39 | [diff] [blame] | 423 | void PluginProcessHost::RequestPluginChannel(Client* client) { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 424 | // 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] | 46b69e4 | 2010-11-02 12:26:39 | [diff] [blame] | 429 | PluginProcessMsg_CreateChannel* msg = |
[email protected] | d5a1916 | 2011-06-30 18:51:54 | [diff] [blame] | 430 | new PluginProcessMsg_CreateChannel( |
| 431 | client->ID(), |
| 432 | client->OffTheRecord()); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 433 | msg->set_unblock(true); |
| 434 | if (Send(msg)) { |
[email protected] | 4befe759 | 2011-09-14 22:49:09 | [diff] [blame] | 435 | sent_requests_.push_back(client); |
| 436 | client->OnSentPluginChannelRequest(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 437 | } else { |
[email protected] | 46b69e4 | 2010-11-02 12:26:39 | [diff] [blame] | 438 | client->OnError(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 439 | } |
| 440 | } |
| 441 | |
[email protected] | 3dfc7a4 | 2009-06-27 01:43:51 | [diff] [blame] | 442 | void PluginProcessHost::OnChannelCreated( |
| 443 | const IPC::ChannelHandle& channel_handle) { |
[email protected] | 46b69e4 | 2010-11-02 12:26:39 | [diff] [blame] | 444 | Client* client = sent_requests_.front(); |
[email protected] | 3dfc7a4 | 2009-06-27 01:43:51 | [diff] [blame] | 445 | |
[email protected] | 4befe759 | 2011-09-14 22:49:09 | [diff] [blame] | 446 | if (client) |
| 447 | client->OnChannelOpened(channel_handle); |
| 448 | sent_requests_.pop_front(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 449 | } |