Revert of Remove OneClickSigninHelper since it is no longer used. (patchset #5 id...
[chromium-blink-merge.git] / chrome / browser / ui / toolbar / toolbar_actions_bar_unittest.cc
blob4924008668efcaded906e8bdf40ad2baccc686cf
1 // Copyright 2014 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.
5 #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
7 #include "base/command_line.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/run_loop.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
13 #include "chrome/browser/extensions/browser_action_test_util.h"
14 #include "chrome/browser/extensions/extension_action.h"
15 #include "chrome/browser/extensions/extension_action_manager.h"
16 #include "chrome/browser/extensions/extension_action_test_util.h"
17 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/extensions/test_extension_system.h"
19 #include "chrome/browser/sessions/session_tab_helper.h"
20 #include "chrome/browser/ui/tabs/tab_strip_model.h"
21 #include "chrome/browser/ui/toolbar/test_toolbar_actions_bar_helper.h"
22 #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h"
23 #include "chrome/browser/ui/toolbar/toolbar_actions_bar_delegate.h"
24 #include "chrome/test/base/browser_with_test_window_test.h"
25 #include "extensions/browser/extension_system.h"
26 #include "extensions/common/extension.h"
27 #include "extensions/common/feature_switch.h"
29 namespace {
31 // Verifies that the toolbar order matches for the given |actions_bar|. If the
32 // order matches, the return value is empty; otherwise, it contains the error.
33 std::string VerifyToolbarOrderForBar(
34 const ToolbarActionsBar* actions_bar,
35 BrowserActionTestUtil* browser_action_test_util,
36 const char* expected_names[],
37 size_t total_size,
38 size_t visible_count) {
39 const std::vector<ToolbarActionViewController*>& toolbar_actions =
40 actions_bar->toolbar_actions();
41 // If the total size is wrong, we risk segfaulting by continuing. Abort now.
42 if (total_size != toolbar_actions.size()) {
43 return base::StringPrintf("Incorrect action count: expected %d, found %d",
44 static_cast<int>(total_size),
45 static_cast<int>(toolbar_actions.size()));
48 // Check that the ToolbarActionsBar matches the expected state.
49 std::string error;
50 for (size_t i = 0; i < total_size; ++i) {
51 if (std::string(expected_names[i]) !=
52 base::UTF16ToUTF8(toolbar_actions[i]->GetActionName())) {
53 error += base::StringPrintf(
54 "Incorrect action in bar at index %d: expected '%s', found '%s'.\n",
55 static_cast<int>(i),
56 expected_names[i],
57 base::UTF16ToUTF8(toolbar_actions[i]->GetActionName()).c_str());
60 size_t icon_count = actions_bar->GetIconCount();
61 if (visible_count != icon_count)
62 error += base::StringPrintf(
63 "Incorrect visible count: expected %d, found %d.\n",
64 static_cast<int>(visible_count), static_cast<int>(icon_count));
66 // Test that the (platform-specific) toolbar view matches the expected state.
67 for (size_t i = 0; i < total_size; ++i) {
68 std::string id = browser_action_test_util->GetExtensionId(i);
69 if (id != toolbar_actions[i]->GetId()) {
70 error += base::StringPrintf(
71 "Incorrect action in view at index %d: expected '%s', found '%s'.\n",
72 static_cast<int>(i),
73 toolbar_actions[i]->GetId().c_str(),
74 id.c_str());
77 size_t view_icon_count = browser_action_test_util->VisibleBrowserActions();
78 if (visible_count != view_icon_count)
79 error += base::StringPrintf(
80 "Incorrect visible count in view: expected %d, found %d.\n",
81 static_cast<int>(visible_count), static_cast<int>(view_icon_count));
83 return error;
86 } // namespace
88 // A cross-platform unit test for the ToolbarActionsBar that uses the
89 // TestToolbarActionsBarHelper to create the platform-specific containers.
90 // TODO(devlin): Since this *does* use the real platform containers, in theory,
91 // we can move all the BrowserActionsBarBrowserTests to be unittests. See about
92 // doing this.
93 class ToolbarActionsBarUnitTest : public BrowserWithTestWindowTest {
94 public:
95 ToolbarActionsBarUnitTest() : toolbar_model_(nullptr), use_redesign_(false) {}
97 // A constructor to allow subclasses to override the redesign value.
98 explicit ToolbarActionsBarUnitTest(bool use_redesign)
99 : toolbar_model_(nullptr),
100 use_redesign_(use_redesign) {}
102 ~ToolbarActionsBarUnitTest() override {}
104 protected:
105 void SetUp() override;
106 void TearDown() override;
108 // Activates the tab at the given |index| in the tab strip model.
109 void ActivateTab(int index);
111 // Set whether or not the given |action| wants to run on the |web_contents|.
112 void SetActionWantsToRunOnTab(ExtensionAction* action,
113 content::WebContents* web_contents,
114 bool wants_to_run);
116 // Creates an extension with the given |name| and |action_type|, adds it to
117 // the associated extension service, and returns the created extension. (It's
118 // safe to ignore the returned value.)
119 scoped_refptr<const extensions::Extension> CreateAndAddExtension(
120 const std::string& name,
121 extensions::extension_action_test_util::ActionType action_type);
123 // Verifies that the toolbar is in order specified by |expected_names|, has
124 // the total action count of |total_size|, and has the same |visible_count|.
125 // This verifies that both the ToolbarActionsBar and the associated
126 // (platform-specific) view is correct.
127 // We use expected names (instead of ids) because they're much more readable
128 // in a debug message. These aren't enforced to be unique, so don't make
129 // duplicates.
130 // If any of these is wrong, returns testing::AssertionFailure() with a
131 // message.
132 testing::AssertionResult VerifyToolbarOrder(
133 const char* expected_names[],
134 size_t total_size,
135 size_t visible_count) WARN_UNUSED_RESULT;
137 ToolbarActionsBar* toolbar_actions_bar() {
138 return main_bar_helper_->GetToolbarActionsBar();
140 ToolbarActionsBar* overflow_bar() {
141 return overflow_bar_helper_->GetToolbarActionsBar();
143 extensions::ExtensionToolbarModel* toolbar_model() {
144 return toolbar_model_;
146 BrowserActionTestUtil* browser_action_test_util() {
147 return browser_action_test_util_.get();
149 BrowserActionTestUtil* overflow_browser_action_test_util() {
150 return overflow_browser_action_test_util_.get();
153 private:
154 // The test helper that owns the ToolbarActionsBar and the platform-specific
155 // view for it.
156 scoped_ptr<TestToolbarActionsBarHelper> main_bar_helper_;
158 // The test helper for the overflow bar; only non-null if |use_redesign| is
159 // true.
160 scoped_ptr<TestToolbarActionsBarHelper> overflow_bar_helper_;
162 // The associated ExtensionToolbarModel (owned by the keyed service setup).
163 extensions::ExtensionToolbarModel* toolbar_model_;
165 // A BrowserActionTestUtil object constructed with the associated
166 // ToolbarActionsBar.
167 scoped_ptr<BrowserActionTestUtil> browser_action_test_util_;
169 // The overflow container's BrowserActionTestUtil (only non-null if
170 // |use_redesign| is true).
171 scoped_ptr<BrowserActionTestUtil> overflow_browser_action_test_util_;
173 // True if the extension action redesign switch should be enabled.
174 bool use_redesign_;
176 scoped_ptr<extensions::FeatureSwitch::ScopedOverride> redesign_switch_;
178 DISALLOW_COPY_AND_ASSIGN(ToolbarActionsBarUnitTest);
181 void ToolbarActionsBarUnitTest::SetUp() {
182 if (use_redesign_) {
183 redesign_switch_.reset(new extensions::FeatureSwitch::ScopedOverride(
184 extensions::FeatureSwitch::extension_action_redesign(), true));
187 BrowserWithTestWindowTest::SetUp();
188 // The toolbar typically displays extension icons, so create some extension
189 // test infrastructure.
190 extensions::TestExtensionSystem* extension_system =
191 static_cast<extensions::TestExtensionSystem*>(
192 extensions::ExtensionSystem::Get(profile()));
193 extension_system->CreateExtensionService(
194 base::CommandLine::ForCurrentProcess(),
195 base::FilePath(),
196 false);
197 toolbar_model_ =
198 extensions::extension_action_test_util::CreateToolbarModelForProfile(
199 profile());
201 main_bar_helper_ = TestToolbarActionsBarHelper::Create(browser(), nullptr);
203 ToolbarActionsBar::disable_animations_for_testing_ = true;
204 ToolbarActionsBar::set_send_overflowed_action_changes_for_testing(false);
205 browser_action_test_util_.reset(
206 new BrowserActionTestUtil(browser(),
207 toolbar_actions_bar()->delegate_for_test()));
209 if (use_redesign_) {
210 overflow_bar_helper_ =
211 TestToolbarActionsBarHelper::Create(browser(), main_bar_helper_.get());
212 overflow_browser_action_test_util_.reset(
213 new BrowserActionTestUtil(browser(),
214 overflow_bar()->delegate_for_test()));
218 void ToolbarActionsBarUnitTest::TearDown() {
219 // Since the profile gets destroyed in BrowserWithTestWindowTest::TearDown(),
220 // we need to delete this now.
221 overflow_bar_helper_.reset();
222 main_bar_helper_.reset();
223 ToolbarActionsBar::disable_animations_for_testing_ = false;
224 redesign_switch_.reset();
225 BrowserWithTestWindowTest::TearDown();
228 void ToolbarActionsBarUnitTest::ActivateTab(int index) {
229 ASSERT_NE(nullptr, browser()->tab_strip_model()->GetWebContentsAt(index));
230 browser()->tab_strip_model()->ActivateTabAt(index, true);
233 scoped_refptr<const extensions::Extension>
234 ToolbarActionsBarUnitTest::CreateAndAddExtension(
235 const std::string& name,
236 extensions::extension_action_test_util::ActionType action_type) {
237 scoped_refptr<const extensions::Extension> extension =
238 extensions::extension_action_test_util::CreateActionExtension(
239 name, action_type);
240 extensions::ExtensionSystem::Get(profile())->extension_service()->
241 AddExtension(extension.get());
242 return extension;
245 void ToolbarActionsBarUnitTest::SetActionWantsToRunOnTab(
246 ExtensionAction* action,
247 content::WebContents* web_contents,
248 bool wants_to_run) {
249 action->SetIsVisible(SessionTabHelper::IdForTab(web_contents), wants_to_run);
250 extensions::ExtensionActionAPI::Get(profile())->NotifyChange(
251 action, web_contents, profile());
254 testing::AssertionResult ToolbarActionsBarUnitTest::VerifyToolbarOrder(
255 const char* expected_names[],
256 size_t total_size,
257 size_t visible_count) {
258 std::string main_bar_error =
259 VerifyToolbarOrderForBar(toolbar_actions_bar(),
260 browser_action_test_util(),
261 expected_names,
262 total_size,
263 visible_count);
264 std::string overflow_bar_error;
265 if (use_redesign_) {
266 overflow_bar_error =
267 VerifyToolbarOrderForBar(overflow_bar(),
268 overflow_browser_action_test_util(),
269 expected_names,
270 total_size,
271 total_size - visible_count);
275 return main_bar_error.empty() && overflow_bar_error.empty() ?
276 testing::AssertionSuccess() :
277 testing::AssertionFailure() << "main bar error:\n" << main_bar_error <<
278 "overflow bar error:\n" << overflow_bar_error;
281 TEST_F(ToolbarActionsBarUnitTest, BasicToolbarActionsBarTest) {
282 // Add three extensions to the profile; this is the easiest way to have
283 // toolbar actions.
284 for (int i = 0; i < 3; ++i) {
285 CreateAndAddExtension(
286 base::StringPrintf("extension %d", i),
287 extensions::extension_action_test_util::BROWSER_ACTION);
290 const ToolbarActionsBar::PlatformSettings& platform_settings =
291 toolbar_actions_bar()->platform_settings();
293 // By default, all three actions should be visible.
294 EXPECT_EQ(3u, toolbar_actions_bar()->GetIconCount());
295 // Check the widths.
296 int expected_width = 3 * ToolbarActionsBar::IconWidth(true) -
297 platform_settings.item_spacing +
298 platform_settings.left_padding +
299 platform_settings.right_padding;
300 EXPECT_EQ(expected_width, toolbar_actions_bar()->GetPreferredSize().width());
301 // Since all icons are showing, the current width should be the max width.
302 int maximum_width = expected_width;
303 EXPECT_EQ(maximum_width, toolbar_actions_bar()->GetMaximumWidth());
304 // The minimum width should be just enough for the chevron to be displayed.
305 int minimum_width = platform_settings.left_padding +
306 platform_settings.right_padding +
307 toolbar_actions_bar()->delegate_for_test()->
308 GetChevronWidth();
309 EXPECT_EQ(minimum_width, toolbar_actions_bar()->GetMinimumWidth());
311 // Test the connection between the ToolbarActionsBar and the model by
312 // adjusting the visible count.
313 toolbar_model()->SetVisibleIconCount(2u);
314 EXPECT_EQ(2u, toolbar_actions_bar()->GetIconCount());
316 // The current width should now be enough for two icons, and the chevron.
317 expected_width = 2 * ToolbarActionsBar::IconWidth(true) -
318 platform_settings.item_spacing +
319 platform_settings.left_padding +
320 platform_settings.right_padding +
321 toolbar_actions_bar()->delegate_for_test()->
322 GetChevronWidth();
323 EXPECT_EQ(expected_width, toolbar_actions_bar()->GetPreferredSize().width());
324 // The maximum and minimum widths should have remained constant (since we have
325 // the same number of actions).
326 EXPECT_EQ(maximum_width, toolbar_actions_bar()->GetMaximumWidth());
327 EXPECT_EQ(minimum_width, toolbar_actions_bar()->GetMinimumWidth());
329 // Test drag-and-drop logic.
330 const char kExtension0[] = "extension 0";
331 const char kExtension1[] = "extension 1";
332 const char kExtension2[] = "extension 2";
335 // The order should start as 0, 1, 2.
336 const char* expected_names[] = { kExtension0, kExtension1, kExtension2 };
337 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 2u));
341 // Drag 0 to be in the second spot; 1, 0, 2, within the same container.
342 toolbar_actions_bar()->OnDragDrop(0, 1, ToolbarActionsBar::DRAG_TO_SAME);
343 const char* expected_names[] = { kExtension1, kExtension0, kExtension2 };
344 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 2u));
348 // Drag 0 to be in the third spot, in the overflow container.
349 // Order should be 1, 2, 0, and the icon count should reduce by 1.
350 toolbar_actions_bar()->OnDragDrop(
351 1, 2, ToolbarActionsBar::DRAG_TO_OVERFLOW);
352 const char* expected_names[] = { kExtension1, kExtension2, kExtension0 };
353 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 1u));
354 // The model should also reflect the updated icon count.
355 EXPECT_EQ(1u, toolbar_model()->visible_icon_count());
356 // Dragging 2 to the main container should work, even if its spot in the
357 // "list" remains constant.
358 // Order remains 1, 2, 0, but now we have 2 icons visible.
359 toolbar_actions_bar()->OnDragDrop(1, 1, ToolbarActionsBar::DRAG_TO_MAIN);
360 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 2u));
361 // Similarly, dragging 2 to overflow, with the same "list" spot, should also
362 // work. Order remains 1, 2, 0, but icon count goes back to 1.
363 toolbar_actions_bar()->OnDragDrop(
364 1, 1, ToolbarActionsBar::DRAG_TO_OVERFLOW);
365 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 1u));
368 // Try resizing the toolbar. Start with the current width (enough for 1 icon).
369 int width = toolbar_actions_bar()->GetPreferredSize().width();
371 // If we try to resize by increasing, without allowing enough room for a new
372 // icon, width, and icon count should stay the same.
373 toolbar_actions_bar()->OnResizeComplete(width + 1);
374 EXPECT_EQ(width, toolbar_actions_bar()->GetPreferredSize().width());
375 EXPECT_EQ(1u, toolbar_actions_bar()->GetIconCount());
377 // If we resize by enough to include a new icon, width and icon count should
378 // both increase.
379 width += ToolbarActionsBar::IconWidth(true);
380 toolbar_actions_bar()->OnResizeComplete(width);
381 EXPECT_EQ(width, toolbar_actions_bar()->GetPreferredSize().width());
382 EXPECT_EQ(2u, toolbar_actions_bar()->GetIconCount());
384 // If we shrink the bar so that a full icon can't fit, it should resize to
385 // hide that icon.
386 toolbar_actions_bar()->OnResizeComplete(width - 1);
387 width -= ToolbarActionsBar::IconWidth(true);
388 EXPECT_EQ(width, toolbar_actions_bar()->GetPreferredSize().width());
389 EXPECT_EQ(1u, toolbar_actions_bar()->GetIconCount());
392 class ToolbarActionsBarPopOutUnitTest
393 : public ToolbarActionsBarUnitTest {
394 public:
395 ToolbarActionsBarPopOutUnitTest() : ToolbarActionsBarUnitTest(true) {}
397 protected:
398 void SetUp() override {
399 ToolbarActionsBar::set_pop_out_actions_to_run_for_testing(true);
400 ToolbarActionsBarUnitTest::SetUp();
403 private:
404 DISALLOW_COPY_AND_ASSIGN(ToolbarActionsBarPopOutUnitTest);
407 // Test that toolbar actions can pop themselves out of overflow if they want to
408 // act on a given tab.
409 TEST_F(ToolbarActionsBarPopOutUnitTest, ActionsPopOutToAct) {
410 // Add three extensions to the profile; this is the easiest way to have
411 // toolbar actions.
412 const char kBrowserAction[] = "browser action";
413 const char kPageAction[] = "page action";
414 const char kSynthetic[] = "synthetic"; // This has a generated action icon.
416 CreateAndAddExtension(kBrowserAction,
417 extensions::extension_action_test_util::BROWSER_ACTION);
418 scoped_refptr<const extensions::Extension> page_action =
419 CreateAndAddExtension(
420 kPageAction, extensions::extension_action_test_util::PAGE_ACTION);
421 CreateAndAddExtension(kSynthetic,
422 extensions::extension_action_test_util::NO_ACTION);
425 // We should start in the order of "browser action", "page action",
426 // "synthetic" and have all actions visible.
427 const char* expected_names[] = { kBrowserAction, kPageAction, kSynthetic };
428 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 3u));
431 // Shrink the bar to only show one action, and move the page action to the
432 // end.
433 toolbar_model()->SetVisibleIconCount(1);
434 toolbar_model()->MoveExtensionIcon(page_action->id(), 2u);
437 // Quickly verify that the move/visible count worked.
438 const char* expected_names[] = { kBrowserAction, kSynthetic, kPageAction };
439 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 1u));
442 // Create two tabs.
443 AddTab(browser(), GURL("http://www.google.com/"));
444 AddTab(browser(), GURL("http://www.youtube.com/"));
445 content::WebContents* web_contents =
446 browser()->tab_strip_model()->GetWebContentsAt(0);
449 // First, check the order for the first tab. Since we haven't changed
450 // anything (i.e., no extensions want to act), this should be the same as we
451 // left it: "browser action", "synthetic", "page action", with only one
452 // visible.
453 ActivateTab(0);
454 const char* expected_names[] = { kBrowserAction, kSynthetic, kPageAction };
455 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 1u));
458 extensions::ExtensionActionManager* action_manager =
459 extensions::ExtensionActionManager::Get(profile());
460 ExtensionAction* action = action_manager->GetExtensionAction(*page_action);
461 ASSERT_TRUE(action);
464 // Make "page action" want to act.
465 SetActionWantsToRunOnTab(action, web_contents, true);
466 // This should result in "page action" being popped out of the overflow
467 // menu.
468 // This has two visible effects:
469 // - page action should moved to the zero-index (left-most side of the bar).
470 // - The visible count should increase by one (so page action is visible).
471 const char* expected_names[] = { kPageAction, kBrowserAction, kSynthetic };
472 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 2u));
476 // This should not have any effect on the second tab, which should still
477 // have the original order and visible count.
478 ActivateTab(1);
479 const char* expected_names[] = { kBrowserAction, kSynthetic, kPageAction };
480 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 1u));
484 // Switching back to the first tab should mean that actions that want to run
485 // are re-popped out.
486 ActivateTab(0);
487 const char* expected_names[] = { kPageAction, kBrowserAction, kSynthetic };
488 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 2u));
492 // Now, set the action to be hidden again, and notify of the change.
493 SetActionWantsToRunOnTab(action, web_contents, false);
494 // The order and visible count should return to normal (the page action
495 // should move back to its original index in overflow).
496 const char* expected_names[] = { kBrowserAction, kSynthetic, kPageAction };
497 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 1u));
501 // Move page action to the second index and increase visible size to 2 (so
502 // it's naturally visible).
503 toolbar_model()->MoveExtensionIcon(page_action->id(), 1u);
504 toolbar_model()->SetVisibleIconCount(2u);
505 const char* expected_names[] = { kBrowserAction, kPageAction, kSynthetic };
506 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 2u));
507 // Make the now-visible page action want to act.
508 // Since the action is already visible, this should have no effect - the
509 // order and visible count should remain unchanged.
510 SetActionWantsToRunOnTab(action, web_contents, true);
511 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 2u));
515 // We should still be able to increase the size of the model, and to move
516 // the page action.
517 toolbar_model()->SetVisibleIconCount(3);
518 toolbar_model()->MoveExtensionIcon(page_action->id(), 0u);
519 const char* expected_names[] = { kPageAction, kBrowserAction, kSynthetic };
520 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 3u));
521 // If we moved the page action, the move should remain in effect even after
522 // the action no longer wants to act.
523 SetActionWantsToRunOnTab(action, web_contents, false);
524 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 3u));
528 // Test the edge case of having no icons visible.
529 toolbar_model()->SetVisibleIconCount(0);
530 const char* expected_names[] = { kPageAction, kBrowserAction, kSynthetic };
531 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 0u));
532 SetActionWantsToRunOnTab(action, web_contents, true);
533 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 1u));
536 // Reset the action, and create another page action extension.
537 SetActionWantsToRunOnTab(action, web_contents, false);
538 const char kPageAction2[] = "page action2";
539 scoped_refptr<const extensions::Extension> page_action2 =
540 CreateAndAddExtension(
541 kPageAction2, extensions::extension_action_test_util::PAGE_ACTION);
542 // The new extension was installed visible. Move it to the last index, and
543 // adjust the visible count.
544 toolbar_model()->MoveExtensionIcon(page_action2->id(), 3u);
545 toolbar_model()->SetVisibleIconCount(0);
548 // The second page action should be added to the end, and no icons should
549 // be visible.
550 const char* expected_names[] =
551 { kPageAction, kBrowserAction, kSynthetic, kPageAction2 };
552 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 4u, 0u));
556 // Make both page actions want to run, with the second triggering first.
557 SetActionWantsToRunOnTab(
558 action_manager->GetExtensionAction(*page_action2), web_contents, true);
559 SetActionWantsToRunOnTab(action, web_contents, true);
561 // Even though the second page action triggered first, the order of actions
562 // wanting to run should respect the normal order of actions.
563 const char* expected_names[] =
564 { kPageAction, kPageAction2, kBrowserAction, kSynthetic };
565 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 4u, 2u));
569 TEST_F(ToolbarActionsBarPopOutUnitTest, AdjustingActionsThatWantToAct) {
570 // Add three extensions to the profile; this is the easiest way to have
571 // toolbar actions.
572 const char kBrowserAction[] = "browser action";
573 const char kPageAction[] = "page action";
574 const char kSynthetic[] = "synthetic"; // This has a generated action icon.
576 CreateAndAddExtension(kBrowserAction,
577 extensions::extension_action_test_util::BROWSER_ACTION);
578 scoped_refptr<const extensions::Extension> page_action =
579 CreateAndAddExtension(
580 kPageAction, extensions::extension_action_test_util::PAGE_ACTION);
581 CreateAndAddExtension(kSynthetic,
582 extensions::extension_action_test_util::NO_ACTION);
584 // Move the page action to the second index and reduce the visible count to 1
585 // so that the page action is hidden (and can pop out when it needs to act).
586 toolbar_model()->SetVisibleIconCount(1);
587 toolbar_model()->MoveExtensionIcon(page_action->id(), 1u);
589 // Create a tab.
590 AddTab(browser(), GURL("http://www.google.com/"));
591 AddTab(browser(), GURL("http://www.youtube.com/"));
592 content::WebContents* web_contents =
593 browser()->tab_strip_model()->GetWebContentsAt(0);
595 extensions::ExtensionActionManager* action_manager =
596 extensions::ExtensionActionManager::Get(profile());
597 ExtensionAction* action = action_manager->GetExtensionAction(*page_action);
598 ASSERT_TRUE(action);
601 // Make the page action pop out, which causes the visible count for tab to
602 // become 2, with the page action at the front.
603 SetActionWantsToRunOnTab(action, web_contents, true);
604 const char* expected_names[] = { kPageAction, kBrowserAction, kSynthetic };
605 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 2u));
609 // Shrink the toolbar count. To the user, this is hiding "browser action",
610 // so that's the effect it should have (browser action should be hidden from
611 // all windows).
612 toolbar_actions_bar()->OnResizeComplete(
613 toolbar_actions_bar()->IconCountToWidth(1u));
614 const char* expected_names[] = { kPageAction, kBrowserAction, kSynthetic };
615 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 1u));
616 // Once the action no longer wants to run, "page action" should go back to
617 // its normal spot, and visible count goes to zero.
618 SetActionWantsToRunOnTab(action, web_contents, false);
619 const char* expected_names2[] = { kBrowserAction, kPageAction, kSynthetic };
620 EXPECT_TRUE(VerifyToolbarOrder(expected_names2, 3u, 0u));
624 // Make the action want to run again - it should pop out, and be the only
625 // action visible on the tab.
626 SetActionWantsToRunOnTab(action, web_contents, true);
627 const char* expected_names[] = { kPageAction, kBrowserAction, kSynthetic };
628 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 1u));
629 // Set the visible icon count for that tab to 2. This uncovers one action,
630 // so the base visible count should be 1, and the order should still be
631 // "page action", "browser action", "synthetic".
632 toolbar_actions_bar()->OnResizeComplete(
633 toolbar_actions_bar()->IconCountToWidth(2u));
634 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 2u));
635 // Next, grow the item order to 3 for the tab. This uncovers the "synthetic"
636 // extension. This is interesting, because for the same action to be
637 // uncovered on other tabs, the underlying order (which was previously
638 // "browser action", "page action", "synthetic") has to chage (to be
639 // "browser action", "synthetic", "page action"). If we don't make this
640 // change, we uncover "synthetic" here, but in other windows, "page action"
641 // is uncovered (which is weird). Ensure that the change that was visible
642 // to the user (uncovering "synthetic") is the one that happens to the
643 // underlying model.
644 toolbar_actions_bar()->OnResizeComplete(
645 toolbar_actions_bar()->IconCountToWidth(3u));
646 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 3u));
647 // So when "page action" finishes, it should go back to overflow, leaving
648 // the other two visible.
649 SetActionWantsToRunOnTab(action, web_contents, false);
650 const char* expected_names2[] = { kBrowserAction, kSynthetic, kPageAction };
651 EXPECT_TRUE(VerifyToolbarOrder(expected_names2, 3u, 2u));
655 // Next, test that moving an action that was popped out for overflow pins
656 // the action to the new spot. Since the action originated in overflow, this
657 // also causes the base visible count to increase.
658 // Set the action to be visible.
659 SetActionWantsToRunOnTab(action, web_contents, true);
660 const char* expected_names[] = { kPageAction, kBrowserAction, kSynthetic };
661 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 3u));
662 // Move the popped out "page action" extension to the first index.
663 toolbar_actions_bar()->OnDragDrop(0, 1, ToolbarActionsBar::DRAG_TO_SAME);
664 const char* expected_names2[] = { kBrowserAction, kPageAction, kSynthetic };
665 EXPECT_TRUE(VerifyToolbarOrder(expected_names2, 3u, 3u));
666 // Since this pinned "page action", the order stays the same after the run.
667 SetActionWantsToRunOnTab(action, web_contents, false);
668 EXPECT_TRUE(VerifyToolbarOrder(expected_names2, 3u, 3u));
672 // Move "page action" back to overflow.
673 toolbar_actions_bar()->OnDragDrop(1, 2, ToolbarActionsBar::DRAG_TO_SAME);
674 toolbar_actions_bar()->OnResizeComplete(
675 toolbar_actions_bar()->IconCountToWidth(2u));
677 // Test moving a popped out extension to the overflow menu; this should have
678 // no effect on the base visible count.
679 SetActionWantsToRunOnTab(action, web_contents, true);
680 const char* expected_names[] = { kPageAction, kBrowserAction, kSynthetic };
681 EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 3u));
682 // Move "page action" to the overflow menu.
683 toolbar_actions_bar()->OnDragDrop(
684 0, 2, ToolbarActionsBar::DRAG_TO_OVERFLOW);
685 const char* expected_names2[] = { kBrowserAction, kSynthetic, kPageAction };
686 EXPECT_TRUE(VerifyToolbarOrder(expected_names2, 3u, 2u));
687 SetActionWantsToRunOnTab(action, web_contents, false);
688 EXPECT_TRUE(VerifyToolbarOrder(expected_names2, 3u, 2u));