• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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