[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 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 |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 9fe4204 | 2013-10-29 21:13:33 | [diff] [blame] | 5 | #include "extensions/browser/lazy_background_task_queue.h" |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 6 | |
dcheng | f5d24108 | 2016-04-21 03:43:11 | [diff] [blame] | 7 | #include <memory> |
| 8 | |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 9 | #include "base/bind.h" |
avi | c9cec10 | 2015-12-23 00:39:26 | [diff] [blame] | 10 | #include "base/macros.h" |
dcheng | f5d24108 | 2016-04-21 03:43:11 | [diff] [blame] | 11 | #include "base/memory/ptr_util.h" |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 12 | #include "components/keyed_service/content/browser_context_dependency_manager.h" |
krasin | 3bc9c19c | 2015-07-29 20:12:45 | [diff] [blame] | 13 | #include "components/pref_registry/testing_pref_service_syncable.h" |
brettw | 06650868 | 2016-02-03 08:22:02 | [diff] [blame] | 14 | #include "components/prefs/testing_pref_service.h" |
reillyg | 0ea3fa90 | 2014-10-28 15:30:23 | [diff] [blame] | 15 | #include "components/user_prefs/user_prefs.h" |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 16 | #include "content/public/test/test_browser_context.h" |
[email protected] | 6b54fda | 2014-07-22 02:13:47 | [diff] [blame] | 17 | #include "extensions/browser/extension_registry.h" |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 18 | #include "extensions/browser/extension_registry_factory.h" |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 19 | #include "extensions/browser/extensions_test.h" |
[email protected] | 98b6d94 | 2013-11-10 00:34:07 | [diff] [blame] | 20 | #include "extensions/browser/process_manager.h" |
reillyg | 0ea3fa90 | 2014-10-28 15:30:23 | [diff] [blame] | 21 | #include "extensions/browser/process_manager_factory.h" |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 22 | #include "extensions/browser/test_extensions_browser_client.h" |
[email protected] | e4452d3 | 2013-11-15 23:07:41 | [diff] [blame] | 23 | #include "extensions/common/extension.h" |
[email protected] | 22b7b2c | 2013-11-05 22:52:42 | [diff] [blame] | 24 | #include "extensions/common/extension_builder.h" |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 25 | #include "testing/gtest/include/gtest/gtest.h" |
| 26 | |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 27 | using content::BrowserContext; |
| 28 | |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 29 | namespace extensions { |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 30 | namespace { |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 31 | |
[email protected] | 98b6d94 | 2013-11-10 00:34:07 | [diff] [blame] | 32 | // A ProcessManager that doesn't create background host pages. |
| 33 | class TestProcessManager : public ProcessManager { |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 34 | public: |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 35 | explicit TestProcessManager(BrowserContext* context) |
| 36 | : ProcessManager(context, context, ExtensionRegistry::Get(context)), |
| 37 | create_count_(0) { |
| 38 | // ProcessManager constructor above assumes non-incognito. |
| 39 | DCHECK(!context->IsOffTheRecord()); |
| 40 | } |
dcheng | 9168b2f | 2014-10-21 12:38:24 | [diff] [blame] | 41 | ~TestProcessManager() override {} |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 42 | |
| 43 | int create_count() { return create_count_; } |
| 44 | |
[email protected] | 98b6d94 | 2013-11-10 00:34:07 | [diff] [blame] | 45 | // ProcessManager overrides: |
dcheng | 9168b2f | 2014-10-21 12:38:24 | [diff] [blame] | 46 | bool CreateBackgroundHost(const Extension* extension, |
| 47 | const GURL& url) override { |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 48 | // Don't actually try to create a web contents. |
| 49 | create_count_++; |
[email protected] | 6ad9cdf7 | 2014-02-27 13:12:41 | [diff] [blame] | 50 | return false; |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 51 | } |
| 52 | |
| 53 | private: |
| 54 | int create_count_; |
| 55 | |
[email protected] | 98b6d94 | 2013-11-10 00:34:07 | [diff] [blame] | 56 | DISALLOW_COPY_AND_ASSIGN(TestProcessManager); |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 57 | }; |
| 58 | |
dcheng | f5d24108 | 2016-04-21 03:43:11 | [diff] [blame] | 59 | std::unique_ptr<KeyedService> CreateTestProcessManager( |
| 60 | BrowserContext* context) { |
ricea | 5e27337 | 2016-08-22 02:51:03 | [diff] [blame] | 61 | return base::MakeUnique<TestProcessManager>(context); |
reillyg | 0ea3fa90 | 2014-10-28 15:30:23 | [diff] [blame] | 62 | } |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 63 | |
| 64 | } // namespace |
| 65 | |
| 66 | // Derives from ExtensionsTest to provide content module and keyed service |
| 67 | // initialization. |
| 68 | class LazyBackgroundTaskQueueTest : public ExtensionsTest { |
| 69 | public: |
rockot | 8cba036 | 2016-08-09 21:43:43 | [diff] [blame] | 70 | LazyBackgroundTaskQueueTest() : task_run_count_(0) {} |
dcheng | f9afb37 | 2014-10-27 21:43:14 | [diff] [blame] | 71 | ~LazyBackgroundTaskQueueTest() override {} |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 72 | |
| 73 | int task_run_count() { return task_run_count_; } |
| 74 | |
| 75 | // A simple callback for AddPendingTask. |
| 76 | void RunPendingTask(ExtensionHost* host) { |
| 77 | task_run_count_++; |
| 78 | } |
| 79 | |
| 80 | // Creates and registers an extension without a background page. |
| 81 | scoped_refptr<Extension> CreateSimpleExtension() { |
limasdf | 21d67e6 | 2015-12-19 12:04:49 | [diff] [blame] | 82 | scoped_refptr<Extension> extension = |
| 83 | ExtensionBuilder() |
dcheng | 794d2bd | 2016-02-27 03:51:32 | [diff] [blame] | 84 | .SetManifest(DictionaryBuilder() |
| 85 | .Set("name", "No background") |
| 86 | .Set("version", "1") |
| 87 | .Set("manifest_version", 2) |
| 88 | .Build()) |
limasdf | 21d67e6 | 2015-12-19 12:04:49 | [diff] [blame] | 89 | .SetID("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") |
| 90 | .Build(); |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 91 | ExtensionRegistry::Get(browser_context())->AddEnabled(extension); |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 92 | return extension; |
| 93 | } |
| 94 | |
| 95 | // Creates and registers an extension with a lazy background page. |
| 96 | scoped_refptr<Extension> CreateLazyBackgroundExtension() { |
limasdf | 21d67e6 | 2015-12-19 12:04:49 | [diff] [blame] | 97 | scoped_refptr<Extension> extension = |
| 98 | ExtensionBuilder() |
dcheng | 794d2bd | 2016-02-27 03:51:32 | [diff] [blame] | 99 | .SetManifest( |
limasdf | 21d67e6 | 2015-12-19 12:04:49 | [diff] [blame] | 100 | DictionaryBuilder() |
| 101 | .Set("name", "Lazy background") |
| 102 | .Set("version", "1") |
| 103 | .Set("manifest_version", 2) |
dcheng | 794d2bd | 2016-02-27 03:51:32 | [diff] [blame] | 104 | .Set("background", DictionaryBuilder() |
| 105 | .Set("page", "background.html") |
| 106 | .SetBoolean("persistent", false) |
| 107 | .Build()) |
| 108 | .Build()) |
limasdf | 21d67e6 | 2015-12-19 12:04:49 | [diff] [blame] | 109 | .SetID("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb") |
| 110 | .Build(); |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 111 | ExtensionRegistry::Get(browser_context())->AddEnabled(extension); |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 112 | return extension; |
| 113 | } |
| 114 | |
reillyg | 0ea3fa90 | 2014-10-28 15:30:23 | [diff] [blame] | 115 | protected: |
dcheng | afa7602 | 2014-12-28 20:31:56 | [diff] [blame] | 116 | void SetUp() override { |
reillyg | 0ea3fa90 | 2014-10-28 15:30:23 | [diff] [blame] | 117 | user_prefs::UserPrefs::Set(browser_context(), &testing_pref_service_); |
| 118 | } |
| 119 | |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 120 | private: |
krasin | 3bc9c19c | 2015-07-29 20:12:45 | [diff] [blame] | 121 | user_prefs::TestingPrefServiceSyncable testing_pref_service_; |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 122 | |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 123 | // The total number of pending tasks that have been executed. |
| 124 | int task_run_count_; |
| 125 | |
| 126 | DISALLOW_COPY_AND_ASSIGN(LazyBackgroundTaskQueueTest); |
| 127 | }; |
| 128 | |
| 129 | // Tests that only extensions with background pages should have tasks queued. |
| 130 | TEST_F(LazyBackgroundTaskQueueTest, ShouldEnqueueTask) { |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 131 | LazyBackgroundTaskQueue queue(browser_context()); |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 132 | |
| 133 | // Build a simple extension with no background page. |
| 134 | scoped_refptr<Extension> no_background = CreateSimpleExtension(); |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 135 | EXPECT_FALSE(queue.ShouldEnqueueTask(browser_context(), no_background.get())); |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 136 | |
| 137 | // Build another extension with a background page. |
| 138 | scoped_refptr<Extension> with_background = CreateLazyBackgroundExtension(); |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 139 | EXPECT_TRUE( |
| 140 | queue.ShouldEnqueueTask(browser_context(), with_background.get())); |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 141 | } |
| 142 | |
| 143 | // Tests that adding tasks actually increases the pending task count, and that |
| 144 | // multiple extensions can have pending tasks. |
| 145 | TEST_F(LazyBackgroundTaskQueueTest, AddPendingTask) { |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 146 | // Get our TestProcessManager. |
reillyg | 0ea3fa90 | 2014-10-28 15:30:23 | [diff] [blame] | 147 | TestProcessManager* process_manager = static_cast<TestProcessManager*>( |
| 148 | ProcessManagerFactory::GetInstance()->SetTestingFactoryAndUse( |
| 149 | browser_context(), CreateTestProcessManager)); |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 150 | |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 151 | LazyBackgroundTaskQueue queue(browser_context()); |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 152 | |
| 153 | // Build a simple extension with no background page. |
| 154 | scoped_refptr<Extension> no_background = CreateSimpleExtension(); |
| 155 | |
| 156 | // Adding a pending task increases the number of extensions with tasks, but |
| 157 | // doesn't run the task. |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 158 | queue.AddPendingTask(browser_context(), |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 159 | no_background->id(), |
| 160 | base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, |
| 161 | base::Unretained(this))); |
| 162 | EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); |
| 163 | EXPECT_EQ(0, task_run_count()); |
| 164 | |
| 165 | // Another task on the same extension doesn't increase the number of |
| 166 | // extensions that have tasks and doesn't run any tasks. |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 167 | queue.AddPendingTask(browser_context(), |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 168 | no_background->id(), |
| 169 | base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, |
| 170 | base::Unretained(this))); |
| 171 | EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); |
| 172 | EXPECT_EQ(0, task_run_count()); |
| 173 | |
| 174 | // Adding a task on an extension with a lazy background page tries to create |
| 175 | // a background host, and if that fails, runs the task immediately. |
| 176 | scoped_refptr<Extension> lazy_background = CreateLazyBackgroundExtension(); |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 177 | queue.AddPendingTask(browser_context(), |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 178 | lazy_background->id(), |
| 179 | base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, |
| 180 | base::Unretained(this))); |
| 181 | EXPECT_EQ(2u, queue.extensions_with_pending_tasks()); |
| 182 | // The process manager tried to create a background host. |
| 183 | EXPECT_EQ(1, process_manager->create_count()); |
| 184 | // The task ran immediately because the creation failed. |
| 185 | EXPECT_EQ(1, task_run_count()); |
| 186 | } |
| 187 | |
| 188 | // Tests that pending tasks are actually run. |
| 189 | TEST_F(LazyBackgroundTaskQueueTest, ProcessPendingTasks) { |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 190 | LazyBackgroundTaskQueue queue(browser_context()); |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 191 | |
| 192 | // ProcessPendingTasks is a no-op if there are no tasks. |
| 193 | scoped_refptr<Extension> extension = CreateSimpleExtension(); |
dcheng | 7921e3f | 2014-08-25 22:20:01 | [diff] [blame] | 194 | queue.ProcessPendingTasks(NULL, browser_context(), extension.get()); |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 195 | EXPECT_EQ(0, task_run_count()); |
| 196 | |
| 197 | // Schedule a task to run. |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 198 | queue.AddPendingTask(browser_context(), |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 199 | extension->id(), |
| 200 | base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask, |
| 201 | base::Unretained(this))); |
| 202 | EXPECT_EQ(0, task_run_count()); |
| 203 | EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); |
| 204 | |
[email protected] | 9fc5bdc8 | 2014-08-03 23:49:26 | [diff] [blame] | 205 | // Trying to run tasks for an unrelated BrowserContext should do nothing. |
| 206 | content::TestBrowserContext unrelated_context; |
dcheng | 7921e3f | 2014-08-25 22:20:01 | [diff] [blame] | 207 | queue.ProcessPendingTasks(NULL, &unrelated_context, extension.get()); |
[email protected] | 9fe4204 | 2013-10-29 21:13:33 | [diff] [blame] | 208 | EXPECT_EQ(0, task_run_count()); |
| 209 | EXPECT_EQ(1u, queue.extensions_with_pending_tasks()); |
| 210 | |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 211 | // Processing tasks when there is one pending runs the task and removes the |
| 212 | // extension from the list of extensions with pending tasks. |
dcheng | 7921e3f | 2014-08-25 22:20:01 | [diff] [blame] | 213 | queue.ProcessPendingTasks(NULL, browser_context(), extension.get()); |
[email protected] | f724021 | 2013-10-27 03:39:12 | [diff] [blame] | 214 | EXPECT_EQ(1, task_run_count()); |
| 215 | EXPECT_EQ(0u, queue.extensions_with_pending_tasks()); |
| 216 | } |
| 217 | |
| 218 | } // namespace extensions |