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