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