| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |