blob: 35c02b87abd740ad5c040d1ac7aa0e1023070bfb [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "extensions/browser/lazy_background_task_queue.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "chrome/browser/extensions/extension_service_unittest.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "extensions/browser/process_manager.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace extensions {
// A ProcessManager that doesn't create background host pages.
class TestProcessManager : public ProcessManager {
public:
explicit TestProcessManager(Profile* profile)
: ProcessManager(profile, profile->GetOriginalProfile()),
create_count_(0) {}
virtual ~TestProcessManager() {}
int create_count() { return create_count_; }
// ProcessManager overrides:
virtual ExtensionHost* CreateBackgroundHost(const Extension* extension,
const GURL& url) OVERRIDE {
// Don't actually try to create a web contents.
create_count_++;
return NULL;
}
private:
int create_count_;
DISALLOW_COPY_AND_ASSIGN(TestProcessManager);
};
// Derives from ExtensionServiceTestBase because ExtensionService is difficult
// to initialize alone.
class LazyBackgroundTaskQueueTest : public ExtensionServiceTestBase {
public:
LazyBackgroundTaskQueueTest() : task_run_count_(0) {}
virtual ~LazyBackgroundTaskQueueTest() {}
int task_run_count() { return task_run_count_; }
// A simple callback for AddPendingTask.
void RunPendingTask(ExtensionHost* host) {
task_run_count_++;
}
// Creates and registers an extension without a background page.
scoped_refptr<Extension> CreateSimpleExtension() {
scoped_refptr<Extension> extension = ExtensionBuilder()
.SetManifest(DictionaryBuilder()
.Set("name", "No background")
.Set("version", "1")
.Set("manifest_version", 2))
.SetID("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
.Build();
service_->AddExtension(extension);
return extension;
}
// Creates and registers an extension with a lazy background page.
scoped_refptr<Extension> CreateLazyBackgroundExtension() {
scoped_refptr<Extension> extension = ExtensionBuilder()
.SetManifest(DictionaryBuilder()
.Set("name", "Lazy background")
.Set("version", "1")
.Set("manifest_version", 2)
.Set("background",
DictionaryBuilder()
.Set("page", "background.html")
.SetBoolean("persistent", false)))
.SetID("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
.Build();
service_->AddExtension(extension);
return extension;
}
private:
// The total number of pending tasks that have been executed.
int task_run_count_;
DISALLOW_COPY_AND_ASSIGN(LazyBackgroundTaskQueueTest);
};
// Tests that only extensions with background pages should have tasks queued.
TEST_F(LazyBackgroundTaskQueueTest, ShouldEnqueueTask) {
InitializeEmptyExtensionService();
InitializeProcessManager();
LazyBackgroundTaskQueue queue(profile_.get());
// Build a simple extension with no background page.
scoped_refptr<Extension> no_background = CreateSimpleExtension();
EXPECT_FALSE(queue.ShouldEnqueueTask(profile_.get(), no_background.get()));
// Build another extension with a background page.
scoped_refptr<Extension> with_background = CreateLazyBackgroundExtension();
EXPECT_TRUE(queue.ShouldEnqueueTask(profile_.get(), with_background.get()));
}
// Tests that adding tasks actually increases the pending task count, and that
// multiple extensions can have pending tasks.
TEST_F(LazyBackgroundTaskQueueTest, AddPendingTask) {
InitializeEmptyExtensionService();
// Swap in our stub TestProcessManager.
TestExtensionSystem* extension_system =
static_cast<extensions::TestExtensionSystem*>(
ExtensionSystem::Get(profile_.get()));
// Owned by |extension_system|.
TestProcessManager* process_manager = new TestProcessManager(profile_.get());
extension_system->SetProcessManager(process_manager);
LazyBackgroundTaskQueue queue(profile_.get());
// Build a simple extension with no background page.
scoped_refptr<Extension> no_background = CreateSimpleExtension();
// Adding a pending task increases the number of extensions with tasks, but
// doesn't run the task.
queue.AddPendingTask(profile_.get(),
no_background->id(),
base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask,
base::Unretained(this)));
EXPECT_EQ(1u, queue.extensions_with_pending_tasks());
EXPECT_EQ(0, task_run_count());
// Another task on the same extension doesn't increase the number of
// extensions that have tasks and doesn't run any tasks.
queue.AddPendingTask(profile_.get(),
no_background->id(),
base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask,
base::Unretained(this)));
EXPECT_EQ(1u, queue.extensions_with_pending_tasks());
EXPECT_EQ(0, task_run_count());
// Adding a task on an extension with a lazy background page tries to create
// a background host, and if that fails, runs the task immediately.
scoped_refptr<Extension> lazy_background = CreateLazyBackgroundExtension();
queue.AddPendingTask(profile_.get(),
lazy_background->id(),
base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask,
base::Unretained(this)));
EXPECT_EQ(2u, queue.extensions_with_pending_tasks());
// The process manager tried to create a background host.
EXPECT_EQ(1, process_manager->create_count());
// The task ran immediately because the creation failed.
EXPECT_EQ(1, task_run_count());
}
// Tests that pending tasks are actually run.
TEST_F(LazyBackgroundTaskQueueTest, ProcessPendingTasks) {
InitializeEmptyExtensionService();
LazyBackgroundTaskQueue queue(profile_.get());
// ProcessPendingTasks is a no-op if there are no tasks.
scoped_refptr<Extension> extension = CreateSimpleExtension();
queue.ProcessPendingTasks(NULL, profile_.get(), extension);
EXPECT_EQ(0, task_run_count());
// Schedule a task to run.
queue.AddPendingTask(profile_.get(),
extension->id(),
base::Bind(&LazyBackgroundTaskQueueTest::RunPendingTask,
base::Unretained(this)));
EXPECT_EQ(0, task_run_count());
EXPECT_EQ(1u, queue.extensions_with_pending_tasks());
// Trying to run tasks for an unrelated profile should do nothing.
TestingProfile profile2;
queue.ProcessPendingTasks(NULL, &profile2, extension);
EXPECT_EQ(0, task_run_count());
EXPECT_EQ(1u, queue.extensions_with_pending_tasks());
// Processing tasks when there is one pending runs the task and removes the
// extension from the list of extensions with pending tasks.
queue.ProcessPendingTasks(NULL, profile_.get(), extension);
EXPECT_EQ(1, task_run_count());
EXPECT_EQ(0u, queue.extensions_with_pending_tasks());
}
} // namespace extensions