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 <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 114 | 114 |
| 115 void PropagateExtensionWakeResult(const base::Callback<void(bool)>& callback, | 115 void PropagateExtensionWakeResult(const base::Callback<void(bool)>& callback, |
| 116 extensions::ExtensionHost* host) { | 116 extensions::ExtensionHost* host) { |
| 117 callback.Run(host != nullptr); | 117 callback.Run(host != nullptr); |
| 118 } | 118 } |
| 119 | 119 |
| 120 } // namespace | 120 } // namespace |
| 121 | 121 |
| 122 struct ProcessManager::BackgroundPageData { | 122 struct ProcessManager::BackgroundPageData { |
| 123 // The count of things keeping the lazy background page alive. | 123 // The count of things keeping the lazy background page alive. |
| 124 int lazy_keepalive_count; | 124 int lazy_keepalive_count = 0; |
| 125 | |
| 126 // Tracks if an impulse event has occured since the last polling check. | |
| 127 bool keepalive_impulse; | |
| 128 bool previous_keepalive_impulse; | |
| 129 | 125 |
| 130 // True if the page responded to the ShouldSuspend message and is currently | 126 // True if the page responded to the ShouldSuspend message and is currently |
| 131 // dispatching the suspend event. During this time any events that arrive will | 127 // dispatching the suspend event. During this time any events that arrive will |
| 132 // cancel the suspend process and an onSuspendCanceled event will be | 128 // cancel the suspend process and an onSuspendCanceled event will be |
| 133 // dispatched to the page. | 129 // dispatched to the page. |
| 134 bool is_closing; | 130 bool is_closing = false; |
| 135 | 131 |
| 136 // Stores the value of the incremented | 132 // Stores the value of the incremented |
| 137 // ProcessManager::last_background_close_sequence_id_ whenever the extension | 133 // ProcessManager::last_background_close_sequence_id_ whenever the extension |
| 138 // is active. A copy of the ID is also passed in the callbacks and IPC | 134 // is active. A copy of the ID is also passed in the callbacks and IPC |
| 139 // messages leading up to CloseLazyBackgroundPageNow. The process is aborted | 135 // messages leading up to CloseLazyBackgroundPageNow. The process is aborted |
| 140 // if the IDs ever differ due to new activity. | 136 // if the IDs ever differ due to new activity. |
| 141 uint64_t close_sequence_id; | 137 uint64_t close_sequence_id = 0ull; |
| 142 | 138 |
| 143 // Keeps track of when this page was last suspended. Used for perf metrics. | 139 // Keeps track of when this page was last suspended. Used for perf metrics. |
| 144 std::unique_ptr<base::ElapsedTimer> since_suspended; | 140 std::unique_ptr<base::ElapsedTimer> since_suspended; |
| 145 | |
| 146 BackgroundPageData() | |
| 147 : lazy_keepalive_count(0), | |
| 148 keepalive_impulse(false), | |
| 149 previous_keepalive_impulse(false), | |
| 150 is_closing(false), | |
| 151 close_sequence_id(0) {} | |
| 152 }; | 141 }; |
| 153 | 142 |
| 154 // Data of a RenderFrameHost associated with an extension. | 143 // Data of a RenderFrameHost associated with an extension. |
| 155 struct ProcessManager::ExtensionRenderFrameData { | 144 struct ProcessManager::ExtensionRenderFrameData { |
| 156 // The type of the view. | 145 // The type of the view. |
| 157 extensions::ViewType view_type; | 146 extensions::ViewType view_type = VIEW_TYPE_INVALID; |
| 158 | 147 |
| 159 // Whether the view is keeping the lazy background page alive or not. | 148 // Whether the view is keeping the lazy background page alive or not. |
| 160 bool has_keepalive; | 149 bool has_keepalive = false; |
| 161 | |
| 162 ExtensionRenderFrameData() | |
| 163 : view_type(VIEW_TYPE_INVALID), has_keepalive(false) {} | |
| 164 | 150 |
| 165 // Returns whether the view can keep the lazy background page alive or not. | 151 // Returns whether the view can keep the lazy background page alive or not. |
| 166 bool CanKeepalive() const { | 152 bool CanKeepalive() const { |
| 167 switch (view_type) { | 153 switch (view_type) { |
| 168 case VIEW_TYPE_APP_WINDOW: | 154 case VIEW_TYPE_APP_WINDOW: |
| 169 case VIEW_TYPE_BACKGROUND_CONTENTS: | 155 case VIEW_TYPE_BACKGROUND_CONTENTS: |
| 170 case VIEW_TYPE_COMPONENT: | 156 case VIEW_TYPE_COMPONENT: |
| 171 case VIEW_TYPE_EXTENSION_DIALOG: | 157 case VIEW_TYPE_EXTENSION_DIALOG: |
| 172 case VIEW_TYPE_EXTENSION_GUEST: | 158 case VIEW_TYPE_EXTENSION_GUEST: |
| 173 case VIEW_TYPE_EXTENSION_POPUP: | 159 case VIEW_TYPE_EXTENSION_POPUP: |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 256 extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, | 242 extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, |
| 257 content::Source<BrowserContext>(original_context)); | 243 content::Source<BrowserContext>(original_context)); |
| 258 } | 244 } |
| 259 registrar_.Add(this, | 245 registrar_.Add(this, |
| 260 extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, | 246 extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, |
| 261 content::Source<BrowserContext>(context)); | 247 content::Source<BrowserContext>(context)); |
| 262 registrar_.Add(this, | 248 registrar_.Add(this, |
| 263 extensions::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, | 249 extensions::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, |
| 264 content::Source<BrowserContext>(context)); | 250 content::Source<BrowserContext>(context)); |
| 265 content::DevToolsAgentHost::AddObserver(this); | 251 content::DevToolsAgentHost::AddObserver(this); |
| 266 | |
| 267 OnKeepaliveImpulseCheck(); | |
| 268 } | 252 } |
| 269 | 253 |
| 270 ProcessManager::~ProcessManager() { | 254 ProcessManager::~ProcessManager() { |
| 271 extension_registry_->RemoveObserver(this); | 255 extension_registry_->RemoveObserver(this); |
| 272 CloseBackgroundHosts(); | 256 CloseBackgroundHosts(); |
| 273 DCHECK(background_hosts_.empty()); | 257 DCHECK(background_hosts_.empty()); |
| 274 content::DevToolsAgentHost::RemoveObserver(this); | 258 content::DevToolsAgentHost::RemoveObserver(this); |
| 275 } | 259 } |
| 276 | 260 |
| 277 void ProcessManager::RegisterRenderFrameHost( | 261 void ProcessManager::RegisterRenderFrameHost( |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 483 if (++count == 1) | 467 if (++count == 1) |
| 484 OnLazyBackgroundPageActive(extension->id()); | 468 OnLazyBackgroundPageActive(extension->id()); |
| 485 } | 469 } |
| 486 } | 470 } |
| 487 | 471 |
| 488 void ProcessManager::DecrementLazyKeepaliveCount(const Extension* extension) { | 472 void ProcessManager::DecrementLazyKeepaliveCount(const Extension* extension) { |
| 489 if (BackgroundInfo::HasLazyBackgroundPage(extension)) | 473 if (BackgroundInfo::HasLazyBackgroundPage(extension)) |
| 490 DecrementLazyKeepaliveCount(extension->id()); | 474 DecrementLazyKeepaliveCount(extension->id()); |
| 491 } | 475 } |
| 492 | 476 |
| 493 // This implementation layers on top of the keepalive count. An impulse sets | |
| 494 // a per extension flag. On a regular interval that flag is checked. Changes | |
| 495 // from the flag not being set to set cause an IncrementLazyKeepaliveCount. | |
| 496 void ProcessManager::KeepaliveImpulse(const Extension* extension) { | |
| 497 if (!BackgroundInfo::HasLazyBackgroundPage(extension)) | |
| 498 return; | |
| 499 | |
| 500 BackgroundPageData& bd = background_page_data_[extension->id()]; | |
| 501 | |
| 502 if (!bd.keepalive_impulse) { | |
| 503 bd.keepalive_impulse = true; | |
| 504 if (!bd.previous_keepalive_impulse) { | |
| 505 IncrementLazyKeepaliveCount(extension); | |
| 506 } | |
| 507 } | |
| 508 | |
| 509 if (!keepalive_impulse_callback_for_testing_.is_null()) { | |
| 510 ImpulseCallbackForTesting callback_may_clear_callbacks_reentrantly = | |
| 511 keepalive_impulse_callback_for_testing_; | |
| 512 callback_may_clear_callbacks_reentrantly.Run(extension->id()); | |
| 513 } | |
| 514 } | |
| 515 | |
| 516 // static | |
| 517 void ProcessManager::OnKeepaliveFromPlugin(int render_process_id, | |
| 518 int render_frame_id, | |
| 519 const std::string& extension_id) { | |
| 520 content::RenderFrameHost* render_frame_host = | |
| 521 content::RenderFrameHost::FromID(render_process_id, render_frame_id); | |
| 522 if (!render_frame_host) | |
| 523 return; | |
| 524 | |
| 525 content::SiteInstance* site_instance = render_frame_host->GetSiteInstance(); | |
| 526 if (!site_instance) | |
| 527 return; | |
| 528 | |
| 529 BrowserContext* browser_context = site_instance->GetBrowserContext(); | |
| 530 const Extension* extension = | |
| 531 ExtensionRegistry::Get(browser_context)->enabled_extensions().GetByID( | |
| 532 extension_id); | |
| 533 if (!extension) | |
| 534 return; | |
| 535 | |
| 536 ProcessManager::Get(browser_context)->KeepaliveImpulse(extension); | |
| 537 } | |
| 538 | |
| 539 void ProcessManager::OnShouldSuspendAck(const std::string& extension_id, | 477 void ProcessManager::OnShouldSuspendAck(const std::string& extension_id, |
| 540 uint64_t sequence_id) { | 478 uint64_t sequence_id) { |
| 541 ExtensionHost* host = GetBackgroundHostForExtension(extension_id); | 479 ExtensionHost* host = GetBackgroundHostForExtension(extension_id); |
| 542 if (host && | 480 if (host && |
| 543 sequence_id == background_page_data_[extension_id].close_sequence_id) { | 481 sequence_id == background_page_data_[extension_id].close_sequence_id) { |
| 544 host->render_process_host()->Send(new ExtensionMsg_Suspend(extension_id)); | 482 host->render_process_host()->Send(new ExtensionMsg_Suspend(extension_id)); |
| 545 } | 483 } |
| 546 } | 484 } |
| 547 | 485 |
| 548 void ProcessManager::OnSuspendAck(const std::string& extension_id) { | 486 void ProcessManager::OnSuspendAck(const std::string& extension_id) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 618 // which will cause the removal of the host from the |background_hosts_| set | 556 // which will cause the removal of the host from the |background_hosts_| set |
| 619 // in the Observe() method below. | 557 // in the Observe() method below. |
| 620 delete host; | 558 delete host; |
| 621 DCHECK_EQ(0u, background_hosts_.count(host)); | 559 DCHECK_EQ(0u, background_hosts_.count(host)); |
| 622 } | 560 } |
| 623 | 561 |
| 624 // At this point there should be nothing left in |background_hosts_|. | 562 // At this point there should be nothing left in |background_hosts_|. |
| 625 DCHECK(background_hosts_.empty()); | 563 DCHECK(background_hosts_.empty()); |
| 626 } | 564 } |
| 627 | 565 |
| 628 void ProcessManager::SetKeepaliveImpulseCallbackForTesting( | |
| 629 const ImpulseCallbackForTesting& callback) { | |
| 630 keepalive_impulse_callback_for_testing_ = callback; | |
| 631 } | |
| 632 | |
| 633 void ProcessManager::SetKeepaliveImpulseDecrementCallbackForTesting( | |
| 634 const ImpulseCallbackForTesting& callback) { | |
| 635 keepalive_impulse_decrement_callback_for_testing_ = callback; | |
| 636 } | |
| 637 | |
| 638 // static | 566 // static |
| 639 void ProcessManager::SetEventPageIdleTimeForTesting(unsigned idle_time_msec) { | 567 void ProcessManager::SetEventPageIdleTimeForTesting(unsigned idle_time_msec) { |
| 640 CHECK_GT(idle_time_msec, 0u); // OnKeepaliveImpulseCheck requires non zero. | 568 CHECK_GT(idle_time_msec, 0u); // OnKeepaliveImpulseCheck requires non zero. |
|
Devlin
2017/03/21 01:08:15
OnKeepaliveImpulseCheck() no longer exists
Wez
2017/03/21 23:59:22
Done.
| |
| 641 g_event_page_idle_time_msec = idle_time_msec; | 569 g_event_page_idle_time_msec = idle_time_msec; |
| 642 } | 570 } |
| 643 | 571 |
| 644 // static | 572 // static |
| 645 void ProcessManager::SetEventPageSuspendingTimeForTesting( | 573 void ProcessManager::SetEventPageSuspendingTimeForTesting( |
| 646 unsigned suspending_time_msec) { | 574 unsigned suspending_time_msec) { |
| 647 g_event_page_suspending_time_msec = suspending_time_msec; | 575 g_event_page_suspending_time_msec = suspending_time_msec; |
| 648 } | 576 } |
| 649 | 577 |
| 650 //////////////////////////////////////////////////////////////////////////////// | 578 //////////////////////////////////////////////////////////////////////////////// |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 788 background_page_data_[extension_id].close_sequence_id = | 716 background_page_data_[extension_id].close_sequence_id = |
| 789 ++last_background_close_sequence_id_; | 717 ++last_background_close_sequence_id_; |
| 790 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 718 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 791 FROM_HERE, base::Bind(&ProcessManager::OnLazyBackgroundPageIdle, | 719 FROM_HERE, base::Bind(&ProcessManager::OnLazyBackgroundPageIdle, |
| 792 weak_ptr_factory_.GetWeakPtr(), extension_id, | 720 weak_ptr_factory_.GetWeakPtr(), extension_id, |
| 793 last_background_close_sequence_id_), | 721 last_background_close_sequence_id_), |
| 794 base::TimeDelta::FromMilliseconds(g_event_page_idle_time_msec)); | 722 base::TimeDelta::FromMilliseconds(g_event_page_idle_time_msec)); |
| 795 } | 723 } |
| 796 } | 724 } |
| 797 | 725 |
| 798 // DecrementLazyKeepaliveCount is called when no calls to KeepaliveImpulse | |
| 799 // have been made for at least g_event_page_idle_time_msec. In the best case an | |
| 800 // impulse was made just before being cleared, and the decrement will occur | |
| 801 // g_event_page_idle_time_msec later, causing a 2 * g_event_page_idle_time_msec | |
| 802 // total time for extension to be shut down based on impulses. Worst case is | |
| 803 // an impulse just after a clear, adding one check cycle and resulting in 3x | |
| 804 // total time. | |
| 805 void ProcessManager::OnKeepaliveImpulseCheck() { | |
| 806 for (BackgroundPageDataMap::iterator i = background_page_data_.begin(); | |
| 807 i != background_page_data_.end(); | |
| 808 ++i) { | |
| 809 if (i->second.previous_keepalive_impulse && !i->second.keepalive_impulse) { | |
| 810 DecrementLazyKeepaliveCount(i->first); | |
| 811 if (!keepalive_impulse_decrement_callback_for_testing_.is_null()) { | |
| 812 ImpulseCallbackForTesting callback_may_clear_callbacks_reentrantly = | |
| 813 keepalive_impulse_decrement_callback_for_testing_; | |
| 814 callback_may_clear_callbacks_reentrantly.Run(i->first); | |
| 815 } | |
| 816 } | |
| 817 | |
| 818 i->second.previous_keepalive_impulse = i->second.keepalive_impulse; | |
| 819 i->second.keepalive_impulse = false; | |
| 820 } | |
| 821 | |
| 822 // OnKeepaliveImpulseCheck() is always called in constructor, but in unit | |
| 823 // tests there will be no thread task runner handle. In that event don't | |
| 824 // schedule tasks. | |
| 825 if (base::ThreadTaskRunnerHandle::IsSet()) { | |
| 826 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 827 FROM_HERE, base::Bind(&ProcessManager::OnKeepaliveImpulseCheck, | |
| 828 weak_ptr_factory_.GetWeakPtr()), | |
| 829 base::TimeDelta::FromMilliseconds(g_event_page_idle_time_msec)); | |
| 830 } | |
| 831 } | |
| 832 | |
| 833 void ProcessManager::OnLazyBackgroundPageIdle(const std::string& extension_id, | 726 void ProcessManager::OnLazyBackgroundPageIdle(const std::string& extension_id, |
| 834 uint64_t sequence_id) { | 727 uint64_t sequence_id) { |
| 835 ExtensionHost* host = GetBackgroundHostForExtension(extension_id); | 728 ExtensionHost* host = GetBackgroundHostForExtension(extension_id); |
| 836 if (host && !background_page_data_[extension_id].is_closing && | 729 if (host && !background_page_data_[extension_id].is_closing && |
| 837 sequence_id == background_page_data_[extension_id].close_sequence_id) { | 730 sequence_id == background_page_data_[extension_id].close_sequence_id) { |
| 838 // Tell the renderer we are about to close. This is a simple ping that the | 731 // Tell the renderer we are about to close. This is a simple ping that the |
| 839 // renderer will respond to. The purpose is to control sequencing: if the | 732 // renderer will respond to. The purpose is to control sequencing: if the |
| 840 // extension remains idle until the renderer responds with an ACK, then we | 733 // extension remains idle until the renderer responds with an ACK, then we |
| 841 // know that the extension process is ready to shut down. If our | 734 // know that the extension process is ready to shut down. If our |
| 842 // close_sequence_id has already changed, then we would ignore the | 735 // close_sequence_id has already changed, then we would ignore the |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 990 if (extension && !IncognitoInfo::IsSplitMode(extension)) { | 883 if (extension && !IncognitoInfo::IsSplitMode(extension)) { |
| 991 BrowserContext* original_context = | 884 BrowserContext* original_context = |
| 992 ExtensionsBrowserClient::Get()->GetOriginalContext(browser_context()); | 885 ExtensionsBrowserClient::Get()->GetOriginalContext(browser_context()); |
| 993 return ProcessManager::Get(original_context)->GetSiteInstanceForURL(url); | 886 return ProcessManager::Get(original_context)->GetSiteInstanceForURL(url); |
| 994 } | 887 } |
| 995 | 888 |
| 996 return ProcessManager::GetSiteInstanceForURL(url); | 889 return ProcessManager::GetSiteInstanceForURL(url); |
| 997 } | 890 } |
| 998 | 891 |
| 999 } // namespace extensions | 892 } // namespace extensions |
| OLD | NEW |