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 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 130 | 130 |
| 131 ProcessManager* process_manager_; | 131 ProcessManager* process_manager_; |
| 132 | 132 |
| 133 DISALLOW_COPY_AND_ASSIGN(RenderViewHostDestructionObserver); | 133 DISALLOW_COPY_AND_ASSIGN(RenderViewHostDestructionObserver); |
| 134 }; | 134 }; |
| 135 | 135 |
| 136 struct ProcessManager::BackgroundPageData { | 136 struct ProcessManager::BackgroundPageData { |
| 137 // The count of things keeping the lazy background page alive. | 137 // The count of things keeping the lazy background page alive. |
| 138 int lazy_keepalive_count; | 138 int lazy_keepalive_count; |
| 139 | 139 |
| 140 // Tracks if an impulse event has occured since the last polling check. | |
| 141 bool keepalive_impulse; | |
| 142 bool previous_keepalive_impulse; | |
| 143 | |
| 140 // This is used with the ShouldSuspend message, to ensure that the extension | 144 // This is used with the ShouldSuspend message, to ensure that the extension |
| 141 // remained idle between sending the message and receiving the ack. | 145 // remained idle between sending the message and receiving the ack. |
| 142 int close_sequence_id; | 146 int close_sequence_id; |
| 143 | 147 |
| 144 // True if the page responded to the ShouldSuspend message and is currently | 148 // True if the page responded to the ShouldSuspend message and is currently |
| 145 // dispatching the suspend event. During this time any events that arrive will | 149 // dispatching the suspend event. During this time any events that arrive will |
| 146 // cancel the suspend process and an onSuspendCanceled event will be | 150 // cancel the suspend process and an onSuspendCanceled event will be |
| 147 // dispatched to the page. | 151 // dispatched to the page. |
| 148 bool is_closing; | 152 bool is_closing; |
| 149 | 153 |
| 150 // Keeps track of when this page was last suspended. Used for perf metrics. | 154 // Keeps track of when this page was last suspended. Used for perf metrics. |
| 151 linked_ptr<base::ElapsedTimer> since_suspended; | 155 linked_ptr<base::ElapsedTimer> since_suspended; |
| 152 | 156 |
| 153 BackgroundPageData() | 157 BackgroundPageData() |
| 154 : lazy_keepalive_count(0), close_sequence_id(0), is_closing(false) {} | 158 : lazy_keepalive_count(0), |
| 159 keepalive_impulse(false), | |
| 160 previous_keepalive_impulse(false), | |
| 161 close_sequence_id(0), | |
| 162 is_closing(false) {} | |
| 155 }; | 163 }; |
| 156 | 164 |
| 157 // | 165 // |
| 158 // ProcessManager | 166 // ProcessManager |
| 159 // | 167 // |
| 160 | 168 |
| 161 // static | 169 // static |
| 162 ProcessManager* ProcessManager::Create(BrowserContext* context) { | 170 ProcessManager* ProcessManager::Create(BrowserContext* context) { |
| 163 if (context->IsOffTheRecord()) { | 171 if (context->IsOffTheRecord()) { |
| 164 BrowserContext* original_context = | 172 BrowserContext* original_context = |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 210 unsigned suspending_time_sec = 0; | 218 unsigned suspending_time_sec = 0; |
| 211 if (base::StringToUint(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 219 if (base::StringToUint(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 212 extensions::switches::kEventPageSuspendingTime), | 220 extensions::switches::kEventPageSuspendingTime), |
| 213 &suspending_time_sec)) { | 221 &suspending_time_sec)) { |
| 214 event_page_suspending_time_ = | 222 event_page_suspending_time_ = |
| 215 base::TimeDelta::FromSeconds(suspending_time_sec); | 223 base::TimeDelta::FromSeconds(suspending_time_sec); |
| 216 } | 224 } |
| 217 | 225 |
| 218 content::DevToolsManager::GetInstance()->AddAgentStateCallback( | 226 content::DevToolsManager::GetInstance()->AddAgentStateCallback( |
| 219 devtools_callback_); | 227 devtools_callback_); |
| 228 | |
| 229 OnKeepaliveImpulseCheck(); | |
| 220 } | 230 } |
| 221 | 231 |
| 222 ProcessManager::~ProcessManager() { | 232 ProcessManager::~ProcessManager() { |
| 223 CloseBackgroundHosts(); | 233 CloseBackgroundHosts(); |
| 224 DCHECK(background_hosts_.empty()); | 234 DCHECK(background_hosts_.empty()); |
| 225 content::DevToolsManager::GetInstance()->RemoveAgentStateCallback( | 235 content::DevToolsManager::GetInstance()->RemoveAgentStateCallback( |
| 226 devtools_callback_); | 236 devtools_callback_); |
| 227 } | 237 } |
| 228 | 238 |
| 229 const ProcessManager::ViewSet ProcessManager::GetAllViews() const { | 239 const ProcessManager::ViewSet ProcessManager::GetAllViews() const { |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 365 int& count = background_page_data_[extension->id()].lazy_keepalive_count; | 375 int& count = background_page_data_[extension->id()].lazy_keepalive_count; |
| 366 if (++count == 1) | 376 if (++count == 1) |
| 367 OnLazyBackgroundPageActive(extension->id()); | 377 OnLazyBackgroundPageActive(extension->id()); |
| 368 | 378 |
| 369 return count; | 379 return count; |
| 370 } | 380 } |
| 371 | 381 |
| 372 int ProcessManager::DecrementLazyKeepaliveCount(const Extension* extension) { | 382 int ProcessManager::DecrementLazyKeepaliveCount(const Extension* extension) { |
| 373 if (!BackgroundInfo::HasLazyBackgroundPage(extension)) | 383 if (!BackgroundInfo::HasLazyBackgroundPage(extension)) |
| 374 return 0; | 384 return 0; |
| 385 return DecrementLazyKeepaliveCountById(extension->id()); | |
| 386 } | |
| 375 | 387 |
| 376 int& count = background_page_data_[extension->id()].lazy_keepalive_count; | 388 int ProcessManager::DecrementLazyKeepaliveCountById(std::string extension_id) { |
|
Matt Perry
2013/11/19 21:35:08
nit: I think this is similar enough to DecrementLa
scheib
2013/11/19 23:18:25
Done.
| |
| 389 int& count = background_page_data_[extension_id].lazy_keepalive_count; | |
| 377 DCHECK_GT(count, 0); | 390 DCHECK_GT(count, 0); |
| 378 | 391 |
| 379 // If we reach a zero keepalive count when the lazy background page is about | 392 // If we reach a zero keepalive count when the lazy background page is about |
| 380 // to be closed, incrementing close_sequence_id will cancel the close | 393 // to be closed, incrementing close_sequence_id will cancel the close |
| 381 // sequence and cause the background page to linger. So check is_closing | 394 // sequence and cause the background page to linger. So check is_closing |
| 382 // before initiating another close sequence. | 395 // before initiating another close sequence. |
| 383 if (--count == 0 && !background_page_data_[extension->id()].is_closing) { | 396 if (--count == 0 && !background_page_data_[extension_id].is_closing) { |
| 384 base::MessageLoop::current()->PostDelayedTask( | 397 base::MessageLoop::current()->PostDelayedTask( |
| 385 FROM_HERE, | 398 FROM_HERE, |
| 386 base::Bind(&ProcessManager::OnLazyBackgroundPageIdle, | 399 base::Bind(&ProcessManager::OnLazyBackgroundPageIdle, |
| 387 weak_ptr_factory_.GetWeakPtr(), extension->id(), | 400 weak_ptr_factory_.GetWeakPtr(), extension_id, |
| 388 ++background_page_data_[extension->id()].close_sequence_id), | 401 ++background_page_data_[extension_id].close_sequence_id), |
| 389 event_page_idle_time_); | 402 event_page_idle_time_); |
| 390 } | 403 } |
| 391 | 404 |
| 392 return count; | 405 return count; |
| 393 } | 406 } |
| 394 | 407 |
| 395 void ProcessManager::IncrementLazyKeepaliveCountForView( | 408 void ProcessManager::IncrementLazyKeepaliveCountForView( |
| 396 RenderViewHost* render_view_host) { | 409 RenderViewHost* render_view_host) { |
| 397 WebContents* web_contents = | 410 WebContents* web_contents = |
| 398 WebContents::FromRenderViewHost(render_view_host); | 411 WebContents::FromRenderViewHost(render_view_host); |
| 399 ViewType view_type = GetViewType(web_contents); | 412 ViewType view_type = GetViewType(web_contents); |
| 400 if (view_type != VIEW_TYPE_INVALID && | 413 if (view_type != VIEW_TYPE_INVALID && |
| 401 view_type != VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { | 414 view_type != VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { |
| 402 const Extension* extension = GetExtensionForRenderViewHost( | 415 const Extension* extension = GetExtensionForRenderViewHost( |
| 403 render_view_host); | 416 render_view_host); |
| 404 if (extension) | 417 if (extension) |
| 405 IncrementLazyKeepaliveCount(extension); | 418 IncrementLazyKeepaliveCount(extension); |
| 406 } | 419 } |
| 407 } | 420 } |
| 408 | 421 |
| 422 // This implementation layers on top of the keepalive count. An impulse sets | |
| 423 // a per extension flag. On a regular interval that flag is checked. Changes | |
| 424 // from the flag not being set to set cause an IncrementLazyKeepaliveCount. | |
| 425 void ProcessManager::KeepaliveImpulse(const Extension* extension) { | |
| 426 if (!BackgroundInfo::HasLazyBackgroundPage(extension)) | |
| 427 return; | |
| 428 | |
| 429 BackgroundPageData& bd = background_page_data_[extension->id()]; | |
| 430 | |
| 431 if (!bd.keepalive_impulse) { | |
| 432 bd.keepalive_impulse = true; | |
| 433 if (!bd.previous_keepalive_impulse) { | |
| 434 IncrementLazyKeepaliveCount(extension); | |
| 435 } | |
| 436 } | |
| 437 } | |
| 438 | |
| 439 // DecrementLazyKeepaliveCount is called when no calls to KeepaliveImpulse | |
| 440 // have been made for at least event_page_idle_time_. In the best case an | |
| 441 // impulse was made just before being cleared, and the decrement will occur | |
| 442 // event_page_idle_time_ later, causing a 2 * event_page_idle_time_ total time | |
| 443 // for extension to be shut down based on impulses. Worst case is an impulse | |
| 444 // just after a clear, adding one check cycle and resulting in 3x total time. | |
| 445 void ProcessManager::OnKeepaliveImpulseCheck() { | |
| 446 for (BackgroundPageDataMap::iterator i = background_page_data_.begin(); | |
| 447 i != background_page_data_.end(); | |
| 448 ++i) { | |
| 449 bool this_impulse = i->second.keepalive_impulse; | |
| 450 bool previous_impulse = i->second.previous_keepalive_impulse; | |
| 451 i->second.keepalive_impulse = false; | |
| 452 i->second.previous_keepalive_impulse = this_impulse; | |
| 453 | |
| 454 if (previous_impulse && !this_impulse) { | |
| 455 DecrementLazyKeepaliveCountById(i->first); | |
| 456 } | |
| 457 } | |
| 458 | |
| 459 base::MessageLoop::current()->PostDelayedTask( | |
| 460 FROM_HERE, | |
|
Matt Perry
2013/11/19 21:35:08
nit: indent to 4
scheib
2013/11/19 23:18:25
Done.
| |
| 461 base::Bind(&ProcessManager::OnKeepaliveImpulseCheck, | |
| 462 weak_ptr_factory_.GetWeakPtr()), | |
| 463 event_page_idle_time_); | |
| 464 } | |
| 465 | |
| 409 void ProcessManager::OnLazyBackgroundPageIdle(const std::string& extension_id, | 466 void ProcessManager::OnLazyBackgroundPageIdle(const std::string& extension_id, |
| 410 int sequence_id) { | 467 int sequence_id) { |
| 411 ExtensionHost* host = GetBackgroundHostForExtension(extension_id); | 468 ExtensionHost* host = GetBackgroundHostForExtension(extension_id); |
| 412 if (host && !background_page_data_[extension_id].is_closing && | 469 if (host && !background_page_data_[extension_id].is_closing && |
| 413 sequence_id == background_page_data_[extension_id].close_sequence_id) { | 470 sequence_id == background_page_data_[extension_id].close_sequence_id) { |
| 414 // Tell the renderer we are about to close. This is a simple ping that the | 471 // Tell the renderer we are about to close. This is a simple ping that the |
| 415 // renderer will respond to. The purpose is to control sequencing: if the | 472 // renderer will respond to. The purpose is to control sequencing: if the |
| 416 // extension remains idle until the renderer responds with an ACK, then we | 473 // extension remains idle until the renderer responds with an ACK, then we |
| 417 // know that the extension process is ready to shut down. If our | 474 // know that the extension process is ready to shut down. If our |
| 418 // close_sequence_id has already changed, then we would ignore the | 475 // close_sequence_id has already changed, then we would ignore the |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 818 } | 875 } |
| 819 | 876 |
| 820 bool IncognitoProcessManager::IsIncognitoEnabled(const Extension* extension) { | 877 bool IncognitoProcessManager::IsIncognitoEnabled(const Extension* extension) { |
| 821 // Keep in sync with duplicate in extension_info_map.cc. | 878 // Keep in sync with duplicate in extension_info_map.cc. |
| 822 ExtensionService* service = ExtensionSystem::GetForBrowserContext( | 879 ExtensionService* service = ExtensionSystem::GetForBrowserContext( |
| 823 GetBrowserContext())->extension_service(); | 880 GetBrowserContext())->extension_service(); |
| 824 return extension_util::IsIncognitoEnabled(extension->id(), service); | 881 return extension_util::IsIncognitoEnabled(extension->id(), service); |
| 825 } | 882 } |
| 826 | 883 |
| 827 } // namespace extensions | 884 } // namespace extensions |
| OLD | NEW |