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