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

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: review fixins 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 base::PropertyBag* bag = 46 base::PropertyBag* bag =
47 profile->GetExtensionService()->GetPropertyBag(extension); 47 profile->GetExtensionService()->GetPropertyBag(extension);
48 int* count = g_property_accessor.Get().GetProperty(bag); 48 int* count = g_property_accessor.Get().GetProperty(bag);
49 if (!count) { 49 if (!count) {
50 g_property_accessor.Get().SetProperty(bag, 0); 50 g_property_accessor.Get().SetProperty(bag, 0);
51 count = g_property_accessor.Get().GetProperty(bag); 51 count = g_property_accessor.Get().GetProperty(bag);
52 } 52 }
53 return *count; 53 return *count;
54 } 54 }
55 55
56 std::string GetExtensionID(RenderViewHost* render_view_host) {
57 // This works for both apps and extensions because the site has been
58 // normalized to the extension URL for apps.
59 return render_view_host->site_instance()->GetSite().host();
60 }
61
56 // Incognito profiles use this process manager. It is mostly a shim that decides 62 // Incognito profiles use this process manager. It is mostly a shim that decides
57 // whether to fall back on the original profile's ExtensionProcessManager based 63 // whether to fall back on the original profile's ExtensionProcessManager based
58 // on whether a given extension uses "split" or "spanning" incognito behavior. 64 // on whether a given extension uses "split" or "spanning" incognito behavior.
59 class IncognitoExtensionProcessManager : public ExtensionProcessManager { 65 class IncognitoExtensionProcessManager : public ExtensionProcessManager {
60 public: 66 public:
61 explicit IncognitoExtensionProcessManager(Profile* profile); 67 explicit IncognitoExtensionProcessManager(Profile* profile);
62 virtual ~IncognitoExtensionProcessManager() {} 68 virtual ~IncognitoExtensionProcessManager() {}
63 virtual ExtensionHost* CreateViewHost( 69 virtual ExtensionHost* CreateViewHost(
64 const Extension* extension, 70 const Extension* extension,
65 const GURL& url, 71 const GURL& url,
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY, 122 registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY,
117 content::Source<Profile>(original_profile)); 123 content::Source<Profile>(original_profile));
118 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 124 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
119 content::Source<Profile>(original_profile)); 125 content::Source<Profile>(original_profile));
120 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 126 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
121 content::Source<Profile>(original_profile)); 127 content::Source<Profile>(original_profile));
122 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, 128 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED,
123 content::Source<Profile>(profile)); 129 content::Source<Profile>(profile));
124 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, 130 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE,
125 content::Source<Profile>(profile)); 131 content::Source<Profile>(profile));
132 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
133 content::NotificationService::AllSources());
126 registrar_.Add(this, content::NOTIFICATION_APP_TERMINATING, 134 registrar_.Add(this, content::NOTIFICATION_APP_TERMINATING,
127 content::NotificationService::AllSources()); 135 content::NotificationService::AllSources());
128 } 136 }
129 137
130 ExtensionProcessManager::~ExtensionProcessManager() { 138 ExtensionProcessManager::~ExtensionProcessManager() {
131 CloseBackgroundHosts(); 139 CloseBackgroundHosts();
132 DCHECK(background_hosts_.empty()); 140 DCHECK(background_hosts_.empty());
133 } 141 }
134 142
135 ExtensionHost* ExtensionProcessManager::CreateShellHost( 143 ExtensionHost* ExtensionProcessManager::CreateShellHost(
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 264
257 ExtensionHost* ExtensionProcessManager::GetBackgroundHostForExtension( 265 ExtensionHost* ExtensionProcessManager::GetBackgroundHostForExtension(
258 const std::string& extension_id) { 266 const std::string& extension_id) {
259 for (ExtensionHostSet::iterator iter = background_hosts_.begin(); 267 for (ExtensionHostSet::iterator iter = background_hosts_.begin();
260 iter != background_hosts_.end(); ++iter) { 268 iter != background_hosts_.end(); ++iter) {
261 ExtensionHost* host = *iter; 269 ExtensionHost* host = *iter;
262 if (host->extension_id() == extension_id) 270 if (host->extension_id() == extension_id)
263 return host; 271 return host;
264 } 272 }
265 return NULL; 273 return NULL;
266
267 } 274 }
268 275
269 std::set<RenderViewHost*> 276 std::set<RenderViewHost*>
270 ExtensionProcessManager::GetRenderViewHostsForExtension( 277 ExtensionProcessManager::GetRenderViewHostsForExtension(
271 const std::string& extension_id) { 278 const std::string& extension_id) {
272 std::set<RenderViewHost*> result; 279 std::set<RenderViewHost*> result;
273 280
274 SiteInstance* site_instance = GetSiteInstanceForURL( 281 SiteInstance* site_instance = GetSiteInstanceForURL(
275 Extension::GetBaseURLFromExtensionId(extension_id)); 282 Extension::GetBaseURLFromExtensionId(extension_id));
276 if (!site_instance) 283 if (!site_instance)
277 return result; 284 return result;
278 285
279 // Gather up all the views for that site. 286 // Gather up all the views for that site.
280 for (RenderViewHostSet::iterator view = all_extension_views_.begin(); 287 for (ExtensionRenderViews::iterator view = all_extension_views_.begin();
281 view != all_extension_views_.end(); ++view) { 288 view != all_extension_views_.end(); ++view) {
282 if ((*view)->site_instance() == site_instance) 289 if (view->first->site_instance() == site_instance)
283 result.insert(*view); 290 result.insert(view->first);
284 } 291 }
285 292
286 return result; 293 return result;
287 } 294 }
288 295
289 void ExtensionProcessManager::RegisterRenderViewHost( 296 void ExtensionProcessManager::RegisterRenderViewHost(
290 RenderViewHost* render_view_host, 297 RenderViewHost* render_view_host,
291 const Extension* extension) { 298 const Extension* extension) {
292 all_extension_views_.insert(render_view_host); 299 all_extension_views_[render_view_host] = content::VIEW_TYPE_INVALID;
293 } 300 }
294 301
295 void ExtensionProcessManager::UnregisterRenderViewHost( 302 void ExtensionProcessManager::UnregisterRenderViewHost(
296 RenderViewHost* render_view_host) { 303 RenderViewHost* render_view_host) {
297 all_extension_views_.erase(render_view_host); 304 ExtensionRenderViews::iterator view =
305 all_extension_views_.find(render_view_host);
306 if (view == all_extension_views_.end())
307 return;
308
309 content::ViewType view_type = view->second;
310 all_extension_views_.erase(view);
311
312 // Keepalive count, balanced in UpdateRegisteredRenderView.
313 if (view_type != content::VIEW_TYPE_INVALID &&
314 view_type != chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
315 const Extension* extension =
316 GetProfile()->GetExtensionService()->extensions()->GetByID(
317 GetExtensionID(render_view_host));
318 if (extension)
319 DecrementLazyKeepaliveCount(extension);
320 }
298 } 321 }
299 322
300 SiteInstance* ExtensionProcessManager::GetSiteInstanceForURL( 323 void ExtensionProcessManager::UpdateRegisteredRenderView(
301 const GURL& url) { 324 RenderViewHost* render_view_host) {
325 ExtensionRenderViews::iterator view =
326 all_extension_views_.find(render_view_host);
327 if (view == all_extension_views_.end())
328 return;
329
330 view->second = render_view_host->delegate()->GetRenderViewType();
331
332 // Keep the lazy background page alive as long as any non-background-page
333 // extension views are visible. Keepalive count balanced in
334 // UnregisterRenderViewHost.
335 if (view->second != content::VIEW_TYPE_INVALID &&
336 view->second != chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
337 const Extension* extension =
338 GetProfile()->GetExtensionService()->extensions()->GetByID(
339 GetExtensionID(render_view_host));
340 if (extension)
341 IncrementLazyKeepaliveCount(extension);
342 }
343 }
344
345 SiteInstance* ExtensionProcessManager::GetSiteInstanceForURL(const GURL& url) {
302 return site_instance_->GetRelatedSiteInstance(url); 346 return site_instance_->GetRelatedSiteInstance(url);
303 } 347 }
304 348
305 bool ExtensionProcessManager::HasExtensionHost(ExtensionHost* host) const { 349 bool ExtensionProcessManager::HasExtensionHost(ExtensionHost* host) const {
306 return all_hosts_.find(host) != all_hosts_.end(); 350 return all_hosts_.find(host) != all_hosts_.end();
307 } 351 }
308 352
309 int ExtensionProcessManager::GetLazyKeepaliveCount(const Extension* extension) { 353 int ExtensionProcessManager::GetLazyKeepaliveCount(const Extension* extension) {
310 if (extension->background_page_persists()) 354 if (extension->background_page_persists())
311 return 0; 355 return 0;
312 356
313 return ::GetLazyKeepaliveCount(GetProfile(), extension); 357 return ::GetLazyKeepaliveCount(GetProfile(), extension);
314 } 358 }
315 359
316 int ExtensionProcessManager::IncrementLazyKeepaliveCount( 360 int ExtensionProcessManager::IncrementLazyKeepaliveCount(
317 const Extension* extension) { 361 const Extension* extension) {
318 if (extension->background_page_persists()) 362 if (extension->background_page_persists())
319 return 0; 363 return 0;
320 364
321 // TODO(mpcomplete): Handle visible views changing.
322 int& count = ::GetLazyKeepaliveCount(GetProfile(), extension); 365 int& count = ::GetLazyKeepaliveCount(GetProfile(), extension);
323 if (++count == 1) 366 if (++count == 1)
324 OnLazyBackgroundPageActive(extension->id()); 367 OnLazyBackgroundPageActive(extension->id());
325 368
326 return count; 369 return count;
327 } 370 }
328 371
329 int ExtensionProcessManager::DecrementLazyKeepaliveCount( 372 int ExtensionProcessManager::DecrementLazyKeepaliveCount(
330 const Extension* extension) { 373 const Extension* extension) {
331 if (extension->background_page_persists()) 374 if (extension->background_page_persists())
332 return 0; 375 return 0;
333 376
334 int& count = ::GetLazyKeepaliveCount(GetProfile(), extension); 377 int& count = ::GetLazyKeepaliveCount(GetProfile(), extension);
335 DCHECK(count > 0); 378 DCHECK(count > 0);
336 if (--count == 0) 379 if (--count == 0)
337 OnLazyBackgroundPageIdle(extension->id()); 380 OnLazyBackgroundPageIdle(extension->id());
338 381
339 return count; 382 return count;
340 } 383 }
341 384
342 void ExtensionProcessManager::OnLazyBackgroundPageIdle( 385 void ExtensionProcessManager::OnLazyBackgroundPageIdle(
343 const std::string& extension_id) { 386 const std::string& extension_id) {
344 ExtensionHost* host = GetBackgroundHostForExtension(extension_id); 387 ExtensionHost* host = GetBackgroundHostForExtension(extension_id);
345 if (host && !HasVisibleViews(extension_id)) 388 if (host)
346 host->SendShouldClose(); 389 host->SendShouldClose();
347 } 390 }
348 391
349 void ExtensionProcessManager::OnLazyBackgroundPageActive( 392 void ExtensionProcessManager::OnLazyBackgroundPageActive(
350 const std::string& extension_id) { 393 const std::string& extension_id) {
351 ExtensionHost* host = GetBackgroundHostForExtension(extension_id); 394 ExtensionHost* host = GetBackgroundHostForExtension(extension_id);
352 if (host) 395 if (host)
353 host->CancelShouldClose(); 396 host->CancelShouldClose();
354 } 397 }
355 398
356 void ExtensionProcessManager::OnShouldCloseAck( 399 void ExtensionProcessManager::OnShouldCloseAck(
357 const std::string& extension_id, int sequence_id) { 400 const std::string& extension_id, int sequence_id) {
358 ExtensionHost* host = GetBackgroundHostForExtension(extension_id); 401 ExtensionHost* host = GetBackgroundHostForExtension(extension_id);
359 if (host) 402 if (host)
360 host->OnShouldCloseAck(sequence_id); 403 host->OnShouldCloseAck(sequence_id);
361 } 404 }
362 405
363 bool ExtensionProcessManager::HasVisibleViews(const std::string& extension_id) { 406 void ExtensionProcessManager::OnNetworkRequestStarted(
364 const std::set<RenderViewHost*>& views = 407 RenderViewHost* render_view_host) {
365 GetRenderViewHostsForExtension(extension_id); 408 ExtensionHost* host = GetBackgroundHostForExtension(
366 for (std::set<RenderViewHost*>::const_iterator it = views.begin(); 409 GetExtensionID(render_view_host));
367 it != views.end(); ++it) { 410 if (host)
368 const RenderViewHost* host = *it; 411 IncrementLazyKeepaliveCount(host->extension());
369 if (host->site_instance()->GetSite().host() == extension_id && 412 }
370 host->delegate()->GetRenderViewType() != 413
371 chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { 414 void ExtensionProcessManager::OnNetworkRequestDone(
372 return true; 415 RenderViewHost* render_view_host) {
373 } 416 ExtensionHost* host = GetBackgroundHostForExtension(
374 } 417 GetExtensionID(render_view_host));
375 return false; 418 if (host)
419 DecrementLazyKeepaliveCount(host->extension());
376 } 420 }
377 421
378 void ExtensionProcessManager::Observe( 422 void ExtensionProcessManager::Observe(
379 int type, 423 int type,
380 const content::NotificationSource& source, 424 const content::NotificationSource& source,
381 const content::NotificationDetails& details) { 425 const content::NotificationDetails& details) {
382 switch (type) { 426 switch (type) {
383 case chrome::NOTIFICATION_EXTENSIONS_READY: { 427 case chrome::NOTIFICATION_EXTENSIONS_READY: {
384 CreateBackgroundHostsForProfileStartup(this, 428 CreateBackgroundHostsForProfileStartup(this,
385 content::Source<Profile>(source).ptr()-> 429 content::Source<Profile>(source).ptr()->
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 465
422 case chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE: { 466 case chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE: {
423 ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); 467 ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
424 if (host->extension_host_type() == 468 if (host->extension_host_type() ==
425 chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) { 469 chrome::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
426 CloseBackgroundHost(host); 470 CloseBackgroundHost(host);
427 } 471 }
428 break; 472 break;
429 } 473 }
430 474
475 case content::NOTIFICATION_WEB_CONTENTS_CONNECTED: {
476 content::WebContents* contents =
477 content::Source<content::WebContents>(source).ptr();
478 UpdateRegisteredRenderView(contents->GetRenderViewHost());
479 break;
480 }
481
431 case content::NOTIFICATION_APP_TERMINATING: { 482 case content::NOTIFICATION_APP_TERMINATING: {
432 // Close background hosts when the last browser is closed so that they 483 // Close background hosts when the last browser is closed so that they
433 // have time to shutdown various objects on different threads. Our 484 // have time to shutdown various objects on different threads. Our
434 // destructor is called too late in the shutdown sequence. 485 // destructor is called too late in the shutdown sequence.
435 CloseBackgroundHosts(); 486 CloseBackgroundHosts();
436 break; 487 break;
437 } 488 }
438 489
439 default: 490 default:
440 NOTREACHED(); 491 NOTREACHED();
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 if (service && service->is_ready()) 605 if (service && service->is_ready())
555 CreateBackgroundHostsForProfileStartup(this, service->extensions()); 606 CreateBackgroundHostsForProfileStartup(this, service->extensions());
556 } 607 }
557 break; 608 break;
558 } 609 }
559 default: 610 default:
560 ExtensionProcessManager::Observe(type, source, details); 611 ExtensionProcessManager::Observe(type, source, details);
561 break; 612 break;
562 } 613 }
563 } 614 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698