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
5 #include "extensions/browser/lazy_background_task_queue.h"
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/extensions/extension_service_test_base.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/process_manager.h"
15 #include "extensions/common/extension.h"
16 #include "extensions/common/extension_builder.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace extensions {
20
21 // A ProcessManager that doesn't create background host pages.
22 class TestProcessManager : public ProcessManager {
23 public:
TestProcessManager(Profile * profile)24 explicit TestProcessManager(Profile* profile)
25 : ProcessManager(profile, profile->GetOriginalProfile()),
26 create_count_(0) {}
~TestProcessManager()27 virtual ~TestProcessManager() {}
28
create_count()29 int create_count() { return create_count_; }
30
31 // ProcessManager overrides:
CreateBackgroundHost(const Extension * extension,const GURL & url)32 virtual bool CreateBackgroundHost(const Extension* extension,
33 const GURL& url) OVERRIDE {
34 // Don't actually try to create a web contents.
35 create_count_++;
36 return false;
37 }
38
39 private:
40 int create_count_;
41
42 DISALLOW_COPY_AND_ASSIGN(TestProcessManager);
43 };
44
45 // Derives from ExtensionServiceTestBase because ExtensionService is difficult
46 // to initialize alone.
47 class LazyBackgroundTaskQueueTest
48 : public extensions::ExtensionServiceTestBase {
49 public:
LazyBackgroundTaskQueueTest()50 LazyBackgroundTaskQueueTest() : task_run_count_(0) {}
~LazyBackgroundTaskQueueTest()51 virtual ~LazyBackgroundTaskQueueTest() {}
52
task_run_count()53 int task_run_count() { return task_run_count_; }
54
55 // A simple callback for AddPendingTask.
RunPendingTask(ExtensionHost * host)56 void RunPendingTask(ExtensionHost* host) {
57 task_run_count_++;
58 }
59
60 // Creates and registers an extension without a background page.
CreateSimpleExtension()61 scoped_refptr<Extension> CreateSimpleExtension() {
62 scoped_refptr<Extension> extension = ExtensionBuilder()
63 .SetManifest(DictionaryBuilder()
64 .Set("name", "No background")
65 .Set("version", "1")
66 .Set("manifest_version", 2))
67 .SetID("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
68 .Build();
69 service_->AddExtension(extension);
70 return extension;
71 }
72
73 // Creates and registers an extension with a lazy background page.
CreateLazyBackgroundExtension()74 scoped_refptr<Extension> CreateLazyBackgroundExtension() {
75 scoped_refptr<Extension> extension = ExtensionBuilder()
76 .SetManifest(DictionaryBuilder()
77 .Set("name", "Lazy background")
78 .Set("version", "1")
79 .Set("manifest_version", 2)
80 .Set("background",
81 DictionaryBuilder()
82 .Set("page", "background.html")
83 .SetBoolean("persistent", false)))
84 .SetID("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
85 .Build();
86 service_->AddExtension(extension);
87 return extension;
88 }
89
90 private:
91 // The total number of pending tasks that have been executed.
92 int task_run_count_;
93
94 DISALLOW_COPY_AND_ASSIGN(LazyBackgroundTaskQueueTest);
95 };
96
97 // Tests that only extensions with background pages should have tasks queued.
TEST_F(LazyBackgroundTaskQueueTest,ShouldEnqueueTask)98 TEST_F(LazyBackgroundTaskQueueTest, ShouldEnqueueTask) {
99 InitializeEmptyExtensionService();
100 InitializeProcessManager();
101
102 LazyBackgroundTaskQueue queue(profile_.get());
103
104 // Build a simple extension with no background page.
105 scoped_refptr<Extension> no_background = CreateSimpleExtension();
106 EXPECT_FALSE(queue.ShouldEnqueueTask(profile_.get(), no_background.get()));
107
108 // Build another extension with a background page.
109 scoped_refptr<Extension> with_background = CreateLazyBackgroundExtension();
110 EXPECT_TRUE(queue.ShouldEnqueueTask(profile_.get(), with_background.get()));
111 }
112
113 // Tests that adding tasks actually increases the pending task count, and that
114 // multiple extensions can have pending tasks.
TEST_F(LazyBackgroundTaskQueueTest,AddPendingTask)115 TEST_F(LazyBackgroundTaskQueueTest, AddPendingTask) {
116 InitializeEmptyExtensionService();
117
118 // Swap in our stub TestProcessManager.
119 TestExtensionSystem* extension_system =
120 static_cast<extensions::TestExtensionSystem*>(
121 ExtensionSystem::Get(profile_.get()));
122 // Owned by |extension_system|.
123 TestProcessManager* process_manager = new TestProcessManager(profile_.get());
124 extension_system->SetProcessManager(process_manager);
125
126 LazyBackgroundTaskQueue queue(profile_.get());
127
128 // Build a simple extension with no background page.
129 scoped_refptr<Extension> no_background = CreateSimpleExtension();
130
131 // Adding a pending task increases the number of extensions with tasks, but
132 // doesn't run the task.
133 queue.AddPendingTask(profile_.get(),
134 no_background->id(),
135 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask,
136 base::Unretained(this)));
137 EXPECT_EQ(1u, queue.extensions_with_pending_tasks());
138 EXPECT_EQ(0, task_run_count());
139
140 // Another task on the same extension doesn't increase the number of
141 // extensions that have tasks and doesn't run any tasks.
142 queue.AddPendingTask(profile_.get(),
143 no_background->id(),
144 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask,
145 base::Unretained(this)));
146 EXPECT_EQ(1u, queue.extensions_with_pending_tasks());
147 EXPECT_EQ(0, task_run_count());
148
149 // Adding a task on an extension with a lazy background page tries to create
150 // a background host, and if that fails, runs the task immediately.
151 scoped_refptr<Extension> lazy_background = CreateLazyBackgroundExtension();
152 queue.AddPendingTask(profile_.get(),
153 lazy_background->id(),
154 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask,
155 base::Unretained(this)));
156 EXPECT_EQ(2u, queue.extensions_with_pending_tasks());
157 // The process manager tried to create a background host.
158 EXPECT_EQ(1, process_manager->create_count());
159 // The task ran immediately because the creation failed.
160 EXPECT_EQ(1, task_run_count());
161 }
162
163 // Tests that pending tasks are actually run.
TEST_F(LazyBackgroundTaskQueueTest,ProcessPendingTasks)164 TEST_F(LazyBackgroundTaskQueueTest, ProcessPendingTasks) {
165 InitializeEmptyExtensionService();
166
167 LazyBackgroundTaskQueue queue(profile_.get());
168
169 // ProcessPendingTasks is a no-op if there are no tasks.
170 scoped_refptr<Extension> extension = CreateSimpleExtension();
171 queue.ProcessPendingTasks(NULL, profile_.get(), extension);
172 EXPECT_EQ(0, task_run_count());
173
174 // Schedule a task to run.
175 queue.AddPendingTask(profile_.get(),
176 extension->id(),
177 base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask,
178 base::Unretained(this)));
179 EXPECT_EQ(0, task_run_count());
180 EXPECT_EQ(1u, queue.extensions_with_pending_tasks());
181
182 // Trying to run tasks for an unrelated profile should do nothing.
183 TestingProfile profile2;
184 queue.ProcessPendingTasks(NULL, &profile2, extension);
185 EXPECT_EQ(0, task_run_count());
186 EXPECT_EQ(1u, queue.extensions_with_pending_tasks());
187
188 // Processing tasks when there is one pending runs the task and removes the
189 // extension from the list of extensions with pending tasks.
190 queue.ProcessPendingTasks(NULL, profile_.get(), extension);
191 EXPECT_EQ(1, task_run_count());
192 EXPECT_EQ(0u, queue.extensions_with_pending_tasks());
193 }
194
195 } // namespace extensions
196