Home | History | Annotate | Download | only in toolbar
      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 "chrome/browser/ui/views/toolbar/browser_actions_container.h"
      6 
      7 #include "chrome/browser/chrome_notification_types.h"
      8 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
      9 #include "chrome/browser/extensions/browser_action_test_util.h"
     10 #include "chrome/browser/extensions/extension_browsertest.h"
     11 #include "chrome/browser/extensions/extension_toolbar_model.h"
     12 #include "chrome/browser/ui/browser_window.h"
     13 #include "chrome/browser/ui/views/toolbar/browser_action_view.h"
     14 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
     15 #include "content/public/test/test_utils.h"
     16 #include "extensions/browser/extension_prefs.h"
     17 #include "extensions/common/extension.h"
     18 #include "ui/gfx/geometry/point.h"
     19 #include "ui/views/view.h"
     20 
     21 class BrowserActionsContainerTest : public ExtensionBrowserTest {
     22  public:
     23   BrowserActionsContainerTest() {
     24   }
     25   virtual ~BrowserActionsContainerTest() {}
     26 
     27   virtual void SetUpOnMainThread() OVERRIDE {
     28     browser_actions_bar_.reset(new BrowserActionTestUtil(browser()));
     29   }
     30 
     31   BrowserActionTestUtil* browser_actions_bar() {
     32     return browser_actions_bar_.get();
     33   }
     34 
     35   // Make sure extension with index |extension_index| has an icon.
     36   void EnsureExtensionHasIcon(int extension_index) {
     37     if (!browser_actions_bar_->HasIcon(extension_index)) {
     38       // The icon is loaded asynchronously and a notification is then sent to
     39       // observers. So we wait on it.
     40       ExtensionAction* browser_action =
     41           browser_actions_bar_->GetExtensionAction(extension_index);
     42 
     43       content::WindowedNotificationObserver observer(
     44           chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED,
     45           content::Source<ExtensionAction>(browser_action));
     46       observer.Wait();
     47     }
     48     EXPECT_TRUE(browser_actions_bar()->HasIcon(extension_index));
     49   }
     50 
     51  private:
     52   scoped_ptr<BrowserActionTestUtil> browser_actions_bar_;
     53 };
     54 
     55 // Test the basic functionality.
     56 // http://crbug.com/120770
     57 #if defined(OS_WIN)
     58 IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest, DISABLED_Basic) {
     59 #else
     60 IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest, Basic) {
     61 #endif
     62   BrowserActionsContainer::disable_animations_during_testing_ = true;
     63 
     64   // Load an extension with no browser action.
     65   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
     66                                           .AppendASCII("browser_action")
     67                                           .AppendASCII("none")));
     68   // This extension should not be in the model (has no browser action).
     69   EXPECT_EQ(0, browser_actions_bar()->NumberOfBrowserActions());
     70 
     71   // Load an extension with a browser action.
     72   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
     73                                           .AppendASCII("browser_action")
     74                                           .AppendASCII("basics")));
     75   EXPECT_EQ(1, browser_actions_bar()->NumberOfBrowserActions());
     76   EnsureExtensionHasIcon(0);
     77 
     78   // Unload the extension.
     79   std::string id = browser_actions_bar()->GetExtensionId(0);
     80   UnloadExtension(id);
     81   EXPECT_EQ(0, browser_actions_bar()->NumberOfBrowserActions());
     82 }
     83 
     84 IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest, Visibility) {
     85   BrowserActionsContainer::disable_animations_during_testing_ = true;
     86 
     87   // Load extension A (contains browser action).
     88   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
     89                                           .AppendASCII("browser_action")
     90                                           .AppendASCII("basics")));
     91   EXPECT_EQ(1, browser_actions_bar()->NumberOfBrowserActions());
     92   EnsureExtensionHasIcon(0);
     93   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
     94   std::string idA = browser_actions_bar()->GetExtensionId(0);
     95 
     96   // Load extension B (contains browser action).
     97   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
     98                                           .AppendASCII("browser_action")
     99                                           .AppendASCII("add_popup")));
    100   EXPECT_EQ(2, browser_actions_bar()->NumberOfBrowserActions());
    101   EnsureExtensionHasIcon(0);
    102   EXPECT_EQ(2, browser_actions_bar()->VisibleBrowserActions());
    103   std::string idB = browser_actions_bar()->GetExtensionId(1);
    104 
    105   EXPECT_NE(idA, idB);
    106 
    107   // Load extension C (contains browser action).
    108   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
    109                                           .AppendASCII("browser_action")
    110                                           .AppendASCII("remove_popup")));
    111   EXPECT_EQ(3, browser_actions_bar()->NumberOfBrowserActions());
    112   EnsureExtensionHasIcon(2);
    113   EXPECT_EQ(3, browser_actions_bar()->VisibleBrowserActions());
    114   std::string idC = browser_actions_bar()->GetExtensionId(2);
    115 
    116   // Change container to show only one action, rest in overflow: A, [B, C].
    117   browser_actions_bar()->SetIconVisibilityCount(1);
    118   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
    119 
    120   // Disable extension A (should disappear). State becomes: B [C].
    121   DisableExtension(idA);
    122   EXPECT_EQ(2, browser_actions_bar()->NumberOfBrowserActions());
    123   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
    124   EXPECT_EQ(idB, browser_actions_bar()->GetExtensionId(0));
    125 
    126   // Enable A again. A should get its spot in the same location and the bar
    127   // should not grow (chevron is showing). For details: http://crbug.com/35349.
    128   // State becomes: A, [B, C].
    129   EnableExtension(idA);
    130   EXPECT_EQ(3, browser_actions_bar()->NumberOfBrowserActions());
    131   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
    132   EXPECT_EQ(idA, browser_actions_bar()->GetExtensionId(0));
    133 
    134   // Disable C (in overflow). State becomes: A, [B].
    135   DisableExtension(idC);
    136   EXPECT_EQ(2, browser_actions_bar()->NumberOfBrowserActions());
    137   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
    138   EXPECT_EQ(idA, browser_actions_bar()->GetExtensionId(0));
    139 
    140   // Enable C again. State becomes: A, [B, C].
    141   EnableExtension(idC);
    142   EXPECT_EQ(3, browser_actions_bar()->NumberOfBrowserActions());
    143   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
    144   EXPECT_EQ(idA, browser_actions_bar()->GetExtensionId(0));
    145 
    146   // Now we have 3 extensions. Make sure they are all visible. State: A, B, C.
    147   browser_actions_bar()->SetIconVisibilityCount(3);
    148   EXPECT_EQ(3, browser_actions_bar()->VisibleBrowserActions());
    149 
    150   // Disable extension A (should disappear). State becomes: B, C.
    151   DisableExtension(idA);
    152   EXPECT_EQ(2, browser_actions_bar()->NumberOfBrowserActions());
    153   EXPECT_EQ(2, browser_actions_bar()->VisibleBrowserActions());
    154   EXPECT_EQ(idB, browser_actions_bar()->GetExtensionId(0));
    155 
    156   // Disable extension B (should disappear). State becomes: C.
    157   DisableExtension(idB);
    158   EXPECT_EQ(1, browser_actions_bar()->NumberOfBrowserActions());
    159   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
    160   EXPECT_EQ(idC, browser_actions_bar()->GetExtensionId(0));
    161 
    162   // Enable B. State becomes: B, C.
    163   EnableExtension(idB);
    164   EXPECT_EQ(2, browser_actions_bar()->NumberOfBrowserActions());
    165   EXPECT_EQ(2, browser_actions_bar()->VisibleBrowserActions());
    166   EXPECT_EQ(idB, browser_actions_bar()->GetExtensionId(0));
    167 
    168   // Enable A. State becomes: A, B, C.
    169   EnableExtension(idA);
    170   EXPECT_EQ(3, browser_actions_bar()->NumberOfBrowserActions());
    171   EXPECT_EQ(3, browser_actions_bar()->VisibleBrowserActions());
    172   EXPECT_EQ(idA, browser_actions_bar()->GetExtensionId(0));
    173 }
    174 
    175 IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest, ForceHide) {
    176   BrowserActionsContainer::disable_animations_during_testing_ = true;
    177 
    178   // Load extension A (contains browser action).
    179   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
    180                                           .AppendASCII("browser_action")
    181                                           .AppendASCII("basics")));
    182   EXPECT_EQ(1, browser_actions_bar()->NumberOfBrowserActions());
    183   EnsureExtensionHasIcon(0);
    184   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
    185   std::string idA = browser_actions_bar()->GetExtensionId(0);
    186 
    187   // Force hide this browser action.
    188   extensions::ExtensionActionAPI::SetBrowserActionVisibility(
    189       extensions::ExtensionPrefs::Get(browser()->profile()), idA, false);
    190   EXPECT_EQ(0, browser_actions_bar()->VisibleBrowserActions());
    191 }
    192 
    193 // Test that the BrowserActionsContainer responds correctly when the underlying
    194 // model enters highlight mode, and that browser actions are undraggable in
    195 // highlight mode. (Highlight mode itself it tested more thoroughly in the
    196 // ExtensionToolbarModel browsertests).
    197 IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest, HighlightMode) {
    198   BrowserActionsContainer::disable_animations_during_testing_ = true;
    199 
    200   // Load three extensions with browser actions.
    201   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
    202                                           .AppendASCII("browser_action")
    203                                           .AppendASCII("basics")));
    204   std::string id_a = browser_actions_bar()->GetExtensionId(0);
    205   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
    206                                           .AppendASCII("browser_action")
    207                                           .AppendASCII("add_popup")));
    208   std::string id_b = browser_actions_bar()->GetExtensionId(1);
    209   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
    210                                           .AppendASCII("browser_action")
    211                                           .AppendASCII("remove_popup")));
    212 
    213   EXPECT_EQ(3, browser_actions_bar()->VisibleBrowserActions());
    214   EXPECT_EQ(3, browser_actions_bar()->NumberOfBrowserActions());
    215 
    216   BrowserActionsContainer* container = browser()
    217                                            ->window()
    218                                            ->GetBrowserWindowTesting()
    219                                            ->GetToolbarView()
    220                                            ->browser_actions();
    221 
    222   // Currently, dragging should be enabled.
    223   BrowserActionView* action_view = container->GetBrowserActionViewAt(0);
    224   ASSERT_TRUE(action_view);
    225   gfx::Point point(action_view->x(), action_view->y());
    226   EXPECT_TRUE(container->CanStartDragForView(action_view, point, point));
    227 
    228   extensions::ExtensionToolbarModel* model =
    229       extensions::ExtensionToolbarModel::Get(profile());
    230 
    231   extensions::ExtensionIdList extension_ids;
    232   extension_ids.push_back(id_a);
    233   extension_ids.push_back(id_b);
    234   model->HighlightExtensions(extension_ids);
    235 
    236   // Only two browser actions should be visible.
    237   EXPECT_EQ(2, browser_actions_bar()->VisibleBrowserActions());
    238   EXPECT_EQ(2, browser_actions_bar()->NumberOfBrowserActions());
    239 
    240   // We shouldn't be able to drag in highlight mode.
    241   action_view = container->GetBrowserActionViewAt(0);
    242   EXPECT_FALSE(container->CanStartDragForView(action_view, point, point));
    243 
    244   // We should go back to normal after leaving highlight mode.
    245   model->StopHighlighting();
    246   EXPECT_EQ(3, browser_actions_bar()->VisibleBrowserActions());
    247   EXPECT_EQ(3, browser_actions_bar()->NumberOfBrowserActions());
    248   action_view = container->GetBrowserActionViewAt(0);
    249   EXPECT_TRUE(container->CanStartDragForView(action_view, point, point));
    250 }
    251