Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 #include "extensions/browser/process_manager.h" | 5 #include "extensions/browser/process_manager.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 | 126 |
| 127 ProcessManager* process_manager_; | 127 ProcessManager* process_manager_; |
| 128 | 128 |
| 129 DISALLOW_COPY_AND_ASSIGN(RenderViewHostDestructionObserver); | 129 DISALLOW_COPY_AND_ASSIGN(RenderViewHostDestructionObserver); |
| 130 }; | 130 }; |
| 131 | 131 |
| 132 struct ProcessManager::BackgroundPageData { | 132 struct ProcessManager::BackgroundPageData { |
| 133 // The count of things keeping the lazy background page alive. | 133 // The count of things keeping the lazy background page alive. |
| 134 int lazy_keepalive_count; | 134 int lazy_keepalive_count; |
| 135 | 135 |
| 136 // Tracks if an impulse event has occured since the last polling check. | |
| 137 bool keepalive_impulse; | |
| 138 bool previous_keepalive_impulse; | |
| 139 | |
| 136 // This is used with the ShouldSuspend message, to ensure that the extension | 140 // This is used with the ShouldSuspend message, to ensure that the extension |
| 137 // remained idle between sending the message and receiving the ack. | 141 // remained idle between sending the message and receiving the ack. |
| 138 int close_sequence_id; | 142 int close_sequence_id; |
| 139 | 143 |
| 140 // True if the page responded to the ShouldSuspend message and is currently | 144 // True if the page responded to the ShouldSuspend message and is currently |
| 141 // dispatching the suspend event. During this time any events that arrive will | 145 // dispatching the suspend event. During this time any events that arrive will |
| 142 // cancel the suspend process and an onSuspendCanceled event will be | 146 // cancel the suspend process and an onSuspendCanceled event will be |
| 143 // dispatched to the page. | 147 // dispatched to the page. |
| 144 bool is_closing; | 148 bool is_closing; |
| 145 | 149 |
| 146 // Keeps track of when this page was last suspended. Used for perf metrics. | 150 // Keeps track of when this page was last suspended. Used for perf metrics. |
| 147 linked_ptr<base::ElapsedTimer> since_suspended; | 151 linked_ptr<base::ElapsedTimer> since_suspended; |
| 148 | 152 |
| 149 BackgroundPageData() | 153 BackgroundPageData() |
| 150 : lazy_keepalive_count(0), close_sequence_id(0), is_closing(false) {} | 154 : lazy_keepalive_count(0), |
| 155 keepalive_impulse(false), | |
| 156 previous_keepalive_impulse(false), | |
| 157 close_sequence_id(0), | |
| 158 is_closing(false) {} | |
| 151 }; | 159 }; |
| 152 | 160 |
| 153 // | 161 // |
| 154 // ProcessManager | 162 // ProcessManager |
| 155 // | 163 // |
| 156 | 164 |
| 157 // static | 165 // static |
| 158 ProcessManager* ProcessManager::Create(BrowserContext* context) { | 166 ProcessManager* ProcessManager::Create(BrowserContext* context) { |
| 159 if (context->IsOffTheRecord()) { | 167 if (context->IsOffTheRecord()) { |
| 160 BrowserContext* original_context = | 168 BrowserContext* original_context = |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 190 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, | 198 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, |
| 191 content::Source<BrowserContext>(original_context)); | 199 content::Source<BrowserContext>(original_context)); |
| 192 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, | 200 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, |
| 193 content::Source<BrowserContext>(context)); | 201 content::Source<BrowserContext>(context)); |
| 194 if (context->IsOffTheRecord()) { | 202 if (context->IsOffTheRecord()) { |
| 195 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, | 203 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, |
| 196 content::Source<BrowserContext>(original_context)); | 204 content::Source<BrowserContext>(original_context)); |
| 197 } | 205 } |
| 198 | 206 |
| 199 event_page_idle_time_ = base::TimeDelta::FromSeconds(10); | 207 event_page_idle_time_ = base::TimeDelta::FromSeconds(10); |
| 200 unsigned idle_time_sec = 0; | 208 unsigned idle_time_msec = 0; |
| 201 if (base::StringToUint(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 209 if (base::StringToUint(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 202 extensions::switches::kEventPageIdleTime), &idle_time_sec)) { | 210 extensions::switches::kEventPageIdleTime), &idle_time_msec)) { |
| 203 event_page_idle_time_ = base::TimeDelta::FromSeconds(idle_time_sec); | 211 CHECK(idle_time_msec > 0); // OnKeepaliveImpulseCheck requires non zero. |
|
tapted
2013/11/28 03:03:37
optional nit: maybe CHECK_NE(0u, idle_time_msec)?
scheib
2013/12/02 21:22:38
I think this check output is pretty clear as is wi
| |
| 212 event_page_idle_time_ = base::TimeDelta::FromMilliseconds(idle_time_msec); | |
| 204 } | 213 } |
| 205 event_page_suspending_time_ = base::TimeDelta::FromSeconds(5); | 214 event_page_suspending_time_ = base::TimeDelta::FromSeconds(5); |
| 206 unsigned suspending_time_sec = 0; | 215 unsigned suspending_time_msec = 0; |
| 207 if (base::StringToUint(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 216 if (base::StringToUint(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 208 extensions::switches::kEventPageSuspendingTime), | 217 extensions::switches::kEventPageSuspendingTime), |
| 209 &suspending_time_sec)) { | 218 &suspending_time_msec)) { |
| 210 event_page_suspending_time_ = | 219 event_page_suspending_time_ = |
| 211 base::TimeDelta::FromSeconds(suspending_time_sec); | 220 base::TimeDelta::FromMilliseconds(suspending_time_msec); |
| 212 } | 221 } |
| 213 | 222 |
| 214 content::DevToolsManager::GetInstance()->AddAgentStateCallback( | 223 content::DevToolsManager::GetInstance()->AddAgentStateCallback( |
| 215 devtools_callback_); | 224 devtools_callback_); |
| 225 | |
| 226 OnKeepaliveImpulseCheck(); | |
| 216 } | 227 } |
| 217 | 228 |
| 218 ProcessManager::~ProcessManager() { | 229 ProcessManager::~ProcessManager() { |
| 219 CloseBackgroundHosts(); | 230 CloseBackgroundHosts(); |
| 220 DCHECK(background_hosts_.empty()); | 231 DCHECK(background_hosts_.empty()); |
| 221 content::DevToolsManager::GetInstance()->RemoveAgentStateCallback( | 232 content::DevToolsManager::GetInstance()->RemoveAgentStateCallback( |
| 222 devtools_callback_); | 233 devtools_callback_); |
| 223 } | 234 } |
| 224 | 235 |
| 225 const ProcessManager::ViewSet ProcessManager::GetAllViews() const { | 236 const ProcessManager::ViewSet ProcessManager::GetAllViews() const { |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 353 int& count = background_page_data_[extension->id()].lazy_keepalive_count; | 364 int& count = background_page_data_[extension->id()].lazy_keepalive_count; |
| 354 if (++count == 1) | 365 if (++count == 1) |
| 355 OnLazyBackgroundPageActive(extension->id()); | 366 OnLazyBackgroundPageActive(extension->id()); |
| 356 | 367 |
| 357 return count; | 368 return count; |
| 358 } | 369 } |
| 359 | 370 |
| 360 int ProcessManager::DecrementLazyKeepaliveCount(const Extension* extension) { | 371 int ProcessManager::DecrementLazyKeepaliveCount(const Extension* extension) { |
| 361 if (!BackgroundInfo::HasLazyBackgroundPage(extension)) | 372 if (!BackgroundInfo::HasLazyBackgroundPage(extension)) |
| 362 return 0; | 373 return 0; |
| 374 return DecrementLazyKeepaliveCount(extension->id()); | |
| 375 } | |
| 363 | 376 |
| 364 int& count = background_page_data_[extension->id()].lazy_keepalive_count; | 377 int ProcessManager::DecrementLazyKeepaliveCount(std::string extension_id) { |
| 378 int& count = background_page_data_[extension_id].lazy_keepalive_count; | |
| 365 DCHECK_GT(count, 0); | 379 DCHECK_GT(count, 0); |
| 366 | 380 |
| 367 // If we reach a zero keepalive count when the lazy background page is about | 381 // If we reach a zero keepalive count when the lazy background page is about |
| 368 // to be closed, incrementing close_sequence_id will cancel the close | 382 // to be closed, incrementing close_sequence_id will cancel the close |
| 369 // sequence and cause the background page to linger. So check is_closing | 383 // sequence and cause the background page to linger. So check is_closing |
| 370 // before initiating another close sequence. | 384 // before initiating another close sequence. |
| 371 if (--count == 0 && !background_page_data_[extension->id()].is_closing) { | 385 if (--count == 0 && !background_page_data_[extension_id].is_closing) { |
| 372 base::MessageLoop::current()->PostDelayedTask( | 386 base::MessageLoop::current()->PostDelayedTask( |
| 373 FROM_HERE, | 387 FROM_HERE, |
| 374 base::Bind(&ProcessManager::OnLazyBackgroundPageIdle, | 388 base::Bind(&ProcessManager::OnLazyBackgroundPageIdle, |
| 375 weak_ptr_factory_.GetWeakPtr(), extension->id(), | 389 weak_ptr_factory_.GetWeakPtr(), extension_id, |
| 376 ++background_page_data_[extension->id()].close_sequence_id), | 390 ++background_page_data_[extension_id].close_sequence_id), |
| 377 event_page_idle_time_); | 391 event_page_idle_time_); |
| 378 } | 392 } |
| 379 | 393 |
| 380 return count; | 394 return count; |
| 381 } | 395 } |
| 382 | 396 |
| 383 void ProcessManager::IncrementLazyKeepaliveCountForView( | 397 void ProcessManager::IncrementLazyKeepaliveCountForView( |
| 384 RenderViewHost* render_view_host) { | 398 RenderViewHost* render_view_host) { |
| 385 WebContents* web_contents = | 399 WebContents* web_contents = |
| 386 WebContents::FromRenderViewHost(render_view_host); | 400 WebContents::FromRenderViewHost(render_view_host); |
| 387 ViewType view_type = GetViewType(web_contents); | 401 ViewType view_type = GetViewType(web_contents); |
| 388 if (view_type != VIEW_TYPE_INVALID && | 402 if (view_type != VIEW_TYPE_INVALID && |
| 389 view_type != VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { | 403 view_type != VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { |
| 390 const Extension* extension = GetExtensionForRenderViewHost( | 404 const Extension* extension = GetExtensionForRenderViewHost( |
| 391 render_view_host); | 405 render_view_host); |
| 392 if (extension) | 406 if (extension) |
| 393 IncrementLazyKeepaliveCount(extension); | 407 IncrementLazyKeepaliveCount(extension); |
| 394 } | 408 } |
| 395 } | 409 } |
| 396 | 410 |
| 411 // This implementation layers on top of the keepalive count. An impulse sets | |
| 412 // a per extension flag. On a regular interval that flag is checked. Changes | |
| 413 // from the flag not being set to set cause an IncrementLazyKeepaliveCount. | |
| 414 void ProcessManager::KeepaliveImpulse(const Extension* extension) { | |
| 415 if (!BackgroundInfo::HasLazyBackgroundPage(extension)) | |
| 416 return; | |
| 417 | |
| 418 BackgroundPageData& bd = background_page_data_[extension->id()]; | |
| 419 | |
| 420 if (!bd.keepalive_impulse) { | |
| 421 bd.keepalive_impulse = true; | |
| 422 if (!bd.previous_keepalive_impulse) { | |
| 423 IncrementLazyKeepaliveCount(extension); | |
| 424 } | |
| 425 } | |
| 426 } | |
| 427 | |
| 428 // DecrementLazyKeepaliveCount is called when no calls to KeepaliveImpulse | |
| 429 // have been made for at least event_page_idle_time_. In the best case an | |
| 430 // impulse was made just before being cleared, and the decrement will occur | |
| 431 // event_page_idle_time_ later, causing a 2 * event_page_idle_time_ total time | |
| 432 // for extension to be shut down based on impulses. Worst case is an impulse | |
| 433 // just after a clear, adding one check cycle and resulting in 3x total time. | |
| 434 void ProcessManager::OnKeepaliveImpulseCheck() { | |
| 435 for (BackgroundPageDataMap::iterator i = background_page_data_.begin(); | |
| 436 i != background_page_data_.end(); | |
| 437 ++i) { | |
| 438 bool this_impulse = i->second.keepalive_impulse; | |
|
tapted
2013/11/28 03:03:37
(optional) This might be easier to read without th
scheib
2013/12/02 21:22:38
Done; your first suggestion. The latter didn't reu
| |
| 439 bool previous_impulse = i->second.previous_keepalive_impulse; | |
| 440 i->second.keepalive_impulse = false; | |
| 441 i->second.previous_keepalive_impulse = this_impulse; | |
| 442 | |
| 443 if (previous_impulse && !this_impulse) | |
| 444 DecrementLazyKeepaliveCount(i->first); | |
|
tapted
2013/11/28 03:03:37
I thought it weird that the return value wasn't ch
scheib
2013/12/02 21:22:38
Done.
| |
| 445 } | |
| 446 | |
| 447 if (base::MessageLoop::current()) { | |
|
tapted
2013/11/28 03:03:37
Maybe a comment here to explain this check (e.g. S
scheib
2013/12/02 21:22:38
Done.
| |
| 448 base::MessageLoop::current()->PostDelayedTask( | |
| 449 FROM_HERE, | |
| 450 base::Bind(&ProcessManager::OnKeepaliveImpulseCheck, | |
| 451 weak_ptr_factory_.GetWeakPtr()), | |
| 452 event_page_idle_time_); | |
| 453 } | |
| 454 } | |
| 455 | |
| 397 void ProcessManager::OnLazyBackgroundPageIdle(const std::string& extension_id, | 456 void ProcessManager::OnLazyBackgroundPageIdle(const std::string& extension_id, |
| 398 int sequence_id) { | 457 int sequence_id) { |
| 399 ExtensionHost* host = GetBackgroundHostForExtension(extension_id); | 458 ExtensionHost* host = GetBackgroundHostForExtension(extension_id); |
| 400 if (host && !background_page_data_[extension_id].is_closing && | 459 if (host && !background_page_data_[extension_id].is_closing && |
| 401 sequence_id == background_page_data_[extension_id].close_sequence_id) { | 460 sequence_id == background_page_data_[extension_id].close_sequence_id) { |
| 402 // Tell the renderer we are about to close. This is a simple ping that the | 461 // Tell the renderer we are about to close. This is a simple ping that the |
| 403 // renderer will respond to. The purpose is to control sequencing: if the | 462 // renderer will respond to. The purpose is to control sequencing: if the |
| 404 // extension remains idle until the renderer responds with an ACK, then we | 463 // extension remains idle until the renderer responds with an ACK, then we |
| 405 // know that the extension process is ready to shut down. If our | 464 // know that the extension process is ready to shut down. If our |
| 406 // close_sequence_id has already changed, then we would ignore the | 465 // close_sequence_id has already changed, then we would ignore the |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 806 } | 865 } |
| 807 | 866 |
| 808 bool IncognitoProcessManager::IsIncognitoEnabled(const Extension* extension) { | 867 bool IncognitoProcessManager::IsIncognitoEnabled(const Extension* extension) { |
| 809 // Keep in sync with duplicate in extension_info_map.cc. | 868 // Keep in sync with duplicate in extension_info_map.cc. |
| 810 ExtensionService* service = ExtensionSystem::GetForBrowserContext( | 869 ExtensionService* service = ExtensionSystem::GetForBrowserContext( |
| 811 GetBrowserContext())->extension_service(); | 870 GetBrowserContext())->extension_service(); |
| 812 return extension_util::IsIncognitoEnabled(extension->id(), service); | 871 return extension_util::IsIncognitoEnabled(extension->id(), service); |
| 813 } | 872 } |
| 814 | 873 |
| 815 } // namespace extensions | 874 } // namespace extensions |
| OLD | NEW |