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 |