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/common/pref_names.h"
25 #include "chrome/test/base/browser_with_test_window_test.h"
26 #include "extensions/browser/extension_system.h"
27 #include "extensions/common/extension.h"
28 #include "extensions/common/feature_switch.h"
32 // Verifies that the toolbar order matches for the given |actions_bar|. If the
33 // order matches, the return value is empty; otherwise, it contains the error.
34 std::string
VerifyToolbarOrderForBar(
35 const ToolbarActionsBar
* actions_bar
,
36 BrowserActionTestUtil
* browser_action_test_util
,
37 const char* expected_names
[],
39 size_t visible_count
) {
40 const std::vector
<ToolbarActionViewController
*>& toolbar_actions
=
41 actions_bar
->toolbar_actions();
42 // If the total size is wrong, we risk segfaulting by continuing. Abort now.
43 if (total_size
!= toolbar_actions
.size()) {
44 return base::StringPrintf("Incorrect action count: expected %d, found %d",
45 static_cast<int>(total_size
),
46 static_cast<int>(toolbar_actions
.size()));
49 // Check that the ToolbarActionsBar matches the expected state.
51 for (size_t i
= 0; i
< total_size
; ++i
) {
52 if (std::string(expected_names
[i
]) !=
53 base::UTF16ToUTF8(toolbar_actions
[i
]->GetActionName())) {
54 error
+= base::StringPrintf(
55 "Incorrect action in bar at index %d: expected '%s', found '%s'.\n",
58 base::UTF16ToUTF8(toolbar_actions
[i
]->GetActionName()).c_str());
61 size_t icon_count
= actions_bar
->GetIconCount();
62 if (visible_count
!= icon_count
)
63 error
+= base::StringPrintf(
64 "Incorrect visible count: expected %d, found %d.\n",
65 static_cast<int>(visible_count
), static_cast<int>(icon_count
));
67 // Test that the (platform-specific) toolbar view matches the expected state.
68 for (size_t i
= 0; i
< total_size
; ++i
) {
69 std::string id
= browser_action_test_util
->GetExtensionId(i
);
70 if (id
!= toolbar_actions
[i
]->GetId()) {
71 error
+= base::StringPrintf(
72 "Incorrect action in view at index %d: expected '%s', found '%s'.\n",
74 toolbar_actions
[i
]->GetId().c_str(),
78 size_t view_icon_count
= browser_action_test_util
->VisibleBrowserActions();
79 if (visible_count
!= view_icon_count
)
80 error
+= base::StringPrintf(
81 "Incorrect visible count in view: expected %d, found %d.\n",
82 static_cast<int>(visible_count
), static_cast<int>(view_icon_count
));
89 // A cross-platform unit test for the ToolbarActionsBar that uses the
90 // TestToolbarActionsBarHelper to create the platform-specific containers.
91 // TODO(devlin): Since this *does* use the real platform containers, in theory,
92 // we can move all the BrowserActionsBarBrowserTests to be unittests. See about
94 class ToolbarActionsBarUnitTest
: public BrowserWithTestWindowTest
{
96 ToolbarActionsBarUnitTest() : toolbar_model_(nullptr), use_redesign_(false) {}
98 // A constructor to allow subclasses to override the redesign value.
99 explicit ToolbarActionsBarUnitTest(bool use_redesign
)
100 : toolbar_model_(nullptr),
101 use_redesign_(use_redesign
) {}
103 ~ToolbarActionsBarUnitTest() override
{}
106 void SetUp() override
;
107 void TearDown() override
;
109 // Activates the tab at the given |index| in the tab strip model.
110 void ActivateTab(int index
);
112 // Set whether or not the given |action| wants to run on the |web_contents|.
113 void SetActionWantsToRunOnTab(ExtensionAction
* action
,
114 content::WebContents
* web_contents
,
117 // Creates an extension with the given |name| and |action_type|, adds it to
118 // the associated extension service, and returns the created extension. (It's
119 // safe to ignore the returned value.)
120 scoped_refptr
<const extensions::Extension
> CreateAndAddExtension(
121 const std::string
& name
,
122 extensions::extension_action_test_util::ActionType action_type
);
124 // Verifies that the toolbar is in order specified by |expected_names|, has
125 // the total action count of |total_size|, and has the same |visible_count|.
126 // This verifies that both the ToolbarActionsBar and the associated
127 // (platform-specific) view is correct.
128 // We use expected names (instead of ids) because they're much more readable
129 // in a debug message. These aren't enforced to be unique, so don't make
131 // If any of these is wrong, returns testing::AssertionFailure() with a
133 testing::AssertionResult
VerifyToolbarOrder(
134 const char* expected_names
[],
136 size_t visible_count
) WARN_UNUSED_RESULT
;
138 ToolbarActionsBar
* toolbar_actions_bar() {
139 return main_bar_helper_
->GetToolbarActionsBar();
141 ToolbarActionsBar
* overflow_bar() {
142 return overflow_bar_helper_
->GetToolbarActionsBar();
144 extensions::ExtensionToolbarModel
* toolbar_model() {
145 return toolbar_model_
;
147 BrowserActionTestUtil
* browser_action_test_util() {
148 return browser_action_test_util_
.get();
150 BrowserActionTestUtil
* overflow_browser_action_test_util() {
151 return overflow_browser_action_test_util_
.get();
155 // The test helper that owns the ToolbarActionsBar and the platform-specific
157 scoped_ptr
<TestToolbarActionsBarHelper
> main_bar_helper_
;
159 // The test helper for the overflow bar; only non-null if |use_redesign| is
161 scoped_ptr
<TestToolbarActionsBarHelper
> overflow_bar_helper_
;
163 // The associated ExtensionToolbarModel (owned by the keyed service setup).
164 extensions::ExtensionToolbarModel
* toolbar_model_
;
166 // A BrowserActionTestUtil object constructed with the associated
167 // ToolbarActionsBar.
168 scoped_ptr
<BrowserActionTestUtil
> browser_action_test_util_
;
170 // The overflow container's BrowserActionTestUtil (only non-null if
171 // |use_redesign| is true).
172 scoped_ptr
<BrowserActionTestUtil
> overflow_browser_action_test_util_
;
174 // True if the extension action redesign switch should be enabled.
177 scoped_ptr
<extensions::FeatureSwitch::ScopedOverride
> redesign_switch_
;
179 DISALLOW_COPY_AND_ASSIGN(ToolbarActionsBarUnitTest
);
182 void ToolbarActionsBarUnitTest::SetUp() {
184 redesign_switch_
.reset(new extensions::FeatureSwitch::ScopedOverride(
185 extensions::FeatureSwitch::extension_action_redesign(), true));
188 BrowserWithTestWindowTest::SetUp();
189 // The toolbar typically displays extension icons, so create some extension
190 // test infrastructure.
191 extensions::TestExtensionSystem
* extension_system
=
192 static_cast<extensions::TestExtensionSystem
*>(
193 extensions::ExtensionSystem::Get(profile()));
194 extension_system
->CreateExtensionService(
195 base::CommandLine::ForCurrentProcess(),
199 extensions::extension_action_test_util::CreateToolbarModelForProfile(
202 main_bar_helper_
= TestToolbarActionsBarHelper::Create(browser(), nullptr);
204 ToolbarActionsBar::disable_animations_for_testing_
= true;
205 ToolbarActionsBar::set_send_overflowed_action_changes_for_testing(false);
206 browser_action_test_util_
.reset(
207 new BrowserActionTestUtil(browser(),
208 toolbar_actions_bar()->delegate_for_test()));
211 overflow_bar_helper_
=
212 TestToolbarActionsBarHelper::Create(browser(), main_bar_helper_
.get());
213 overflow_browser_action_test_util_
.reset(
214 new BrowserActionTestUtil(browser(),
215 overflow_bar()->delegate_for_test()));
219 void ToolbarActionsBarUnitTest::TearDown() {
220 // Since the profile gets destroyed in BrowserWithTestWindowTest::TearDown(),
221 // we need to delete this now.
222 overflow_bar_helper_
.reset();
223 main_bar_helper_
.reset();
224 ToolbarActionsBar::disable_animations_for_testing_
= false;
225 redesign_switch_
.reset();
226 BrowserWithTestWindowTest::TearDown();
229 void ToolbarActionsBarUnitTest::ActivateTab(int index
) {
230 ASSERT_NE(nullptr, browser()->tab_strip_model()->GetWebContentsAt(index
));
231 browser()->tab_strip_model()->ActivateTabAt(index
, true);
234 scoped_refptr
<const extensions::Extension
>
235 ToolbarActionsBarUnitTest::CreateAndAddExtension(
236 const std::string
& name
,
237 extensions::extension_action_test_util::ActionType action_type
) {
238 scoped_refptr
<const extensions::Extension
> extension
=
239 extensions::extension_action_test_util::CreateActionExtension(
241 extensions::ExtensionSystem::Get(profile())->extension_service()->
242 AddExtension(extension
.get());
246 void ToolbarActionsBarUnitTest::SetActionWantsToRunOnTab(
247 ExtensionAction
* action
,
248 content::WebContents
* web_contents
,
250 action
->SetIsVisible(SessionTabHelper::IdForTab(web_contents
), wants_to_run
);
251 extensions::ExtensionActionAPI::Get(profile())->NotifyChange(
252 action
, web_contents
, profile());
255 testing::AssertionResult
ToolbarActionsBarUnitTest::VerifyToolbarOrder(
256 const char* expected_names
[],
258 size_t visible_count
) {
259 std::string main_bar_error
=
260 VerifyToolbarOrderForBar(toolbar_actions_bar(),
261 browser_action_test_util(),
265 std::string overflow_bar_error
;
268 VerifyToolbarOrderForBar(overflow_bar(),
269 overflow_browser_action_test_util(),
272 total_size
- visible_count
);
276 return main_bar_error
.empty() && overflow_bar_error
.empty() ?
277 testing::AssertionSuccess() :
278 testing::AssertionFailure() << "main bar error:\n" << main_bar_error
<<
279 "overflow bar error:\n" << overflow_bar_error
;
282 TEST_F(ToolbarActionsBarUnitTest
, BasicToolbarActionsBarTest
) {
283 // Add three extensions to the profile; this is the easiest way to have
285 for (int i
= 0; i
< 3; ++i
) {
286 CreateAndAddExtension(
287 base::StringPrintf("extension %d", i
),
288 extensions::extension_action_test_util::BROWSER_ACTION
);
291 const ToolbarActionsBar::PlatformSettings
& platform_settings
=
292 toolbar_actions_bar()->platform_settings();
294 // By default, all three actions should be visible.
295 EXPECT_EQ(3u, toolbar_actions_bar()->GetIconCount());
297 int expected_width
= 3 * ToolbarActionsBar::IconWidth(true) -
298 platform_settings
.item_spacing
+
299 platform_settings
.left_padding
+
300 platform_settings
.right_padding
;
301 EXPECT_EQ(expected_width
, toolbar_actions_bar()->GetPreferredSize().width());
302 // Since all icons are showing, the current width should be the max width.
303 int maximum_width
= expected_width
;
304 EXPECT_EQ(maximum_width
, toolbar_actions_bar()->GetMaximumWidth());
305 // The minimum width should be just enough for the chevron to be displayed.
306 int minimum_width
= platform_settings
.left_padding
+
307 platform_settings
.right_padding
+
308 toolbar_actions_bar()->delegate_for_test()->
310 EXPECT_EQ(minimum_width
, toolbar_actions_bar()->GetMinimumWidth());
312 // Test the connection between the ToolbarActionsBar and the model by
313 // adjusting the visible count.
314 toolbar_model()->SetVisibleIconCount(2u);
315 EXPECT_EQ(2u, toolbar_actions_bar()->GetIconCount());
317 // The current width should now be enough for two icons, and the chevron.
318 expected_width
= 2 * ToolbarActionsBar::IconWidth(true) -
319 platform_settings
.item_spacing
+
320 platform_settings
.left_padding
+
321 platform_settings
.right_padding
+
322 toolbar_actions_bar()->delegate_for_test()->
324 EXPECT_EQ(expected_width
, toolbar_actions_bar()->GetPreferredSize().width());
325 // The maximum and minimum widths should have remained constant (since we have
326 // the same number of actions).
327 EXPECT_EQ(maximum_width
, toolbar_actions_bar()->GetMaximumWidth());
328 EXPECT_EQ(minimum_width
, toolbar_actions_bar()->GetMinimumWidth());
330 // Test drag-and-drop logic.
331 const char kExtension0
[] = "extension 0";
332 const char kExtension1
[] = "extension 1";
333 const char kExtension2
[] = "extension 2";
336 // The order should start as 0, 1, 2.
337 const char* expected_names
[] = { kExtension0
, kExtension1
, kExtension2
};
338 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 2u));
342 // Drag 0 to be in the second spot; 1, 0, 2, within the same container.
343 toolbar_actions_bar()->OnDragDrop(0, 1, ToolbarActionsBar::DRAG_TO_SAME
);
344 const char* expected_names
[] = { kExtension1
, kExtension0
, kExtension2
};
345 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 2u));
349 // Drag 0 to be in the third spot, in the overflow container.
350 // Order should be 1, 2, 0, and the icon count should reduce by 1.
351 toolbar_actions_bar()->OnDragDrop(
352 1, 2, ToolbarActionsBar::DRAG_TO_OVERFLOW
);
353 const char* expected_names
[] = { kExtension1
, kExtension2
, kExtension0
};
354 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 1u));
355 // The model should also reflect the updated icon count.
356 EXPECT_EQ(1u, toolbar_model()->visible_icon_count());
357 // Dragging 2 to the main container should work, even if its spot in the
358 // "list" remains constant.
359 // Order remains 1, 2, 0, but now we have 2 icons visible.
360 toolbar_actions_bar()->OnDragDrop(1, 1, ToolbarActionsBar::DRAG_TO_MAIN
);
361 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 2u));
362 // Similarly, dragging 2 to overflow, with the same "list" spot, should also
363 // work. Order remains 1, 2, 0, but icon count goes back to 1.
364 toolbar_actions_bar()->OnDragDrop(
365 1, 1, ToolbarActionsBar::DRAG_TO_OVERFLOW
);
366 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 1u));
369 // Try resizing the toolbar. Start with the current width (enough for 1 icon).
370 int width
= toolbar_actions_bar()->GetPreferredSize().width();
372 // If we try to resize by increasing, without allowing enough room for a new
373 // icon, width, and icon count should stay the same.
374 toolbar_actions_bar()->OnResizeComplete(width
+ 1);
375 EXPECT_EQ(width
, toolbar_actions_bar()->GetPreferredSize().width());
376 EXPECT_EQ(1u, toolbar_actions_bar()->GetIconCount());
378 // If we resize by enough to include a new icon, width and icon count should
380 width
+= ToolbarActionsBar::IconWidth(true);
381 toolbar_actions_bar()->OnResizeComplete(width
);
382 EXPECT_EQ(width
, toolbar_actions_bar()->GetPreferredSize().width());
383 EXPECT_EQ(2u, toolbar_actions_bar()->GetIconCount());
385 // If we shrink the bar so that a full icon can't fit, it should resize to
387 toolbar_actions_bar()->OnResizeComplete(width
- 1);
388 width
-= ToolbarActionsBar::IconWidth(true);
389 EXPECT_EQ(width
, toolbar_actions_bar()->GetPreferredSize().width());
390 EXPECT_EQ(1u, toolbar_actions_bar()->GetIconCount());
393 class ToolbarActionsBarRedesignUnitTest
: public ToolbarActionsBarUnitTest
{
395 ToolbarActionsBarRedesignUnitTest() : ToolbarActionsBarUnitTest(true) {}
396 ~ToolbarActionsBarRedesignUnitTest() override
{}
399 DISALLOW_COPY_AND_ASSIGN(ToolbarActionsBarRedesignUnitTest
);
402 TEST_F(ToolbarActionsBarRedesignUnitTest
, IconSurfacingBubbleAppearance
) {
403 // Without showing anything new, we shouldn't show the bubble, and should
404 // auto-acknowledge it.
405 EXPECT_FALSE(toolbar_actions_bar()->ShouldShowInfoBubble());
406 PrefService
* prefs
= profile()->GetPrefs();
408 prefs
->GetBoolean(prefs::kToolbarIconSurfacingBubbleAcknowledged
));
410 // Clear the pref for testing, and add an extension that wouldn't normally
411 // have an icon. We should now show the bubble.
412 prefs
->ClearPref(prefs::kToolbarIconSurfacingBubbleAcknowledged
);
413 CreateAndAddExtension("extension",
414 extensions::extension_action_test_util::NO_ACTION
);
415 EXPECT_TRUE(toolbar_actions_bar()->ShouldShowInfoBubble());
417 // If the bubble was recently shown, we shouldn't show it again...
418 ToolbarActionsBarBubbleDelegate
* bubble_delegate
=
419 static_cast<ToolbarActionsBarBubbleDelegate
*>(toolbar_actions_bar());
420 bubble_delegate
->OnToolbarActionsBarBubbleShown();
421 bubble_delegate
->OnToolbarActionsBarBubbleClosed(
422 ToolbarActionsBarBubbleDelegate::DISMISSED
);
423 EXPECT_FALSE(toolbar_actions_bar()->ShouldShowInfoBubble());
425 // ...But if it was only dismissed, we should show it before too long.
426 base::Time two_days_ago
= base::Time::Now() - base::TimeDelta::FromDays(2);
427 prefs
->SetInt64(prefs::kToolbarIconSurfacingBubbleLastShowTime
,
428 two_days_ago
.ToInternalValue());
429 EXPECT_TRUE(toolbar_actions_bar()->ShouldShowInfoBubble());
431 // If it's acknowledged, then it should never show again, and should be
432 // recorded as acknowledged.
433 bubble_delegate
->OnToolbarActionsBarBubbleShown();
434 bubble_delegate
->OnToolbarActionsBarBubbleClosed(
435 ToolbarActionsBarBubbleDelegate::ACKNOWLEDGED
);
436 EXPECT_FALSE(toolbar_actions_bar()->ShouldShowInfoBubble());
437 base::Time one_week_ago
= base::Time::Now() - base::TimeDelta::FromDays(7);
438 prefs
->SetInt64(prefs::kToolbarIconSurfacingBubbleLastShowTime
,
439 one_week_ago
.ToInternalValue());
441 prefs
->GetBoolean(prefs::kToolbarIconSurfacingBubbleAcknowledged
));
444 class ToolbarActionsBarPopOutUnitTest
445 : public ToolbarActionsBarRedesignUnitTest
{
447 ToolbarActionsBarPopOutUnitTest() {}
450 void SetUp() override
{
451 ToolbarActionsBar::set_pop_out_actions_to_run_for_testing(true);
452 ToolbarActionsBarUnitTest::SetUp();
456 DISALLOW_COPY_AND_ASSIGN(ToolbarActionsBarPopOutUnitTest
);
459 // Test that toolbar actions can pop themselves out of overflow if they want to
460 // act on a given tab.
461 TEST_F(ToolbarActionsBarPopOutUnitTest
, ActionsPopOutToAct
) {
462 // Add three extensions to the profile; this is the easiest way to have
464 const char kBrowserAction
[] = "browser action";
465 const char kPageAction
[] = "page action";
466 const char kSynthetic
[] = "synthetic"; // This has a generated action icon.
468 CreateAndAddExtension(kBrowserAction
,
469 extensions::extension_action_test_util::BROWSER_ACTION
);
470 scoped_refptr
<const extensions::Extension
> page_action
=
471 CreateAndAddExtension(
472 kPageAction
, extensions::extension_action_test_util::PAGE_ACTION
);
473 CreateAndAddExtension(kSynthetic
,
474 extensions::extension_action_test_util::NO_ACTION
);
477 // We should start in the order of "browser action", "page action",
478 // "synthetic" and have all actions visible.
479 const char* expected_names
[] = { kBrowserAction
, kPageAction
, kSynthetic
};
480 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 3u));
483 // Shrink the bar to only show one action, and move the page action to the
485 toolbar_model()->SetVisibleIconCount(1);
486 toolbar_model()->MoveExtensionIcon(page_action
->id(), 2u);
489 // Quickly verify that the move/visible count worked.
490 const char* expected_names
[] = { kBrowserAction
, kSynthetic
, kPageAction
};
491 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 1u));
495 AddTab(browser(), GURL("http://www.google.com/"));
496 AddTab(browser(), GURL("http://www.youtube.com/"));
497 content::WebContents
* web_contents
=
498 browser()->tab_strip_model()->GetWebContentsAt(0);
501 // First, check the order for the first tab. Since we haven't changed
502 // anything (i.e., no extensions want to act), this should be the same as we
503 // left it: "browser action", "synthetic", "page action", with only one
506 const char* expected_names
[] = { kBrowserAction
, kSynthetic
, kPageAction
};
507 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 1u));
510 extensions::ExtensionActionManager
* action_manager
=
511 extensions::ExtensionActionManager::Get(profile());
512 ExtensionAction
* action
= action_manager
->GetExtensionAction(*page_action
);
516 // Make "page action" want to act.
517 SetActionWantsToRunOnTab(action
, web_contents
, true);
518 // This should result in "page action" being popped out of the overflow
520 // This has two visible effects:
521 // - page action should moved to the zero-index (left-most side of the bar).
522 // - The visible count should increase by one (so page action is visible).
523 const char* expected_names
[] = { kPageAction
, kBrowserAction
, kSynthetic
};
524 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 2u));
528 // This should not have any effect on the second tab, which should still
529 // have the original order and visible count.
531 const char* expected_names
[] = { kBrowserAction
, kSynthetic
, kPageAction
};
532 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 1u));
536 // Switching back to the first tab should mean that actions that want to run
537 // are re-popped out.
539 const char* expected_names
[] = { kPageAction
, kBrowserAction
, kSynthetic
};
540 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 2u));
544 // Now, set the action to be hidden again, and notify of the change.
545 SetActionWantsToRunOnTab(action
, web_contents
, false);
546 // The order and visible count should return to normal (the page action
547 // should move back to its original index in overflow).
548 const char* expected_names
[] = { kBrowserAction
, kSynthetic
, kPageAction
};
549 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 1u));
553 // Move page action to the second index and increase visible size to 2 (so
554 // it's naturally visible).
555 toolbar_model()->MoveExtensionIcon(page_action
->id(), 1u);
556 toolbar_model()->SetVisibleIconCount(2u);
557 const char* expected_names
[] = { kBrowserAction
, kPageAction
, kSynthetic
};
558 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 2u));
559 // Make the now-visible page action want to act.
560 // Since the action is already visible, this should have no effect - the
561 // order and visible count should remain unchanged.
562 SetActionWantsToRunOnTab(action
, web_contents
, true);
563 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 2u));
567 // We should still be able to increase the size of the model, and to move
569 toolbar_model()->SetVisibleIconCount(3);
570 toolbar_model()->MoveExtensionIcon(page_action
->id(), 0u);
571 const char* expected_names
[] = { kPageAction
, kBrowserAction
, kSynthetic
};
572 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 3u));
573 // If we moved the page action, the move should remain in effect even after
574 // the action no longer wants to act.
575 SetActionWantsToRunOnTab(action
, web_contents
, false);
576 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 3u));
580 // Test the edge case of having no icons visible.
581 toolbar_model()->SetVisibleIconCount(0);
582 const char* expected_names
[] = { kPageAction
, kBrowserAction
, kSynthetic
};
583 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 0u));
584 SetActionWantsToRunOnTab(action
, web_contents
, true);
585 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 1u));
588 // Reset the action, and create another page action extension.
589 SetActionWantsToRunOnTab(action
, web_contents
, false);
590 const char kPageAction2
[] = "page action2";
591 scoped_refptr
<const extensions::Extension
> page_action2
=
592 CreateAndAddExtension(
593 kPageAction2
, extensions::extension_action_test_util::PAGE_ACTION
);
594 // The new extension was installed visible. Move it to the last index, and
595 // adjust the visible count.
596 toolbar_model()->MoveExtensionIcon(page_action2
->id(), 3u);
597 toolbar_model()->SetVisibleIconCount(0);
600 // The second page action should be added to the end, and no icons should
602 const char* expected_names
[] =
603 { kPageAction
, kBrowserAction
, kSynthetic
, kPageAction2
};
604 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 4u, 0u));
608 // Make both page actions want to run, with the second triggering first.
609 SetActionWantsToRunOnTab(
610 action_manager
->GetExtensionAction(*page_action2
), web_contents
, true);
611 SetActionWantsToRunOnTab(action
, web_contents
, true);
613 // Even though the second page action triggered first, the order of actions
614 // wanting to run should respect the normal order of actions.
615 const char* expected_names
[] =
616 { kPageAction
, kPageAction2
, kBrowserAction
, kSynthetic
};
617 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 4u, 2u));
621 TEST_F(ToolbarActionsBarPopOutUnitTest
, AdjustingActionsThatWantToAct
) {
622 // Add three extensions to the profile; this is the easiest way to have
624 const char kBrowserAction
[] = "browser action";
625 const char kPageAction
[] = "page action";
626 const char kSynthetic
[] = "synthetic"; // This has a generated action icon.
628 CreateAndAddExtension(kBrowserAction
,
629 extensions::extension_action_test_util::BROWSER_ACTION
);
630 scoped_refptr
<const extensions::Extension
> page_action
=
631 CreateAndAddExtension(
632 kPageAction
, extensions::extension_action_test_util::PAGE_ACTION
);
633 CreateAndAddExtension(kSynthetic
,
634 extensions::extension_action_test_util::NO_ACTION
);
636 // Move the page action to the second index and reduce the visible count to 1
637 // so that the page action is hidden (and can pop out when it needs to act).
638 toolbar_model()->SetVisibleIconCount(1);
639 toolbar_model()->MoveExtensionIcon(page_action
->id(), 1u);
642 AddTab(browser(), GURL("http://www.google.com/"));
643 AddTab(browser(), GURL("http://www.youtube.com/"));
644 content::WebContents
* web_contents
=
645 browser()->tab_strip_model()->GetWebContentsAt(0);
647 extensions::ExtensionActionManager
* action_manager
=
648 extensions::ExtensionActionManager::Get(profile());
649 ExtensionAction
* action
= action_manager
->GetExtensionAction(*page_action
);
653 // Make the page action pop out, which causes the visible count for tab to
654 // become 2, with the page action at the front.
655 SetActionWantsToRunOnTab(action
, web_contents
, true);
656 const char* expected_names
[] = { kPageAction
, kBrowserAction
, kSynthetic
};
657 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 2u));
661 // Shrink the toolbar count. To the user, this is hiding "browser action",
662 // so that's the effect it should have (browser action should be hidden from
664 toolbar_actions_bar()->OnResizeComplete(
665 toolbar_actions_bar()->IconCountToWidth(1u));
666 const char* expected_names
[] = { kPageAction
, kBrowserAction
, kSynthetic
};
667 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 1u));
668 // Once the action no longer wants to run, "page action" should go back to
669 // its normal spot, and visible count goes to zero.
670 SetActionWantsToRunOnTab(action
, web_contents
, false);
671 const char* expected_names2
[] = { kBrowserAction
, kPageAction
, kSynthetic
};
672 EXPECT_TRUE(VerifyToolbarOrder(expected_names2
, 3u, 0u));
676 // Make the action want to run again - it should pop out, and be the only
677 // action visible on the tab.
678 SetActionWantsToRunOnTab(action
, web_contents
, true);
679 const char* expected_names
[] = { kPageAction
, kBrowserAction
, kSynthetic
};
680 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 1u));
681 // Set the visible icon count for that tab to 2. This uncovers one action,
682 // so the base visible count should be 1, and the order should still be
683 // "page action", "browser action", "synthetic".
684 toolbar_actions_bar()->OnResizeComplete(
685 toolbar_actions_bar()->IconCountToWidth(2u));
686 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 2u));
687 // Next, grow the item order to 3 for the tab. This uncovers the "synthetic"
688 // extension. This is interesting, because for the same action to be
689 // uncovered on other tabs, the underlying order (which was previously
690 // "browser action", "page action", "synthetic") has to chage (to be
691 // "browser action", "synthetic", "page action"). If we don't make this
692 // change, we uncover "synthetic" here, but in other windows, "page action"
693 // is uncovered (which is weird). Ensure that the change that was visible
694 // to the user (uncovering "synthetic") is the one that happens to the
696 toolbar_actions_bar()->OnResizeComplete(
697 toolbar_actions_bar()->IconCountToWidth(3u));
698 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 3u));
699 // So when "page action" finishes, it should go back to overflow, leaving
700 // the other two visible.
701 SetActionWantsToRunOnTab(action
, web_contents
, false);
702 const char* expected_names2
[] = { kBrowserAction
, kSynthetic
, kPageAction
};
703 EXPECT_TRUE(VerifyToolbarOrder(expected_names2
, 3u, 2u));
707 // Next, test that moving an action that was popped out for overflow pins
708 // the action to the new spot. Since the action originated in overflow, this
709 // also causes the base visible count to increase.
710 // Set the action to be visible.
711 SetActionWantsToRunOnTab(action
, web_contents
, true);
712 const char* expected_names
[] = { kPageAction
, kBrowserAction
, kSynthetic
};
713 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 3u));
714 // Move the popped out "page action" extension to the first index.
715 toolbar_actions_bar()->OnDragDrop(0, 1, ToolbarActionsBar::DRAG_TO_SAME
);
716 const char* expected_names2
[] = { kBrowserAction
, kPageAction
, kSynthetic
};
717 EXPECT_TRUE(VerifyToolbarOrder(expected_names2
, 3u, 3u));
718 // Since this pinned "page action", the order stays the same after the run.
719 SetActionWantsToRunOnTab(action
, web_contents
, false);
720 EXPECT_TRUE(VerifyToolbarOrder(expected_names2
, 3u, 3u));
724 // Move "page action" back to overflow.
725 toolbar_actions_bar()->OnDragDrop(1, 2, ToolbarActionsBar::DRAG_TO_SAME
);
726 toolbar_actions_bar()->OnResizeComplete(
727 toolbar_actions_bar()->IconCountToWidth(2u));
729 // Test moving a popped out extension to the overflow menu; this should have
730 // no effect on the base visible count.
731 SetActionWantsToRunOnTab(action
, web_contents
, true);
732 const char* expected_names
[] = { kPageAction
, kBrowserAction
, kSynthetic
};
733 EXPECT_TRUE(VerifyToolbarOrder(expected_names
, 3u, 3u));
734 // Move "page action" to the overflow menu.
735 toolbar_actions_bar()->OnDragDrop(
736 0, 2, ToolbarActionsBar::DRAG_TO_OVERFLOW
);
737 const char* expected_names2
[] = { kBrowserAction
, kSynthetic
, kPageAction
};
738 EXPECT_TRUE(VerifyToolbarOrder(expected_names2
, 3u, 2u));
739 SetActionWantsToRunOnTab(action
, web_contents
, false);
740 EXPECT_TRUE(VerifyToolbarOrder(expected_names2
, 3u, 2u));