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

Side by Side Diff: chrome/browser/extensions/extension_process_manager.cc

Issue 9562017: Keep lazy background page alive while there are pending network requests or (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 9 months 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "base/bind.h" 5 #include "base/bind.h"
6 #include "base/command_line.h" 6 #include "base/command_line.h"
7 #include "chrome/browser/extensions/extension_process_manager.h" 7 #include "chrome/browser/extensions/extension_process_manager.h"
8 8
9 #include "chrome/browser/extensions/extension_event_router.h" 9 #include "chrome/browser/extensions/extension_event_router.h"
10 #include "chrome/browser/ui/browser_window.h" 10 #include "chrome/browser/ui/browser_window.h"
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY, 116 registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY,
117 content::Source<Profile>(original_profile)); 117 content::Source<Profile>(original_profile));
118 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 118 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
119 content::Source<Profile>(original_profile)); 119 content::Source<Profile>(original_profile));
120 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 120 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
121 content::Source<Profile>(original_profile)); 121 content::Source<Profile>(original_profile));
122 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, 122 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
123 content::Source<Profile>(profile)); 123 content::Source<Profile>(profile));
124 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, 124 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE,
125 content::Source<Profile>(profile)); 125 content::Source<Profile>(profile));
126 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
127 content::NotificationService::AllSources());
126 registrar_.Add(this, content::NOTIFICATION_APP_TERMINATING, 128 registrar_.Add(this, content::NOTIFICATION_APP_TERMINATING,
127 content::NotificationService::AllSources()); 129 content::NotificationService::AllSources());
128 } 130 }
129 131
130 ExtensionProcessManager::~ExtensionProcessManager() { 132 ExtensionProcessManager::~ExtensionProcessManager() {
131 CloseBackgroundHosts(); 133 CloseBackgroundHosts();
132 DCHECK(background_hosts_.empty()); 134 DCHECK(background_hosts_.empty());
133 } 135 }
134 136
135 ExtensionHost* ExtensionProcessManager::CreateShellHost( 137 ExtensionHost* ExtensionProcessManager::CreateShellHost(
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 258
257 ExtensionHost* ExtensionProcessManager::GetBackgroundHostForExtension( 259 ExtensionHost* ExtensionProcessManager::GetBackgroundHostForExtension(
258 const std::string& extension_id) { 260 const std::string& extension_id) {
259 for (ExtensionHostSet::iterator iter = background_hosts_.begin(); 261 for (ExtensionHostSet::iterator iter = background_hosts_.begin();
260 iter != background_hosts_.end(); ++iter) { 262 iter != background_hosts_.end(); ++iter) {
261 ExtensionHost* host = *iter; 263 ExtensionHost* host = *iter;
262 if (host->extension_id() == extension_id) 264 if (host->extension_id() == extension_id)
263 return host; 265 return host;
264 } 266 }
265 return NULL; 267 return NULL;
266
267 } 268 }
268 269
269 std::set<RenderViewHost*> 270 std::set<RenderViewHost*>
270 ExtensionProcessManager::GetRenderViewHostsForExtension( 271 ExtensionProcessManager::GetRenderViewHostsForExtension(
271 const std::string& extension_id) { 272 const std::string& extension_id) {
272 std::set<RenderViewHost*> result; 273 std::set<RenderViewHost*> result;
273 274
274 SiteInstance* site_instance = GetSiteInstanceForURL( 275 SiteInstance* site_instance = GetSiteInstanceForURL(
275 Extension::GetBaseURLFromExtensionId(extension_id)); 276 Extension::GetBaseURLFromExtensionId(extension_id));
276 if (!site_instance) 277 if (!site_instance)
277 return result; 278 return result;
278 279
279 // Gather up all the views for that site. 280 // Gather up all the views for that site.
280 for (RenderViewHostSet::iterator view = all_extension_views_.begin(); 281 for (ExtensionRenderViews::iterator view = all_extension_views_.begin();
281 view != all_extension_views_.end(); ++view) { 282 view != all_extension_views_.end(); ++view) {
282 if ((*view)->site_instance() == site_instance) 283 if (view->first->site_instance() == site_instance)
283 result.insert(*view); 284 result.insert(view->first);
284 } 285 }
285 286
286 return result; 287 return result;
287 } 288 }
288 289
289 void ExtensionProcessManager::RegisterRenderViewHost( 290 void ExtensionProcessManager::RegisterRenderViewHost(
290 RenderViewHost* render_view_host, 291 RenderViewHost* render_view_host,
291 const Extension* extension) { 292 const Extension* extension) {
292 all_extension_views_.insert(render_view_host); 293 all_extension_views_[render_view_host] = content::VIEW_TYPE_INVALID;
293 } 294 }
294 295
295 void ExtensionProcessManager::UnregisterRenderViewHost( 296 void ExtensionProcessManager::UnregisterRenderViewHost(
296 RenderViewHost* render_view_host) { 297 RenderViewHost* render_view_host) {
297 all_extension_views_.erase(render_view_host); 298 ExtensionRenderViews::iterator view =
299 all_extension_views_.find(render_view_host);
300 if (view == all_extension_views_.end())
301 return;
302
303 content::ViewType view_type = view->second;
304 all_extension_views_.erase(view);
305
306 // Keepalive count, balanced in UpdateRegisteredRenderView.
307 if (view_type != content::VIEW_TYPE_INVALID &&
308 view_type != chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
309 const Extension* extension =
310 GetProfile()->GetExtensionService()->extensions()->GetByID(
311 render_view_host->site_instance()->GetSite().host());
Yoyo Zhou 2012/03/02 03:10:46 Maybe a TODO: it seems like this could be a helper
Matt Perry 2012/03/02 20:25:21 Added a local helper.
312 if (extension)
313 DecrementLazyKeepaliveCount(extension);
314 }
298 } 315 }
299 316
300 SiteInstance* ExtensionProcessManager::GetSiteInstanceForURL( 317 void ExtensionProcessManager::UpdateRegisteredRenderView(
301 const GURL& url) { 318 RenderViewHost* render_view_host) {
319 ExtensionRenderViews::iterator view =
320 all_extension_views_.find(render_view_host);
321 if (view == all_extension_views_.end())
322 return;
323
324 view->second = render_view_host->delegate()->GetRenderViewType();
325
326 // Keep the lazy background page alive as long as any non-background-page
327 // extension views are visible. Keepalive count balanced in
328 // UnregisterRenderViewHost.
329 if (view->second != content::VIEW_TYPE_INVALID &&
330 view->second != chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
331 const Extension* extension =
332 GetProfile()->GetExtensionService()->extensions()->GetByID(
333 render_view_host->site_instance()->GetSite().host());
334 if (extension)
335 IncrementLazyKeepaliveCount(extension);
336 }
337 }
338
339 SiteInstance* ExtensionProcessManager::GetSiteInstanceForURL(const GURL& url) {
302 return site_instance_->GetRelatedSiteInstance(url); 340 return site_instance_->GetRelatedSiteInstance(url);
303 } 341 }
304 342
305 bool ExtensionProcessManager::HasExtensionHost(ExtensionHost* host) const { 343 bool ExtensionProcessManager::HasExtensionHost(ExtensionHost* host) const {
306 return all_hosts_.find(host) != all_hosts_.end(); 344 return all_hosts_.find(host) != all_hosts_.end();
307 } 345 }
308 346
309 int ExtensionProcessManager::GetLazyKeepaliveCount(const Extension* extension) { 347 int ExtensionProcessManager::GetLazyKeepaliveCount(const Extension* extension) {
310 if (extension->background_page_persists()) 348 if (extension->background_page_persists())
311 return 0; 349 return 0;
312 350
313 return ::GetLazyKeepaliveCount(GetProfile(), extension); 351 return ::GetLazyKeepaliveCount(GetProfile(), extension);
314 } 352 }
315 353
316 int ExtensionProcessManager::IncrementLazyKeepaliveCount( 354 int ExtensionProcessManager::IncrementLazyKeepaliveCount(
317 const Extension* extension) { 355 const Extension* extension) {
318 if (extension->background_page_persists()) 356 if (extension->background_page_persists())
319 return 0; 357 return 0;
320 358
321 // TODO(mpcomplete): Handle visible views changing.
322 int& count = ::GetLazyKeepaliveCount(GetProfile(), extension); 359 int& count = ::GetLazyKeepaliveCount(GetProfile(), extension);
323 if (++count == 1) 360 if (++count == 1)
324 OnLazyBackgroundPageActive(extension->id()); 361 OnLazyBackgroundPageActive(extension->id());
325 362
326 return count; 363 return count;
327 } 364 }
328 365
329 int ExtensionProcessManager::DecrementLazyKeepaliveCount( 366 int ExtensionProcessManager::DecrementLazyKeepaliveCount(
330 const Extension* extension) { 367 const Extension* extension) {
331 if (extension->background_page_persists()) 368 if (extension->background_page_persists())
332 return 0; 369 return 0;
333 370
334 int& count = ::GetLazyKeepaliveCount(GetProfile(), extension); 371 int& count = ::GetLazyKeepaliveCount(GetProfile(), extension);
335 DCHECK(count > 0); 372 DCHECK(count > 0);
336 if (--count == 0) 373 if (--count == 0)
337 OnLazyBackgroundPageIdle(extension->id()); 374 OnLazyBackgroundPageIdle(extension->id());
338 375
339 return count; 376 return count;
340 } 377 }
341 378
342 void ExtensionProcessManager::OnLazyBackgroundPageIdle( 379 void ExtensionProcessManager::OnLazyBackgroundPageIdle(
343 const std::string& extension_id) { 380 const std::string& extension_id) {
344 ExtensionHost* host = GetBackgroundHostForExtension(extension_id); 381 ExtensionHost* host = GetBackgroundHostForExtension(extension_id);
345 if (host && !HasVisibleViews(extension_id)) 382 if (host)
346 host->SendShouldClose(); 383 host->SendShouldClose();
347 } 384 }
348 385
349 void ExtensionProcessManager::OnLazyBackgroundPageActive( 386 void ExtensionProcessManager::OnLazyBackgroundPageActive(
350 const std::string& extension_id) { 387 const std::string& extension_id) {
351 ExtensionHost* host = GetBackgroundHostForExtension(extension_id); 388 ExtensionHost* host = GetBackgroundHostForExtension(extension_id);
352 if (host) 389 if (host)
353 host->CancelShouldClose(); 390 host->CancelShouldClose();
354 } 391 }
355 392
356 void ExtensionProcessManager::OnShouldCloseAck( 393 void ExtensionProcessManager::OnShouldCloseAck(
357 const std::string& extension_id, int sequence_id) { 394 const std::string& extension_id, int sequence_id) {
358 ExtensionHost* host = GetBackgroundHostForExtension(extension_id); 395 ExtensionHost* host = GetBackgroundHostForExtension(extension_id);
359 if (host) 396 if (host)
360 host->OnShouldCloseAck(sequence_id); 397 host->OnShouldCloseAck(sequence_id);
361 } 398 }
362 399
363 bool ExtensionProcessManager::HasVisibleViews(const std::string& extension_id) { 400 void ExtensionProcessManager::OnNetworkRequestStarted(
364 const std::set<RenderViewHost*>& views = 401 RenderViewHost* render_view_host) {
365 GetRenderViewHostsForExtension(extension_id); 402 ExtensionHost* host = GetBackgroundHostForExtension(
366 for (std::set<RenderViewHost*>::const_iterator it = views.begin(); 403 render_view_host->site_instance()->GetSite().host());
367 it != views.end(); ++it) { 404 if (host)
368 const RenderViewHost* host = *it; 405 IncrementLazyKeepaliveCount(host->extension());
369 if (host->site_instance()->GetSite().host() == extension_id && 406 }
370 host->delegate()->GetRenderViewType() != 407
371 chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { 408 void ExtensionProcessManager::OnNetworkRequestDone(
372 return true; 409 RenderViewHost* render_view_host) {
373 } 410 ExtensionHost* host = GetBackgroundHostForExtension(
374 } 411 render_view_host->site_instance()->GetSite().host());
375 return false; 412 if (host)
413 DecrementLazyKeepaliveCount(host->extension());
376 } 414 }
377 415
378 void ExtensionProcessManager::Observe( 416 void ExtensionProcessManager::Observe(
379 int type, 417 int type,
380 const content::NotificationSource& source, 418 const content::NotificationSource& source,
381 const content::NotificationDetails& details) { 419 const content::NotificationDetails& details) {
382 switch (type) { 420 switch (type) {
383 case chrome::NOTIFICATION_EXTENSIONS_READY: { 421 case chrome::NOTIFICATION_EXTENSIONS_READY: {
384 CreateBackgroundHostsForProfileStartup(this, 422 CreateBackgroundHostsForProfileStartup(this,
385 content::Source<Profile>(source).ptr()-> 423 content::Source<Profile>(source).ptr()->
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 459
422 case chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE: { 460 case chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE: {
423 ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); 461 ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
424 if (host->extension_host_type() == 462 if (host->extension_host_type() ==
425 chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { 463 chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
426 CloseBackgroundHost(host); 464 CloseBackgroundHost(host);
427 } 465 }
428 break; 466 break;
429 } 467 }
430 468
469 case content::NOTIFICATION_WEB_CONTENTS_CONNECTED: {
Yoyo Zhou 2012/03/02 03:10:46 Naively, it seems like this should be balanced wit
Matt Perry 2012/03/02 20:25:21 No need - UnregisterRenderViewHost cleans up our R
470 content::WebContents* contents =
471 content::Source<content::WebContents>(source).ptr();
472 UpdateRegisteredRenderView(contents->GetRenderViewHost());
473 break;
474 }
475
431 case content::NOTIFICATION_APP_TERMINATING: { 476 case content::NOTIFICATION_APP_TERMINATING: {
432 // Close background hosts when the last browser is closed so that they 477 // Close background hosts when the last browser is closed so that they
433 // have time to shutdown various objects on different threads. Our 478 // have time to shutdown various objects on different threads. Our
434 // destructor is called too late in the shutdown sequence. 479 // destructor is called too late in the shutdown sequence.
435 CloseBackgroundHosts(); 480 CloseBackgroundHosts();
436 break; 481 break;
437 } 482 }
438 483
439 default: 484 default:
440 NOTREACHED(); 485 NOTREACHED();
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 if (service && service->is_ready()) 599 if (service && service->is_ready())
555 CreateBackgroundHostsForProfileStartup(this, service->extensions()); 600 CreateBackgroundHostsForProfileStartup(this, service->extensions());
556 } 601 }
557 break; 602 break;
558 } 603 }
559 default: 604 default:
560 ExtensionProcessManager::Observe(type, source, details); 605 ExtensionProcessManager::Observe(type, source, details);
561 break; 606 break;
562 } 607 }
563 } 608 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698