OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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 "content/browser/renderer_host/render_process_host_impl.h" | 8 #include "content/browser/renderer_host/render_process_host_impl.h" |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 StoragePartitionImpl* storage_partition_impl, | 478 StoragePartitionImpl* storage_partition_impl, |
479 bool is_for_guests_only) | 479 bool is_for_guests_only) |
480 : fast_shutdown_started_(false), | 480 : fast_shutdown_started_(false), |
481 deleting_soon_(false), | 481 deleting_soon_(false), |
482 #ifndef NDEBUG | 482 #ifndef NDEBUG |
483 is_self_deleted_(false), | 483 is_self_deleted_(false), |
484 #endif | 484 #endif |
485 pending_views_(0), | 485 pending_views_(0), |
486 mojo_application_host_(new MojoApplicationHost), | 486 mojo_application_host_(new MojoApplicationHost), |
487 visible_widgets_(0), | 487 visible_widgets_(0), |
488 backgrounded_(true), | 488 is_process_backgrounded_(false), |
489 is_initialized_(false), | 489 is_initialized_(false), |
490 id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()), | 490 id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()), |
491 browser_context_(browser_context), | 491 browser_context_(browser_context), |
492 storage_partition_impl_(storage_partition_impl), | 492 storage_partition_impl_(storage_partition_impl), |
493 sudden_termination_allowed_(true), | 493 sudden_termination_allowed_(true), |
494 ignore_input_events_(false), | 494 ignore_input_events_(false), |
495 is_for_guests_only_(is_for_guests_only), | 495 is_for_guests_only_(is_for_guests_only), |
496 gpu_observer_registered_(false), | 496 gpu_observer_registered_(false), |
497 delayed_cleanup_needed_(false), | 497 delayed_cleanup_needed_(false), |
498 within_process_died_observer_(false), | 498 within_process_died_observer_(false), |
(...skipping 17 matching lines...) Expand all Loading... |
516 if (!GetBrowserContext()->IsOffTheRecord() && | 516 if (!GetBrowserContext()->IsOffTheRecord() && |
517 !base::CommandLine::ForCurrentProcess()->HasSwitch( | 517 !base::CommandLine::ForCurrentProcess()->HasSwitch( |
518 switches::kDisableGpuShaderDiskCache)) { | 518 switches::kDisableGpuShaderDiskCache)) { |
519 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 519 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
520 base::Bind(&CacheShaderInfo, GetID(), | 520 base::Bind(&CacheShaderInfo, GetID(), |
521 storage_partition_impl_->GetPath())); | 521 storage_partition_impl_->GetPath())); |
522 } | 522 } |
523 subscribe_uniform_enabled_ = | 523 subscribe_uniform_enabled_ = |
524 base::CommandLine::ForCurrentProcess()->HasSwitch( | 524 base::CommandLine::ForCurrentProcess()->HasSwitch( |
525 switches::kEnableSubscribeUniformExtension); | 525 switches::kEnableSubscribeUniformExtension); |
526 | |
527 // Note: When we create the RenderProcessHostImpl, it's technically | |
528 // backgrounded, because it has no visible listeners. But the process | |
529 // doesn't actually exist yet, so we'll Background it later, after | |
530 // creation. | |
531 } | 526 } |
532 | 527 |
533 // static | 528 // static |
534 void RenderProcessHostImpl::ShutDownInProcessRenderer() { | 529 void RenderProcessHostImpl::ShutDownInProcessRenderer() { |
535 DCHECK(g_run_renderer_in_process_); | 530 DCHECK(g_run_renderer_in_process_); |
536 | 531 |
537 switch (g_all_hosts.Pointer()->size()) { | 532 switch (g_all_hosts.Pointer()->size()) { |
538 case 0: | 533 case 0: |
539 return; | 534 return; |
540 case 1: { | 535 case 1: { |
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1072 // In single process mode it is better if we don't suicide but just | 1067 // In single process mode it is better if we don't suicide but just |
1073 // crash. | 1068 // crash. |
1074 CHECK(false); | 1069 CHECK(false); |
1075 } | 1070 } |
1076 // We kill the renderer but don't include a NOTREACHED, because we want the | 1071 // We kill the renderer but don't include a NOTREACHED, because we want the |
1077 // browser to try to survive when it gets illegal messages from the renderer. | 1072 // browser to try to survive when it gets illegal messages from the renderer. |
1078 Shutdown(RESULT_CODE_KILLED_BAD_MESSAGE, false); | 1073 Shutdown(RESULT_CODE_KILLED_BAD_MESSAGE, false); |
1079 } | 1074 } |
1080 | 1075 |
1081 void RenderProcessHostImpl::WidgetRestored() { | 1076 void RenderProcessHostImpl::WidgetRestored() { |
1082 // Verify we were properly backgrounded. | |
1083 DCHECK_EQ(backgrounded_, (visible_widgets_ == 0)); | |
1084 visible_widgets_++; | 1077 visible_widgets_++; |
1085 SetBackgrounded(false); | 1078 UpdateProcessPriority(); |
| 1079 DCHECK(!is_process_backgrounded_); |
1086 } | 1080 } |
1087 | 1081 |
1088 void RenderProcessHostImpl::WidgetHidden() { | 1082 void RenderProcessHostImpl::WidgetHidden() { |
1089 // On startup, the browser will call Hide | 1083 // On startup, the browser will call Hide. We ignore this call. |
1090 if (backgrounded_) | 1084 if (visible_widgets_ == 0) |
1091 return; | 1085 return; |
1092 | 1086 |
1093 DCHECK_EQ(backgrounded_, (visible_widgets_ == 0)); | 1087 --visible_widgets_; |
1094 visible_widgets_--; | |
1095 DCHECK_GE(visible_widgets_, 0); | |
1096 if (visible_widgets_ == 0) { | 1088 if (visible_widgets_ == 0) { |
1097 DCHECK(!backgrounded_); | 1089 DCHECK(!is_process_backgrounded_); |
1098 SetBackgrounded(true); | 1090 UpdateProcessPriority(); |
1099 } | 1091 } |
1100 } | 1092 } |
1101 | 1093 |
1102 int RenderProcessHostImpl::VisibleWidgetCount() const { | 1094 int RenderProcessHostImpl::VisibleWidgetCount() const { |
1103 return visible_widgets_; | 1095 return visible_widgets_; |
1104 } | 1096 } |
1105 | 1097 |
| 1098 void RenderProcessHostImpl::AudioStateChanged() { |
| 1099 UpdateProcessPriority(); |
| 1100 } |
| 1101 |
1106 bool RenderProcessHostImpl::IsForGuestsOnly() const { | 1102 bool RenderProcessHostImpl::IsForGuestsOnly() const { |
1107 return is_for_guests_only_; | 1103 return is_for_guests_only_; |
1108 } | 1104 } |
1109 | 1105 |
1110 StoragePartition* RenderProcessHostImpl::GetStoragePartition() const { | 1106 StoragePartition* RenderProcessHostImpl::GetStoragePartition() const { |
1111 return storage_partition_impl_; | 1107 return storage_partition_impl_; |
1112 } | 1108 } |
1113 | 1109 |
1114 static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) { | 1110 static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) { |
1115 if (IsPropertyTreeVerificationEnabled()) | 1111 if (IsPropertyTreeVerificationEnabled()) |
(...skipping 1002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2118 | 2114 |
2119 RendererClosedDetails details(status, exit_code); | 2115 RendererClosedDetails details(status, exit_code); |
2120 mojo_application_host_->WillDestroySoon(); | 2116 mojo_application_host_->WillDestroySoon(); |
2121 | 2117 |
2122 child_process_launcher_.reset(); | 2118 child_process_launcher_.reset(); |
2123 channel_.reset(); | 2119 channel_.reset(); |
2124 while (!queued_messages_.empty()) { | 2120 while (!queued_messages_.empty()) { |
2125 delete queued_messages_.front(); | 2121 delete queued_messages_.front(); |
2126 queued_messages_.pop(); | 2122 queued_messages_.pop(); |
2127 } | 2123 } |
| 2124 UpdateProcessPriority(); |
| 2125 DCHECK(!is_process_backgrounded_); |
2128 | 2126 |
2129 within_process_died_observer_ = true; | 2127 within_process_died_observer_ = true; |
2130 NotificationService::current()->Notify( | 2128 NotificationService::current()->Notify( |
2131 NOTIFICATION_RENDERER_PROCESS_CLOSED, | 2129 NOTIFICATION_RENDERER_PROCESS_CLOSED, |
2132 Source<RenderProcessHost>(this), | 2130 Source<RenderProcessHost>(this), |
2133 Details<RendererClosedDetails>(&details)); | 2131 Details<RendererClosedDetails>(&details)); |
2134 FOR_EACH_OBSERVER(RenderProcessHostObserver, | 2132 FOR_EACH_OBSERVER(RenderProcessHostObserver, |
2135 observers_, | 2133 observers_, |
2136 RenderProcessExited(this, status, exit_code)); | 2134 RenderProcessExited(this, status, exit_code)); |
2137 within_process_died_observer_ = false; | 2135 within_process_died_observer_ = false; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2235 | 2233 |
2236 mojo_application_host_->WillDestroySoon(); | 2234 mojo_application_host_->WillDestroySoon(); |
2237 | 2235 |
2238 Send(new ChildProcessMsg_Shutdown()); | 2236 Send(new ChildProcessMsg_Shutdown()); |
2239 } | 2237 } |
2240 | 2238 |
2241 void RenderProcessHostImpl::SuddenTerminationChanged(bool enabled) { | 2239 void RenderProcessHostImpl::SuddenTerminationChanged(bool enabled) { |
2242 SetSuddenTerminationAllowed(enabled); | 2240 SetSuddenTerminationAllowed(enabled); |
2243 } | 2241 } |
2244 | 2242 |
2245 void RenderProcessHostImpl::SetBackgrounded(bool backgrounded) { | 2243 void RenderProcessHostImpl::UpdateProcessPriority() { |
2246 TRACE_EVENT1("renderer_host", "RenderProcessHostImpl::SetBackgrounded", | 2244 if (!child_process_launcher_.get() || child_process_launcher_->IsStarting()) { |
2247 "backgrounded", backgrounded); | 2245 is_process_backgrounded_ = false; |
2248 // Note: we always set the backgrounded_ value. If the process is NULL | 2246 return; |
2249 // (and hence hasn't been created yet), we will set the process priority | 2247 } |
2250 // later when we create the process. | 2248 |
2251 backgrounded_ = backgrounded; | 2249 // We background a process as soon as it hosts no active audio streams and no |
2252 if (!child_process_launcher_.get() || child_process_launcher_->IsStarting()) | 2250 // visible widgets -- the callers must call this function whenever we |
| 2251 // transition in/out of thoses states. Processes are initially launched with |
| 2252 // foreground priority, so when the process doesn't exist. |
| 2253 const bool should_background = |
| 2254 visible_widgets_ == 0 && !audio_renderer_host_->HasActiveAudio() && |
| 2255 !base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 2256 switches::kDisableRendererBackgrounding); |
| 2257 |
| 2258 if (is_process_backgrounded_ == should_background) |
2253 return; | 2259 return; |
2254 | 2260 |
2255 // Don't background processes which have active audio streams. | 2261 TRACE_EVENT1("renderer_host", "RenderProcessHostImpl::UpdateProcessPriority", |
2256 if (backgrounded_ && audio_renderer_host_->HasActiveAudio()) | 2262 "should_background", should_background); |
2257 return; | 2263 is_process_backgrounded_ = should_background; |
2258 | |
2259 const base::CommandLine* command_line = | |
2260 base::CommandLine::ForCurrentProcess(); | |
2261 if (command_line->HasSwitch(switches::kDisableRendererBackgrounding)) | |
2262 return; | |
2263 | 2264 |
2264 #if defined(OS_WIN) | 2265 #if defined(OS_WIN) |
2265 // The cbstext.dll loads as a global GetMessage hook in the browser process | 2266 // The cbstext.dll loads as a global GetMessage hook in the browser process |
2266 // and intercepts/unintercepts the kernel32 API SetPriorityClass in a | 2267 // and intercepts/unintercepts the kernel32 API SetPriorityClass in a |
2267 // background thread. If the UI thread invokes this API just when it is | 2268 // background thread. If the UI thread invokes this API just when it is |
2268 // intercepted the stack is messed up on return from the interceptor | 2269 // intercepted the stack is messed up on return from the interceptor |
2269 // which causes random crashes in the browser process. Our hack for now | 2270 // which causes random crashes in the browser process. Our hack for now |
2270 // is to not invoke the SetPriorityClass API if the dll is loaded. | 2271 // is to not invoke the SetPriorityClass API if the dll is loaded. |
2271 if (GetModuleHandle(L"cbstext.dll")) | 2272 if (GetModuleHandle(L"cbstext.dll")) |
2272 return; | 2273 return; |
2273 #endif // OS_WIN | 2274 #endif // OS_WIN |
2274 | 2275 |
2275 #if defined(OS_WIN) || defined(OS_MACOSX) | 2276 #if defined(OS_WIN) || defined(OS_MACOSX) |
2276 // Same as below, but bound to an experiment (http://crbug.com/458594 on | 2277 // Same as below, but bound to an experiment (http://crbug.com/458594 on |
2277 // Windows, http://crbug.com/398103 on the Mac). Enabled by default in the | 2278 // Windows, http://crbug.com/398103 on the Mac). Enabled by default in the |
2278 // absence of field trials to get coverage on the perf waterfall. | 2279 // absence of field trials to get coverage on the perf waterfall. |
2279 base::FieldTrial* trial = | 2280 base::FieldTrial* trial = |
2280 base::FieldTrialList::Find("BackgroundRendererProcesses"); | 2281 base::FieldTrialList::Find("BackgroundRendererProcesses"); |
2281 if (!trial || !base::StartsWith(trial->group_name(), "Disallow", | 2282 if (!trial || !base::StartsWith(trial->group_name(), "Disallow", |
2282 base::CompareCase::SENSITIVE)) { | 2283 base::CompareCase::SENSITIVE)) { |
2283 child_process_launcher_->SetProcessBackgrounded(backgrounded); | 2284 child_process_launcher_->SetProcessBackgrounded(should_background); |
2284 } | 2285 } |
2285 #else | 2286 #else |
2286 // Control the background state from the browser process, otherwise the task | 2287 // Control the background state from the browser process, otherwise the task |
2287 // telling the renderer to "unbackground" itself may be preempted by other | 2288 // telling the renderer to "unbackground" itself may be preempted by other |
2288 // tasks executing at lowered priority ahead of it or simply by not being | 2289 // tasks executing at lowered priority ahead of it or simply by not being |
2289 // swiftly scheduled by the OS per the low process priority | 2290 // swiftly scheduled by the OS per the low process priority |
2290 // (http://crbug.com/398103). | 2291 // (http://crbug.com/398103). |
2291 child_process_launcher_->SetProcessBackgrounded(backgrounded); | 2292 child_process_launcher_->SetProcessBackgrounded(should_background); |
2292 #endif // OS_WIN | 2293 #endif // OS_WIN |
2293 | 2294 |
2294 // Notify the child process of background state. | 2295 // Notify the child process of background state. |
2295 Send(new ChildProcessMsg_SetProcessBackgrounded(backgrounded)); | 2296 Send(new ChildProcessMsg_SetProcessBackgrounded(should_background)); |
2296 } | 2297 } |
2297 | 2298 |
2298 void RenderProcessHostImpl::OnProcessLaunched() { | 2299 void RenderProcessHostImpl::OnProcessLaunched() { |
2299 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 | 2300 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 |
2300 // is fixed. | 2301 // is fixed. |
2301 tracked_objects::ScopedTracker tracking_profile1( | 2302 tracked_objects::ScopedTracker tracking_profile1( |
2302 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 2303 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
2303 "465841 RenderProcessHostImpl::OnProcessLaunched::Start")); | 2304 "465841 RenderProcessHostImpl::OnProcessLaunched::Start")); |
2304 // No point doing anything, since this object will be destructed soon. We | 2305 // No point doing anything, since this object will be destructed soon. We |
2305 // especially don't want to send the RENDERER_PROCESS_CREATED notification, | 2306 // especially don't want to send the RENDERER_PROCESS_CREATED notification, |
2306 // since some clients might expect a RENDERER_PROCESS_TERMINATED afterwards to | 2307 // since some clients might expect a RENDERER_PROCESS_TERMINATED afterwards to |
2307 // properly cleanup. | 2308 // properly cleanup. |
2308 if (deleting_soon_) | 2309 if (deleting_soon_) |
2309 return; | 2310 return; |
2310 | 2311 |
2311 if (child_process_launcher_) { | 2312 if (child_process_launcher_) { |
2312 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 | 2313 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 |
2313 // is fixed. | 2314 // is fixed. |
2314 tracked_objects::ScopedTracker tracking_profile2( | 2315 tracked_objects::ScopedTracker tracking_profile2( |
2315 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 2316 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
2316 "465841 RenderProcessHostImpl::OnProcessLaunched::Backgrounded")); | 2317 "465841 RenderProcessHostImpl::OnProcessLaunched::Backgrounded")); |
2317 DCHECK(child_process_launcher_->GetProcess().IsValid()); | 2318 DCHECK(child_process_launcher_->GetProcess().IsValid()); |
2318 SetBackgrounded(backgrounded_); | 2319 DCHECK(!is_process_backgrounded_); |
| 2320 UpdateProcessPriority(); |
2319 } | 2321 } |
2320 | 2322 |
2321 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 | 2323 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 |
2322 // is fixed. | 2324 // is fixed. |
2323 tracked_objects::ScopedTracker tracking_profile3( | 2325 tracked_objects::ScopedTracker tracking_profile3( |
2324 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 2326 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
2325 "465841 RenderProcessHostImpl::OnProcessLaunched::Notify")); | 2327 "465841 RenderProcessHostImpl::OnProcessLaunched::Notify")); |
2326 // NOTE: This needs to be before sending queued messages because | 2328 // NOTE: This needs to be before sending queued messages because |
2327 // ExtensionService uses this notification to initialize the renderer process | 2329 // ExtensionService uses this notification to initialize the renderer process |
2328 // with state that must be there before any JavaScript executes. | 2330 // with state that must be there before any JavaScript executes. |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2518 void RenderProcessHostImpl::GetAudioOutputControllers( | 2520 void RenderProcessHostImpl::GetAudioOutputControllers( |
2519 const GetAudioOutputControllersCallback& callback) const { | 2521 const GetAudioOutputControllersCallback& callback) const { |
2520 audio_renderer_host()->GetOutputControllers(callback); | 2522 audio_renderer_host()->GetOutputControllers(callback); |
2521 } | 2523 } |
2522 | 2524 |
2523 BluetoothDispatcherHost* RenderProcessHostImpl::GetBluetoothDispatcherHost() { | 2525 BluetoothDispatcherHost* RenderProcessHostImpl::GetBluetoothDispatcherHost() { |
2524 return bluetooth_dispatcher_host_.get(); | 2526 return bluetooth_dispatcher_host_.get(); |
2525 } | 2527 } |
2526 | 2528 |
2527 } // namespace content | 2529 } // namespace content |
OLD | NEW |