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