Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(294)

Side by Side Diff: extensions/browser/process_manager.cc

Issue 60613004: Add KeepaliveImpulse to extension process manager. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: tapted comments addressed Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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.
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 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 return (host && background_page_data_[extension_id].is_closing); 350 return (host && background_page_data_[extension_id].is_closing);
340 } 351 }
341 352
342 int ProcessManager::GetLazyKeepaliveCount(const Extension* extension) { 353 int ProcessManager::GetLazyKeepaliveCount(const Extension* extension) {
343 if (!BackgroundInfo::HasLazyBackgroundPage(extension)) 354 if (!BackgroundInfo::HasLazyBackgroundPage(extension))
344 return 0; 355 return 0;
345 356
346 return background_page_data_[extension->id()].lazy_keepalive_count; 357 return background_page_data_[extension->id()].lazy_keepalive_count;
347 } 358 }
348 359
349 int ProcessManager::IncrementLazyKeepaliveCount(const Extension* extension) { 360 void ProcessManager::IncrementLazyKeepaliveCount(const Extension* extension) {
350 if (!BackgroundInfo::HasLazyBackgroundPage(extension)) 361 if (!BackgroundInfo::HasLazyBackgroundPage(extension))
351 return 0; 362 return;
352 363
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
357 return count;
358 } 367 }
359 368
360 int ProcessManager::DecrementLazyKeepaliveCount(const Extension* extension) { 369 void ProcessManager::DecrementLazyKeepaliveCount(const Extension* extension) {
361 if (!BackgroundInfo::HasLazyBackgroundPage(extension)) 370 if (!BackgroundInfo::HasLazyBackgroundPage(extension))
362 return 0; 371 return;
372 DecrementLazyKeepaliveCount(extension->id());
373 }
363 374
364 int& count = background_page_data_[extension->id()].lazy_keepalive_count; 375 void ProcessManager::DecrementLazyKeepaliveCount(
376 const std::string& extension_id) {
377 int& count = background_page_data_[extension_id].lazy_keepalive_count;
365 DCHECK_GT(count, 0); 378 DCHECK_GT(count, 0);
366 379
367 // If we reach a zero keepalive count when the lazy background page is about 380 // 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 381 // to be closed, incrementing close_sequence_id will cancel the close
369 // sequence and cause the background page to linger. So check is_closing 382 // sequence and cause the background page to linger. So check is_closing
370 // before initiating another close sequence. 383 // before initiating another close sequence.
371 if (--count == 0 && !background_page_data_[extension->id()].is_closing) { 384 if (--count == 0 && !background_page_data_[extension_id].is_closing) {
372 base::MessageLoop::current()->PostDelayedTask( 385 base::MessageLoop::current()->PostDelayedTask(
373 FROM_HERE, 386 FROM_HERE,
374 base::Bind(&ProcessManager::OnLazyBackgroundPageIdle, 387 base::Bind(&ProcessManager::OnLazyBackgroundPageIdle,
375 weak_ptr_factory_.GetWeakPtr(), extension->id(), 388 weak_ptr_factory_.GetWeakPtr(), extension_id,
376 ++background_page_data_[extension->id()].close_sequence_id), 389 ++background_page_data_[extension_id].close_sequence_id),
377 event_page_idle_time_); 390 event_page_idle_time_);
378 } 391 }
379
380 return count;
381 } 392 }
382 393
383 void ProcessManager::IncrementLazyKeepaliveCountForView( 394 void ProcessManager::IncrementLazyKeepaliveCountForView(
384 RenderViewHost* render_view_host) { 395 RenderViewHost* render_view_host) {
385 WebContents* web_contents = 396 WebContents* web_contents =
386 WebContents::FromRenderViewHost(render_view_host); 397 WebContents::FromRenderViewHost(render_view_host);
387 ViewType view_type = GetViewType(web_contents); 398 ViewType view_type = GetViewType(web_contents);
388 if (view_type != VIEW_TYPE_INVALID && 399 if (view_type != VIEW_TYPE_INVALID &&
389 view_type != VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { 400 view_type != VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
390 const Extension* extension = GetExtensionForRenderViewHost( 401 const Extension* extension = GetExtensionForRenderViewHost(
391 render_view_host); 402 render_view_host);
392 if (extension) 403 if (extension)
393 IncrementLazyKeepaliveCount(extension); 404 IncrementLazyKeepaliveCount(extension);
394 } 405 }
395 } 406 }
396 407
408 // This implementation layers on top of the keepalive count. An impulse sets
409 // a per extension flag. On a regular interval that flag is checked. Changes
410 // from the flag not being set to set cause an IncrementLazyKeepaliveCount.
411 void ProcessManager::KeepaliveImpulse(const Extension* extension) {
412 if (!BackgroundInfo::HasLazyBackgroundPage(extension))
413 return;
414
415 BackgroundPageData& bd = background_page_data_[extension->id()];
416
417 if (!bd.keepalive_impulse) {
418 bd.keepalive_impulse = true;
419 if (!bd.previous_keepalive_impulse) {
420 IncrementLazyKeepaliveCount(extension);
421 }
422 }
423 }
424
425 // DecrementLazyKeepaliveCount is called when no calls to KeepaliveImpulse
426 // have been made for at least event_page_idle_time_. In the best case an
427 // impulse was made just before being cleared, and the decrement will occur
428 // event_page_idle_time_ later, causing a 2 * event_page_idle_time_ total time
429 // for extension to be shut down based on impulses. Worst case is an impulse
430 // just after a clear, adding one check cycle and resulting in 3x total time.
431 void ProcessManager::OnKeepaliveImpulseCheck() {
432 for (BackgroundPageDataMap::iterator i = background_page_data_.begin();
433 i != background_page_data_.end();
434 ++i) {
435 if (i->second.previous_keepalive_impulse && !i->second.keepalive_impulse)
436 DecrementLazyKeepaliveCount(i->first);
437
438 i->second.previous_keepalive_impulse = i->second.keepalive_impulse;
439 i->second.keepalive_impulse = false;
440 }
441
442 // OnKeepaliveImpulseCheck() is always called in constructor, but in unit
443 // tests there will be no message loop. In that event don't schedule tasks.
444 if (base::MessageLoop::current()) {
445 base::MessageLoop::current()->PostDelayedTask(
446 FROM_HERE,
447 base::Bind(&ProcessManager::OnKeepaliveImpulseCheck,
448 weak_ptr_factory_.GetWeakPtr()),
449 event_page_idle_time_);
450 }
451 }
452
397 void ProcessManager::OnLazyBackgroundPageIdle(const std::string& extension_id, 453 void ProcessManager::OnLazyBackgroundPageIdle(const std::string& extension_id,
398 int sequence_id) { 454 int sequence_id) {
399 ExtensionHost* host = GetBackgroundHostForExtension(extension_id); 455 ExtensionHost* host = GetBackgroundHostForExtension(extension_id);
400 if (host && !background_page_data_[extension_id].is_closing && 456 if (host && !background_page_data_[extension_id].is_closing &&
401 sequence_id == background_page_data_[extension_id].close_sequence_id) { 457 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 458 // 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 459 // 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 460 // 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 461 // know that the extension process is ready to shut down. If our
406 // close_sequence_id has already changed, then we would ignore the 462 // close_sequence_id has already changed, then we would ignore the
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
806 } 862 }
807 863
808 bool IncognitoProcessManager::IsIncognitoEnabled(const Extension* extension) { 864 bool IncognitoProcessManager::IsIncognitoEnabled(const Extension* extension) {
809 // Keep in sync with duplicate in extension_info_map.cc. 865 // Keep in sync with duplicate in extension_info_map.cc.
810 ExtensionService* service = ExtensionSystem::GetForBrowserContext( 866 ExtensionService* service = ExtensionSystem::GetForBrowserContext(
811 GetBrowserContext())->extension_service(); 867 GetBrowserContext())->extension_service();
812 return extension_util::IsIncognitoEnabled(extension->id(), service); 868 return extension_util::IsIncognitoEnabled(extension->id(), service);
813 } 869 }
814 870
815 } // namespace extensions 871 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698