| 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 | 5 // Represents the browser side of the browser <--> renderer communication |
| 6 // channel. There will be one RenderProcessHost per renderer process. | 6 // channel. There will be one RenderProcessHost per renderer process. |
| 7 | 7 |
| 8 #include "chrome/browser/renderer_host/browser_render_process_host.h" | 8 #include "chrome/browser/renderer_host/browser_render_process_host.h" |
| 9 | 9 |
| 10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 const int32 kInvalidViewID = -1; | 114 const int32 kInvalidViewID = -1; |
| 115 | 115 |
| 116 // Get the path to the renderer executable, which is the same as the | 116 // Get the path to the renderer executable, which is the same as the |
| 117 // current executable. | 117 // current executable. |
| 118 bool GetRendererPath(std::wstring* cmd_line) { | 118 bool GetRendererPath(std::wstring* cmd_line) { |
| 119 return PathService::Get(base::FILE_EXE, cmd_line); | 119 return PathService::Get(base::FILE_EXE, cmd_line); |
| 120 } | 120 } |
| 121 | 121 |
| 122 const wchar_t* const kDesktopName = L"ChromeRendererDesktop"; | 122 const wchar_t* const kDesktopName = L"ChromeRendererDesktop"; |
| 123 | 123 |
| 124 // static | |
| 125 void BrowserRenderProcessHost::RegisterPrefs(PrefService* prefs) { | |
| 126 prefs->RegisterBooleanPref(prefs::kStartRenderersManually, false); | |
| 127 } | |
| 128 | |
| 129 BrowserRenderProcessHost::BrowserRenderProcessHost(Profile* profile) | 124 BrowserRenderProcessHost::BrowserRenderProcessHost(Profile* profile) |
| 130 : RenderProcessHost(profile), | 125 : RenderProcessHost(profile), |
| 131 visible_widgets_(0), | 126 visible_widgets_(0), |
| 132 backgrounded_(true), | 127 backgrounded_(true), |
| 133 ALLOW_THIS_IN_INITIALIZER_LIST(cached_dibs_cleaner_( | 128 ALLOW_THIS_IN_INITIALIZER_LIST(cached_dibs_cleaner_( |
| 134 base::TimeDelta::FromSeconds(5), | 129 base::TimeDelta::FromSeconds(5), |
| 135 this, &BrowserRenderProcessHost::ClearTransportDIBCache)) { | 130 this, &BrowserRenderProcessHost::ClearTransportDIBCache)) { |
| 136 DCHECK(host_id() >= 0); // We use a negative host_id_ in destruction. | 131 DCHECK(host_id() >= 0); // We use a negative host_id_ in destruction. |
| 137 widget_helper_ = new RenderWidgetHelper(host_id()); | 132 widget_helper_ = new RenderWidgetHelper(host_id()); |
| 138 | 133 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 } | 166 } |
| 172 | 167 |
| 173 profile()->GetPrefs()->RemovePrefObserver(prefs::kBlockPopups, this); | 168 profile()->GetPrefs()->RemovePrefObserver(prefs::kBlockPopups, this); |
| 174 | 169 |
| 175 NotificationService::current()->RemoveObserver(this, | 170 NotificationService::current()->RemoveObserver(this, |
| 176 NotificationType::USER_SCRIPTS_LOADED, NotificationService::AllSources()); | 171 NotificationType::USER_SCRIPTS_LOADED, NotificationService::AllSources()); |
| 177 | 172 |
| 178 ClearTransportDIBCache(); | 173 ClearTransportDIBCache(); |
| 179 } | 174 } |
| 180 | 175 |
| 181 // When we're started with the --start-renderers-manually flag, we pop up a | |
| 182 // modal dialog requesting the user manually start up a renderer. | |
| 183 // |cmd_line| is the command line to start the renderer with. | |
| 184 static void RunStartRenderersManuallyDialog(const CommandLine& cmd_line) { | |
| 185 #if defined(OS_WIN) | |
| 186 std::wstring message = | |
| 187 L"Please start a renderer process using:\n" + | |
| 188 cmd_line.command_line_string(); | |
| 189 | |
| 190 // We don't know the owner window for RenderProcessHost and therefore we | |
| 191 // pass a NULL HWND argument. | |
| 192 win_util::MessageBox(NULL, | |
| 193 message, | |
| 194 switches::kBrowserStartRenderersManually, | |
| 195 MB_OK); | |
| 196 #else | |
| 197 // TODO(port): refactor above code / pop up a message box here. | |
| 198 NOTIMPLEMENTED(); | |
| 199 #endif | |
| 200 } | |
| 201 | |
| 202 bool BrowserRenderProcessHost::Init() { | 176 bool BrowserRenderProcessHost::Init() { |
| 203 // calling Init() more than once does nothing, this makes it more convenient | 177 // calling Init() more than once does nothing, this makes it more convenient |
| 204 // for the view host which may not be sure in some cases | 178 // for the view host which may not be sure in some cases |
| 205 if (channel_.get()) | 179 if (channel_.get()) |
| 206 return true; | 180 return true; |
| 207 | 181 |
| 208 // run the IPC channel on the shared IO thread. | 182 // run the IPC channel on the shared IO thread. |
| 209 base::Thread* io_thread = g_browser_process->io_thread(); | 183 base::Thread* io_thread = g_browser_process->io_thread(); |
| 210 | 184 |
| 211 // Construct the AudioRendererHost with the IO thread. | 185 // Construct the AudioRendererHost with the IO thread. |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 // RenderThread is both responsible for rendering and also for | 316 // RenderThread is both responsible for rendering and also for |
| 343 // communicating IO. This can lead to deadlocks where the RenderThread is | 317 // communicating IO. This can lead to deadlocks where the RenderThread is |
| 344 // waiting for the IO to complete, while the browsermain is trying to pass | 318 // waiting for the IO to complete, while the browsermain is trying to pass |
| 345 // an event to the RenderThread. | 319 // an event to the RenderThread. |
| 346 in_process_renderer_.reset(new RendererMainThread(channel_id)); | 320 in_process_renderer_.reset(new RendererMainThread(channel_id)); |
| 347 | 321 |
| 348 base::Thread::Options options; | 322 base::Thread::Options options; |
| 349 options.message_loop_type = MessageLoop::TYPE_IO; | 323 options.message_loop_type = MessageLoop::TYPE_IO; |
| 350 in_process_renderer_->StartWithOptions(options); | 324 in_process_renderer_->StartWithOptions(options); |
| 351 } else { | 325 } else { |
| 352 if (g_browser_process->local_state() && | |
| 353 g_browser_process->local_state()->GetBoolean( | |
| 354 prefs::kStartRenderersManually)) { | |
| 355 RunStartRenderersManuallyDialog(cmd_line); | |
| 356 } else { | |
| 357 #if defined(OS_WIN) | 326 #if defined(OS_WIN) |
| 358 if (in_sandbox) { | 327 if (in_sandbox) { |
| 359 // spawn the child process in the sandbox | 328 // spawn the child process in the sandbox |
| 360 sandbox::BrokerServices* broker_service = | 329 sandbox::BrokerServices* broker_service = |
| 361 g_browser_process->broker_services(); | 330 g_browser_process->broker_services(); |
| 362 | 331 |
| 363 sandbox::ResultCode result; | 332 sandbox::ResultCode result; |
| 364 PROCESS_INFORMATION target = {0}; | 333 PROCESS_INFORMATION target = {0}; |
| 365 sandbox::TargetPolicy* policy = broker_service->CreatePolicy(); | 334 sandbox::TargetPolicy* policy = broker_service->CreatePolicy(); |
| 366 policy->SetJobLevel(sandbox::JOB_LOCKDOWN, 0); | 335 policy->SetJobLevel(sandbox::JOB_LOCKDOWN, 0); |
| 367 | 336 |
| 368 sandbox::TokenLevel initial_token = sandbox::USER_UNPROTECTED; | 337 sandbox::TokenLevel initial_token = sandbox::USER_UNPROTECTED; |
| 369 if (win_util::GetWinVersion() > win_util::WINVERSION_XP) { | 338 if (win_util::GetWinVersion() > win_util::WINVERSION_XP) { |
| 370 // On 2003/Vista the initial token has to be restricted if the main | 339 // On 2003/Vista the initial token has to be restricted if the main |
| 371 // token is restricted. | 340 // token is restricted. |
| 372 initial_token = sandbox::USER_RESTRICTED_SAME_ACCESS; | 341 initial_token = sandbox::USER_RESTRICTED_SAME_ACCESS; |
| 373 } | 342 } |
| 374 | 343 |
| 375 policy->SetTokenLevel(initial_token, sandbox::USER_LOCKDOWN); | 344 policy->SetTokenLevel(initial_token, sandbox::USER_LOCKDOWN); |
| 376 policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW); | 345 policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW); |
| 377 | 346 |
| 378 HDESK desktop = CreateDesktop(kDesktopName, NULL, NULL, 0, | 347 HDESK desktop = CreateDesktop(kDesktopName, NULL, NULL, 0, |
| 379 DESKTOP_CREATEWINDOW, NULL); | 348 DESKTOP_CREATEWINDOW, NULL); |
| 380 if (desktop) { | 349 if (desktop) { |
| 381 policy->SetDesktop(kDesktopName); | 350 policy->SetDesktop(kDesktopName); |
| 382 } else { | 351 } else { |
| 383 DLOG(WARNING) << "Failed to apply desktop security to the renderer"; | 352 DLOG(WARNING) << "Failed to apply desktop security to the renderer"; |
| 384 } | 353 } |
| 385 | 354 |
| 386 if (!AddGenericPolicy(policy)) { | 355 if (!AddGenericPolicy(policy)) { |
| 356 NOTREACHED(); |
| 357 return false; |
| 358 } |
| 359 |
| 360 if (browser_command_line.HasSwitch(switches::kGearsInRenderer)) { |
| 361 if (!AddPolicyForGearsInRenderer(policy)) { |
| 387 NOTREACHED(); | 362 NOTREACHED(); |
| 388 return false; | 363 return false; |
| 389 } | 364 } |
| 365 } |
| 390 | 366 |
| 391 if (browser_command_line.HasSwitch(switches::kGearsInRenderer)) { | 367 if (!AddDllEvictionPolicy(policy)) { |
| 392 if (!AddPolicyForGearsInRenderer(policy)) { | 368 NOTREACHED(); |
| 393 NOTREACHED(); | 369 return false; |
| 394 return false; | 370 } |
| 395 } | |
| 396 } | |
| 397 | 371 |
| 398 if (!AddDllEvictionPolicy(policy)) { | 372 result = |
| 399 NOTREACHED(); | 373 broker_service->SpawnTarget(renderer_path.c_str(), |
| 400 return false; | 374 cmd_line.command_line_string().c_str(), |
| 401 } | 375 policy, &target); |
| 376 policy->Release(); |
| 402 | 377 |
| 403 result = | 378 if (desktop) |
| 404 broker_service->SpawnTarget(renderer_path.c_str(), | 379 CloseDesktop(desktop); |
| 405 cmd_line.command_line_string().c_str(), | |
| 406 policy, &target); | |
| 407 policy->Release(); | |
| 408 | 380 |
| 409 if (desktop) | 381 if (sandbox::SBOX_ALL_OK != result) |
| 410 CloseDesktop(desktop); | 382 return false; |
| 411 | 383 |
| 412 if (sandbox::SBOX_ALL_OK != result) | 384 bool on_sandbox_desktop = (desktop != NULL); |
| 413 return false; | 385 NotificationService::current()->Notify( |
| 386 NotificationType::RENDERER_PROCESS_IN_SBOX, |
| 387 Source<BrowserRenderProcessHost>(this), |
| 388 Details<bool>(&on_sandbox_desktop)); |
| 414 | 389 |
| 415 bool on_sandbox_desktop = (desktop != NULL); | 390 ResumeThread(target.hThread); |
| 416 NotificationService::current()->Notify( | 391 CloseHandle(target.hThread); |
| 417 NotificationType::RENDERER_PROCESS_IN_SBOX, | 392 process_.set_handle(target.hProcess); |
| 418 Source<BrowserRenderProcessHost>(this), | |
| 419 Details<bool>(&on_sandbox_desktop)); | |
| 420 | 393 |
| 421 ResumeThread(target.hThread); | 394 // Help the process a little. It can't start the debugger by itself if |
| 422 CloseHandle(target.hThread); | 395 // the process is in a sandbox. |
| 423 process_.set_handle(target.hProcess); | 396 if (child_needs_help) |
| 424 | 397 DebugUtil::SpawnDebuggerOnProcess(target.dwProcessId); |
| 425 // Help the process a little. It can't start the debugger by itself if | 398 } else |
| 426 // the process is in a sandbox. | |
| 427 if (child_needs_help) | |
| 428 DebugUtil::SpawnDebuggerOnProcess(target.dwProcessId); | |
| 429 } else | |
| 430 #endif // OS_WIN and sandbox | 399 #endif // OS_WIN and sandbox |
| 431 { | 400 { |
| 432 // spawn child process | 401 // spawn child process |
| 433 base::ProcessHandle process = 0; | 402 base::ProcessHandle process = 0; |
| 434 if (!SpawnChild(cmd_line, channel_.get(), &process)) | 403 if (!SpawnChild(cmd_line, channel_.get(), &process)) |
| 435 return false; | 404 return false; |
| 436 process_.set_handle(process); | 405 process_.set_handle(process); |
| 437 } | |
| 438 } | 406 } |
| 439 } | 407 } |
| 440 | 408 |
| 441 // Now that the process is created, set it's backgrounding accordingly. | 409 // Now that the process is created, set it's backgrounding accordingly. |
| 442 SetBackgrounded(backgrounded_); | 410 SetBackgrounded(backgrounded_); |
| 443 | 411 |
| 444 InitVisitedLinks(); | 412 InitVisitedLinks(); |
| 445 InitUserScripts(); | 413 InitUserScripts(); |
| 446 | 414 |
| 447 if (max_page_id_ != -1) | 415 if (max_page_id_ != -1) |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 897 SendUserScriptsUpdate(shared_memory); | 865 SendUserScriptsUpdate(shared_memory); |
| 898 } | 866 } |
| 899 break; | 867 break; |
| 900 } | 868 } |
| 901 default: { | 869 default: { |
| 902 NOTREACHED(); | 870 NOTREACHED(); |
| 903 break; | 871 break; |
| 904 } | 872 } |
| 905 } | 873 } |
| 906 } | 874 } |
| OLD | NEW |