OLD | NEW |
---|---|
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Represents the browser side of the browser <--> renderer communication | |
6 // channel. There will be one RenderProcessHost per renderer process. | |
7 | |
5 #include "chrome/browser/renderer_host/browser_render_process_host.h" | 8 #include "chrome/browser/renderer_host/browser_render_process_host.h" |
6 | 9 |
10 #include "build/build_config.h" | |
11 | |
7 #include <algorithm> | 12 #include <algorithm> |
8 #include <sstream> | 13 #include <sstream> |
9 #include <vector> | 14 #include <vector> |
10 | 15 |
11 #include "base/command_line.h" | 16 #include "base/command_line.h" |
12 #include "base/debug_util.h" | 17 #include "base/debug_util.h" |
13 #include "base/file_util.h" | 18 #include "base/file_util.h" |
14 #include "base/logging.h" | 19 #include "base/logging.h" |
15 #include "base/path_service.h" | 20 #include "base/path_service.h" |
16 #include "base/process_util.h" | 21 #include "base/process_util.h" |
17 #include "base/shared_memory.h" | 22 #include "base/shared_memory.h" |
18 #include "base/singleton.h" | 23 #include "base/singleton.h" |
19 #include "base/string_util.h" | 24 #include "base/string_util.h" |
20 #include "base/thread.h" | 25 #include "base/thread.h" |
21 #include "base/win_util.h" | |
22 #include "chrome/app/result_codes.h" | 26 #include "chrome/app/result_codes.h" |
23 #include "chrome/browser/browser.h" | 27 // #include "chrome/browser/browser.h" |
brettw
2009/01/21 19:18:50
Be sure to remove these commented ones.
brettw
2009/01/21 19:18:50
Be sure to remove these commented-out ones.
| |
24 #include "chrome/browser/browser_process.h" | 28 #include "chrome/browser/browser_process.h" |
25 #include "chrome/browser/cache_manager_host.h" | 29 #include "chrome/browser/cache_manager_host.h" |
26 #include "chrome/browser/extensions/user_script_master.h" | 30 #include "chrome/browser/extensions/user_script_master.h" |
27 #include "chrome/browser/history/history.h" | 31 #include "chrome/browser/history/history.h" |
28 #include "chrome/browser/plugin_service.h" | 32 #include "chrome/browser/plugin_service.h" |
29 #include "chrome/browser/render_widget_helper.h" | 33 #include "chrome/browser/render_widget_helper.h" |
30 #include "chrome/browser/render_view_host.h" | |
31 #include "chrome/browser/renderer_security_policy.h" | 34 #include "chrome/browser/renderer_security_policy.h" |
32 #include "chrome/browser/resource_message_filter.h" | 35 #include "chrome/browser/resource_message_filter.h" |
33 #include "chrome/browser/sandbox_policy.h" | |
34 #include "chrome/browser/spellchecker.h" | 36 #include "chrome/browser/spellchecker.h" |
35 #include "chrome/browser/visitedlink_master.h" | 37 #include "chrome/browser/visitedlink_master.h" |
36 #include "chrome/browser/tab_contents/web_contents.h" | 38 // #include "chrome/browser/tab_contents/web_contents.h" |
37 #include "chrome/common/chrome_paths.h" | 39 #include "chrome/common/chrome_paths.h" |
38 #include "chrome/common/chrome_switches.h" | 40 #include "chrome/common/chrome_switches.h" |
39 #include "chrome/common/debug_flags.h" | 41 #include "chrome/common/debug_flags.h" |
40 #include "chrome/common/l10n_util.h" | 42 #include "chrome/common/l10n_util.h" |
41 #include "chrome/common/logging_chrome.h" | 43 #include "chrome/common/logging_chrome.h" |
42 #include "chrome/common/pref_names.h" | 44 #include "chrome/common/pref_names.h" |
43 #include "chrome/common/pref_service.h" | 45 #include "chrome/common/pref_service.h" |
44 #include "chrome/common/process_watcher.h" | 46 #include "chrome/common/process_watcher.h" |
45 #include "chrome/common/win_util.h" | |
46 #include "chrome/renderer/render_process.h" | 47 #include "chrome/renderer/render_process.h" |
47 #include "net/base/cookie_monster.h" | 48 #include "net/base/cookie_monster.h" |
48 #include "net/base/net_util.h" | 49 #include "net/base/net_util.h" |
50 | |
51 #if defined(OS_WIN) | |
52 // TODO(port): see comment by the only usage of RenderViewHost in this file. | |
53 #include "chrome/browser/render_view_host.h" | |
54 | |
55 // Once the above TODO is finished, then this block is all Windows-specific | |
56 // files. | |
57 #include "base/win_util.h" | |
58 #include "chrome/browser/sandbox_policy.h" | |
59 #include "chrome/common/win_util.h" | |
49 #include "sandbox/src/sandbox.h" | 60 #include "sandbox/src/sandbox.h" |
61 #endif | |
50 | 62 |
51 #include "SkBitmap.h" | 63 #include "SkBitmap.h" |
52 | 64 |
53 #include "generated_resources.h" | 65 #include "generated_resources.h" |
54 | 66 |
55 namespace { | 67 namespace { |
56 | 68 |
57 // ---------------------------------------------------------------------------- | 69 // ---------------------------------------------------------------------------- |
58 | 70 |
59 class RendererMainThread : public base::Thread { | 71 class RendererMainThread : public base::Thread { |
60 public: | 72 public: |
61 explicit RendererMainThread(const std::wstring& channel_id) | 73 explicit RendererMainThread(const std::wstring& channel_id) |
62 : base::Thread("Chrome_InProcRendererThread"), | 74 : base::Thread("Chrome_InProcRendererThread"), |
63 channel_id_(channel_id) { | 75 channel_id_(channel_id) { |
64 } | 76 } |
65 | 77 |
66 protected: | 78 protected: |
67 virtual void Init() { | 79 virtual void Init() { |
80 #if defined(OS_WIN) | |
68 CoInitialize(NULL); | 81 CoInitialize(NULL); |
82 #endif | |
69 | 83 |
70 bool rv = RenderProcess::GlobalInit(channel_id_); | 84 bool rv = RenderProcess::GlobalInit(channel_id_); |
71 DCHECK(rv); | 85 DCHECK(rv); |
72 // It's a little lame to manually set this flag. But the single process | 86 // It's a little lame to manually set this flag. But the single process |
73 // RendererThread will receive the WM_QUIT. We don't need to assert on | 87 // RendererThread will receive the WM_QUIT. We don't need to assert on |
74 // this thread, so just force the flag manually. | 88 // this thread, so just force the flag manually. |
75 // If we want to avoid this, we could create the InProcRendererThread | 89 // If we want to avoid this, we could create the InProcRendererThread |
76 // directly with _beginthreadex() rather than using the Thread class. | 90 // directly with _beginthreadex() rather than using the Thread class. |
77 base::Thread::SetThreadWasQuitProperly(true); | 91 base::Thread::SetThreadWasQuitProperly(true); |
78 } | 92 } |
79 | 93 |
80 virtual void CleanUp() { | 94 virtual void CleanUp() { |
81 RenderProcess::GlobalCleanup(); | 95 RenderProcess::GlobalCleanup(); |
82 | 96 |
97 #if defined(OS_WIN) | |
83 CoUninitialize(); | 98 CoUninitialize(); |
99 #endif | |
84 } | 100 } |
85 | 101 |
86 private: | 102 private: |
87 std::wstring channel_id_; | 103 std::wstring channel_id_; |
88 }; | 104 }; |
89 | 105 |
90 // Used for a View_ID where the renderer has not been attached yet | 106 // Used for a View_ID where the renderer has not been attached yet |
91 const int32 kInvalidViewID = -1; | 107 const int32 kInvalidViewID = -1; |
92 | 108 |
93 // Get the path to the renderer executable, which is the same as the | 109 // Get the path to the renderer executable, which is the same as the |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
132 | 148 |
133 BrowserRenderProcessHost::~BrowserRenderProcessHost() { | 149 BrowserRenderProcessHost::~BrowserRenderProcessHost() { |
134 // Some tests hold BrowserRenderProcessHost in a scoped_ptr, so we must call | 150 // Some tests hold BrowserRenderProcessHost in a scoped_ptr, so we must call |
135 // Unregister here as well as in response to Release(). | 151 // Unregister here as well as in response to Release(). |
136 Unregister(); | 152 Unregister(); |
137 | 153 |
138 // We may have some unsent messages at this point, but that's OK. | 154 // We may have some unsent messages at this point, but that's OK. |
139 channel_.reset(); | 155 channel_.reset(); |
140 | 156 |
141 if (process_.handle() && !run_renderer_in_process()) { | 157 if (process_.handle() && !run_renderer_in_process()) { |
142 watcher_.StopWatching(); | |
143 ProcessWatcher::EnsureProcessTerminated(process_.handle()); | 158 ProcessWatcher::EnsureProcessTerminated(process_.handle()); |
144 } | 159 } |
145 | 160 |
146 profile()->GetPrefs()->RemovePrefObserver(prefs::kBlockPopups, this); | 161 profile()->GetPrefs()->RemovePrefObserver(prefs::kBlockPopups, this); |
147 | 162 |
148 NotificationService::current()->RemoveObserver(this, | 163 NotificationService::current()->RemoveObserver(this, |
149 NOTIFY_USER_SCRIPTS_LOADED, NotificationService::AllSources()); | 164 NOTIFY_USER_SCRIPTS_LOADED, NotificationService::AllSources()); |
150 } | 165 } |
151 | 166 |
167 // When we're started with the --start-renderers-manually flag, we pop up a | |
168 // modal dialog requesting the user manually start up a renderer. | |
169 // |cmd_line| is the command line to start the renderer with. | |
170 static void RunStartRenderersManuallyDialog(const std::wstring& cmd_line) { | |
171 #if defined(OS_WIN) | |
172 std::wstring message = | |
173 L"Please start a renderer process using:\n" + cmd_line; | |
174 | |
175 // We don't know the owner window for RenderProcessHost and therefore we | |
176 // pass a NULL HWND argument. | |
177 win_util::MessageBox(NULL, | |
178 message, | |
179 switches::kBrowserStartRenderersManually, | |
180 MB_OK); | |
181 #else | |
182 // TODO(port): refactor above code / pop up a message box here. | |
183 NOTIMPLEMENTED(); | |
184 #endif | |
185 } | |
186 | |
152 bool BrowserRenderProcessHost::Init() { | 187 bool BrowserRenderProcessHost::Init() { |
153 // calling Init() more than once does nothing, this makes it more convenient | 188 // calling Init() more than once does nothing, this makes it more convenient |
154 // for the view host which may not be sure in some cases | 189 // for the view host which may not be sure in some cases |
155 if (channel_.get()) | 190 if (channel_.get()) |
156 return true; | 191 return true; |
157 | 192 |
158 // run the IPC channel on the shared IO thread. | 193 // run the IPC channel on the shared IO thread. |
159 base::Thread* io_thread = g_browser_process->io_thread(); | 194 base::Thread* io_thread = g_browser_process->io_thread(); |
160 | 195 |
161 scoped_refptr<ResourceMessageFilter> resource_message_filter = | 196 scoped_refptr<ResourceMessageFilter> resource_message_filter = |
162 new ResourceMessageFilter(g_browser_process->resource_dispatcher_host(), | 197 new ResourceMessageFilter(g_browser_process->resource_dispatcher_host(), |
163 PluginService::GetInstance(), | 198 PluginService::GetInstance(), |
164 g_browser_process->print_job_manager(), | 199 g_browser_process->print_job_manager(), |
165 host_id(), | 200 host_id(), |
166 profile(), | 201 profile(), |
167 widget_helper_, | 202 widget_helper_, |
168 profile()->GetSpellChecker()); | 203 profile()->GetSpellChecker()); |
169 | 204 |
170 CommandLine browser_command_line; | 205 CommandLine browser_command_line; |
171 | 206 |
207 #if defined(OS_WIN) | |
172 // setup IPC channel | 208 // setup IPC channel |
173 std::wstring channel_id = GenerateRandomChannelID(this); | 209 const std::wstring channel_id = GenerateRandomChannelID(this); |
174 channel_.reset( | 210 channel_.reset( |
175 new IPC::SyncChannel(channel_id, IPC::Channel::MODE_SERVER, this, | 211 new IPC::SyncChannel(channel_id, IPC::Channel::MODE_SERVER, this, |
176 resource_message_filter, | 212 resource_message_filter, |
177 io_thread->message_loop(), true, | 213 io_thread->message_loop(), true, |
178 g_browser_process->shutdown_event())); | 214 g_browser_process->shutdown_event())); |
179 // As a preventive mesure, we DCHECK if someone sends a synchronous message | 215 // As a preventive mesure, we DCHECK if someone sends a synchronous message |
180 // with no time-out, which in the context of the browser process we should not | 216 // with no time-out, which in the context of the browser process we should not |
181 // be doing. | 217 // be doing. |
182 channel_->set_sync_messages_with_no_timeout_allowed(false); | 218 channel_->set_sync_messages_with_no_timeout_allowed(false); |
219 #else | |
220 // TODO(port): this depends on resource_message_filter | |
221 NOTIMPLEMENTED(); | |
222 io_thread = io_thread; | |
223 static const std::wstring channel_id = L"set to quiet the compiler"; | |
224 #endif | |
183 | 225 |
184 // build command line for renderer, we have to quote the executable name to | 226 // build command line for renderer, we have to quote the executable name to |
185 // deal with spaces | 227 // deal with spaces |
186 std::wstring renderer_path = | 228 std::wstring renderer_path = |
187 browser_command_line.GetSwitchValue(switches::kRendererPath); | 229 browser_command_line.GetSwitchValue(switches::kRendererPath); |
188 if (renderer_path.empty()) | 230 if (renderer_path.empty()) |
189 if (!GetRendererPath(&renderer_path)) | 231 if (!GetRendererPath(&renderer_path)) |
190 return false; | 232 return false; |
191 std::wstring cmd_line; | 233 std::wstring cmd_line; |
192 cmd_line = L"\"" + renderer_path + L"\""; | 234 cmd_line = L"\"" + renderer_path + L"\""; |
(...skipping 27 matching lines...) Expand all Loading... | |
220 switches::kMessageLoopHistogrammer, | 262 switches::kMessageLoopHistogrammer, |
221 switches::kEnableDCHECK, | 263 switches::kEnableDCHECK, |
222 switches::kSilentDumpOnDCHECK, | 264 switches::kSilentDumpOnDCHECK, |
223 switches::kDisablePopupBlocking, | 265 switches::kDisablePopupBlocking, |
224 switches::kUseLowFragHeapCrt, | 266 switches::kUseLowFragHeapCrt, |
225 switches::kGearsInRenderer, | 267 switches::kGearsInRenderer, |
226 switches::kEnableUserScripts, | 268 switches::kEnableUserScripts, |
227 switches::kEnableVideo, | 269 switches::kEnableVideo, |
228 }; | 270 }; |
229 | 271 |
230 for (int i = 0; i < arraysize(switch_names); ++i) { | 272 for (size_t i = 0; i < arraysize(switch_names); ++i) { |
231 if (browser_command_line.HasSwitch(switch_names[i])) { | 273 if (browser_command_line.HasSwitch(switch_names[i])) { |
232 CommandLine::AppendSwitchWithValue( | 274 CommandLine::AppendSwitchWithValue( |
233 &cmd_line, switch_names[i], | 275 &cmd_line, switch_names[i], |
234 browser_command_line.GetSwitchValue(switch_names[i])); | 276 browser_command_line.GetSwitchValue(switch_names[i])); |
235 } | 277 } |
236 } | 278 } |
237 | 279 |
238 // Pass on the browser locale. | 280 // Pass on the browser locale. |
239 const std::wstring locale = g_browser_process->GetApplicationLocale(); | 281 const std::wstring locale = g_browser_process->GetApplicationLocale(); |
240 CommandLine::AppendSwitchWithValue(&cmd_line, switches::kLang, locale); | 282 CommandLine::AppendSwitchWithValue(&cmd_line, switches::kLang, locale); |
241 | 283 |
242 bool in_sandbox = !browser_command_line.HasSwitch(switches::kNoSandbox); | 284 bool in_sandbox = !browser_command_line.HasSwitch(switches::kNoSandbox); |
243 if (browser_command_line.HasSwitch(switches::kInProcessPlugins)) { | 285 if (browser_command_line.HasSwitch(switches::kInProcessPlugins)) { |
244 // In process plugins won't work if the sandbox is enabled. | 286 // In process plugins won't work if the sandbox is enabled. |
245 in_sandbox = false; | 287 in_sandbox = false; |
246 } | 288 } |
247 | 289 |
290 #if defined(OS_WIN) | |
248 bool child_needs_help = | 291 bool child_needs_help = |
249 DebugFlags::ProcessDebugFlags(&cmd_line, | 292 DebugFlags::ProcessDebugFlags(&cmd_line, |
250 DebugFlags::RENDERER, | 293 DebugFlags::RENDERER, |
251 in_sandbox); | 294 in_sandbox); |
295 #endif | |
252 CommandLine::AppendSwitchWithValue(&cmd_line, | 296 CommandLine::AppendSwitchWithValue(&cmd_line, |
253 switches::kProcessType, | 297 switches::kProcessType, |
254 switches::kRendererProcess); | 298 switches::kRendererProcess); |
255 | 299 |
256 CommandLine::AppendSwitchWithValue(&cmd_line, | 300 CommandLine::AppendSwitchWithValue(&cmd_line, |
257 switches::kProcessChannelID, | 301 switches::kProcessChannelID, |
258 channel_id); | 302 channel_id); |
259 | 303 |
260 const std::wstring& profile_path = | 304 const std::wstring& profile_path = |
261 browser_command_line.GetSwitchValue(switches::kUserDataDir); | 305 browser_command_line.GetSwitchValue(switches::kUserDataDir); |
(...skipping 16 matching lines...) Expand all Loading... | |
278 // | 322 // |
279 // TODO: We should consider how to better cleanup threads on exit. | 323 // TODO: We should consider how to better cleanup threads on exit. |
280 base::Thread *render_thread = new RendererMainThread(channel_id); | 324 base::Thread *render_thread = new RendererMainThread(channel_id); |
281 base::Thread::Options options; | 325 base::Thread::Options options; |
282 options.message_loop_type = MessageLoop::TYPE_IO; | 326 options.message_loop_type = MessageLoop::TYPE_IO; |
283 render_thread->StartWithOptions(options); | 327 render_thread->StartWithOptions(options); |
284 } else { | 328 } else { |
285 if (g_browser_process->local_state() && | 329 if (g_browser_process->local_state() && |
286 g_browser_process->local_state()->GetBoolean( | 330 g_browser_process->local_state()->GetBoolean( |
287 prefs::kStartRenderersManually)) { | 331 prefs::kStartRenderersManually)) { |
288 std::wstring message = | 332 RunStartRenderersManuallyDialog(cmd_line); |
289 L"Please start a renderer process using:\n" + cmd_line; | |
290 | |
291 // We don't know the owner window for BrowserRenderProcessHost and therefo re we | |
292 // pass a NULL HWND argument. | |
293 win_util::MessageBox(NULL, | |
294 message, | |
295 switches::kBrowserStartRenderersManually, | |
296 MB_OK); | |
297 } else { | 333 } else { |
334 #if defined(OS_WIN) | |
298 if (in_sandbox) { | 335 if (in_sandbox) { |
299 // spawn the child process in the sandbox | 336 // spawn the child process in the sandbox |
300 sandbox::BrokerServices* broker_service = | 337 sandbox::BrokerServices* broker_service = |
301 g_browser_process->broker_services(); | 338 g_browser_process->broker_services(); |
302 | 339 |
303 sandbox::ResultCode result; | 340 sandbox::ResultCode result; |
304 PROCESS_INFORMATION target = {0}; | 341 PROCESS_INFORMATION target = {0}; |
305 sandbox::TargetPolicy* policy = broker_service->CreatePolicy(); | 342 sandbox::TargetPolicy* policy = broker_service->CreatePolicy(); |
306 policy->SetJobLevel(sandbox::JOB_LOCKDOWN, 0); | 343 policy->SetJobLevel(sandbox::JOB_LOCKDOWN, 0); |
307 | 344 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
358 Details<bool>(&on_sandbox_desktop)); | 395 Details<bool>(&on_sandbox_desktop)); |
359 | 396 |
360 ResumeThread(target.hThread); | 397 ResumeThread(target.hThread); |
361 CloseHandle(target.hThread); | 398 CloseHandle(target.hThread); |
362 process_.set_handle(target.hProcess); | 399 process_.set_handle(target.hProcess); |
363 | 400 |
364 // Help the process a little. It can't start the debugger by itself if | 401 // Help the process a little. It can't start the debugger by itself if |
365 // the process is in a sandbox. | 402 // the process is in a sandbox. |
366 if (child_needs_help) | 403 if (child_needs_help) |
367 DebugUtil::SpawnDebuggerOnProcess(target.dwProcessId); | 404 DebugUtil::SpawnDebuggerOnProcess(target.dwProcessId); |
368 } else { | 405 } else |
406 #endif // OS_WIN and sandbox | |
407 { | |
369 // spawn child process | 408 // spawn child process |
370 HANDLE process; | 409 base::ProcessHandle process = 0; |
410 // TODO(port): LaunchApp is actually no good on POSIX when | |
411 // we've constructed the command line as we have here, as the above | |
412 // calls all append to a single string while LaunchApp reaches in to | |
413 // the argv array. CommandLine should be fixed, but once it is, this | |
414 // code will be correct. | |
371 if (!base::LaunchApp(cmd_line, false, false, &process)) | 415 if (!base::LaunchApp(cmd_line, false, false, &process)) |
372 return false; | 416 return false; |
373 process_.set_handle(process); | 417 process_.set_handle(process); |
374 } | 418 } |
375 | |
376 watcher_.StartWatching(process_.handle(), this); | |
377 } | 419 } |
378 } | 420 } |
379 | 421 |
380 // Now that the process is created, set it's backgrounding accordingly. | 422 // Now that the process is created, set it's backgrounding accordingly. |
381 SetBackgrounded(backgrounded_); | 423 SetBackgrounded(backgrounded_); |
382 | 424 |
383 InitVisitedLinks(); | 425 InitVisitedLinks(); |
384 InitUserScripts(); | 426 InitUserScripts(); |
385 | 427 |
386 if (max_page_id_ != -1) | 428 if (max_page_id_ != -1) |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
500 channel_->Send(new ViewMsg_UserScripts_NewScripts(handle_for_process)); | 542 channel_->Send(new ViewMsg_UserScripts_NewScripts(handle_for_process)); |
501 } | 543 } |
502 } | 544 } |
503 | 545 |
504 bool BrowserRenderProcessHost::FastShutdownIfPossible() { | 546 bool BrowserRenderProcessHost::FastShutdownIfPossible() { |
505 if (!process_.handle()) | 547 if (!process_.handle()) |
506 return false; // Render process is probably crashed. | 548 return false; // Render process is probably crashed. |
507 if (BrowserRenderProcessHost::run_renderer_in_process()) | 549 if (BrowserRenderProcessHost::run_renderer_in_process()) |
508 return false; // Since process mode can't do fast shutdown. | 550 return false; // Since process mode can't do fast shutdown. |
509 | 551 |
552 #if defined(OS_WIN) | |
510 // Test if there's an unload listener | 553 // Test if there's an unload listener |
511 BrowserRenderProcessHost::listeners_iterator iter; | 554 BrowserRenderProcessHost::listeners_iterator iter; |
512 // NOTE: This is a bit dangerous. We know that for now, listeners are | 555 // NOTE: This is a bit dangerous. We know that for now, listeners are |
513 // always RenderWidgetHosts. But in theory, they don't have to be. | 556 // always RenderWidgetHosts. But in theory, they don't have to be. |
514 for (iter = listeners_begin(); iter != listeners_end(); ++iter) { | 557 for (iter = listeners_begin(); iter != listeners_end(); ++iter) { |
515 RenderWidgetHost* widget = static_cast<RenderWidgetHost*>(iter->second); | 558 RenderWidgetHost* widget = static_cast<RenderWidgetHost*>(iter->second); |
516 DCHECK(widget); | 559 DCHECK(widget); |
517 if (!widget || !widget->IsRenderView()) | 560 if (!widget || !widget->IsRenderView()) |
518 continue; | 561 continue; |
519 RenderViewHost* rvh = static_cast<RenderViewHost*>(widget); | 562 RenderViewHost* rvh = static_cast<RenderViewHost*>(widget); |
520 if (!rvh->CanTerminate()) { | 563 if (!rvh->CanTerminate()) { |
521 // NOTE: It's possible that an onunload listener may be installed | 564 // NOTE: It's possible that an onunload listener may be installed |
522 // while we're shutting down, so there's a small race here. Given that | 565 // while we're shutting down, so there's a small race here. Given that |
523 // the window is small, it's unlikely that the web page has much | 566 // the window is small, it's unlikely that the web page has much |
524 // state that will be lost by not calling its unload handlers properly. | 567 // state that will be lost by not calling its unload handlers properly. |
525 return false; | 568 return false; |
526 } | 569 } |
527 } | 570 } |
571 #else | |
572 // TODO(port): the above is the only reason this file pulls in | |
573 // RenderWidgetHost and RenderViewHost. | |
574 // Perhaps IPC::Channel::Listener needs another method like CanTerminate()? | |
575 // No matter what, some abstractions are getting broken here... | |
576 NOTIMPLEMENTED(); | |
577 #endif | |
528 | 578 |
529 // Otherwise, we're allowed to just terminate the process. Using exit code 0 | 579 // Otherwise, we're allowed to just terminate the process. Using exit code 0 |
530 // means that UMA won't treat this as a renderer crash. | 580 // means that UMA won't treat this as a renderer crash. |
531 process_.Terminate(ResultCodes::NORMAL_EXIT); | 581 process_.Terminate(ResultCodes::NORMAL_EXIT); |
532 return true; | 582 return true; |
533 } | 583 } |
534 | 584 |
535 bool BrowserRenderProcessHost::Send(IPC::Message* msg) { | 585 bool BrowserRenderProcessHost::Send(IPC::Message* msg) { |
536 if (!channel_.get()) { | 586 if (!channel_.get()) { |
537 delete msg; | 587 delete msg; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
570 Send(reply); | 620 Send(reply); |
571 } | 621 } |
572 return; | 622 return; |
573 } | 623 } |
574 listener->OnMessageReceived(msg); | 624 listener->OnMessageReceived(msg); |
575 } | 625 } |
576 | 626 |
577 void BrowserRenderProcessHost::OnChannelConnected(int32 peer_pid) { | 627 void BrowserRenderProcessHost::OnChannelConnected(int32 peer_pid) { |
578 // process_ is not NULL if we created the renderer process | 628 // process_ is not NULL if we created the renderer process |
579 if (!process_.handle()) { | 629 if (!process_.handle()) { |
580 if (GetCurrentProcessId() == peer_pid) { | 630 if (base::GetCurrentProcId() == peer_pid) { |
581 // We are in single-process mode. In theory we should have access to | 631 // We are in single-process mode. In theory we should have access to |
582 // ourself but it may happen that we don't. | 632 // ourself but it may happen that we don't. |
583 process_.set_handle(GetCurrentProcess()); | 633 process_.set_handle(base::GetCurrentProcessHandle()); |
584 } else { | 634 } else { |
635 #if defined(OS_WIN) | |
585 // Request MAXIMUM_ALLOWED to match the access a handle | 636 // Request MAXIMUM_ALLOWED to match the access a handle |
586 // returned by CreateProcess() has to the process object. | 637 // returned by CreateProcess() has to the process object. |
587 process_.set_handle(OpenProcess(MAXIMUM_ALLOWED, FALSE, peer_pid)); | 638 process_.set_handle(OpenProcess(MAXIMUM_ALLOWED, FALSE, peer_pid)); |
639 #elif defined(OS_POSIX) | |
640 // ProcessHandle is just a pid. | |
641 process_.set_handle(peer_pid); | |
642 #endif | |
588 DCHECK(process_.handle()); | 643 DCHECK(process_.handle()); |
589 watcher_.StartWatching(process_.handle(), this); | |
590 } | 644 } |
591 } else { | 645 } else { |
592 // Need to verify that the peer_pid is actually the process we know, if | 646 // Need to verify that the peer_pid is actually the process we know, if |
593 // it is not, we need to panic now. See bug 1002150. | 647 // it is not, we need to panic now. See bug 1002150. |
594 CHECK(peer_pid == process_.pid()); | 648 CHECK(peer_pid == process_.pid()); |
595 } | 649 } |
596 } | 650 } |
597 | 651 |
598 // Static. This function can be called from the IO Thread or from the UI thread. | 652 void RenderProcessHost::OnChannelError() { |
599 void BrowserRenderProcessHost::BadMessageTerminateProcess(uint16 msg_type, | 653 // Our child process has died. If we didn't expect it, it's a crash. |
600 HANDLE process) { | 654 // In any case, we need to let everyone know it's gone. |
601 LOG(ERROR) << "bad message " << msg_type << " terminating renderer."; | |
602 if (BrowserRenderProcessHost::run_renderer_in_process()) { | |
603 // In single process mode it is better if we don't suicide but just crash. | |
604 CHECK(false); | |
605 } | |
606 NOTREACHED(); | |
607 ::TerminateProcess(process, ResultCodes::KILLED_BAD_MESSAGE); | |
608 } | |
609 | 655 |
610 // indicates the renderer process has exited | |
611 void BrowserRenderProcessHost::OnObjectSignaled(HANDLE object) { | |
612 DCHECK(process_.handle()); | 656 DCHECK(process_.handle()); |
613 DCHECK(channel_.get()); | 657 DCHECK(channel_.get()); |
614 DCHECK_EQ(object, process_.handle()); | 658 base::ProcessHandle process = process_.handle(); |
615 | 659 |
616 bool clean_shutdown = !base::DidProcessCrash(object); | 660 bool clean_shutdown = !base::DidProcessCrash(process); |
617 | 661 |
618 process_.Close(); | 662 process_.Close(); |
619 | 663 |
620 channel_.reset(); | 664 channel_.reset(); |
621 | 665 |
622 if (!notified_termination_) { | 666 if (!notified_termination_) { |
623 // If |close_expected| is false, it means the renderer process went away | 667 // If |close_expected| is false, it means the renderer process went away |
624 // before the web views expected it; count it as a crash. | 668 // before the web views expected it; count it as a crash. |
625 NotificationService::current()->Notify(NOTIFY_RENDERER_PROCESS_TERMINATED, | 669 NotificationService::current()->Notify(NOTIFY_RENDERER_PROCESS_TERMINATED, |
626 Source<RenderProcessHost>(this), | 670 Source<RenderProcessHost>(this), |
627 Details<bool>(&clean_shutdown)); | 671 Details<bool>(&clean_shutdown)); |
628 notified_termination_ = true; | 672 notified_termination_ = true; |
629 } | 673 } |
630 | 674 |
631 // This process should detach all the listeners, causing the object to be | 675 // This process should detach all the listeners, causing the object to be |
632 // deleted. We therefore need a stack copy of the web view list to avoid | 676 // deleted. We therefore need a stack copy of the web view list to avoid |
633 // crashing when checking for the termination condition the last time. | 677 // crashing when checking for the termination condition the last time. |
634 IDMap<IPC::Channel::Listener> local_listeners(listeners_); | 678 IDMap<IPC::Channel::Listener> local_listeners(listeners_); |
635 for (IDMap<IPC::Channel::Listener>::const_iterator i = local_listeners.begin() ; | 679 for (listeners_iterator i = local_listeners.begin(); |
636 i != local_listeners.end(); ++i) { | 680 i != local_listeners.end(); ++i) { |
637 i->second->OnMessageReceived(ViewHostMsg_RendererGone(i->first)); | 681 i->second->OnMessageReceived(ViewHostMsg_RendererGone(i->first)); |
638 } | 682 } |
639 // at this point, this object should be deleted | 683 // at this point, this object should be deleted |
640 } | 684 } |
641 | 685 |
642 void BrowserRenderProcessHost::Unregister() { | 686 void BrowserRenderProcessHost::Unregister() { |
643 // RenderProcessHost::Unregister will clean up the host_id_, so we must | 687 // RenderProcessHost::Unregister will clean up the host_id_, so we must |
644 // do our cleanup that uses that variable before we call it. | 688 // do our cleanup that uses that variable before we call it. |
645 if (host_id() >= 0) { | 689 if (host_id() >= 0) { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
721 SendUserScriptsUpdate(shared_memory); | 765 SendUserScriptsUpdate(shared_memory); |
722 } | 766 } |
723 break; | 767 break; |
724 } | 768 } |
725 default: { | 769 default: { |
726 NOTREACHED(); | 770 NOTREACHED(); |
727 break; | 771 break; |
728 } | 772 } |
729 } | 773 } |
730 } | 774 } |
775 | |
776 std::wstring GenerateRandomChannelID(void* instance) { | |
777 // Note: the string must start with the current process id, this is how | |
778 // child processes determine the pid of the parent. | |
779 // Build the channel ID. This is composed of a unique identifier for the | |
780 // parent browser process, an identifier for the renderer/plugin instance, | |
781 // and a random component. We use a random component so that a hacked child | |
782 // process can't cause denial of service by causing future named pipe creation | |
783 // to fail. | |
784 return StringPrintf(L"%d.%x.%d", | |
785 base::GetCurrentProcId(), instance, | |
786 base::RandInt(0, std::numeric_limits<int>::max())); | |
787 } | |
OLD | NEW |