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 "chrome/browser/extensions/extension_process_manager.h" | 5 #include "chrome/browser/extensions/extension_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" |
11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
14 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
15 #include "base/time/time.h" | 15 #include "base/time/time.h" |
16 #include "chrome/browser/chrome_notification_types.h" | 16 #include "chrome/browser/chrome_notification_types.h" |
17 #include "chrome/browser/extensions/api/runtime/runtime_api.h" | 17 #include "chrome/browser/extensions/api/runtime/runtime_api.h" |
18 #include "chrome/browser/extensions/extension_host.h" | 18 #include "chrome/browser/extensions/extension_host.h" |
19 #include "chrome/browser/extensions/extension_info_map.h" | 19 #include "chrome/browser/extensions/extension_info_map.h" |
20 #include "chrome/browser/extensions/extension_service.h" | 20 #include "chrome/browser/extensions/extension_service.h" |
21 #include "chrome/browser/extensions/extension_system.h" | 21 #include "chrome/browser/extensions/extension_system.h" |
22 #include "chrome/browser/extensions/extension_util.h" | 22 #include "chrome/browser/extensions/extension_util.h" |
23 #include "chrome/browser/profiles/profile.h" | |
24 #include "chrome/browser/ui/browser.h" | 23 #include "chrome/browser/ui/browser.h" |
25 #include "chrome/common/extensions/background_info.h" | 24 #include "chrome/common/extensions/background_info.h" |
26 #include "chrome/common/extensions/extension.h" | 25 #include "chrome/common/extensions/extension.h" |
27 #include "chrome/common/extensions/extension_messages.h" | 26 #include "chrome/common/extensions/extension_messages.h" |
28 #include "chrome/common/extensions/incognito_handler.h" | 27 #include "chrome/common/extensions/incognito_handler.h" |
29 #include "chrome/common/extensions/manifest_url_handler.h" | 28 #include "chrome/common/extensions/manifest_url_handler.h" |
30 #include "chrome/common/url_constants.h" | 29 #include "chrome/common/url_constants.h" |
31 #include "content/public/browser/browser_thread.h" | 30 #include "content/public/browser/browser_thread.h" |
32 #include "content/public/browser/devtools_agent_host.h" | 31 #include "content/public/browser/devtools_agent_host.h" |
33 #include "content/public/browser/devtools_manager.h" | 32 #include "content/public/browser/devtools_manager.h" |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 virtual ExtensionHost* CreateViewHost( | 91 virtual ExtensionHost* CreateViewHost( |
93 const Extension* extension, | 92 const Extension* extension, |
94 const GURL& url, | 93 const GURL& url, |
95 Browser* browser, | 94 Browser* browser, |
96 extensions::ViewType view_type) OVERRIDE; | 95 extensions::ViewType view_type) OVERRIDE; |
97 virtual ExtensionHost* CreateBackgroundHost(const Extension* extension, | 96 virtual ExtensionHost* CreateBackgroundHost(const Extension* extension, |
98 const GURL& url) OVERRIDE; | 97 const GURL& url) OVERRIDE; |
99 virtual SiteInstance* GetSiteInstanceForURL(const GURL& url) OVERRIDE; | 98 virtual SiteInstance* GetSiteInstanceForURL(const GURL& url) OVERRIDE; |
100 | 99 |
101 private: | 100 private: |
102 // content::NotificationObserver: | |
103 virtual void Observe(int type, | |
104 const content::NotificationSource& source, | |
105 const content::NotificationDetails& details) OVERRIDE; | |
106 | |
107 // Returns true if the extension is allowed to run in incognito mode. | 101 // Returns true if the extension is allowed to run in incognito mode. |
108 bool IsIncognitoEnabled(const Extension* extension); | 102 bool IsIncognitoEnabled(const Extension* extension); |
109 | 103 |
110 ExtensionProcessManager* original_manager_; | 104 ExtensionProcessManager* original_manager_; |
| 105 |
| 106 DISALLOW_COPY_AND_ASSIGN(IncognitoExtensionProcessManager); |
111 }; | 107 }; |
112 | 108 |
113 static void CreateBackgroundHostForExtensionLoad( | 109 static void CreateBackgroundHostForExtensionLoad( |
114 ExtensionProcessManager* manager, const Extension* extension) { | 110 ExtensionProcessManager* manager, const Extension* extension) { |
115 DVLOG(1) << "CreateBackgroundHostForExtensionLoad"; | 111 DVLOG(1) << "CreateBackgroundHostForExtensionLoad"; |
116 if (BackgroundInfo::HasPersistentBackgroundPage(extension)) | 112 if (BackgroundInfo::HasPersistentBackgroundPage(extension)) |
117 manager->CreateBackgroundHost(extension, | 113 manager->CreateBackgroundHost(extension, |
118 BackgroundInfo::GetBackgroundURL(extension)); | 114 BackgroundInfo::GetBackgroundURL(extension)); |
119 } | 115 } |
120 | 116 |
121 } // namespace | 117 } // namespace |
122 | 118 |
123 class RenderViewHostDestructionObserver | 119 class RenderViewHostDestructionObserver |
124 : public content::WebContentsObserver, | 120 : public content::WebContentsObserver, |
125 public content::WebContentsUserData<RenderViewHostDestructionObserver> { | 121 public content::WebContentsUserData<RenderViewHostDestructionObserver> { |
126 public: | 122 public: |
127 virtual ~RenderViewHostDestructionObserver() {} | 123 virtual ~RenderViewHostDestructionObserver() {} |
128 | 124 |
129 private: | 125 private: |
130 explicit RenderViewHostDestructionObserver(WebContents* web_contents) | 126 explicit RenderViewHostDestructionObserver(WebContents* web_contents) |
131 : WebContentsObserver(web_contents) { | 127 : WebContentsObserver(web_contents) { |
132 Profile* profile = | 128 BrowserContext* context = web_contents->GetBrowserContext(); |
133 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | |
134 process_manager_ = | 129 process_manager_ = |
135 extensions::ExtensionSystem::Get(profile)->process_manager(); | 130 ExtensionSystem::GetForBrowserContext(context)->process_manager(); |
136 } | 131 } |
137 | 132 |
138 friend class content::WebContentsUserData<RenderViewHostDestructionObserver>; | 133 friend class content::WebContentsUserData<RenderViewHostDestructionObserver>; |
139 | 134 |
140 // content::WebContentsObserver overrides. | 135 // content::WebContentsObserver overrides. |
141 virtual void RenderViewDeleted(RenderViewHost* render_view_host) OVERRIDE { | 136 virtual void RenderViewDeleted(RenderViewHost* render_view_host) OVERRIDE { |
142 process_manager_->UnregisterRenderViewHost(render_view_host); | 137 process_manager_->UnregisterRenderViewHost(render_view_host); |
143 } | 138 } |
144 | 139 |
145 ExtensionProcessManager* process_manager_; | 140 ExtensionProcessManager* process_manager_; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 return new IncognitoExtensionProcessManager(context, original_context); | 176 return new IncognitoExtensionProcessManager(context, original_context); |
182 } | 177 } |
183 return new ExtensionProcessManager(context, context); | 178 return new ExtensionProcessManager(context, context); |
184 } | 179 } |
185 | 180 |
186 ExtensionProcessManager::ExtensionProcessManager( | 181 ExtensionProcessManager::ExtensionProcessManager( |
187 BrowserContext* context, | 182 BrowserContext* context, |
188 BrowserContext* original_context) | 183 BrowserContext* original_context) |
189 : site_instance_(SiteInstance::Create(context)), | 184 : site_instance_(SiteInstance::Create(context)), |
190 defer_background_host_creation_(false), | 185 defer_background_host_creation_(false), |
| 186 startup_background_hosts_created_(false), |
191 devtools_callback_(base::Bind( | 187 devtools_callback_(base::Bind( |
192 &ExtensionProcessManager::OnDevToolsStateChanged, | 188 &ExtensionProcessManager::OnDevToolsStateChanged, |
193 base::Unretained(this))), | 189 base::Unretained(this))), |
194 weak_ptr_factory_(this) { | 190 weak_ptr_factory_(this) { |
195 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_WINDOW_READY, | |
196 content::NotificationService::AllSources()); | |
197 registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY, | 191 registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY, |
198 content::Source<BrowserContext>(original_context)); | 192 content::Source<BrowserContext>(original_context)); |
199 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, | 193 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, |
200 content::Source<BrowserContext>(original_context)); | 194 content::Source<BrowserContext>(original_context)); |
201 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | 195 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
202 content::Source<BrowserContext>(original_context)); | 196 content::Source<BrowserContext>(original_context)); |
203 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, | 197 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, |
204 content::Source<BrowserContext>(context)); | 198 content::Source<BrowserContext>(context)); |
205 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, | 199 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, |
206 content::Source<BrowserContext>(context)); | 200 content::Source<BrowserContext>(context)); |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
595 void ExtensionProcessManager::DeferBackgroundHostCreation(bool defer) { | 589 void ExtensionProcessManager::DeferBackgroundHostCreation(bool defer) { |
596 bool previous = defer_background_host_creation_; | 590 bool previous = defer_background_host_creation_; |
597 defer_background_host_creation_ = defer; | 591 defer_background_host_creation_ = defer; |
598 | 592 |
599 // If we were deferred, and we switch to non-deferred, then create the | 593 // If we were deferred, and we switch to non-deferred, then create the |
600 // background hosts. | 594 // background hosts. |
601 if (previous && !defer_background_host_creation_) | 595 if (previous && !defer_background_host_creation_) |
602 CreateBackgroundHostsForProfileStartup(); | 596 CreateBackgroundHostsForProfileStartup(); |
603 } | 597 } |
604 | 598 |
| 599 void ExtensionProcessManager::OnBrowserWindowReady() { |
| 600 ExtensionService* service = ExtensionSystem::GetForBrowserContext( |
| 601 GetBrowserContext())->extension_service(); |
| 602 // On Chrome OS, a login screen is implemented as a browser. |
| 603 // This browser has no extension service. In this case, |
| 604 // service will be NULL. |
| 605 if (!service || !service->is_ready()) |
| 606 return; |
| 607 |
| 608 CreateBackgroundHostsForProfileStartup(); |
| 609 } |
| 610 |
| 611 content::BrowserContext* ExtensionProcessManager::GetBrowserContext() const { |
| 612 return site_instance_->GetBrowserContext(); |
| 613 } |
| 614 |
605 void ExtensionProcessManager::Observe( | 615 void ExtensionProcessManager::Observe( |
606 int type, | 616 int type, |
607 const content::NotificationSource& source, | 617 const content::NotificationSource& source, |
608 const content::NotificationDetails& details) { | 618 const content::NotificationDetails& details) { |
609 switch (type) { | 619 switch (type) { |
610 case chrome::NOTIFICATION_BROWSER_WINDOW_READY: { | |
611 // If a window for this profile, or this profile's incognito profile, | |
612 // has been opened, make sure this profile's background hosts have | |
613 // been loaded. | |
614 Browser* browser = content::Source<Browser>(source).ptr(); | |
615 if (browser->profile() != GetProfile() && | |
616 !(GetProfile()->HasOffTheRecordProfile() && | |
617 browser->profile() == GetProfile()->GetOffTheRecordProfile())) | |
618 break; | |
619 | |
620 ExtensionService* service = ExtensionSystem::GetForBrowserContext( | |
621 GetBrowserContext())->extension_service(); | |
622 if (!service || !service->is_ready()) | |
623 break; | |
624 | |
625 CreateBackgroundHostsForProfileStartup(); | |
626 break; | |
627 } | |
628 case chrome::NOTIFICATION_EXTENSIONS_READY: | 620 case chrome::NOTIFICATION_EXTENSIONS_READY: |
629 case chrome::NOTIFICATION_PROFILE_CREATED: { | 621 case chrome::NOTIFICATION_PROFILE_CREATED: { |
630 CreateBackgroundHostsForProfileStartup(); | 622 CreateBackgroundHostsForProfileStartup(); |
631 break; | 623 break; |
632 } | 624 } |
633 | 625 |
634 case chrome::NOTIFICATION_EXTENSION_LOADED: { | 626 case chrome::NOTIFICATION_EXTENSION_LOADED: { |
635 Profile* profile = content::Source<Profile>(source).ptr(); | 627 BrowserContext* context = content::Source<BrowserContext>(source).ptr(); |
636 ExtensionService* service = | 628 ExtensionService* service = |
637 extensions::ExtensionSystem::Get(profile)->extension_service(); | 629 ExtensionSystem::GetForBrowserContext(context)->extension_service(); |
638 if (service->is_ready()) { | 630 if (service->is_ready()) { |
639 const Extension* extension = | 631 const Extension* extension = |
640 content::Details<const Extension>(details).ptr(); | 632 content::Details<const Extension>(details).ptr(); |
641 CreateBackgroundHostForExtensionLoad(this, extension); | 633 CreateBackgroundHostForExtensionLoad(this, extension); |
642 } | 634 } |
643 break; | 635 break; |
644 } | 636 } |
645 | 637 |
646 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { | 638 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { |
647 const Extension* extension = | 639 const Extension* extension = |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 if (attached) { | 741 if (attached) { |
750 // Keep the lazy background page alive while it's being inspected. | 742 // Keep the lazy background page alive while it's being inspected. |
751 CancelSuspend(extension); | 743 CancelSuspend(extension); |
752 IncrementLazyKeepaliveCount(extension); | 744 IncrementLazyKeepaliveCount(extension); |
753 } else { | 745 } else { |
754 DecrementLazyKeepaliveCount(extension); | 746 DecrementLazyKeepaliveCount(extension); |
755 } | 747 } |
756 } | 748 } |
757 | 749 |
758 void ExtensionProcessManager::CreateBackgroundHostsForProfileStartup() { | 750 void ExtensionProcessManager::CreateBackgroundHostsForProfileStartup() { |
759 DVLOG(1) << "CreateBackgroundHostsForProfileStartup"; | 751 if (startup_background_hosts_created_) |
| 752 return; |
| 753 |
760 // Don't load background hosts now if the loading should be deferred. | 754 // Don't load background hosts now if the loading should be deferred. |
761 // Instead they will be loaded when a browser window for this profile | 755 // Instead they will be loaded when a browser window for this profile |
762 // (or an incognito profile from this profile) is ready, or when | 756 // (or an incognito profile from this profile) is ready, or when |
763 // DeferBackgroundHostCreation is called with false. | 757 // DeferBackgroundHostCreation is called with false. |
764 if (DeferLoadingBackgroundHosts()) | 758 if (DeferLoadingBackgroundHosts()) |
765 return; | 759 return; |
766 | 760 |
767 ExtensionService* service = ExtensionSystem::GetForBrowserContext( | 761 ExtensionService* service = ExtensionSystem::GetForBrowserContext( |
768 GetBrowserContext())->extension_service(); | 762 GetBrowserContext())->extension_service(); |
769 DCHECK(service); | 763 DCHECK(service); |
770 for (ExtensionSet::const_iterator extension = service->extensions()->begin(); | 764 for (ExtensionSet::const_iterator extension = service->extensions()->begin(); |
771 extension != service->extensions()->end(); ++extension) { | 765 extension != service->extensions()->end(); ++extension) { |
772 CreateBackgroundHostForExtensionLoad(this, extension->get()); | 766 CreateBackgroundHostForExtensionLoad(this, extension->get()); |
773 | 767 |
774 extensions::RuntimeEventRouter::DispatchOnStartupEvent( | 768 extensions::RuntimeEventRouter::DispatchOnStartupEvent( |
775 GetBrowserContext(), (*extension)->id()); | 769 GetBrowserContext(), (*extension)->id()); |
776 } | 770 } |
| 771 startup_background_hosts_created_ = true; |
777 | 772 |
778 // Background pages should only be loaded once. To prevent any further loads | 773 // Background pages should only be loaded once. To prevent any further loads |
779 // occurring, we remove the notification listeners. | 774 // occurring, we remove the notification listeners. |
780 BrowserContext* original_context = | 775 BrowserContext* original_context = |
781 ExtensionsBrowserClient::Get()->GetOriginalContext(GetBrowserContext()); | 776 ExtensionsBrowserClient::Get()->GetOriginalContext(GetBrowserContext()); |
782 registrar_.Remove(this, chrome::NOTIFICATION_BROWSER_WINDOW_READY, | |
783 content::NotificationService::AllSources()); | |
784 if (registrar_.IsRegistered( | 777 if (registrar_.IsRegistered( |
785 this, | 778 this, |
786 chrome::NOTIFICATION_PROFILE_CREATED, | 779 chrome::NOTIFICATION_PROFILE_CREATED, |
787 content::Source<BrowserContext>(original_context))) { | 780 content::Source<BrowserContext>(original_context))) { |
788 registrar_.Remove(this, | 781 registrar_.Remove(this, |
789 chrome::NOTIFICATION_PROFILE_CREATED, | 782 chrome::NOTIFICATION_PROFILE_CREATED, |
790 content::Source<BrowserContext>(original_context)); | 783 content::Source<BrowserContext>(original_context)); |
791 } | 784 } |
792 if (registrar_.IsRegistered( | 785 if (registrar_.IsRegistered( |
793 this, | 786 this, |
794 chrome::NOTIFICATION_EXTENSIONS_READY, | 787 chrome::NOTIFICATION_EXTENSIONS_READY, |
795 content::Source<BrowserContext>(original_context))) { | 788 content::Source<BrowserContext>(original_context))) { |
796 registrar_.Remove(this, | 789 registrar_.Remove(this, |
797 chrome::NOTIFICATION_EXTENSIONS_READY, | 790 chrome::NOTIFICATION_EXTENSIONS_READY, |
798 content::Source<BrowserContext>(original_context)); | 791 content::Source<BrowserContext>(original_context)); |
799 } | 792 } |
800 } | 793 } |
801 | 794 |
802 Profile* ExtensionProcessManager::GetProfile() const { | |
803 return Profile::FromBrowserContext(site_instance_->GetBrowserContext()); | |
804 } | |
805 | |
806 content::BrowserContext* ExtensionProcessManager::GetBrowserContext() const { | |
807 return site_instance_->GetBrowserContext(); | |
808 } | |
809 | |
810 void ExtensionProcessManager::OnExtensionHostCreated(ExtensionHost* host, | 795 void ExtensionProcessManager::OnExtensionHostCreated(ExtensionHost* host, |
811 bool is_background) { | 796 bool is_background) { |
812 DCHECK_EQ(site_instance_->GetBrowserContext(), host->browser_context()); | 797 DCHECK_EQ(site_instance_->GetBrowserContext(), host->browser_context()); |
813 if (is_background) { | 798 if (is_background) { |
814 background_hosts_.insert(host); | 799 background_hosts_.insert(host); |
815 | 800 |
816 if (BackgroundInfo::HasLazyBackgroundPage(host->extension())) { | 801 if (BackgroundInfo::HasLazyBackgroundPage(host->extension())) { |
817 linked_ptr<base::ElapsedTimer> since_suspended( | 802 linked_ptr<base::ElapsedTimer> since_suspended( |
818 background_page_data_[host->extension()->id()]. | 803 background_page_data_[host->extension()->id()]. |
819 since_suspended.release()); | 804 since_suspended.release()); |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
965 return ExtensionProcessManager::GetSiteInstanceForURL(url); | 950 return ExtensionProcessManager::GetSiteInstanceForURL(url); |
966 } | 951 } |
967 | 952 |
968 bool IncognitoExtensionProcessManager::IsIncognitoEnabled( | 953 bool IncognitoExtensionProcessManager::IsIncognitoEnabled( |
969 const Extension* extension) { | 954 const Extension* extension) { |
970 // Keep in sync with duplicate in extension_info_map.cc. | 955 // Keep in sync with duplicate in extension_info_map.cc. |
971 ExtensionService* service = ExtensionSystem::GetForBrowserContext( | 956 ExtensionService* service = ExtensionSystem::GetForBrowserContext( |
972 GetBrowserContext())->extension_service(); | 957 GetBrowserContext())->extension_service(); |
973 return extension_util::IsIncognitoEnabled(extension->id(), service); | 958 return extension_util::IsIncognitoEnabled(extension->id(), service); |
974 } | 959 } |
975 | |
976 void IncognitoExtensionProcessManager::Observe( | |
977 int type, | |
978 const content::NotificationSource& source, | |
979 const content::NotificationDetails& details) { | |
980 switch (type) { | |
981 // Do not use ExtensionProcessManager's handler for | |
982 // NOTIFICATION_BROWSER_WINDOW_READY. | |
983 case chrome::NOTIFICATION_BROWSER_WINDOW_READY: { | |
984 // We want to spawn our background hosts as soon as the user opens an | |
985 // incognito window. Watch for new browsers and create the hosts if | |
986 // it matches our profile. | |
987 Browser* browser = content::Source<Browser>(source).ptr(); | |
988 if (browser->profile() == site_instance_->GetBrowserContext()) { | |
989 // On Chrome OS, a login screen is implemented as a browser. | |
990 // This browser has no extension service. In this case, | |
991 // service will be NULL. | |
992 ExtensionService* service = ExtensionSystem::GetForBrowserContext( | |
993 GetBrowserContext())->extension_service(); | |
994 if (service && service->is_ready()) | |
995 CreateBackgroundHostsForProfileStartup(); | |
996 } | |
997 break; | |
998 } | |
999 default: | |
1000 ExtensionProcessManager::Observe(type, source, details); | |
1001 break; | |
1002 } | |
1003 } | |
OLD | NEW |