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 |