Home | History | Annotate | Download | only in browser
      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