blob: 1e57fc61d9f9de268855491f8d4a41441c8d6dd7 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.h"
#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
#include "chrome/browser/extensions/extension_action.h"
#include "chrome/browser/extensions/extension_action_manager.h"
#include "chrome/browser/extensions/extension_action_test_util.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/layout_constants.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h"
#include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
#include "chrome/browser/ui/toolbar/toolbar_actions_bar_delegate.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension.h"
#include "ui/base/test/material_design_controller_test_api.h"
namespace {
using ActionType = extensions::ExtensionBuilder::ActionType;
// Verifies that the toolbar order matches for the given |actions_bar|. If the
// order matches, the return value is empty; otherwise, it contains the error.
std::string VerifyToolbarOrderForBar(
const ToolbarActionsBar* actions_bar,
BrowserActionTestUtil* browser_action_test_util,
const char* expected_names[],
size_t total_size,
size_t visible_count) {
const ToolbarActionsBar::ToolbarActions& toolbar_actions =
actions_bar->toolbar_actions_unordered();
// If the total size is wrong, we risk segfaulting by continuing. Abort now.
if (total_size != toolbar_actions.size()) {
return base::StringPrintf("Incorrect action count: expected %d, found %d",
static_cast<int>(total_size),
static_cast<int>(toolbar_actions.size()));
}
// Check that the ToolbarActionsBar matches the expected state.
std::string error;
for (size_t i = 0; i < total_size; ++i) {
if (std::string(expected_names[i]) !=
base::UTF16ToUTF8(toolbar_actions[i]->GetActionName())) {
error += base::StringPrintf(
"Incorrect action in bar at index %d: expected '%s', found '%s'.\n",
static_cast<int>(i),
expected_names[i],
base::UTF16ToUTF8(toolbar_actions[i]->GetActionName()).c_str());
}
}
size_t icon_count = actions_bar->GetIconCount();
if (visible_count != icon_count)
error += base::StringPrintf(
"Incorrect visible count: expected %d, found %d.\n",
static_cast<int>(visible_count), static_cast<int>(icon_count));
// Test that the (platform-specific) toolbar view matches the expected state.
for (size_t i = 0; i < total_size; ++i) {
std::string id = browser_action_test_util->GetExtensionId(i);
if (id != toolbar_actions[i]->GetId()) {
error += base::StringPrintf(
"Incorrect action in view at index %d: expected '%s', found '%s'.\n",
static_cast<int>(i),
toolbar_actions[i]->GetId().c_str(),
id.c_str());
}
}
size_t view_icon_count = browser_action_test_util->VisibleBrowserActions();
if (visible_count != view_icon_count)
error += base::StringPrintf(
"Incorrect visible count in view: expected %d, found %d.\n",
static_cast<int>(visible_count), static_cast<int>(view_icon_count));
return error;
}
} // namespace
ToolbarActionsBarUnitTest::ToolbarActionsBarUnitTest()
: toolbar_model_(nullptr) {}
ToolbarActionsBarUnitTest::~ToolbarActionsBarUnitTest() {}
void ToolbarActionsBarUnitTest::SetUp() {
BrowserWithTestWindowTest::SetUp();
local_state_.reset(
new ScopedTestingLocalState(TestingBrowserProcess::GetGlobal()));
// The toolbar typically displays extension icons, so create some extension
// test infrastructure.
extensions::TestExtensionSystem* extension_system =
static_cast<extensions::TestExtensionSystem*>(
extensions::ExtensionSystem::Get(profile()));
extension_system->CreateExtensionService(
base::CommandLine::ForCurrentProcess(),
base::FilePath(),
false);
toolbar_model_ =
extensions::extension_action_test_util::CreateToolbarModelForProfile(
profile());
material_design_state_.reset(
new ui::test::MaterialDesignControllerTestAPI(GetParam()));
ToolbarActionsBar::disable_animations_for_testing_ = true;
browser_action_test_util_.reset(new BrowserActionTestUtil(browser(), false));
overflow_browser_action_test_util_ =
browser_action_test_util_->CreateOverflowBar();
}
void ToolbarActionsBarUnitTest::TearDown() {
// Since the profile gets destroyed in BrowserWithTestWindowTest::TearDown(),
// we need to delete this now.
browser_action_test_util_.reset();
overflow_browser_action_test_util_.reset();
ToolbarActionsBar::disable_animations_for_testing_ = false;
material_design_state_.reset();
local_state_.reset();
BrowserWithTestWindowTest::TearDown();
}
void ToolbarActionsBarUnitTest::ActivateTab(int index) {
ASSERT_NE(nullptr, browser()->tab_strip_model()->GetWebContentsAt(index));
browser()->tab_strip_model()->ActivateTabAt(index, true);
}
scoped_refptr<const extensions::Extension>
ToolbarActionsBarUnitTest::CreateAndAddExtension(const std::string& name,
ActionType action_type) {
scoped_refptr<const extensions::Extension> extension =
extensions::ExtensionBuilder(name)
.SetAction(action_type)
.SetLocation(extensions::Manifest::INTERNAL)
.Build();
extensions::ExtensionSystem::Get(profile())->extension_service()->
AddExtension(extension.get());
return extension;
}
void ToolbarActionsBarUnitTest::SetActionWantsToRunOnTab(
ExtensionAction* action,
content::WebContents* web_contents,
bool wants_to_run) {
action->SetIsVisible(SessionTabHelper::IdForTab(web_contents), wants_to_run);
extensions::ExtensionActionAPI::Get(profile())->NotifyChange(
action, web_contents, profile());
}
testing::AssertionResult ToolbarActionsBarUnitTest::VerifyToolbarOrder(
const char* expected_names[],
size_t total_size,
size_t visible_count) {
std::string main_bar_error =
VerifyToolbarOrderForBar(toolbar_actions_bar(),
browser_action_test_util(),
expected_names,
total_size,
visible_count);
std::string overflow_bar_error;
overflow_bar_error = VerifyToolbarOrderForBar(
overflow_bar(), overflow_browser_action_test_util(), expected_names,
total_size, total_size - visible_count);
return main_bar_error.empty() && overflow_bar_error.empty() ?
testing::AssertionSuccess() :
testing::AssertionFailure() << "main bar error:\n" << main_bar_error <<
"overflow bar error:\n" << overflow_bar_error;
}
// Note: First argument is optional and intentionally left blank.
// (it's a prefix for the generated test cases)
INSTANTIATE_TEST_CASE_P(
,
ToolbarActionsBarUnitTest,
testing::Values(ui::MaterialDesignController::MATERIAL_NORMAL,
ui::MaterialDesignController::MATERIAL_HYBRID));
TEST_P(ToolbarActionsBarUnitTest, BasicToolbarActionsBarTest) {
// Add three extensions to the profile; this is the easiest way to have
// toolbar actions.
for (int i = 0; i < 3; ++i) {
CreateAndAddExtension(base::StringPrintf("extension %d", i),
ActionType::BROWSER_ACTION);
}
const ToolbarActionsBar::PlatformSettings& platform_settings =
toolbar_actions_bar()->platform_settings();
// By default, all three actions should be visible.
EXPECT_EQ(3u, toolbar_actions_bar()->GetIconCount());
// Check the widths. IconWidth(true) includes the spacing to the left of
// each icon and |item_spacing| accounts for the spacing to the right
// of the rightmost icon.
int expected_width =
3 * ToolbarActionsBar::IconWidth(true) + platform_settings.item_spacing;
EXPECT_EQ(expected_width, toolbar_actions_bar()->GetFullSize().width());
// Since all icons are showing, the current width should be the max width.
int maximum_width = expected_width;
EXPECT_EQ(maximum_width, toolbar_actions_bar()->GetMaximumWidth());
// The minimum width should be be non-zero (as long as there are any icons) so
// we can render the grippy to allow the user to drag to adjust the width.
int minimum_width = platform_settings.item_spacing;
EXPECT_EQ(minimum_width, toolbar_actions_bar()->GetMinimumWidth());
// Test the connection between the ToolbarActionsBar and the model by
// adjusting the visible count.
toolbar_model()->SetVisibleIconCount(2u);
EXPECT_EQ(2u, toolbar_actions_bar()->GetIconCount());
// The current width should now be enough for two icons.
// IconWidth(true) includes the spacing to the left of each icon and
// |item_spacing| accounts for the spacing to the right of the rightmost
// icon.
expected_width = 2 * ToolbarActionsBar::IconWidth(true) +
platform_settings.item_spacing;
EXPECT_EQ(expected_width, toolbar_actions_bar()->GetFullSize().width());
// The maximum and minimum widths should have remained constant (since we have
// the same number of actions).
EXPECT_EQ(maximum_width, toolbar_actions_bar()->GetMaximumWidth());
EXPECT_EQ(minimum_width, toolbar_actions_bar()->GetMinimumWidth());
// Test drag-and-drop logic.
const char kExtension0[] = "extension 0";
const char kExtension1[] = "extension 1";
const char kExtension2[] = "extension 2";
{
// The order should start as 0, 1, 2.
const char* expected_names[] = { kExtension0, kExtension1, kExtension2 };
EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 2u));
}
{
// Drag 0 to be in the second spot; 1, 0, 2, within the same container.
toolbar_actions_bar()->OnDragDrop(0, 1, ToolbarActionsBar::DRAG_TO_SAME);
const char* expected_names[] = { kExtension1, kExtension0, kExtension2 };
EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 2u));
}
{
// Drag 0 to be in the third spot, in the overflow container.
// Order should be 1, 2, 0, and the icon count should reduce by 1.
toolbar_actions_bar()->OnDragDrop(
1, 2, ToolbarActionsBar::DRAG_TO_OVERFLOW);
const char* expected_names[] = { kExtension1, kExtension2, kExtension0 };
EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 1u));
// The model should also reflect the updated icon count.
EXPECT_EQ(1u, toolbar_model()->visible_icon_count());
// Dragging 2 to the main container should work, even if its spot in the
// "list" remains constant.
// Order remains 1, 2, 0, but now we have 2 icons visible.
toolbar_actions_bar()->OnDragDrop(1, 1, ToolbarActionsBar::DRAG_TO_MAIN);
EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 2u));
// Similarly, dragging 2 to overflow, with the same "list" spot, should also
// work. Order remains 1, 2, 0, but icon count goes back to 1.
toolbar_actions_bar()->OnDragDrop(
1, 1, ToolbarActionsBar::DRAG_TO_OVERFLOW);
EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 1u));
}
// Try resizing the toolbar. Start with the current width (enough for 1 icon).
int width = toolbar_actions_bar()->GetFullSize().width();
// If we try to resize by increasing, without allowing enough room for a new
// icon, width, and icon count should stay the same.
toolbar_actions_bar()->OnResizeComplete(width + 1);
EXPECT_EQ(width, toolbar_actions_bar()->GetFullSize().width());
EXPECT_EQ(1u, toolbar_actions_bar()->GetIconCount());
// If we resize by enough to include a new icon, width and icon count should
// both increase.
width += ToolbarActionsBar::IconWidth(true);
toolbar_actions_bar()->OnResizeComplete(width);
EXPECT_EQ(width, toolbar_actions_bar()->GetFullSize().width());
EXPECT_EQ(2u, toolbar_actions_bar()->GetIconCount());
// If we shrink the bar so that a full icon can't fit, it should resize to
// hide that icon.
toolbar_actions_bar()->OnResizeComplete(width - 1);
width -= ToolbarActionsBar::IconWidth(true);
EXPECT_EQ(width, toolbar_actions_bar()->GetFullSize().width());
EXPECT_EQ(1u, toolbar_actions_bar()->GetIconCount());
}
TEST_P(ToolbarActionsBarUnitTest, ToolbarActionsReorderOnPrefChange) {
for (int i = 0; i < 3; ++i) {
CreateAndAddExtension(base::StringPrintf("extension %d", i),
ActionType::BROWSER_ACTION);
}
EXPECT_EQ(3u, toolbar_actions_bar()->GetIconCount());
// Change the value of the toolbar preference.
// Test drag-and-drop logic.
const char kExtension0[] = "extension 0";
const char kExtension1[] = "extension 1";
const char kExtension2[] = "extension 2";
{
// The order should start as 0, 1, 2.
const char* expected_names[] = { kExtension0, kExtension1, kExtension2 };
EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 3u));
}
std::vector<std::string> new_order;
new_order.push_back(toolbar_actions_bar()->toolbar_actions_unordered()[1]->
GetId());
new_order.push_back(toolbar_actions_bar()->toolbar_actions_unordered()[2]->
GetId());
extensions::ExtensionPrefs::Get(profile())->SetToolbarOrder(new_order);
{
// The order should now reflect the prefs, and be 1, 2, 0.
const char* expected_names[] = { kExtension1, kExtension2, kExtension0 };
EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 3u));
}
}
TEST_P(ToolbarActionsBarUnitTest, TestHighlightMode) {
std::vector<std::string> ids;
for (int i = 0; i < 3; ++i) {
ids.push_back(CreateAndAddExtension(base::StringPrintf("extension %d", i),
ActionType::BROWSER_ACTION)
->id());
}
EXPECT_EQ(3u, toolbar_actions_bar()->GetIconCount());
const char kExtension0[] = "extension 0";
const char kExtension1[] = "extension 1";
const char kExtension2[] = "extension 2";
{
// The order should start as 0, 1, 2.
const char* expected_names[] = {kExtension0, kExtension1, kExtension2};
EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 3u));
}
std::vector<std::string> ids_to_highlight;
ids_to_highlight.push_back(ids[0]);
ids_to_highlight.push_back(ids[2]);
toolbar_model()->HighlightActions(ids_to_highlight,
ToolbarActionsModel::HIGHLIGHT_WARNING);
{
// The order should now be 0, 2, since 1 is not being highlighted.
const char* expected_names[] = {kExtension0, kExtension2};
EXPECT_TRUE(VerifyToolbarOrder(expected_names, 2u, 2u));
}
toolbar_model()->StopHighlighting();
{
// The order should go back to normal.
const char* expected_names[] = {kExtension0, kExtension1, kExtension2};
EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 3u));
}
ids_to_highlight.push_back(ids[1]);
toolbar_model()->HighlightActions(ids_to_highlight,
ToolbarActionsModel::HIGHLIGHT_WARNING);
{
// All actions should be highlighted (in the order of the vector passed in,
// so with '1' at the end).
const char* expected_names[] = {kExtension0, kExtension2, kExtension1};
EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 3u));
}
ids_to_highlight.clear();
ids_to_highlight.push_back(ids[1]);
toolbar_model()->HighlightActions(ids_to_highlight,
ToolbarActionsModel::HIGHLIGHT_WARNING);
{
// Only extension 1 should be visible.
const char* expected_names[] = {kExtension1};
EXPECT_TRUE(VerifyToolbarOrder(expected_names, 1u, 1u));
}
toolbar_model()->StopHighlighting();
{
// And, again, back to normal.
const char* expected_names[] = {kExtension0, kExtension1, kExtension2};
EXPECT_TRUE(VerifyToolbarOrder(expected_names, 3u, 3u));
}
}
// Test the bounds calculation for different indices.
TEST_P(ToolbarActionsBarUnitTest, TestActionFrameBounds) {
const int kIconWidth = ToolbarActionsBar::IconWidth(false);
const int kIconHeight = ToolbarActionsBar::IconHeight();
const int kIconWidthWithPadding = ToolbarActionsBar::IconWidth(true);
const int kIconSpacing = GetLayoutConstant(TOOLBAR_STANDARD_SPACING);
const int kIconsPerOverflowRow = 3;
const int kNumExtensions = 7;
const int kSpacing =
toolbar_actions_bar()->platform_settings().item_spacing;
// Initialization: 7 total extensions, with 3 visible per row in overflow.
// Start with all visible on the main bar.
for (int i = 0; i < kNumExtensions; ++i) {
CreateAndAddExtension(base::StringPrintf("extension %d", i),
ActionType::BROWSER_ACTION);
}
toolbar_model()->SetVisibleIconCount(kNumExtensions);
overflow_bar()->SetOverflowRowWidth(
kIconWidthWithPadding * kIconsPerOverflowRow + kIconSpacing);
EXPECT_EQ(kIconsPerOverflowRow,
overflow_bar()->platform_settings().icons_per_overflow_menu_row);
// Check main bar calculations. Actions should be laid out in a line, so
// all on the same (0) y-axis.
EXPECT_EQ(gfx::Rect(kSpacing, 0, kIconWidth, kIconHeight),
toolbar_actions_bar()->GetFrameForIndex(0));
EXPECT_EQ(gfx::Rect(kSpacing + kIconWidthWithPadding, 0, kIconWidth,
kIconHeight),
toolbar_actions_bar()->GetFrameForIndex(1));
EXPECT_EQ(gfx::Rect(kSpacing + kIconWidthWithPadding * (kNumExtensions - 1),
0, kIconWidth, kIconHeight),
toolbar_actions_bar()->GetFrameForIndex(kNumExtensions - 1));
// Check overflow bar calculations.
toolbar_model()->SetVisibleIconCount(3);
// Any actions that are shown on the main bar should have an empty rect for
// the frame.
EXPECT_EQ(gfx::Rect(), overflow_bar()->GetFrameForIndex(0));
EXPECT_EQ(gfx::Rect(), overflow_bar()->GetFrameForIndex(2));
// Other actions should start from their relative index; that is, the first
// action shown should be in the first spot's bounds, even though it's the
// third action by index.
EXPECT_EQ(gfx::Rect(kSpacing, 0, kIconWidth, kIconHeight),
overflow_bar()->GetFrameForIndex(3));
EXPECT_EQ(gfx::Rect(kSpacing + kIconWidthWithPadding, 0, kIconWidth,
kIconHeight),
overflow_bar()->GetFrameForIndex(4));
EXPECT_EQ(gfx::Rect(kSpacing + kIconWidthWithPadding * 2, 0, kIconWidth,
kIconHeight),
overflow_bar()->GetFrameForIndex(5));
// And the actions should wrap, so that it starts back at the left on a new
// row.
EXPECT_EQ(gfx::Rect(kSpacing, kIconHeight, kIconWidth, kIconHeight),
overflow_bar()->GetFrameForIndex(6));
// Check with > 2 rows.
toolbar_model()->SetVisibleIconCount(0);
EXPECT_EQ(gfx::Rect(kSpacing, 0, kIconWidth, kIconHeight),
overflow_bar()->GetFrameForIndex(0));
EXPECT_EQ(gfx::Rect(kSpacing, kIconHeight * 2, kIconWidth, kIconHeight),
overflow_bar()->GetFrameForIndex(6));
}
TEST_P(ToolbarActionsBarUnitTest, TestStartAndEndIndexes) {
const int kIconWidthWithPadding = ToolbarActionsBar::IconWidth(true);
const int kIconSpacing = GetLayoutConstant(TOOLBAR_STANDARD_SPACING);
for (int i = 0; i < 3; ++i) {
CreateAndAddExtension(base::StringPrintf("extension %d", i),
ActionType::BROWSER_ACTION);
}
// At the start, all icons should be present on the main bar, and no
// overflow should be needed.
EXPECT_EQ(3u, toolbar_actions_bar()->GetIconCount());
EXPECT_EQ(0u, toolbar_actions_bar()->GetStartIndexInBounds());
EXPECT_EQ(3u, toolbar_actions_bar()->GetEndIndexInBounds());
EXPECT_EQ(3u, overflow_bar()->GetStartIndexInBounds());
EXPECT_EQ(3u, overflow_bar()->GetEndIndexInBounds());
EXPECT_FALSE(toolbar_actions_bar()->NeedsOverflow());
// Shrink the width of the view to be a little over enough for one icon.
browser_action_test_util()->SetWidth(kIconWidthWithPadding +
kIconSpacing + 2);
// Tricky: GetIconCount() is what we use to determine our preferred size,
// stored pref size, etc, and should not be affected by a minimum size that is
// too small to show everything. It should remain constant.
EXPECT_EQ(3u, toolbar_actions_bar()->GetIconCount());
// The main container should display only the first icon, with the overflow
// displaying the rest.
EXPECT_EQ(0u, toolbar_actions_bar()->GetStartIndexInBounds());
EXPECT_EQ(1u, toolbar_actions_bar()->GetEndIndexInBounds());
EXPECT_EQ(1u, overflow_bar()->GetStartIndexInBounds());
EXPECT_EQ(3u, overflow_bar()->GetEndIndexInBounds());
EXPECT_TRUE(toolbar_actions_bar()->NeedsOverflow());
// Shrink the container again to be too small to display even one icon.
// The overflow container should be displaying everything.
browser_action_test_util()->SetWidth(kIconWidthWithPadding - 10);
EXPECT_EQ(3u, toolbar_actions_bar()->GetIconCount());
EXPECT_EQ(0u, toolbar_actions_bar()->GetStartIndexInBounds());
EXPECT_EQ(0u, toolbar_actions_bar()->GetEndIndexInBounds());
EXPECT_EQ(0u, overflow_bar()->GetStartIndexInBounds());
EXPECT_EQ(3u, overflow_bar()->GetEndIndexInBounds());
EXPECT_TRUE(toolbar_actions_bar()->NeedsOverflow());
// Set the width back to the preferred width. All should be back to normal.
browser_action_test_util()->SetWidth(
toolbar_actions_bar()->GetFullSize().width());
EXPECT_EQ(3u, toolbar_actions_bar()->GetIconCount());
EXPECT_EQ(0u, toolbar_actions_bar()->GetStartIndexInBounds());
EXPECT_EQ(3u, toolbar_actions_bar()->GetEndIndexInBounds());
EXPECT_EQ(3u, overflow_bar()->GetStartIndexInBounds());
EXPECT_EQ(3u, overflow_bar()->GetEndIndexInBounds());
EXPECT_FALSE(toolbar_actions_bar()->NeedsOverflow());
}
// Tests the logic for determining if the container needs an overflow menu item.
TEST_P(ToolbarActionsBarUnitTest, TestNeedsOverflow) {
CreateAndAddExtension("extension 1", ActionType::BROWSER_ACTION);
// One extension on the main bar, none overflowed. Overflow not needed.
EXPECT_EQ(1u, toolbar_actions_bar()->GetIconCount());
EXPECT_EQ(0u, overflow_bar()->GetIconCount());
EXPECT_FALSE(toolbar_actions_bar()->NeedsOverflow());
// Set one extension in the overflow menu, none on the main bar. Overflow
// needed.
toolbar_model()->SetVisibleIconCount(0u);
EXPECT_EQ(0u, toolbar_actions_bar()->GetIconCount());
EXPECT_EQ(1u, overflow_bar()->GetIconCount());
EXPECT_TRUE(toolbar_actions_bar()->NeedsOverflow());
// Pop out an extension for a non-sticky popup. Even though the extension is
// on the main bar, overflow is still needed because it will pop back in
// when the menu is opened.
ToolbarActionViewController* action = toolbar_actions_bar()->GetActions()[0];
{
base::RunLoop run_loop;
toolbar_actions_bar()->PopOutAction(action, false, run_loop.QuitClosure());
run_loop.Run();
}
EXPECT_EQ(1u, toolbar_actions_bar()->GetIconCount());
EXPECT_TRUE(toolbar_actions_bar()->NeedsOverflow());
// Back to one in overflow, none on the main bar.
toolbar_actions_bar()->UndoPopOut();
EXPECT_EQ(0u, toolbar_actions_bar()->GetIconCount());
EXPECT_EQ(1u, overflow_bar()->GetIconCount());
EXPECT_TRUE(toolbar_actions_bar()->NeedsOverflow());
// Pop out an extension for a sticky popup. Overflow shouldn't be needed now
// because the extension will remain popped out even when the menu opens.
{
base::RunLoop run_loop;
toolbar_actions_bar()->PopOutAction(action, true, run_loop.QuitClosure());
run_loop.Run();
}
EXPECT_EQ(1u, toolbar_actions_bar()->GetIconCount());
EXPECT_FALSE(toolbar_actions_bar()->NeedsOverflow());
// Add another extension and verify that if one is still in overflow when
// another is popped out, we still need overflow.
toolbar_actions_bar()->UndoPopOut();
CreateAndAddExtension("extension 2", ActionType::BROWSER_ACTION);
toolbar_model()->SetVisibleIconCount(0u);
{
base::RunLoop run_loop;
toolbar_actions_bar()->PopOutAction(action, true, run_loop.QuitClosure());
run_loop.Run();
}
EXPECT_EQ(1u, toolbar_actions_bar()->GetIconCount());
EXPECT_TRUE(toolbar_actions_bar()->NeedsOverflow());
}