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