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 |