[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 1 | // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "extensions/browser/process_manager.h" |
| 6 | |
avi | c9cec10 | 2015-12-23 00:39:26 | [diff] [blame] | 7 | #include "base/macros.h" |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 8 | #include "content/public/browser/content_browser_client.h" |
| 9 | #include "content/public/browser/notification_service.h" |
| 10 | #include "content/public/browser/site_instance.h" |
[email protected] | 39ca2051 | 2014-07-24 12:35:52 | [diff] [blame] | 11 | #include "content/public/common/content_client.h" |
[email protected] | 49e7741e | 2014-07-21 01:57:42 | [diff] [blame] | 12 | #include "content/public/test/test_browser_context.h" |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 13 | #include "extensions/browser/extension_registry.h" |
[email protected] | a80de911 | 2014-07-31 03:15:08 | [diff] [blame] | 14 | #include "extensions/browser/extensions_test.h" |
[email protected] | adf5a10 | 2014-07-31 12:44:06 | [diff] [blame] | 15 | #include "extensions/browser/notification_types.h" |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 16 | #include "extensions/browser/process_manager_delegate.h" |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 17 | #include "extensions/browser/test_extensions_browser_client.h" |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 18 | |
| 19 | using content::BrowserContext; |
| 20 | using content::SiteInstance; |
[email protected] | 49e7741e | 2014-07-21 01:57:42 | [diff] [blame] | 21 | using content::TestBrowserContext; |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 22 | |
| 23 | namespace extensions { |
| 24 | |
| 25 | namespace { |
| 26 | |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 27 | // A trivial ProcessManagerDelegate. |
| 28 | class TestProcessManagerDelegate : public ProcessManagerDelegate { |
| 29 | public: |
| 30 | TestProcessManagerDelegate() |
| 31 | : is_background_page_allowed_(true), |
| 32 | defer_creating_startup_background_hosts_(false) {} |
dcheng | 9168b2f | 2014-10-21 12:38:24 | [diff] [blame] | 33 | ~TestProcessManagerDelegate() override {} |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 34 | |
| 35 | // ProcessManagerDelegate implementation. |
achuith | d3da4f0 | 2017-03-23 20:05:29 | [diff] [blame] | 36 | bool AreBackgroundPagesAllowedForContext( |
| 37 | BrowserContext* context) const override { |
| 38 | return is_background_page_allowed_; |
| 39 | } |
| 40 | bool IsExtensionBackgroundPageAllowed( |
| 41 | BrowserContext* context, |
| 42 | const Extension& extension) const override { |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 43 | return is_background_page_allowed_; |
| 44 | } |
dcheng | 9168b2f | 2014-10-21 12:38:24 | [diff] [blame] | 45 | bool DeferCreatingStartupBackgroundHosts( |
mostynb | 0eac4e1b | 2014-10-03 16:32:19 | [diff] [blame] | 46 | BrowserContext* context) const override { |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 47 | return defer_creating_startup_background_hosts_; |
| 48 | } |
| 49 | |
| 50 | bool is_background_page_allowed_; |
| 51 | bool defer_creating_startup_background_hosts_; |
| 52 | }; |
| 53 | |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 54 | } // namespace |
| 55 | |
[email protected] | a80de911 | 2014-07-31 03:15:08 | [diff] [blame] | 56 | class ProcessManagerTest : public ExtensionsTest { |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 57 | public: |
karandeepb | fb19fb9 | 2017-04-12 00:23:20 | [diff] [blame] | 58 | ProcessManagerTest() {} |
| 59 | |
| 60 | ~ProcessManagerTest() override {} |
| 61 | |
| 62 | void SetUp() override { |
| 63 | ExtensionsTest::SetUp(); |
| 64 | extension_registry_ = |
Jeremy Roman | 16529d0e | 2017-08-24 18:13:47 | [diff] [blame] | 65 | std::make_unique<ExtensionRegistry>(browser_context()); |
[email protected] | a80de911 | 2014-07-31 03:15:08 | [diff] [blame] | 66 | extensions_browser_client()->set_process_manager_delegate( |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 67 | &process_manager_delegate_); |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 68 | } |
| 69 | |
[email protected] | a80de911 | 2014-07-31 03:15:08 | [diff] [blame] | 70 | // Use original_context() to make it clear it is a non-incognito context. |
| 71 | BrowserContext* original_context() { return browser_context(); } |
karandeepb | fb19fb9 | 2017-04-12 00:23:20 | [diff] [blame] | 72 | ExtensionRegistry* extension_registry() { return extension_registry_.get(); } |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 73 | TestProcessManagerDelegate* process_manager_delegate() { |
| 74 | return &process_manager_delegate_; |
| 75 | } |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 76 | |
| 77 | // Returns true if the notification |type| is registered for |manager| with |
| 78 | // source |context|. Pass NULL for |context| for all sources. |
| 79 | static bool IsRegistered(ProcessManager* manager, |
| 80 | int type, |
| 81 | BrowserContext* context) { |
| 82 | return manager->registrar_.IsRegistered( |
| 83 | manager, type, content::Source<BrowserContext>(context)); |
| 84 | } |
| 85 | |
[email protected] | 46a19f6 | 2014-07-17 17:21:45 | [diff] [blame] | 86 | private: |
karandeepb | fb19fb9 | 2017-04-12 00:23:20 | [diff] [blame] | 87 | std::unique_ptr<ExtensionRegistry> |
| 88 | extension_registry_; // Shared between BrowserContexts. |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 89 | TestProcessManagerDelegate process_manager_delegate_; |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 90 | |
| 91 | DISALLOW_COPY_AND_ASSIGN(ProcessManagerTest); |
| 92 | }; |
| 93 | |
| 94 | // Test that notification registration works properly. |
| 95 | TEST_F(ProcessManagerTest, ExtensionNotificationRegistration) { |
| 96 | // Test for a normal context ProcessManager. |
dcheng | f5d24108 | 2016-04-21 03:43:11 | [diff] [blame] | 97 | std::unique_ptr<ProcessManager> manager1(ProcessManager::CreateForTesting( |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 98 | original_context(), extension_registry())); |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 99 | |
rdevlin.cronin | 6ae04a01 | 2015-04-03 20:19:40 | [diff] [blame] | 100 | EXPECT_EQ(original_context(), manager1->browser_context()); |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 101 | EXPECT_EQ(0u, manager1->background_hosts().size()); |
| 102 | |
| 103 | // It observes other notifications from this context. |
| 104 | EXPECT_TRUE(IsRegistered(manager1.get(), |
[email protected] | adf5a10 | 2014-07-31 12:44:06 | [diff] [blame] | 105 | extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 106 | original_context())); |
| 107 | |
| 108 | // Test for an incognito context ProcessManager. |
dcheng | f5d24108 | 2016-04-21 03:43:11 | [diff] [blame] | 109 | std::unique_ptr<ProcessManager> manager2( |
| 110 | ProcessManager::CreateIncognitoForTesting( |
| 111 | incognito_context(), original_context(), extension_registry())); |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 112 | |
rdevlin.cronin | 6ae04a01 | 2015-04-03 20:19:40 | [diff] [blame] | 113 | EXPECT_EQ(incognito_context(), manager2->browser_context()); |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 114 | EXPECT_EQ(0u, manager2->background_hosts().size()); |
| 115 | |
Evan Stade | 1ba771c | 2019-12-05 22:55:19 | [diff] [blame] | 116 | // Notifications are observed for the incognito context. |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 117 | EXPECT_TRUE(IsRegistered(manager2.get(), |
[email protected] | adf5a10 | 2014-07-31 12:44:06 | [diff] [blame] | 118 | extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 119 | incognito_context())); |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 120 | } |
| 121 | |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 122 | // Test that startup background hosts are created when the extension system |
| 123 | // becomes ready. |
| 124 | // |
| 125 | // NOTE: This test and those that follow do not try to create ExtensionsHosts |
| 126 | // because ExtensionHost is tightly coupled to WebContents and can't be |
| 127 | // constructed in unit tests. |
| 128 | TEST_F(ProcessManagerTest, CreateBackgroundHostsOnExtensionsReady) { |
dcheng | f5d24108 | 2016-04-21 03:43:11 | [diff] [blame] | 129 | std::unique_ptr<ProcessManager> manager(ProcessManager::CreateForTesting( |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 130 | original_context(), extension_registry())); |
| 131 | ASSERT_FALSE(manager->startup_background_hosts_created_for_test()); |
| 132 | |
| 133 | // Simulate the extension system becoming ready. |
Evan Stade | 1ba771c | 2019-12-05 22:55:19 | [diff] [blame] | 134 | extension_system()->SetReady(); |
| 135 | base::RunLoop().RunUntilIdle(); |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 136 | EXPECT_TRUE(manager->startup_background_hosts_created_for_test()); |
| 137 | } |
| 138 | |
| 139 | // Test that the embedder can defer background host creation. Chrome does this |
| 140 | // when the profile is created asynchronously, which may take a while. |
| 141 | TEST_F(ProcessManagerTest, CreateBackgroundHostsDeferred) { |
dcheng | f5d24108 | 2016-04-21 03:43:11 | [diff] [blame] | 142 | std::unique_ptr<ProcessManager> manager(ProcessManager::CreateForTesting( |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 143 | original_context(), extension_registry())); |
| 144 | ASSERT_FALSE(manager->startup_background_hosts_created_for_test()); |
| 145 | |
| 146 | // Don't create background hosts if the delegate says to defer them. |
| 147 | process_manager_delegate()->defer_creating_startup_background_hosts_ = true; |
| 148 | manager->MaybeCreateStartupBackgroundHosts(); |
| 149 | EXPECT_FALSE(manager->startup_background_hosts_created_for_test()); |
| 150 | |
| 151 | // The extension system becoming ready still doesn't create the hosts. |
Evan Stade | 1ba771c | 2019-12-05 22:55:19 | [diff] [blame] | 152 | extension_system()->SetReady(); |
| 153 | base::RunLoop().RunUntilIdle(); |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 154 | EXPECT_FALSE(manager->startup_background_hosts_created_for_test()); |
| 155 | |
| 156 | // Once the embedder is ready the background hosts can be created. |
| 157 | process_manager_delegate()->defer_creating_startup_background_hosts_ = false; |
| 158 | manager->MaybeCreateStartupBackgroundHosts(); |
| 159 | EXPECT_TRUE(manager->startup_background_hosts_created_for_test()); |
| 160 | } |
| 161 | |
| 162 | // Test that the embedder can disallow background host creation. |
| 163 | // Chrome OS does this in guest mode. |
| 164 | TEST_F(ProcessManagerTest, IsBackgroundHostAllowed) { |
dcheng | f5d24108 | 2016-04-21 03:43:11 | [diff] [blame] | 165 | std::unique_ptr<ProcessManager> manager(ProcessManager::CreateForTesting( |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 166 | original_context(), extension_registry())); |
| 167 | ASSERT_FALSE(manager->startup_background_hosts_created_for_test()); |
| 168 | |
| 169 | // Don't create background hosts if the delegate disallows them. |
| 170 | process_manager_delegate()->is_background_page_allowed_ = false; |
| 171 | manager->MaybeCreateStartupBackgroundHosts(); |
| 172 | EXPECT_FALSE(manager->startup_background_hosts_created_for_test()); |
| 173 | |
| 174 | // The extension system becoming ready still doesn't create the hosts. |
Evan Stade | 1ba771c | 2019-12-05 22:55:19 | [diff] [blame] | 175 | extension_system()->SetReady(); |
| 176 | base::RunLoop().RunUntilIdle(); |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 177 | EXPECT_FALSE(manager->startup_background_hosts_created_for_test()); |
| 178 | } |
| 179 | |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 180 | // Test that extensions get grouped in the right SiteInstance (and therefore |
| 181 | // process) based on their URLs. |
| 182 | TEST_F(ProcessManagerTest, ProcessGrouping) { |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 183 | // Extensions in different browser contexts should always be different |
| 184 | // SiteInstances. |
dcheng | f5d24108 | 2016-04-21 03:43:11 | [diff] [blame] | 185 | std::unique_ptr<ProcessManager> manager1(ProcessManager::CreateForTesting( |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 186 | original_context(), extension_registry())); |
[email protected] | 49e7741e | 2014-07-21 01:57:42 | [diff] [blame] | 187 | // NOTE: This context is not associated with the TestExtensionsBrowserClient. |
| 188 | // That's OK because we're not testing regular vs. incognito behavior. |
| 189 | TestBrowserContext another_context; |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 190 | ExtensionRegistry another_registry(&another_context); |
dcheng | f5d24108 | 2016-04-21 03:43:11 | [diff] [blame] | 191 | std::unique_ptr<ProcessManager> manager2( |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 192 | ProcessManager::CreateForTesting(&another_context, &another_registry)); |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 193 | |
| 194 | // Extensions with common origins ("scheme://id/") should be grouped in the |
| 195 | // same SiteInstance. |
| 196 | GURL ext1_url1("chrome-extension://ext1_id/index.html"); |
| 197 | GURL ext1_url2("chrome-extension://ext1_id/monkey/monkey.html"); |
| 198 | GURL ext2_url1("chrome-extension://ext2_id/index.html"); |
| 199 | |
| 200 | scoped_refptr<SiteInstance> site11 = |
| 201 | manager1->GetSiteInstanceForURL(ext1_url1); |
| 202 | scoped_refptr<SiteInstance> site12 = |
| 203 | manager1->GetSiteInstanceForURL(ext1_url2); |
| 204 | EXPECT_EQ(site11, site12); |
| 205 | |
| 206 | scoped_refptr<SiteInstance> site21 = |
| 207 | manager1->GetSiteInstanceForURL(ext2_url1); |
| 208 | EXPECT_NE(site11, site21); |
| 209 | |
| 210 | scoped_refptr<SiteInstance> other_profile_site = |
| 211 | manager2->GetSiteInstanceForURL(ext1_url1); |
| 212 | EXPECT_NE(site11, other_profile_site); |
Evan Stade | 1ba771c | 2019-12-05 22:55:19 | [diff] [blame] | 213 | |
| 214 | BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices( |
| 215 | &another_context); |
[email protected] | b9f6ba3 | 2014-03-10 18:34:08 | [diff] [blame] | 216 | } |
| 217 | |
| 218 | } // namespace extensions |