Home | History | Annotate | Download | only in extensions
      1 // Copyright (c) 2010 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 "chrome/browser/extensions/extension_browsertest.h"
      6 #include "chrome/browser/extensions/extension_service.h"
      7 #include "chrome/browser/extensions/extension_toolbar_model.h"
      8 #include "chrome/browser/profiles/profile.h"
      9 #include "chrome/browser/ui/browser.h"
     10 #include "chrome/common/chrome_switches.h"
     11 #include "chrome/test/in_process_browser_test.h"
     12 
     13 // An InProcessBrowserTest for testing the ExtensionToolbarModel.
     14 // TODO(erikkay) It's unfortunate that this needs to be an in-proc browser test.
     15 // It would be nice to refactor things so that ExtensionService could run
     16 // without so much of the browser in place.
     17 class ExtensionToolbarModelTest : public ExtensionBrowserTest,
     18                                   public ExtensionToolbarModel::Observer {
     19  public:
     20   virtual void SetUp() {
     21     inserted_count_ = 0;
     22     removed_count_ = 0;
     23     moved_count_ = 0;
     24 
     25     ExtensionBrowserTest::SetUp();
     26   }
     27 
     28   virtual Browser* CreateBrowser(Profile* profile) {
     29     Browser* b = InProcessBrowserTest::CreateBrowser(profile);
     30     ExtensionService* service = b->profile()->GetExtensionService();
     31     model_ = service->toolbar_model();
     32     model_->AddObserver(this);
     33     return b;
     34   }
     35 
     36   virtual void CleanUpOnMainThread() {
     37     model_->RemoveObserver(this);
     38   }
     39 
     40   virtual void BrowserActionAdded(const Extension* extension, int index) {
     41     inserted_count_++;
     42   }
     43 
     44   virtual void BrowserActionRemoved(const Extension* extension) {
     45     removed_count_++;
     46   }
     47 
     48   virtual void BrowserActionMoved(const Extension* extension, int index) {
     49     moved_count_++;
     50   }
     51 
     52   const Extension* ExtensionAt(int index) {
     53     for (ExtensionList::iterator i = model_->begin(); i < model_->end(); ++i) {
     54       if (index-- == 0)
     55         return *i;
     56     }
     57     return NULL;
     58   }
     59 
     60  protected:
     61   ExtensionToolbarModel* model_;
     62 
     63   int inserted_count_;
     64   int removed_count_;
     65   int moved_count_;
     66 };
     67 
     68 IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, Basic) {
     69   CommandLine::ForCurrentProcess()->AppendSwitch(
     70       switches::kEnableExperimentalExtensionApis);
     71 
     72   // Load an extension with no browser action.
     73   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
     74                                           .AppendASCII("browser_action")
     75                                           .AppendASCII("none")));
     76 
     77   // This extension should not be in the model (has no browser action).
     78   EXPECT_EQ(0, inserted_count_);
     79   EXPECT_EQ(0u, model_->size());
     80   ASSERT_EQ(NULL, ExtensionAt(0));
     81 
     82   // Load an extension with a browser action.
     83   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
     84                                           .AppendASCII("browser_action")
     85                                           .AppendASCII("basics")));
     86 
     87   // We should now find our extension in the model.
     88   EXPECT_EQ(1, inserted_count_);
     89   EXPECT_EQ(1u, model_->size());
     90   const Extension* extension = ExtensionAt(0);
     91   ASSERT_TRUE(NULL != extension);
     92   EXPECT_STREQ("A browser action with no icon that makes the page red",
     93                extension->name().c_str());
     94 
     95   // Should be a no-op, but still fires the events.
     96   model_->MoveBrowserAction(extension, 0);
     97   EXPECT_EQ(1, moved_count_);
     98   EXPECT_EQ(1u, model_->size());
     99   const Extension* extension2 = ExtensionAt(0);
    100   EXPECT_EQ(extension, extension2);
    101 
    102   UnloadExtension(extension->id());
    103   EXPECT_EQ(1, removed_count_);
    104   EXPECT_EQ(0u, model_->size());
    105   EXPECT_EQ(NULL, ExtensionAt(0));
    106 }
    107 
    108 IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, ReorderAndReinsert) {
    109   CommandLine::ForCurrentProcess()->AppendSwitch(
    110       switches::kEnableExperimentalExtensionApis);
    111 
    112   // Load an extension with a browser action.
    113   FilePath extension_a_path(test_data_dir_.AppendASCII("api_test")
    114                                           .AppendASCII("browser_action")
    115                                           .AppendASCII("basics"));
    116   ASSERT_TRUE(LoadExtension(extension_a_path));
    117 
    118   // First extension loaded.
    119   EXPECT_EQ(1, inserted_count_);
    120   EXPECT_EQ(1u, model_->size());
    121   const Extension* extensionA = ExtensionAt(0);
    122   ASSERT_TRUE(NULL != extensionA);
    123   EXPECT_STREQ("A browser action with no icon that makes the page red",
    124                extensionA->name().c_str());
    125 
    126   // Load another extension with a browser action.
    127   FilePath extension_b_path(test_data_dir_.AppendASCII("api_test")
    128                                           .AppendASCII("browser_action")
    129                                           .AppendASCII("popup"));
    130   ASSERT_TRUE(LoadExtension(extension_b_path));
    131 
    132   // Second extension loaded.
    133   EXPECT_EQ(2, inserted_count_);
    134   EXPECT_EQ(2u, model_->size());
    135   const Extension* extensionB = ExtensionAt(1);
    136   ASSERT_TRUE(NULL != extensionB);
    137   EXPECT_STREQ("Popup tester", extensionB->name().c_str());
    138 
    139   // Load yet another extension with a browser action.
    140   FilePath extension_c_path(test_data_dir_.AppendASCII("api_test")
    141                                           .AppendASCII("browser_action")
    142                                           .AppendASCII("remove_popup"));
    143   ASSERT_TRUE(LoadExtension(extension_c_path));
    144 
    145   // Third extension loaded.
    146   EXPECT_EQ(3, inserted_count_);
    147   EXPECT_EQ(3u, model_->size());
    148   const Extension* extensionC = ExtensionAt(2);
    149   ASSERT_TRUE(NULL != extensionC);
    150   EXPECT_STREQ("A page action which removes a popup.",
    151                extensionC->name().c_str());
    152 
    153   // Order is now A, B, C. Let's put C first.
    154   model_->MoveBrowserAction(extensionC, 0);
    155   EXPECT_EQ(1, moved_count_);
    156   EXPECT_EQ(3u, model_->size());
    157   EXPECT_EQ(extensionC, ExtensionAt(0));
    158   EXPECT_EQ(extensionA, ExtensionAt(1));
    159   EXPECT_EQ(extensionB, ExtensionAt(2));
    160   EXPECT_EQ(NULL, ExtensionAt(3));
    161 
    162   // Order is now C, A, B. Let's put A last.
    163   model_->MoveBrowserAction(extensionA, 2);
    164   EXPECT_EQ(2, moved_count_);
    165   EXPECT_EQ(3u, model_->size());
    166   EXPECT_EQ(extensionC, ExtensionAt(0));
    167   EXPECT_EQ(extensionB, ExtensionAt(1));
    168   EXPECT_EQ(extensionA, ExtensionAt(2));
    169   EXPECT_EQ(NULL, ExtensionAt(3));
    170 
    171   // Order is now C, B, A. Let's remove B.
    172   std::string idB = extensionB->id();
    173   UnloadExtension(idB);
    174   EXPECT_EQ(1, removed_count_);
    175   EXPECT_EQ(2u, model_->size());
    176   EXPECT_EQ(extensionC, ExtensionAt(0));
    177   EXPECT_EQ(extensionA, ExtensionAt(1));
    178   EXPECT_EQ(NULL, ExtensionAt(2));
    179 
    180   // Load extension B again.
    181   ASSERT_TRUE(LoadExtension(extension_b_path));
    182 
    183   // Extension B loaded again.
    184   EXPECT_EQ(4, inserted_count_);
    185   EXPECT_EQ(3u, model_->size());
    186   // Make sure it gets its old spot in the list. We should get the same
    187   // extension again, otherwise the order has changed.
    188   ASSERT_STREQ(idB.c_str(), ExtensionAt(1)->id().c_str());
    189 
    190   // Unload B again.
    191   UnloadExtension(idB);
    192   EXPECT_EQ(2, removed_count_);
    193   EXPECT_EQ(2u, model_->size());
    194   EXPECT_EQ(extensionC, ExtensionAt(0));
    195   EXPECT_EQ(extensionA, ExtensionAt(1));
    196   EXPECT_EQ(NULL, ExtensionAt(2));
    197 
    198   // Order is now C, A. Flip it.
    199   model_->MoveBrowserAction(extensionA, 0);
    200   EXPECT_EQ(3, moved_count_);
    201   EXPECT_EQ(2u, model_->size());
    202   EXPECT_EQ(extensionA, ExtensionAt(0));
    203   EXPECT_EQ(extensionC, ExtensionAt(1));
    204   EXPECT_EQ(NULL, ExtensionAt(2));
    205 
    206   // Move A to the location it already occupies.
    207   model_->MoveBrowserAction(extensionA, 0);
    208   EXPECT_EQ(4, moved_count_);
    209   EXPECT_EQ(2u, model_->size());
    210   EXPECT_EQ(extensionA, ExtensionAt(0));
    211   EXPECT_EQ(extensionC, ExtensionAt(1));
    212   EXPECT_EQ(NULL, ExtensionAt(2));
    213 
    214   // Order is now A, C. Remove C.
    215   std::string idC = extensionC->id();
    216   UnloadExtension(idC);
    217   EXPECT_EQ(3, removed_count_);
    218   EXPECT_EQ(1u, model_->size());
    219   EXPECT_EQ(extensionA, ExtensionAt(0));
    220   EXPECT_EQ(NULL, ExtensionAt(1));
    221 
    222   // Load extension C again.
    223   ASSERT_TRUE(LoadExtension(extension_c_path));
    224 
    225   // Extension C loaded again.
    226   EXPECT_EQ(5, inserted_count_);
    227   EXPECT_EQ(2u, model_->size());
    228   // Make sure it gets its old spot in the list (at the very end).
    229   ASSERT_STREQ(idC.c_str(), ExtensionAt(1)->id().c_str());
    230 }
    231