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: 24 explicit TestProcessManager(Profile* profile) 25 : ProcessManager(profile, profile->GetOriginalProfile()), 26 create_count_(0) {} 27 virtual ~TestProcessManager() {} 28 29 int create_count() { return create_count_; } 30 31 // ProcessManager overrides: 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: 50 LazyBackgroundTaskQueueTest() : task_run_count_(0) {} 51 virtual ~LazyBackgroundTaskQueueTest() {} 52 53 int task_run_count() { return task_run_count_; } 54 55 // A simple callback for AddPendingTask. 56 void RunPendingTask(ExtensionHost* host) { 57 task_run_count_++; 58 } 59 60 // Creates and registers an extension without a background page. 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. 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. 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. 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. 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