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

Side by Side Diff: extensions/browser/process_manager_unittest.cc

Issue 381283002: Refactor code that defers extension background page loading (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: larger DeferLoadingBackgroundHosts Created 6 years, 5 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 2014 The Chromium Authors. All rights reserved. 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 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 "extensions/browser/process_manager.h" 5 #include "extensions/browser/process_manager.h"
6 6
7 #include "chrome/browser/chrome_notification_types.h" 7 #include "chrome/browser/chrome_notification_types.h"
8 #include "components/keyed_service/content/browser_context_dependency_manager.h"
8 #include "content/public/browser/content_browser_client.h" 9 #include "content/public/browser/content_browser_client.h"
9 #include "content/public/browser/notification_service.h" 10 #include "content/public/browser/notification_service.h"
10 #include "content/public/browser/site_instance.h" 11 #include "content/public/browser/site_instance.h"
11 #include "content/public/test/test_browser_context.h" 12 #include "content/public/test/test_browser_context.h"
13 #include "extensions/browser/extension_system.h"
14 #include "extensions/browser/extension_system_provider.h"
12 #include "extensions/browser/test_extensions_browser_client.h" 15 #include "extensions/browser/test_extensions_browser_client.h"
16 #include "extensions/common/extension_set.h"
17 #include "extensions/common/one_shot_event.h"
13 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
14 19
15 using content::BrowserContext; 20 using content::BrowserContext;
16 using content::SiteInstance; 21 using content::SiteInstance;
17 using content::TestBrowserContext; 22 using content::TestBrowserContext;
18 23
19 namespace extensions { 24 namespace extensions {
20 25
21 namespace { 26 namespace {
22 27
23 // An incognito version of a TestBrowserContext. 28 // An incognito version of a TestBrowserContext.
24 class TestBrowserContextIncognito : public TestBrowserContext { 29 class TestBrowserContextIncognito : public TestBrowserContext {
25 public: 30 public:
26 TestBrowserContextIncognito() {} 31 TestBrowserContextIncognito() {}
27 virtual ~TestBrowserContextIncognito() {} 32 virtual ~TestBrowserContextIncognito() {}
28 33
29 // TestBrowserContext implementation. 34 // TestBrowserContext implementation.
30 virtual bool IsOffTheRecord() const OVERRIDE { return true; } 35 virtual bool IsOffTheRecord() const OVERRIDE { return true; }
31 36
32 private: 37 private:
33 DISALLOW_COPY_AND_ASSIGN(TestBrowserContextIncognito); 38 DISALLOW_COPY_AND_ASSIGN(TestBrowserContextIncognito);
34 }; 39 };
35 40
41 // An ExtensionSystem that only provides a ready signal.
42 class MockExtensionSystem : public ExtensionSystem {
43 public:
44 MockExtensionSystem() {}
45 virtual ~MockExtensionSystem() {}
46
47 // ExtensionSystem overrides:
48 virtual void InitForRegularProfile(bool extensions_enabled) OVERRIDE {}
49 virtual ExtensionService* extension_service() OVERRIDE { return NULL; }
50 virtual RuntimeData* runtime_data() OVERRIDE { return NULL; }
51 virtual ManagementPolicy* management_policy() OVERRIDE { return NULL; }
52 virtual UserScriptMaster* user_script_master() OVERRIDE { return NULL; }
53 virtual ProcessManager* process_manager() OVERRIDE { return NULL; }
54 virtual StateStore* state_store() OVERRIDE { return NULL; }
55 virtual StateStore* rules_store() OVERRIDE { return NULL; }
56 virtual InfoMap* info_map() OVERRIDE { return NULL; }
57 virtual LazyBackgroundTaskQueue* lazy_background_task_queue() OVERRIDE {
58 return NULL;
59 }
60 virtual EventRouter* event_router() OVERRIDE { return NULL; }
61 virtual ExtensionWarningService* warning_service() OVERRIDE { return NULL; }
62 virtual Blacklist* blacklist() OVERRIDE { return NULL; }
63 virtual ErrorConsole* error_console() OVERRIDE { return NULL; }
64 virtual InstallVerifier* install_verifier() OVERRIDE { return NULL; }
65 virtual QuotaService* quota_service() OVERRIDE { return NULL; }
66 virtual const OneShotEvent& ready() const OVERRIDE { return ready_; }
67 virtual ContentVerifier* content_verifier() OVERRIDE { return NULL; }
68 virtual scoped_ptr<ExtensionSet> GetDependentExtensions(
69 const Extension* extension) OVERRIDE {
70 return scoped_ptr<ExtensionSet>();
71 }
72
73 void SetReady() {
74 ready_.Signal();
75 }
76
77 private:
78 OneShotEvent ready_;
79
80 DISALLOW_COPY_AND_ASSIGN(MockExtensionSystem);
81 };
82
83 // An ExtensionSystemProvider for the MockExtensionSystem.
84 class MockExtensionSystemFactory : public ExtensionSystemProvider {
Yoyo Zhou 2014/07/11 01:51:53 Is it possible to use SetTestingFactoryAndUse? You
James Cook 2014/07/11 21:19:29 It turns out I don't need any of this.
85 public:
86 // ExtensionSystemProvider implementation:
87 virtual ExtensionSystem* GetForBrowserContext(
88 content::BrowserContext* context) OVERRIDE {
89 return static_cast<ExtensionSystem*>(
90 GetInstance()->GetServiceForBrowserContext(context, true));
91 }
92
93 static MockExtensionSystemFactory* GetInstance() {
94 return Singleton<MockExtensionSystemFactory>::get();
95 }
96
97 private:
98 friend struct DefaultSingletonTraits<MockExtensionSystemFactory>;
99
100 MockExtensionSystemFactory()
101 : ExtensionSystemProvider(
102 "MockExtensionSystem",
103 BrowserContextDependencyManager::GetInstance()) {}
104
105 virtual ~MockExtensionSystemFactory() {}
106
107 // BrowserContextKeyedServiceFactory implementation:
108 virtual KeyedService* BuildServiceInstanceFor(
109 content::BrowserContext* context) const OVERRIDE {
110 return new MockExtensionSystem;
111 }
112
113 virtual content::BrowserContext* GetBrowserContextToUse(
114 content::BrowserContext* context) const OVERRIDE {
115 // Use a separate instance for incognito.
116 return context;
117 }
118
119 virtual bool ServiceIsCreatedWithBrowserContext() const OVERRIDE {
120 return true;
121 }
122
123 DISALLOW_COPY_AND_ASSIGN(MockExtensionSystemFactory);
124 };
125
36 } // namespace 126 } // namespace
37 127
38 class ProcessManagerTest : public testing::Test { 128 class ProcessManagerTest : public testing::Test {
39 public: 129 public:
40 ProcessManagerTest() : extensions_browser_client_(&original_context_) { 130 ProcessManagerTest() : extensions_browser_client_(&original_context_) {
41 extensions_browser_client_.SetIncognitoContext(&incognito_context_); 131 extensions_browser_client_.SetIncognitoContext(&incognito_context_);
132 extensions_browser_client_.set_extension_system_factory(
133 MockExtensionSystemFactory::GetInstance());
42 ExtensionsBrowserClient::Set(&extensions_browser_client_); 134 ExtensionsBrowserClient::Set(&extensions_browser_client_);
43 } 135 }
44 136
45 virtual ~ProcessManagerTest() { 137 virtual ~ProcessManagerTest() {
46 ExtensionsBrowserClient::Set(NULL); 138 ExtensionsBrowserClient::Set(NULL);
47 } 139 }
48 140
49 BrowserContext* original_context() { return &original_context_; } 141 BrowserContext* original_context() { return &original_context_; }
50 BrowserContext* incognito_context() { return &incognito_context_; } 142 BrowserContext* incognito_context() { return &incognito_context_; }
143 TestExtensionsBrowserClient* extensions_browser_client() {
144 return &extensions_browser_client_;
145 }
146
147 virtual void SetUp() OVERRIDE {
148 BrowserContextDependencyManager::GetInstance()->
149 CreateBrowserContextServicesForTest(&original_context_);
150 BrowserContextDependencyManager::GetInstance()->
151 CreateBrowserContextServicesForTest(&incognito_context_);
152 }
153
154 virtual void TearDown() OVERRIDE {
155 BrowserContextDependencyManager::GetInstance()->
156 DestroyBrowserContextServices(&incognito_context_);
157 BrowserContextDependencyManager::GetInstance()->
158 DestroyBrowserContextServices(&original_context_);
159 }
51 160
52 // Returns true if the notification |type| is registered for |manager| with 161 // Returns true if the notification |type| is registered for |manager| with
53 // source |context|. Pass NULL for |context| for all sources. 162 // source |context|. Pass NULL for |context| for all sources.
54 static bool IsRegistered(ProcessManager* manager, 163 static bool IsRegistered(ProcessManager* manager,
55 int type, 164 int type,
56 BrowserContext* context) { 165 BrowserContext* context) {
57 return manager->registrar_.IsRegistered( 166 return manager->registrar_.IsRegistered(
58 manager, type, content::Source<BrowserContext>(context)); 167 manager, type, content::Source<BrowserContext>(context));
59 } 168 }
60 169
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 EXPECT_FALSE(IsRegistered(manager2.get(), 227 EXPECT_FALSE(IsRegistered(manager2.get(),
119 chrome::NOTIFICATION_EXTENSIONS_READY, 228 chrome::NOTIFICATION_EXTENSIONS_READY,
120 original_context())); 229 original_context()));
121 230
122 // This notification is observed for incognito contexts only. 231 // This notification is observed for incognito contexts only.
123 EXPECT_TRUE(IsRegistered(manager2.get(), 232 EXPECT_TRUE(IsRegistered(manager2.get(),
124 chrome::NOTIFICATION_PROFILE_DESTROYED, 233 chrome::NOTIFICATION_PROFILE_DESTROYED,
125 incognito_context())); 234 incognito_context()));
126 } 235 }
127 236
237 // Test that startup background hosts can be created when the browser context is
238 // created before the extension system is ready (the usual order).
239 //
240 // NOTE: This test does not try to create real ExtensionsHosts because
241 // ExtensionHost is tightly coupled to WebContents and can't be constructed in
242 // unit tests.
243 TEST_F(ProcessManagerTest, StartupBrowserContextFirst) {
244 scoped_ptr<ProcessManager> manager(
245 ProcessManager::Create(original_context()));
246 ASSERT_FALSE(manager->startup_background_hosts_created_for_test());
247
248 // Simulate the BrowserContext load completing.
249 content::NotificationService::current()->Notify(
250 chrome::NOTIFICATION_PROFILE_CREATED,
Yoyo Zhou 2014/07/11 01:51:53 We're trying to avoid this in src/extensions, righ
James Cook 2014/07/11 21:19:29 Yes, this was the initial "test driven development
251 content::Source<BrowserContext>(original_context()),
252 content::NotificationService::NoDetails());
253
254 // Simulate the extension system becoming ready. Background hosts should be
255 // created.
256 content::NotificationService::current()->Notify(
257 chrome::NOTIFICATION_EXTENSIONS_READY,
258 content::Source<BrowserContext>(original_context()),
259 content::NotificationService::NoDetails());
260 EXPECT_TRUE(manager->startup_background_hosts_created_for_test());
261 }
262
263 // Test that startup background hosts can be created if the extension system is
264 // ready before the browser context (due to an abnormally slow async load).
265 TEST_F(ProcessManagerTest, StartupExtensionsReadyFirst) {
266 // Pretend the context is still loading.
267 extensions_browser_client()->set_defer_loading_background_hosts(true);
Yoyo Zhou 2014/07/11 01:51:53 I think this is an issue. If we set_defer_loading_
James Cook 2014/07/11 21:19:29 This should be clearer now. From the extensions mo
268
269 scoped_ptr<ProcessManager> manager(
270 ProcessManager::Create(original_context()));
271 ASSERT_FALSE(manager->startup_background_hosts_created_for_test());
272
273 // Simulate the extension system becoming ready. Should not create hosts
274 // because the BrowserContext isn't valid.
275 content::NotificationService::current()->Notify(
276 chrome::NOTIFICATION_EXTENSIONS_READY,
277 content::Source<BrowserContext>(original_context()),
278 content::NotificationService::NoDetails());
279 EXPECT_FALSE(manager->startup_background_hosts_created_for_test());
280
281 // Simulate the BrowserContext load completing. Now hosts should be created.
282 extensions_browser_client()->set_defer_loading_background_hosts(false);
283 content::NotificationService::current()->Notify(
284 chrome::NOTIFICATION_PROFILE_CREATED,
285 content::Source<BrowserContext>(original_context()),
286 content::NotificationService::NoDetails());
287 EXPECT_TRUE(manager->startup_background_hosts_created_for_test());
288 }
289
290 // Test that an extension embedder can defer extension host creation initially,
291 // then have the hosts created when a browser window opens. (Chrome does this
292 // when it is launched to show the app list)
293 TEST_F(ProcessManagerTest, DeferUntilBrowserWindowReady) {
Yoyo Zhou 2014/07/11 01:51:53 Do you also want a test in the opposite order (bro
James Cook 2014/07/11 21:19:28 More tests added.
294 extensions_browser_client()->set_defer_loading_background_hosts(true);
295
296 scoped_ptr<ProcessManager> manager(
297 ProcessManager::Create(original_context()));
298 ASSERT_FALSE(manager->startup_background_hosts_created_for_test());
299
300 // Extension system ready but not yet browser window.
301 static_cast<MockExtensionSystem*>(ExtensionSystem::Get(original_context()))
302 ->SetReady();
303 content::NotificationService::current()->Notify(
304 chrome::NOTIFICATION_EXTENSIONS_READY,
305 content::Source<BrowserContext>(original_context()),
306 content::NotificationService::NoDetails());
307 EXPECT_FALSE(manager->startup_background_hosts_created_for_test());
308
309 // Browser window opens.
310 extensions_browser_client()->set_defer_loading_background_hosts(false);
311 manager->OnBrowserWindowReady();
312 EXPECT_TRUE(manager->startup_background_hosts_created_for_test());
313 }
314
128 // Test that extensions get grouped in the right SiteInstance (and therefore 315 // Test that extensions get grouped in the right SiteInstance (and therefore
129 // process) based on their URLs. 316 // process) based on their URLs.
130 TEST_F(ProcessManagerTest, ProcessGrouping) { 317 TEST_F(ProcessManagerTest, ProcessGrouping) {
131 content::ContentBrowserClient content_browser_client; 318 content::ContentBrowserClient content_browser_client;
132 content::SetBrowserClientForTesting(&content_browser_client); 319 content::SetBrowserClientForTesting(&content_browser_client);
133 320
134 // Extensions in different browser contexts should always be different 321 // Extensions in different browser contexts should always be different
135 // SiteInstances. 322 // SiteInstances.
136 scoped_ptr<ProcessManager> manager1( 323 scoped_ptr<ProcessManager> manager1(
137 ProcessManager::Create(original_context())); 324 ProcessManager::Create(original_context()));
(...skipping 17 matching lines...) Expand all
155 scoped_refptr<SiteInstance> site21 = 342 scoped_refptr<SiteInstance> site21 =
156 manager1->GetSiteInstanceForURL(ext2_url1); 343 manager1->GetSiteInstanceForURL(ext2_url1);
157 EXPECT_NE(site11, site21); 344 EXPECT_NE(site11, site21);
158 345
159 scoped_refptr<SiteInstance> other_profile_site = 346 scoped_refptr<SiteInstance> other_profile_site =
160 manager2->GetSiteInstanceForURL(ext1_url1); 347 manager2->GetSiteInstanceForURL(ext1_url1);
161 EXPECT_NE(site11, other_profile_site); 348 EXPECT_NE(site11, other_profile_site);
162 } 349 }
163 350
164 } // namespace extensions 351 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698