Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/lazy_background_task_queue.h" | 5 #include "extensions/browser/lazy_background_task_queue.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/command_line.h" | 8 #include "components/keyed_service/content/browser_context_dependency_manager.h" |
| 9 #include "chrome/browser/extensions/extension_service.h" | 9 #include "content/public/browser/notification_service.h" |
| 10 #include "chrome/browser/extensions/extension_service_test_base.h" | 10 #include "content/public/test/test_browser_context.h" |
| 11 #include "chrome/browser/extensions/test_extension_system.h" | |
| 12 #include "chrome/test/base/testing_profile.h" | |
| 13 #include "content/public/test/test_browser_thread_bundle.h" | |
| 14 #include "extensions/browser/extension_registry.h" | 11 #include "extensions/browser/extension_registry.h" |
| 12 #include "extensions/browser/extension_registry_factory.h" | |
| 13 #include "extensions/browser/extension_system.h" | |
| 14 #include "extensions/browser/extension_system_provider.h" | |
| 15 #include "extensions/browser/extensions_test.h" | |
| 15 #include "extensions/browser/process_manager.h" | 16 #include "extensions/browser/process_manager.h" |
| 17 #include "extensions/browser/test_extensions_browser_client.h" | |
| 16 #include "extensions/common/extension.h" | 18 #include "extensions/common/extension.h" |
| 17 #include "extensions/common/extension_builder.h" | 19 #include "extensions/common/extension_builder.h" |
| 20 #include "extensions/common/one_shot_event.h" | |
| 18 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
| 19 | 22 |
| 23 using content::BrowserContext; | |
| 24 | |
| 20 namespace extensions { | 25 namespace extensions { |
| 26 namespace { | |
| 21 | 27 |
| 22 // A ProcessManager that doesn't create background host pages. | 28 // A ProcessManager that doesn't create background host pages. |
| 23 class TestProcessManager : public ProcessManager { | 29 class TestProcessManager : public ProcessManager { |
| 24 public: | 30 public: |
| 25 explicit TestProcessManager(Profile* profile) | 31 explicit TestProcessManager(BrowserContext* context) |
| 26 : ProcessManager(profile, | 32 : ProcessManager(context, context, ExtensionRegistry::Get(context)), |
| 27 profile->GetOriginalProfile(), | 33 create_count_(0) { |
| 28 ExtensionRegistry::Get(profile)), | 34 // ProcessManager constructor above assumes non-incognito. |
| 29 create_count_(0) {} | 35 DCHECK(!context->IsOffTheRecord()); |
| 36 } | |
| 30 virtual ~TestProcessManager() {} | 37 virtual ~TestProcessManager() {} |
| 31 | 38 |
| 32 int create_count() { return create_count_; } | 39 int create_count() { return create_count_; } |
| 33 | 40 |
| 34 // ProcessManager overrides: | 41 // ProcessManager overrides: |
| 35 virtual bool CreateBackgroundHost(const Extension* extension, | 42 virtual bool CreateBackgroundHost(const Extension* extension, |
| 36 const GURL& url) OVERRIDE { | 43 const GURL& url) OVERRIDE { |
| 37 // Don't actually try to create a web contents. | 44 // Don't actually try to create a web contents. |
| 38 create_count_++; | 45 create_count_++; |
| 39 return false; | 46 return false; |
| 40 } | 47 } |
| 41 | 48 |
| 42 private: | 49 private: |
| 43 int create_count_; | 50 int create_count_; |
| 44 | 51 |
| 45 DISALLOW_COPY_AND_ASSIGN(TestProcessManager); | 52 DISALLOW_COPY_AND_ASSIGN(TestProcessManager); |
| 46 }; | 53 }; |
| 47 | 54 |
| 48 // Derives from ExtensionServiceTestBase because ExtensionService is difficult | 55 // A simple ExtensionSystem that returns a TestProcessManager. |
| 49 // to initialize alone. | 56 class MockExtensionSystem : public ExtensionSystem { |
|
Yoyo Zhou
2014/08/01 22:13:09
Thanks for looking at this test - I had gotten a l
| |
| 50 class LazyBackgroundTaskQueueTest | |
| 51 : public extensions::ExtensionServiceTestBase { | |
| 52 public: | 57 public: |
| 53 LazyBackgroundTaskQueueTest() : task_run_count_(0) {} | 58 explicit MockExtensionSystem(BrowserContext* context) |
| 59 : test_process_manager_(context) {} | |
| 60 virtual ~MockExtensionSystem() {} | |
| 61 | |
| 62 virtual void InitForRegularProfile(bool extensions_enabled) OVERRIDE {} | |
| 63 virtual ExtensionService* extension_service() OVERRIDE { return NULL; } | |
| 64 virtual RuntimeData* runtime_data() OVERRIDE { return NULL; } | |
| 65 virtual ManagementPolicy* management_policy() OVERRIDE { return NULL; } | |
| 66 virtual UserScriptMaster* user_script_master() OVERRIDE { return NULL; } | |
| 67 virtual ProcessManager* process_manager() OVERRIDE { | |
| 68 return &test_process_manager_; | |
| 69 } | |
| 70 virtual StateStore* state_store() OVERRIDE { return NULL; } | |
| 71 virtual StateStore* rules_store() OVERRIDE { return NULL; } | |
| 72 virtual InfoMap* info_map() OVERRIDE { return NULL; } | |
| 73 virtual LazyBackgroundTaskQueue* lazy_background_task_queue() OVERRIDE { | |
| 74 return NULL; | |
| 75 } | |
| 76 virtual EventRouter* event_router() OVERRIDE { return NULL; } | |
| 77 virtual ExtensionWarningService* warning_service() OVERRIDE { return NULL; } | |
| 78 virtual Blacklist* blacklist() OVERRIDE { return NULL; } | |
| 79 virtual ErrorConsole* error_console() OVERRIDE { return NULL; } | |
| 80 virtual InstallVerifier* install_verifier() OVERRIDE { return NULL; } | |
| 81 virtual QuotaService* quota_service() OVERRIDE { return NULL; } | |
| 82 virtual const OneShotEvent& ready() const OVERRIDE { return ready_; } | |
| 83 virtual ContentVerifier* content_verifier() OVERRIDE { return NULL; } | |
| 84 virtual scoped_ptr<ExtensionSet> GetDependentExtensions( | |
| 85 const Extension* extension) OVERRIDE { | |
| 86 return scoped_ptr<ExtensionSet>(); | |
| 87 } | |
| 88 | |
| 89 private: | |
| 90 TestProcessManager test_process_manager_; | |
| 91 OneShotEvent ready_; | |
| 92 }; | |
| 93 | |
| 94 // A factory to create a MockExtensionSystem. | |
| 95 class MockExtensionSystemFactory : public ExtensionSystemProvider { | |
| 96 public: | |
| 97 MockExtensionSystemFactory() | |
| 98 : ExtensionSystemProvider( | |
| 99 "MockExtensionSystem", | |
| 100 BrowserContextDependencyManager::GetInstance()) { | |
| 101 DependsOn(ExtensionRegistryFactory::GetInstance()); | |
| 102 } | |
| 103 virtual ~MockExtensionSystemFactory() {} | |
| 104 | |
| 105 static MockExtensionSystemFactory* GetInstance() { | |
| 106 return Singleton<MockExtensionSystemFactory>::get(); | |
| 107 } | |
| 108 | |
| 109 // BrowserContextKeyedServiceFactory overrides: | |
| 110 virtual KeyedService* BuildServiceInstanceFor( | |
| 111 BrowserContext* context) const OVERRIDE { | |
| 112 return new MockExtensionSystem(context); | |
| 113 } | |
| 114 | |
| 115 // ExtensionSystemProvider overrides: | |
| 116 virtual ExtensionSystem* GetForBrowserContext( | |
| 117 BrowserContext* context) OVERRIDE { | |
| 118 return static_cast<MockExtensionSystem*>( | |
| 119 GetInstance()->GetServiceForBrowserContext(context, true)); | |
| 120 } | |
| 121 | |
| 122 private: | |
| 123 friend struct DefaultSingletonTraits<MockExtensionSystemFactory>; | |
|
Yoyo Zhou
2014/08/01 22:13:09
nit: it's more or less equivalent but I prefer Laz
James Cook
2014/08/01 22:48:03
On closer inspection it doesn't need to be a singl
| |
| 124 | |
| 125 DISALLOW_COPY_AND_ASSIGN(MockExtensionSystemFactory); | |
| 126 }; | |
| 127 | |
| 128 } // namespace | |
| 129 | |
| 130 // Derives from ExtensionsTest to provide content module and keyed service | |
| 131 // initialization. | |
| 132 class LazyBackgroundTaskQueueTest : public ExtensionsTest { | |
| 133 public: | |
| 134 LazyBackgroundTaskQueueTest() | |
| 135 : notification_service_(content::NotificationService::Create()), | |
| 136 task_run_count_(0) { | |
| 137 extensions_browser_client()->set_extension_system_factory( | |
| 138 &extension_system_factory_); | |
| 139 } | |
| 54 virtual ~LazyBackgroundTaskQueueTest() {} | 140 virtual ~LazyBackgroundTaskQueueTest() {} |
| 55 | 141 |
| 56 int task_run_count() { return task_run_count_; } | 142 int task_run_count() { return task_run_count_; } |
| 57 | 143 |
| 58 // A simple callback for AddPendingTask. | 144 // A simple callback for AddPendingTask. |
| 59 void RunPendingTask(ExtensionHost* host) { | 145 void RunPendingTask(ExtensionHost* host) { |
| 60 task_run_count_++; | 146 task_run_count_++; |
| 61 } | 147 } |
| 62 | 148 |
| 63 // Creates and registers an extension without a background page. | 149 // Creates and registers an extension without a background page. |
| 64 scoped_refptr<Extension> CreateSimpleExtension() { | 150 scoped_refptr<Extension> CreateSimpleExtension() { |
| 65 scoped_refptr<Extension> extension = ExtensionBuilder() | 151 scoped_refptr<Extension> extension = ExtensionBuilder() |
| 66 .SetManifest(DictionaryBuilder() | 152 .SetManifest(DictionaryBuilder() |
| 67 .Set("name", "No background") | 153 .Set("name", "No background") |
| 68 .Set("version", "1") | 154 .Set("version", "1") |
| 69 .Set("manifest_version", 2)) | 155 .Set("manifest_version", 2)) |
| 70 .SetID("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") | 156 .SetID("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") |
| 71 .Build(); | 157 .Build(); |
| 72 service_->AddExtension(extension); | 158 ExtensionRegistry::Get(browser_context())->AddEnabled(extension); |
| 73 return extension; | 159 return extension; |
| 74 } | 160 } |
| 75 | 161 |
| 76 // Creates and registers an extension with a lazy background page. | 162 // Creates and registers an extension with a lazy background page. |
| 77 scoped_refptr<Extension> CreateLazyBackgroundExtension() { | 163 scoped_refptr<Extension> CreateLazyBackgroundExtension() { |
| 78 scoped_refptr<Extension> extension = ExtensionBuilder() | 164 scoped_refptr<Extension> extension = ExtensionBuilder() |
| 79 .SetManifest(DictionaryBuilder() | 165 .SetManifest(DictionaryBuilder() |
| 80 .Set("name", "Lazy background") | 166 .Set("name", "Lazy background") |
| 81 .Set("version", "1") | 167 .Set("version", "1") |
| 82 .Set("manifest_version", 2) | 168 .Set("manifest_version", 2) |
| 83 .Set("background", | 169 .Set("background", |
| 84 DictionaryBuilder() | 170 DictionaryBuilder() |
| 85 .Set("page", "background.html") | 171 .Set("page", "background.html") |
| 86 .SetBoolean("persistent", false))) | 172 .SetBoolean("persistent", false))) |
| 87 .SetID("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb") | 173 .SetID("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb") |
| 88 .Build(); | 174 .Build(); |
| 89 service_->AddExtension(extension); | 175 ExtensionRegistry::Get(browser_context())->AddEnabled(extension); |
| 90 return extension; | 176 return extension; |
| 91 } | 177 } |
| 92 | 178 |
| 93 private: | 179 private: |
| 180 scoped_ptr<content::NotificationService> notification_service_; | |
| 181 MockExtensionSystemFactory extension_system_factory_; | |
| 182 | |
| 94 // The total number of pending tasks that have been executed. | 183 // The total number of pending tasks that have been executed. |
| 95 int task_run_count_; | 184 int task_run_count_; |
| 96 | 185 |
| 97 DISALLOW_COPY_AND_ASSIGN(LazyBackgroundTaskQueueTest); | 186 DISALLOW_COPY_AND_ASSIGN(LazyBackgroundTaskQueueTest); |
| 98 }; | 187 }; |
| 99 | 188 |
| 100 // Tests that only extensions with background pages should have tasks queued. | 189 // Tests that only extensions with background pages should have tasks queued. |
| 101 TEST_F(LazyBackgroundTaskQueueTest, ShouldEnqueueTask) { | 190 TEST_F(LazyBackgroundTaskQueueTest, ShouldEnqueueTask) { |
| 102 InitializeEmptyExtensionService(); | 191 LazyBackgroundTaskQueue queue(browser_context()); |
| 103 InitializeProcessManager(); | |
| 104 | |
| 105 LazyBackgroundTaskQueue queue(profile_.get()); | |
| 106 | 192 |
| 107 // Build a simple extension with no background page. | 193 // Build a simple extension with no background page. |
| 108 scoped_refptr<Extension> no_background = CreateSimpleExtension(); | 194 scoped_refptr<Extension> no_background = CreateSimpleExtension(); |
| 109 EXPECT_FALSE(queue.ShouldEnqueueTask(profile_.get(), no_background.get())); | 195 EXPECT_FALSE(queue.ShouldEnqueueTask(browser_context(), no_background.get())); |
| 110 | 196 |
| 111 // Build another extension with a background page. | 197 // Build another extension with a background page. |
| 112 scoped_refptr<Extension> with_background = CreateLazyBackgroundExtension(); | 198 scoped_refptr<Extension> with_background = CreateLazyBackgroundExtension(); |
| 113 EXPECT_TRUE(queue.ShouldEnqueueTask(profile_.get(), with_background.get())); | 199 EXPECT_TRUE( |
| 200 queue.ShouldEnqueueTask(browser_context(), with_background.get())); | |
| 114 } | 201 } |
| 115 | 202 |
| 116 // Tests that adding tasks actually increases the pending task count, and that | 203 // Tests that adding tasks actually increases the pending task count, and that |
| 117 // multiple extensions can have pending tasks. | 204 // multiple extensions can have pending tasks. |
| 118 TEST_F(LazyBackgroundTaskQueueTest, AddPendingTask) { | 205 TEST_F(LazyBackgroundTaskQueueTest, AddPendingTask) { |
| 119 InitializeEmptyExtensionService(); | 206 // Get our TestProcessManager. |
| 207 MockExtensionSystem* extension_system = static_cast<MockExtensionSystem*>( | |
| 208 ExtensionSystem::Get(browser_context())); | |
| 209 TestProcessManager* process_manager = | |
| 210 static_cast<TestProcessManager*>(extension_system->process_manager()); | |
| 120 | 211 |
| 121 // Swap in our stub TestProcessManager. | 212 LazyBackgroundTaskQueue queue(browser_context()); |
| 122 TestExtensionSystem* extension_system = | |
| 123 static_cast<extensions::TestExtensionSystem*>( | |
| 124 ExtensionSystem::Get(profile_.get())); | |
| 125 // Owned by |extension_system|. | |
| 126 TestProcessManager* process_manager = new TestProcessManager(profile_.get()); | |
| 127 extension_system->SetProcessManager(process_manager); | |
| 128 | |
| 129 LazyBackgroundTaskQueue queue(profile_.get()); | |
| 130 | 213 |
| 131 // Build a simple extension with no background page. | 214 // Build a simple extension with no background page. |
| 132 scoped_refptr<Extension> no_background = CreateSimpleExtension(); | 215 scoped_refptr<Extension> no_background = CreateSimpleExtension(); |
| 133 | 216 |
| 134 // Adding a pending task increases the number of extensions with tasks, but | 217 // Adding a pending task increases the number of extensions with tasks, but |
| 135 // doesn't run the task. | 218 // doesn't run the task. |
| 136 queue.AddPendingTask(profile_.get(), | 219 queue.AddPendingTask(browser_context(), |
| 137 no_background->id(), | 220 no_background->id(), |
| 138 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, | 221 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, |
| 139 base::Unretained(this))); | 222 base::Unretained(this))); |
| 140 EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); | 223 EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); |
| 141 EXPECT_EQ(0, task_run_count()); | 224 EXPECT_EQ(0, task_run_count()); |
| 142 | 225 |
| 143 // Another task on the same extension doesn't increase the number of | 226 // Another task on the same extension doesn't increase the number of |
| 144 // extensions that have tasks and doesn't run any tasks. | 227 // extensions that have tasks and doesn't run any tasks. |
| 145 queue.AddPendingTask(profile_.get(), | 228 queue.AddPendingTask(browser_context(), |
| 146 no_background->id(), | 229 no_background->id(), |
| 147 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, | 230 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, |
| 148 base::Unretained(this))); | 231 base::Unretained(this))); |
| 149 EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); | 232 EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); |
| 150 EXPECT_EQ(0, task_run_count()); | 233 EXPECT_EQ(0, task_run_count()); |
| 151 | 234 |
| 152 // Adding a task on an extension with a lazy background page tries to create | 235 // Adding a task on an extension with a lazy background page tries to create |
| 153 // a background host, and if that fails, runs the task immediately. | 236 // a background host, and if that fails, runs the task immediately. |
| 154 scoped_refptr<Extension> lazy_background = CreateLazyBackgroundExtension(); | 237 scoped_refptr<Extension> lazy_background = CreateLazyBackgroundExtension(); |
| 155 queue.AddPendingTask(profile_.get(), | 238 queue.AddPendingTask(browser_context(), |
| 156 lazy_background->id(), | 239 lazy_background->id(), |
| 157 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, | 240 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, |
| 158 base::Unretained(this))); | 241 base::Unretained(this))); |
| 159 EXPECT_EQ(2u, queue.extensions_with_pending_tasks()); | 242 EXPECT_EQ(2u, queue.extensions_with_pending_tasks()); |
| 160 // The process manager tried to create a background host. | 243 // The process manager tried to create a background host. |
| 161 EXPECT_EQ(1, process_manager->create_count()); | 244 EXPECT_EQ(1, process_manager->create_count()); |
| 162 // The task ran immediately because the creation failed. | 245 // The task ran immediately because the creation failed. |
| 163 EXPECT_EQ(1, task_run_count()); | 246 EXPECT_EQ(1, task_run_count()); |
| 164 } | 247 } |
| 165 | 248 |
| 166 // Tests that pending tasks are actually run. | 249 // Tests that pending tasks are actually run. |
| 167 TEST_F(LazyBackgroundTaskQueueTest, ProcessPendingTasks) { | 250 TEST_F(LazyBackgroundTaskQueueTest, ProcessPendingTasks) { |
| 168 InitializeEmptyExtensionService(); | 251 LazyBackgroundTaskQueue queue(browser_context()); |
| 169 | |
| 170 LazyBackgroundTaskQueue queue(profile_.get()); | |
| 171 | 252 |
| 172 // ProcessPendingTasks is a no-op if there are no tasks. | 253 // ProcessPendingTasks is a no-op if there are no tasks. |
| 173 scoped_refptr<Extension> extension = CreateSimpleExtension(); | 254 scoped_refptr<Extension> extension = CreateSimpleExtension(); |
| 174 queue.ProcessPendingTasks(NULL, profile_.get(), extension); | 255 queue.ProcessPendingTasks(NULL, browser_context(), extension); |
| 175 EXPECT_EQ(0, task_run_count()); | 256 EXPECT_EQ(0, task_run_count()); |
| 176 | 257 |
| 177 // Schedule a task to run. | 258 // Schedule a task to run. |
| 178 queue.AddPendingTask(profile_.get(), | 259 queue.AddPendingTask(browser_context(), |
| 179 extension->id(), | 260 extension->id(), |
| 180 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, | 261 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, |
| 181 base::Unretained(this))); | 262 base::Unretained(this))); |
| 182 EXPECT_EQ(0, task_run_count()); | 263 EXPECT_EQ(0, task_run_count()); |
| 183 EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); | 264 EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); |
| 184 | 265 |
| 185 // Trying to run tasks for an unrelated profile should do nothing. | 266 // Trying to run tasks for an unrelated BrowserContext should do nothing. |
| 186 TestingProfile profile2; | 267 content::TestBrowserContext unrelated_context; |
| 187 queue.ProcessPendingTasks(NULL, &profile2, extension); | 268 queue.ProcessPendingTasks(NULL, &unrelated_context, extension); |
| 188 EXPECT_EQ(0, task_run_count()); | 269 EXPECT_EQ(0, task_run_count()); |
| 189 EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); | 270 EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); |
| 190 | 271 |
| 191 // Processing tasks when there is one pending runs the task and removes the | 272 // Processing tasks when there is one pending runs the task and removes the |
| 192 // extension from the list of extensions with pending tasks. | 273 // extension from the list of extensions with pending tasks. |
| 193 queue.ProcessPendingTasks(NULL, profile_.get(), extension); | 274 queue.ProcessPendingTasks(NULL, browser_context(), extension); |
| 194 EXPECT_EQ(1, task_run_count()); | 275 EXPECT_EQ(1, task_run_count()); |
| 195 EXPECT_EQ(0u, queue.extensions_with_pending_tasks()); | 276 EXPECT_EQ(0u, queue.extensions_with_pending_tasks()); |
| 196 } | 277 } |
| 197 | 278 |
| 198 } // namespace extensions | 279 } // namespace extensions |
| OLD | NEW |