Home | History | Annotate | Download | only in extensions
      1 // Copyright (c) 2011 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_system.h"
      8 #include "chrome/browser/extensions/extension_toolbar_model.h"
      9 #include "chrome/browser/profiles/profile.h"
     10 #include "chrome/browser/ui/browser.h"
     11 #include "chrome/test/base/in_process_browser_test.h"
     12 
     13 using extensions::Extension;
     14 
     15 // An InProcessBrowserTest for testing the ExtensionToolbarModel.
     16 // TODO(erikkay) It's unfortunate that this needs to be an in-proc browser test.
     17 // It would be nice to refactor things so that ExtensionService could run
     18 // without so much of the browser in place.
     19 class ExtensionToolbarModelTest : public ExtensionBrowserTest,
     20                                   public ExtensionToolbarModel::Observer {
     21  public:
     22   virtual void SetUp() {
     23     inserted_count_ = 0;
     24     removed_count_ = 0;
     25     moved_count_ = 0;
     26 
     27     ExtensionBrowserTest::SetUp();
     28   }
     29 
     30   virtual void SetUpOnMainThread() OVERRIDE {
     31     ExtensionService* service = extensions::ExtensionSystem::Get(
     32         browser()->profile())->extension_service();
     33     model_ = service->toolbar_model();
     34     model_->AddObserver(this);
     35   }
     36 
     37   virtual void CleanUpOnMainThread() OVERRIDE {
     38     model_->RemoveObserver(this);
     39   }
     40 
     41   virtual void BrowserActionAdded(const Extension* extension,
     42                                   int index) OVERRIDE {
     43     inserted_count_++;
     44   }
     45 
     46   virtual void BrowserActionRemoved(const Extension* extension) OVERRIDE {
     47     removed_count_++;
     48   }
     49 
     50   virtual void BrowserActionMoved(const Extension* extension,
     51                                   int index) OVERRIDE {
     52     moved_count_++;
     53   }
     54 
     55   const Extension* ExtensionAt(int index) {
     56     const extensions::ExtensionList& toolbar_items = model_->toolbar_items();
     57     for (extensions::ExtensionList::const_iterator i = toolbar_items.begin();
     58          i < toolbar_items.end(); ++i) {
     59       if (index-- == 0)
     60         return i->get();
     61     }
     62     return NULL;
     63   }
     64 
     65  protected:
     66   ExtensionToolbarModel* model_;
     67 
     68   int inserted_count_;
     69   int removed_count_;
     70   int moved_count_;
     71 };
     72 
     73 IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, Basic) {
     74   // Load an extension with no browser action.
     75   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
     76                                           .AppendASCII("browser_action")
     77                                           .AppendASCII("none")));
     78 
     79   // This extension should not be in the model (has no browser action).
     80   EXPECT_EQ(0, inserted_count_);
     81   EXPECT_EQ(0u, model_->toolbar_items().size());
     82   ASSERT_EQ(NULL, ExtensionAt(0));
     83 
     84   // Load an extension with a browser action.
     85   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
     86                                           .AppendASCII("browser_action")
     87                                           .AppendASCII("basics")));
     88 
     89   // We should now find our extension in the model.
     90   EXPECT_EQ(1, inserted_count_);
     91   EXPECT_EQ(1u, model_->toolbar_items().size());
     92   const Extension* extension = ExtensionAt(0);
     93   ASSERT_TRUE(NULL != extension);
     94   EXPECT_STREQ("A browser action with no icon that makes the page red",
     95                extension->name().c_str());
     96 
     97   // Should be a no-op, but still fires the events.
     98   model_->MoveBrowserAction(extension, 0);
     99   EXPECT_EQ(1, moved_count_);
    100   EXPECT_EQ(1u, model_->toolbar_items().size());
    101   const Extension* extension2 = ExtensionAt(0);
    102   EXPECT_EQ(extension, extension2);
    103 
    104   UnloadExtension(extension->id());
    105   EXPECT_EQ(1, removed_count_);
    106   EXPECT_EQ(0u, model_->toolbar_items().size());
    107   EXPECT_EQ(NULL, ExtensionAt(0));
    108 }
    109 
    110 IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, ReorderAndReinsert) {
    111   // Load an extension with a browser action.
    112   base::FilePath extension_a_path(test_data_dir_.AppendASCII("api_test")
    113                                           .AppendASCII("browser_action")
    114                                           .AppendASCII("basics"));
    115   ASSERT_TRUE(LoadExtension(extension_a_path));
    116 
    117   // First extension loaded.
    118   EXPECT_EQ(1, inserted_count_);
    119   EXPECT_EQ(1u, model_->toolbar_items().size());
    120   const Extension* extensionA = ExtensionAt(0);
    121   ASSERT_TRUE(NULL != extensionA);
    122   EXPECT_STREQ("A browser action with no icon that makes the page red",
    123                extensionA->name().c_str());
    124 
    125   // Load another extension with a browser action.
    126   base::FilePath extension_b_path(test_data_dir_.AppendASCII("api_test")
    127                                           .AppendASCII("browser_action")
    128                                           .AppendASCII("popup"));
    129   ASSERT_TRUE(LoadExtension(extension_b_path));
    130 
    131   // Second extension loaded.
    132   EXPECT_EQ(2, inserted_count_);
    133   EXPECT_EQ(2u, model_->toolbar_items().size());
    134   const Extension* extensionB = ExtensionAt(1);
    135   ASSERT_TRUE(NULL != extensionB);
    136   EXPECT_STREQ("Popup tester", extensionB->name().c_str());
    137 
    138   // Load yet another extension with a browser action.
    139   base::FilePath extension_c_path(test_data_dir_.AppendASCII("api_test")
    140                                           .AppendASCII("browser_action")
    141                                           .AppendASCII("remove_popup"));
    142   ASSERT_TRUE(LoadExtension(extension_c_path));
    143 
    144   // Third extension loaded.
    145   EXPECT_EQ(3, inserted_count_);
    146   EXPECT_EQ(3u, model_->toolbar_items().size());
    147   const Extension* extensionC = ExtensionAt(2);
    148   ASSERT_TRUE(NULL != extensionC);
    149   EXPECT_STREQ("A page action which removes a popup.",
    150                extensionC->name().c_str());
    151 
    152   // Order is now A, B, C. Let's put C first.
    153   model_->MoveBrowserAction(extensionC, 0);
    154   EXPECT_EQ(1, moved_count_);
    155   EXPECT_EQ(3u, model_->toolbar_items().size());
    156   EXPECT_EQ(extensionC, ExtensionAt(0));
    157   EXPECT_EQ(extensionA, ExtensionAt(1));
    158   EXPECT_EQ(extensionB, ExtensionAt(2));
    159   EXPECT_EQ(NULL, ExtensionAt(3));
    160 
    161   // Order is now C, A, B. Let's put A last.
    162   model_->MoveBrowserAction(extensionA, 2);
    163   EXPECT_EQ(2, moved_count_);
    164   EXPECT_EQ(3u, model_->toolbar_items().size());
    165   EXPECT_EQ(extensionC, ExtensionAt(0));
    166   EXPECT_EQ(extensionB, ExtensionAt(1));
    167   EXPECT_EQ(extensionA, ExtensionAt(2));
    168   EXPECT_EQ(NULL, ExtensionAt(3));
    169 
    170   // Order is now C, B, A. Let's remove B.
    171   std::string idB = extensionB->id();
    172   UnloadExtension(idB);
    173   EXPECT_EQ(1, removed_count_);
    174   EXPECT_EQ(2u, model_->toolbar_items().size());
    175   EXPECT_EQ(extensionC, ExtensionAt(0));
    176   EXPECT_EQ(extensionA, ExtensionAt(1));
    177   EXPECT_EQ(NULL, ExtensionAt(2));
    178 
    179   // Load extension B again.
    180   ASSERT_TRUE(LoadExtension(extension_b_path));
    181 
    182   // Extension B loaded again.
    183   EXPECT_EQ(4, inserted_count_);
    184   EXPECT_EQ(3u, model_->toolbar_items().size());
    185   // Make sure it gets its old spot in the list. We should get the same
    186   // extension again, otherwise the order has changed.
    187   ASSERT_STREQ(idB.c_str(), ExtensionAt(1)->id().c_str());
    188 
    189   // Unload B again.
    190   UnloadExtension(idB);
    191   EXPECT_EQ(2, removed_count_);
    192   EXPECT_EQ(2u, model_->toolbar_items().size());
    193   EXPECT_EQ(extensionC, ExtensionAt(0));
    194   EXPECT_EQ(extensionA, ExtensionAt(1));
    195   EXPECT_EQ(NULL, ExtensionAt(2));
    196 
    197   // Order is now C, A. Flip it.
    198   model_->MoveBrowserAction(extensionA, 0);
    199   EXPECT_EQ(3, moved_count_);
    200   EXPECT_EQ(2u, model_->toolbar_items().size());
    201   EXPECT_EQ(extensionA, ExtensionAt(0));
    202   EXPECT_EQ(extensionC, ExtensionAt(1));
    203   EXPECT_EQ(NULL, ExtensionAt(2));
    204 
    205   // Move A to the location it already occupies.
    206   model_->MoveBrowserAction(extensionA, 0);
    207   EXPECT_EQ(4, moved_count_);
    208   EXPECT_EQ(2u, model_->toolbar_items().size());
    209   EXPECT_EQ(extensionA, ExtensionAt(0));
    210   EXPECT_EQ(extensionC, ExtensionAt(1));
    211   EXPECT_EQ(NULL, ExtensionAt(2));
    212 
    213   // Order is now A, C. Remove C.
    214   std::string idC = extensionC->id();
    215   UnloadExtension(idC);
    216   EXPECT_EQ(3, removed_count_);
    217   EXPECT_EQ(1u, model_->toolbar_items().size());
    218   EXPECT_EQ(extensionA, ExtensionAt(0));
    219   EXPECT_EQ(NULL, ExtensionAt(1));
    220 
    221   // Load extension C again.
    222   ASSERT_TRUE(LoadExtension(extension_c_path));
    223 
    224   // Extension C loaded again.
    225   EXPECT_EQ(5, inserted_count_);
    226   EXPECT_EQ(2u, model_->toolbar_items().size());
    227   // Make sure it gets its old spot in the list (at the very end).
    228   ASSERT_STREQ(idC.c_str(), ExtensionAt(1)->id().c_str());
    229 }
    230 
    231 IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, UnloadAndDisableMultiple) {
    232   // Load three extensions with browser action.
    233   base::FilePath extension_a_path(test_data_dir_.AppendASCII("api_test")
    234                                                 .AppendASCII("browser_action")
    235                                                 .AppendASCII("basics"));
    236   ASSERT_TRUE(LoadExtension(extension_a_path));
    237   base::FilePath extension_b_path(test_data_dir_.AppendASCII("api_test")
    238                                                 .AppendASCII("browser_action")
    239                                                 .AppendASCII("popup"));
    240   ASSERT_TRUE(LoadExtension(extension_b_path));
    241   base::FilePath extension_c_path(test_data_dir_.AppendASCII("api_test")
    242                                                 .AppendASCII("browser_action")
    243                                                 .AppendASCII("remove_popup"));
    244   ASSERT_TRUE(LoadExtension(extension_c_path));
    245 
    246   // Verify we got the three we asked for and that they are ordered as: A, B, C.
    247   const Extension* extensionA = ExtensionAt(0);
    248   const Extension* extensionB = ExtensionAt(1);
    249   const Extension* extensionC = ExtensionAt(2);
    250   std::string idA = extensionA->id();
    251   std::string idB = extensionB->id();
    252   std::string idC = extensionC->id();
    253   EXPECT_STREQ("A browser action with no icon that makes the page red",
    254                extensionA->name().c_str());
    255   EXPECT_STREQ("Popup tester", extensionB->name().c_str());
    256   EXPECT_STREQ("A page action which removes a popup.",
    257                extensionC->name().c_str());
    258 
    259   // Unload B, then C, then A.
    260   UnloadExtension(idB);
    261   UnloadExtension(idC);
    262   UnloadExtension(idA);
    263 
    264   // Load C, then A, then B.
    265   ASSERT_TRUE(LoadExtension(extension_c_path));
    266   ASSERT_TRUE(LoadExtension(extension_a_path));
    267   ASSERT_TRUE(LoadExtension(extension_b_path));
    268   EXPECT_EQ(0, moved_count_);
    269 
    270   extensionA = ExtensionAt(0);
    271   extensionB = ExtensionAt(1);
    272   extensionC = ExtensionAt(2);
    273 
    274   // Make sure we get the order we started with (A, B, C).
    275   EXPECT_STREQ(idA.c_str(), extensionA->id().c_str());
    276   EXPECT_STREQ(idB.c_str(), extensionB->id().c_str());
    277   EXPECT_STREQ(idC.c_str(), extensionC->id().c_str());
    278 
    279   // Put C in the middle and A to the end.
    280   model_->MoveBrowserAction(extensionC, 1);
    281   model_->MoveBrowserAction(extensionA, 2);
    282 
    283   // Make sure we get this order (C, B, A).
    284   EXPECT_STREQ(idC.c_str(), ExtensionAt(0)->id().c_str());
    285   EXPECT_STREQ(idB.c_str(), ExtensionAt(1)->id().c_str());
    286   EXPECT_STREQ(idA.c_str(), ExtensionAt(2)->id().c_str());
    287 
    288   // Disable B, then C, then A.
    289   DisableExtension(idB);
    290   DisableExtension(idC);
    291   DisableExtension(idA);
    292 
    293   // Enable C, then A, then B.
    294   EnableExtension(idA);
    295   EnableExtension(idB);
    296   EnableExtension(idC);
    297 
    298   // Make sure we get the order we started with.
    299   EXPECT_STREQ(idC.c_str(), ExtensionAt(0)->id().c_str());
    300   EXPECT_STREQ(idB.c_str(), ExtensionAt(1)->id().c_str());
    301   EXPECT_STREQ(idA.c_str(), ExtensionAt(2)->id().c_str());
    302 }
    303 
    304 IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, Uninstall) {
    305   // Load two extensions with browser action.
    306   base::FilePath extension_a_path(test_data_dir_.AppendASCII("api_test")
    307                                                 .AppendASCII("browser_action")
    308                                                 .AppendASCII("basics"));
    309   ASSERT_TRUE(LoadExtension(extension_a_path));
    310   base::FilePath extension_b_path(test_data_dir_.AppendASCII("api_test")
    311                                                 .AppendASCII("browser_action")
    312                                                 .AppendASCII("popup"));
    313   ASSERT_TRUE(LoadExtension(extension_b_path));
    314 
    315   // Verify we got what we came for.
    316   const Extension* extensionA = ExtensionAt(0);
    317   const Extension* extensionB = ExtensionAt(1);
    318   std::string idA = extensionA->id();
    319   std::string idB = extensionB->id();
    320   EXPECT_STREQ("A browser action with no icon that makes the page red",
    321                extensionA->name().c_str());
    322   EXPECT_STREQ("Popup tester", extensionB->name().c_str());
    323 
    324   // Order is now A, B. Make B first.
    325   model_->MoveBrowserAction(extensionB, 0);
    326 
    327   // Order is now B, A. Uninstall Extension B.
    328   UninstallExtension(idB);
    329 
    330   // List contains only A now. Validate that.
    331   EXPECT_STREQ(idA.c_str(), ExtensionAt(0)->id().c_str());
    332   EXPECT_EQ(1u, model_->toolbar_items().size());
    333 
    334   // Load Extension B again.
    335   ASSERT_TRUE(LoadExtension(extension_b_path));
    336   EXPECT_EQ(2u, model_->toolbar_items().size());
    337 
    338   // Make sure Extension B is _not_ first (should have been forgotten at
    339   // uninstall time).
    340   EXPECT_STREQ(idA.c_str(), ExtensionAt(0)->id().c_str());
    341   EXPECT_STREQ(idB.c_str(), ExtensionAt(1)->id().c_str());
    342 }
    343 
    344 IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, ReorderOnPrefChange) {
    345   // Load three extensions with browser action.
    346   base::FilePath extension_a_path(test_data_dir_.AppendASCII("api_test")
    347                                                 .AppendASCII("browser_action")
    348                                                 .AppendASCII("basics"));
    349   ASSERT_TRUE(LoadExtension(extension_a_path));
    350   base::FilePath extension_b_path(test_data_dir_.AppendASCII("api_test")
    351                                                 .AppendASCII("browser_action")
    352                                                 .AppendASCII("popup"));
    353   ASSERT_TRUE(LoadExtension(extension_b_path));
    354   base::FilePath extension_c_path(test_data_dir_.AppendASCII("api_test")
    355                                                 .AppendASCII("browser_action")
    356                                                 .AppendASCII("remove_popup"));
    357   ASSERT_TRUE(LoadExtension(extension_c_path));
    358   std::string id_a = ExtensionAt(0)->id();
    359   std::string id_b = ExtensionAt(1)->id();
    360   std::string id_c = ExtensionAt(2)->id();
    361 
    362   // Change value of toolbar preference.
    363   extensions::ExtensionIdList new_order;
    364   new_order.push_back(id_c);
    365   new_order.push_back(id_b);
    366   extensions::ExtensionPrefs::Get(browser()->profile())->SetToolbarOrder(
    367       new_order);
    368 
    369   // Verify order is changed.
    370   EXPECT_EQ(id_c, ExtensionAt(0)->id());
    371   EXPECT_EQ(id_b, ExtensionAt(1)->id());
    372   EXPECT_EQ(id_a, ExtensionAt(2)->id());
    373 }
    374