| 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 { |
| 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 // BrowserContextKeyedServiceFactory overrides: |
| 106 virtual KeyedService* BuildServiceInstanceFor( |
| 107 BrowserContext* context) const OVERRIDE { |
| 108 return new MockExtensionSystem(context); |
| 109 } |
| 110 |
| 111 // ExtensionSystemProvider overrides: |
| 112 virtual ExtensionSystem* GetForBrowserContext( |
| 113 BrowserContext* context) OVERRIDE { |
| 114 return static_cast<MockExtensionSystem*>( |
| 115 GetServiceForBrowserContext(context, true)); |
| 116 } |
| 117 |
| 118 private: |
| 119 DISALLOW_COPY_AND_ASSIGN(MockExtensionSystemFactory); |
| 120 }; |
| 121 |
| 122 } // namespace |
| 123 |
| 124 // Derives from ExtensionsTest to provide content module and keyed service |
| 125 // initialization. |
| 126 class LazyBackgroundTaskQueueTest : public ExtensionsTest { |
| 127 public: |
| 128 LazyBackgroundTaskQueueTest() |
| 129 : notification_service_(content::NotificationService::Create()), |
| 130 task_run_count_(0) { |
| 131 extensions_browser_client()->set_extension_system_factory( |
| 132 &extension_system_factory_); |
| 133 } |
| 54 virtual ~LazyBackgroundTaskQueueTest() {} | 134 virtual ~LazyBackgroundTaskQueueTest() {} |
| 55 | 135 |
| 56 int task_run_count() { return task_run_count_; } | 136 int task_run_count() { return task_run_count_; } |
| 57 | 137 |
| 58 // A simple callback for AddPendingTask. | 138 // A simple callback for AddPendingTask. |
| 59 void RunPendingTask(ExtensionHost* host) { | 139 void RunPendingTask(ExtensionHost* host) { |
| 60 task_run_count_++; | 140 task_run_count_++; |
| 61 } | 141 } |
| 62 | 142 |
| 63 // Creates and registers an extension without a background page. | 143 // Creates and registers an extension without a background page. |
| 64 scoped_refptr<Extension> CreateSimpleExtension() { | 144 scoped_refptr<Extension> CreateSimpleExtension() { |
| 65 scoped_refptr<Extension> extension = ExtensionBuilder() | 145 scoped_refptr<Extension> extension = ExtensionBuilder() |
| 66 .SetManifest(DictionaryBuilder() | 146 .SetManifest(DictionaryBuilder() |
| 67 .Set("name", "No background") | 147 .Set("name", "No background") |
| 68 .Set("version", "1") | 148 .Set("version", "1") |
| 69 .Set("manifest_version", 2)) | 149 .Set("manifest_version", 2)) |
| 70 .SetID("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") | 150 .SetID("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") |
| 71 .Build(); | 151 .Build(); |
| 72 service_->AddExtension(extension); | 152 ExtensionRegistry::Get(browser_context())->AddEnabled(extension); |
| 73 return extension; | 153 return extension; |
| 74 } | 154 } |
| 75 | 155 |
| 76 // Creates and registers an extension with a lazy background page. | 156 // Creates and registers an extension with a lazy background page. |
| 77 scoped_refptr<Extension> CreateLazyBackgroundExtension() { | 157 scoped_refptr<Extension> CreateLazyBackgroundExtension() { |
| 78 scoped_refptr<Extension> extension = ExtensionBuilder() | 158 scoped_refptr<Extension> extension = ExtensionBuilder() |
| 79 .SetManifest(DictionaryBuilder() | 159 .SetManifest(DictionaryBuilder() |
| 80 .Set("name", "Lazy background") | 160 .Set("name", "Lazy background") |
| 81 .Set("version", "1") | 161 .Set("version", "1") |
| 82 .Set("manifest_version", 2) | 162 .Set("manifest_version", 2) |
| 83 .Set("background", | 163 .Set("background", |
| 84 DictionaryBuilder() | 164 DictionaryBuilder() |
| 85 .Set("page", "background.html") | 165 .Set("page", "background.html") |
| 86 .SetBoolean("persistent", false))) | 166 .SetBoolean("persistent", false))) |
| 87 .SetID("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb") | 167 .SetID("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb") |
| 88 .Build(); | 168 .Build(); |
| 89 service_->AddExtension(extension); | 169 ExtensionRegistry::Get(browser_context())->AddEnabled(extension); |
| 90 return extension; | 170 return extension; |
| 91 } | 171 } |
| 92 | 172 |
| 93 private: | 173 private: |
| 174 scoped_ptr<content::NotificationService> notification_service_; |
| 175 MockExtensionSystemFactory extension_system_factory_; |
| 176 |
| 94 // The total number of pending tasks that have been executed. | 177 // The total number of pending tasks that have been executed. |
| 95 int task_run_count_; | 178 int task_run_count_; |
| 96 | 179 |
| 97 DISALLOW_COPY_AND_ASSIGN(LazyBackgroundTaskQueueTest); | 180 DISALLOW_COPY_AND_ASSIGN(LazyBackgroundTaskQueueTest); |
| 98 }; | 181 }; |
| 99 | 182 |
| 100 // Tests that only extensions with background pages should have tasks queued. | 183 // Tests that only extensions with background pages should have tasks queued. |
| 101 TEST_F(LazyBackgroundTaskQueueTest, ShouldEnqueueTask) { | 184 TEST_F(LazyBackgroundTaskQueueTest, ShouldEnqueueTask) { |
| 102 InitializeEmptyExtensionService(); | 185 LazyBackgroundTaskQueue queue(browser_context()); |
| 103 InitializeProcessManager(); | |
| 104 | |
| 105 LazyBackgroundTaskQueue queue(profile_.get()); | |
| 106 | 186 |
| 107 // Build a simple extension with no background page. | 187 // Build a simple extension with no background page. |
| 108 scoped_refptr<Extension> no_background = CreateSimpleExtension(); | 188 scoped_refptr<Extension> no_background = CreateSimpleExtension(); |
| 109 EXPECT_FALSE(queue.ShouldEnqueueTask(profile_.get(), no_background.get())); | 189 EXPECT_FALSE(queue.ShouldEnqueueTask(browser_context(), no_background.get())); |
| 110 | 190 |
| 111 // Build another extension with a background page. | 191 // Build another extension with a background page. |
| 112 scoped_refptr<Extension> with_background = CreateLazyBackgroundExtension(); | 192 scoped_refptr<Extension> with_background = CreateLazyBackgroundExtension(); |
| 113 EXPECT_TRUE(queue.ShouldEnqueueTask(profile_.get(), with_background.get())); | 193 EXPECT_TRUE( |
| 194 queue.ShouldEnqueueTask(browser_context(), with_background.get())); |
| 114 } | 195 } |
| 115 | 196 |
| 116 // Tests that adding tasks actually increases the pending task count, and that | 197 // Tests that adding tasks actually increases the pending task count, and that |
| 117 // multiple extensions can have pending tasks. | 198 // multiple extensions can have pending tasks. |
| 118 TEST_F(LazyBackgroundTaskQueueTest, AddPendingTask) { | 199 TEST_F(LazyBackgroundTaskQueueTest, AddPendingTask) { |
| 119 InitializeEmptyExtensionService(); | 200 // Get our TestProcessManager. |
| 201 MockExtensionSystem* extension_system = static_cast<MockExtensionSystem*>( |
| 202 ExtensionSystem::Get(browser_context())); |
| 203 TestProcessManager* process_manager = |
| 204 static_cast<TestProcessManager*>(extension_system->process_manager()); |
| 120 | 205 |
| 121 // Swap in our stub TestProcessManager. | 206 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 | 207 |
| 131 // Build a simple extension with no background page. | 208 // Build a simple extension with no background page. |
| 132 scoped_refptr<Extension> no_background = CreateSimpleExtension(); | 209 scoped_refptr<Extension> no_background = CreateSimpleExtension(); |
| 133 | 210 |
| 134 // Adding a pending task increases the number of extensions with tasks, but | 211 // Adding a pending task increases the number of extensions with tasks, but |
| 135 // doesn't run the task. | 212 // doesn't run the task. |
| 136 queue.AddPendingTask(profile_.get(), | 213 queue.AddPendingTask(browser_context(), |
| 137 no_background->id(), | 214 no_background->id(), |
| 138 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, | 215 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, |
| 139 base::Unretained(this))); | 216 base::Unretained(this))); |
| 140 EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); | 217 EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); |
| 141 EXPECT_EQ(0, task_run_count()); | 218 EXPECT_EQ(0, task_run_count()); |
| 142 | 219 |
| 143 // Another task on the same extension doesn't increase the number of | 220 // Another task on the same extension doesn't increase the number of |
| 144 // extensions that have tasks and doesn't run any tasks. | 221 // extensions that have tasks and doesn't run any tasks. |
| 145 queue.AddPendingTask(profile_.get(), | 222 queue.AddPendingTask(browser_context(), |
| 146 no_background->id(), | 223 no_background->id(), |
| 147 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, | 224 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, |
| 148 base::Unretained(this))); | 225 base::Unretained(this))); |
| 149 EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); | 226 EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); |
| 150 EXPECT_EQ(0, task_run_count()); | 227 EXPECT_EQ(0, task_run_count()); |
| 151 | 228 |
| 152 // Adding a task on an extension with a lazy background page tries to create | 229 // 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. | 230 // a background host, and if that fails, runs the task immediately. |
| 154 scoped_refptr<Extension> lazy_background = CreateLazyBackgroundExtension(); | 231 scoped_refptr<Extension> lazy_background = CreateLazyBackgroundExtension(); |
| 155 queue.AddPendingTask(profile_.get(), | 232 queue.AddPendingTask(browser_context(), |
| 156 lazy_background->id(), | 233 lazy_background->id(), |
| 157 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, | 234 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, |
| 158 base::Unretained(this))); | 235 base::Unretained(this))); |
| 159 EXPECT_EQ(2u, queue.extensions_with_pending_tasks()); | 236 EXPECT_EQ(2u, queue.extensions_with_pending_tasks()); |
| 160 // The process manager tried to create a background host. | 237 // The process manager tried to create a background host. |
| 161 EXPECT_EQ(1, process_manager->create_count()); | 238 EXPECT_EQ(1, process_manager->create_count()); |
| 162 // The task ran immediately because the creation failed. | 239 // The task ran immediately because the creation failed. |
| 163 EXPECT_EQ(1, task_run_count()); | 240 EXPECT_EQ(1, task_run_count()); |
| 164 } | 241 } |
| 165 | 242 |
| 166 // Tests that pending tasks are actually run. | 243 // Tests that pending tasks are actually run. |
| 167 TEST_F(LazyBackgroundTaskQueueTest, ProcessPendingTasks) { | 244 TEST_F(LazyBackgroundTaskQueueTest, ProcessPendingTasks) { |
| 168 InitializeEmptyExtensionService(); | 245 LazyBackgroundTaskQueue queue(browser_context()); |
| 169 | |
| 170 LazyBackgroundTaskQueue queue(profile_.get()); | |
| 171 | 246 |
| 172 // ProcessPendingTasks is a no-op if there are no tasks. | 247 // ProcessPendingTasks is a no-op if there are no tasks. |
| 173 scoped_refptr<Extension> extension = CreateSimpleExtension(); | 248 scoped_refptr<Extension> extension = CreateSimpleExtension(); |
| 174 queue.ProcessPendingTasks(NULL, profile_.get(), extension); | 249 queue.ProcessPendingTasks(NULL, browser_context(), extension); |
| 175 EXPECT_EQ(0, task_run_count()); | 250 EXPECT_EQ(0, task_run_count()); |
| 176 | 251 |
| 177 // Schedule a task to run. | 252 // Schedule a task to run. |
| 178 queue.AddPendingTask(profile_.get(), | 253 queue.AddPendingTask(browser_context(), |
| 179 extension->id(), | 254 extension->id(), |
| 180 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, | 255 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, |
| 181 base::Unretained(this))); | 256 base::Unretained(this))); |
| 182 EXPECT_EQ(0, task_run_count()); | 257 EXPECT_EQ(0, task_run_count()); |
| 183 EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); | 258 EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); |
| 184 | 259 |
| 185 // Trying to run tasks for an unrelated profile should do nothing. | 260 // Trying to run tasks for an unrelated BrowserContext should do nothing. |
| 186 TestingProfile profile2; | 261 content::TestBrowserContext unrelated_context; |
| 187 queue.ProcessPendingTasks(NULL, &profile2, extension); | 262 queue.ProcessPendingTasks(NULL, &unrelated_context, extension); |
| 188 EXPECT_EQ(0, task_run_count()); | 263 EXPECT_EQ(0, task_run_count()); |
| 189 EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); | 264 EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); |
| 190 | 265 |
| 191 // Processing tasks when there is one pending runs the task and removes the | 266 // Processing tasks when there is one pending runs the task and removes the |
| 192 // extension from the list of extensions with pending tasks. | 267 // extension from the list of extensions with pending tasks. |
| 193 queue.ProcessPendingTasks(NULL, profile_.get(), extension); | 268 queue.ProcessPendingTasks(NULL, browser_context(), extension); |
| 194 EXPECT_EQ(1, task_run_count()); | 269 EXPECT_EQ(1, task_run_count()); |
| 195 EXPECT_EQ(0u, queue.extensions_with_pending_tasks()); | 270 EXPECT_EQ(0u, queue.extensions_with_pending_tasks()); |
| 196 } | 271 } |
| 197 | 272 |
| 198 } // namespace extensions | 273 } // namespace extensions |
| OLD | NEW |