Commit 6f6ce9ce authored by Collin Baker's avatar Collin Baker Committed by Commit Bot

Remove TabGroupsIPHController

After refactors and the introduction of FeaturePromoController, tab
groups IPH logic no longer needs a dedicated class. This moves the
remaining logic to BrowserTabStripController.

Bug: 1106523
Change-Id: I3528da8b4c0d4d60ca033dfebb10c5a61564f036
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2369620
Commit-Queue: Collin Baker <collinbaker@chromium.org>
Reviewed-by: default avatarDana Fried <dfried@chromium.org>
Cr-Commit-Position: refs/heads/master@{#801945}
parent bd104c31
...@@ -3874,8 +3874,6 @@ static_library("ui") { ...@@ -3874,8 +3874,6 @@ static_library("ui") {
"views/tabs/tab_group_underline.h", "views/tabs/tab_group_underline.h",
"views/tabs/tab_group_views.cc", "views/tabs/tab_group_views.cc",
"views/tabs/tab_group_views.h", "views/tabs/tab_group_views.h",
"views/tabs/tab_groups_iph_controller.cc",
"views/tabs/tab_groups_iph_controller.h",
"views/tabs/tab_hover_card_bubble_view.cc", "views/tabs/tab_hover_card_bubble_view.cc",
"views/tabs/tab_hover_card_bubble_view.h", "views/tabs/tab_hover_card_bubble_view.h",
"views/tabs/tab_icon.cc", "views/tabs/tab_icon.cc",
......
...@@ -122,7 +122,6 @@ ...@@ -122,7 +122,6 @@
#include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h" #include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h"
#include "chrome/browser/ui/views/tabs/new_tab_button.h" #include "chrome/browser/ui/views/tabs/new_tab_button.h"
#include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab.h"
#include "chrome/browser/ui/views/tabs/tab_groups_iph_controller.h"
#include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/browser/ui/views/tabs/tab_strip.h"
#include "chrome/browser/ui/views/toolbar/browser_actions_container.h" #include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
#include "chrome/browser/ui/views/toolbar/browser_app_menu_button.h" #include "chrome/browser/ui/views/toolbar/browser_app_menu_button.h"
...@@ -560,12 +559,6 @@ BrowserView::BrowserView(std::unique_ptr<Browser> browser) ...@@ -560,12 +559,6 @@ BrowserView::BrowserView(std::unique_ptr<Browser> browser)
feature_promo_controller_ = feature_promo_controller_ =
std::make_unique<FeaturePromoControllerViews>(this); std::make_unique<FeaturePromoControllerViews>(this);
// Must be destroyed before the tab strip and |feature_promo_controller_|.
tab_groups_iph_controller_ = std::make_unique<TabGroupsIPHController>(
browser_.get(), feature_promo_controller_.get(),
base::BindRepeating(&TabStrip::GetTabViewForPromoAnchor,
base::Unretained(tabstrip_)));
// Create WebViews early so |webui_tab_strip_| can observe their size. // Create WebViews early so |webui_tab_strip_| can observe their size.
auto devtools_web_view = auto devtools_web_view =
std::make_unique<views::WebView>(browser_->profile()); std::make_unique<views::WebView>(browser_->profile());
...@@ -644,9 +637,6 @@ BrowserView::~BrowserView() { ...@@ -644,9 +637,6 @@ BrowserView::~BrowserView() {
extension_keybinding_registry_.get()) extension_keybinding_registry_.get())
global_registry->set_registry_for_active_window(nullptr); global_registry->set_registry_for_active_window(nullptr);
// This has a reference to |tabstrip_| so destroy it first.
tab_groups_iph_controller_.reset();
// The TabStrip attaches a listener to the model. Make sure we shut down the // The TabStrip attaches a listener to the model. Make sure we shut down the
// TabStrip first so that it can cleanly remove the listener. // TabStrip first so that it can cleanly remove the listener.
if (tabstrip_) if (tabstrip_)
......
...@@ -65,7 +65,6 @@ class FullscreenControlHost; ...@@ -65,7 +65,6 @@ class FullscreenControlHost;
class InfoBarContainerView; class InfoBarContainerView;
class LocationBarView; class LocationBarView;
class StatusBubbleViews; class StatusBubbleViews;
class TabGroupsIPHController;
class TabStrip; class TabStrip;
class TabStripRegionView; class TabStripRegionView;
class ToolbarButtonProvider; class ToolbarButtonProvider;
...@@ -306,10 +305,6 @@ class BrowserView : public BrowserWindow, ...@@ -306,10 +305,6 @@ class BrowserView : public BrowserWindow,
return toolbar_button_provider_; return toolbar_button_provider_;
} }
TabGroupsIPHController* tab_groups_iph_controller() {
return tab_groups_iph_controller_.get();
}
FeaturePromoControllerViews* feature_promo_controller() { FeaturePromoControllerViews* feature_promo_controller() {
return feature_promo_controller_.get(); return feature_promo_controller_.get();
} }
...@@ -918,7 +913,6 @@ class BrowserView : public BrowserWindow, ...@@ -918,7 +913,6 @@ class BrowserView : public BrowserWindow,
std::unique_ptr<AccessibilityFocusHighlight> accessibility_focus_highlight_; std::unique_ptr<AccessibilityFocusHighlight> accessibility_focus_highlight_;
std::unique_ptr<TabGroupsIPHController> tab_groups_iph_controller_;
std::unique_ptr<FeaturePromoControllerViews> feature_promo_controller_; std::unique_ptr<FeaturePromoControllerViews> feature_promo_controller_;
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/favicon/favicon_utils.h" #include "chrome/browser/favicon/favicon_utils.h"
#include "chrome/browser/feature_engagement/tracker_factory.h"
#include "chrome/browser/search/search.h" #include "chrome/browser/search/search.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_command_controller.h" #include "chrome/browser/ui/browser_command_controller.h"
...@@ -37,13 +38,17 @@ ...@@ -37,13 +38,17 @@
#include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h"
#include "chrome/browser/ui/tabs/tab_utils.h" #include "chrome/browser/ui/tabs/tab_utils.h"
#include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/views/in_product_help/feature_promo_controller_views.h"
#include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab.h"
#include "chrome/browser/ui/views/tabs/tab_drag_controller.h" #include "chrome/browser/ui/views/tabs/tab_drag_controller.h"
#include "chrome/browser/ui/views/tabs/tab_groups_iph_controller.h"
#include "chrome/browser/ui/views/tabs/tab_strip.h" #include "chrome/browser/ui/views/tabs/tab_strip.h"
#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h" #include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h" #include "chrome/common/url_constants.h"
#include "chrome/grit/generated_resources.h"
#include "components/feature_engagement/public/event_constants.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/feature_engagement/public/tracker.h"
#include "components/omnibox/browser/autocomplete_classifier.h" #include "components/omnibox/browser/autocomplete_classifier.h"
#include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match.h"
#include "components/prefs/pref_service.h" #include "components/prefs/pref_service.h"
...@@ -103,13 +108,23 @@ class BrowserTabStripController::TabContextMenuContents ...@@ -103,13 +108,23 @@ class BrowserTabStripController::TabContextMenuContents
public: public:
TabContextMenuContents(Tab* tab, TabContextMenuContents(Tab* tab,
BrowserTabStripController* controller, BrowserTabStripController* controller,
TabGroupsIPHController* tab_groups_iph_controller) FeaturePromoController* feature_promo_controller)
: tab_(tab), : tab_(tab),
controller_(controller), controller_(controller),
tab_groups_iph_controller_(tab_groups_iph_controller) { feature_promo_controller_(feature_promo_controller) {
model_ = controller_->menu_model_factory_->Create( model_ = controller_->menu_model_factory_->Create(
this, controller->model_, controller->tabstrip_->GetModelIndexOf(tab)); this, controller->model_, controller->tabstrip_->GetModelIndexOf(tab));
// If IPH is showing, continue into the menu. IsCommandIdAlerted()
// is called on |menu_runner_| construction, and we check
// |tab_groups_promo_handle_| there. So we must do this first.
if (feature_promo_controller_->BubbleIsShowing(
feature_engagement::kIPHDesktopTabGroupsNewGroupFeature)) {
tab_groups_promo_handle_ =
feature_promo_controller_->CloseBubbleAndContinuePromo(
feature_engagement::kIPHDesktopTabGroupsNewGroupFeature);
}
// Because we use "new" badging for feature promos, we cannot use system- // Because we use "new" badging for feature promos, we cannot use system-
// native context menus. (See crbug.com/1109256.) // native context menus. (See crbug.com/1109256.)
const int run_flags = const int run_flags =
...@@ -122,7 +137,6 @@ class BrowserTabStripController::TabContextMenuContents ...@@ -122,7 +137,6 @@ class BrowserTabStripController::TabContextMenuContents
void Cancel() { controller_ = nullptr; } void Cancel() { controller_ = nullptr; }
void RunMenuAt(const gfx::Point& point, ui::MenuSourceType source_type) { void RunMenuAt(const gfx::Point& point, ui::MenuSourceType source_type) {
tab_groups_iph_controller_->TabContextMenuOpened();
menu_runner_->RunMenuAt(tab_->GetWidget(), nullptr, menu_runner_->RunMenuAt(tab_->GetWidget(), nullptr,
gfx::Rect(point, gfx::Size()), gfx::Rect(point, gfx::Size()),
views::MenuAnchorPosition::kTopLeft, source_type); views::MenuAnchorPosition::kTopLeft, source_type);
...@@ -138,12 +152,11 @@ class BrowserTabStripController::TabContextMenuContents ...@@ -138,12 +152,11 @@ class BrowserTabStripController::TabContextMenuContents
bool IsCommandIdAlerted(int command_id) const override { bool IsCommandIdAlerted(int command_id) const override {
return command_id == TabStripModel::CommandAddToNewGroup && return command_id == TabStripModel::CommandAddToNewGroup &&
tab_groups_iph_controller_ && tab_groups_promo_handle_;
tab_groups_iph_controller_->ShouldHighlightContextMenuItem();
} }
void MenuClosed(ui::SimpleMenuModel*) override { void MenuClosed(ui::SimpleMenuModel*) override {
tab_groups_iph_controller_->TabContextMenuClosed(); tab_groups_promo_handle_.reset();
} }
bool GetAcceleratorForCommandId(int command_id, bool GetAcceleratorForCommandId(int command_id,
...@@ -178,7 +191,10 @@ class BrowserTabStripController::TabContextMenuContents ...@@ -178,7 +191,10 @@ class BrowserTabStripController::TabContextMenuContents
// A pointer back to our hosting controller, for command state information. // A pointer back to our hosting controller, for command state information.
BrowserTabStripController* controller_; BrowserTabStripController* controller_;
TabGroupsIPHController* const tab_groups_iph_controller_; FeaturePromoController* const feature_promo_controller_;
// Handle we keep if showing menu IPH for tab groups.
base::Optional<FeaturePromoController::PromoHandle> tab_groups_promo_handle_;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
...@@ -191,6 +207,9 @@ BrowserTabStripController::BrowserTabStripController( ...@@ -191,6 +207,9 @@ BrowserTabStripController::BrowserTabStripController(
: model_(model), : model_(model),
tabstrip_(nullptr), tabstrip_(nullptr),
browser_view_(browser_view), browser_view_(browser_view),
feature_engagement_tracker_(
feature_engagement::TrackerFactory::GetForBrowserContext(
browser_view_->browser()->profile())),
hover_tab_selector_(model), hover_tab_selector_(model),
menu_model_factory_(std::move(menu_model_factory_override)) { menu_model_factory_(std::move(menu_model_factory_override)) {
if (!menu_model_factory_) { if (!menu_model_factory_) {
...@@ -418,7 +437,7 @@ void BrowserTabStripController::ShowContextMenuForTab( ...@@ -418,7 +437,7 @@ void BrowserTabStripController::ShowContextMenuForTab(
const gfx::Point& p, const gfx::Point& p,
ui::MenuSourceType source_type) { ui::MenuSourceType source_type) {
context_menu_contents_ = std::make_unique<TabContextMenuContents>( context_menu_contents_ = std::make_unique<TabContextMenuContents>(
tab, this, browser_view_->tab_groups_iph_controller()); tab, this, browser_view_->feature_promo_controller());
context_menu_contents_->RunMenuAt(p, source_type); context_menu_contents_->RunMenuAt(p, source_type);
} }
...@@ -662,6 +681,8 @@ void BrowserTabStripController::OnTabGroupChanged( ...@@ -662,6 +681,8 @@ void BrowserTabStripController::OnTabGroupChanged(
switch (change.type) { switch (change.type) {
case TabGroupChange::kCreated: { case TabGroupChange::kCreated: {
tabstrip_->OnGroupCreated(change.group); tabstrip_->OnGroupCreated(change.group);
feature_engagement_tracker_->NotifyEvent(
feature_engagement::events::kTabGroupCreated);
break; break;
} }
case TabGroupChange::kEditorOpened: { case TabGroupChange::kEditorOpened: {
...@@ -740,6 +761,15 @@ void BrowserTabStripController::AddTab(WebContents* contents, ...@@ -740,6 +761,15 @@ void BrowserTabStripController::AddTab(WebContents* contents,
tabstrip_->AddTabAt(index, TabRendererData::FromTabInModel(model_, index), tabstrip_->AddTabAt(index, TabRendererData::FromTabInModel(model_, index),
is_active); is_active);
// Try to show tab groups IPH if needed.
if (tabstrip_->tab_count() >= 6) {
feature_engagement_tracker_->NotifyEvent(
feature_engagement::events::kSixthTabOpened);
browser_view_->feature_promo_controller()->MaybeShowPromo(
feature_engagement::kIPHDesktopTabGroupsNewGroupFeature);
}
} }
void BrowserTabStripController::UpdateStackedLayout() { void BrowserTabStripController::UpdateStackedLayout() {
......
...@@ -30,6 +30,10 @@ namespace content { ...@@ -30,6 +30,10 @@ namespace content {
class WebContents; class WebContents;
} }
namespace feature_engagement {
class Tracker;
}
namespace ui { namespace ui {
class ListSelectionModel; class ListSelectionModel;
} }
...@@ -158,6 +162,8 @@ class BrowserTabStripController : public TabStripController, ...@@ -158,6 +162,8 @@ class BrowserTabStripController : public TabStripController,
BrowserView* browser_view_; BrowserView* browser_view_;
feature_engagement::Tracker* const feature_engagement_tracker_;
// If non-NULL it means we're showing a menu for the tab. // If non-NULL it means we're showing a menu for the tab.
std::unique_ptr<TabContextMenuContents> context_menu_contents_; std::unique_ptr<TabContextMenuContents> context_menu_contents_;
......
// Copyright 2020 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/views/tabs/tab_groups_iph_controller.h"
#include <utility>
#include "base/logging.h"
#include "base/optional.h"
#include "chrome/browser/feature_engagement/tracker_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/views/in_product_help/feature_promo_bubble_params.h"
#include "chrome/browser/ui/views/in_product_help/feature_promo_bubble_view.h"
#include "chrome/browser/ui/views/in_product_help/feature_promo_controller.h"
#include "chrome/grit/generated_resources.h"
#include "components/feature_engagement/public/event_constants.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/feature_engagement/public/tracker.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/widget/widget.h"
TabGroupsIPHController::TabGroupsIPHController(
Browser* browser,
FeaturePromoController* promo_controller,
GetTabViewCallback get_tab_view)
: promo_controller_(promo_controller),
tracker_(feature_engagement::TrackerFactory::GetForBrowserContext(
browser->profile())),
get_tab_view_(std::move(get_tab_view)) {
DCHECK(promo_controller_);
DCHECK(tracker_);
browser->tab_strip_model()->AddObserver(this);
}
TabGroupsIPHController::~TabGroupsIPHController() = default;
bool TabGroupsIPHController::ShouldHighlightContextMenuItem() {
// If the bubble is currently showing, the promo hasn't timed out yet.
// The promo should continue into the context menu as a highlighted
// item.
return promo_controller_->BubbleIsShowing(
feature_engagement::kIPHDesktopTabGroupsNewGroupFeature);
}
void TabGroupsIPHController::TabContextMenuOpened() {
if (!promo_controller_->BubbleIsShowing(
feature_engagement::kIPHDesktopTabGroupsNewGroupFeature))
return;
// Assume that the context menu code checked
// ShouldHighlightContextMenuItem() and is correctly showing the promo
// there.
promo_handle_for_menu_ = promo_controller_->CloseBubbleAndContinuePromo(
feature_engagement::kIPHDesktopTabGroupsNewGroupFeature);
}
void TabGroupsIPHController::TabContextMenuClosed() {
if (!promo_handle_for_menu_)
return;
promo_handle_for_menu_.reset();
}
void TabGroupsIPHController::OnTabStripModelChanged(
TabStripModel* tab_strip_model,
const TabStripModelChange& change,
const TabStripSelectionChange& selection) {
if (!(change.type() == TabStripModelChange::kInserted &&
tab_strip_model->count() >= 6)) {
return;
}
tracker_->NotifyEvent(feature_engagement::events::kSixthTabOpened);
promo_controller_->MaybeShowPromo(
feature_engagement::kIPHDesktopTabGroupsNewGroupFeature);
}
void TabGroupsIPHController::OnTabGroupChanged(const TabGroupChange& change) {
if (change.type != TabGroupChange::kCreated)
return;
tracker_->NotifyEvent(feature_engagement::events::kTabGroupCreated);
}
// Copyright 2020 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.
#ifndef CHROME_BROWSER_UI_VIEWS_TABS_TAB_GROUPS_IPH_CONTROLLER_H_
#define CHROME_BROWSER_UI_VIEWS_TABS_TAB_GROUPS_IPH_CONTROLLER_H_
#include "base/callback_forward.h"
#include "base/optional.h"
#include "base/scoped_observer.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
#include "chrome/browser/ui/views/in_product_help/feature_promo_controller.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
namespace feature_engagement {
class Tracker;
}
namespace views {
class View;
}
class Browser;
// Manages in-product help for tab groups. Watches for relevant events
// in a browser window, communicates them to the IPH backend, and
// displays IPH when appropriate.
class TabGroupsIPHController : public TabStripModelObserver {
public:
// Callback with an argument N that should return the Nth tab view in
// the tab strip for bubble anchoring. If N is not valid, it should
// return any tab view.
using GetTabViewCallback = base::RepeatingCallback<views::View*(int)>;
// |browser| is the browser window that this instance will track and
// will show IPH in if needed. |promo_controller| is the window's
// FeaturePromoControllerViews, used to start promos. |get_tab_view| should
// get an appropriate tab to anchor the bubble in |browser|.
TabGroupsIPHController(Browser* browser,
FeaturePromoController* promo_controller,
GetTabViewCallback get_tab_view);
~TabGroupsIPHController() override;
// Whether the add-to-new-group item in the tab context menu should be
// highlighted. Must be checked just before TabContextMenuOpened() is
// called on the same task.
bool ShouldHighlightContextMenuItem();
// Should be called when a tab context menu is opened.
void TabContextMenuOpened();
// Likewise, should be called when a tab context menu is closed.
void TabContextMenuClosed();
// TabStripModelObserver:
void OnTabStripModelChanged(
TabStripModel* tab_strip_model,
const TabStripModelChange& change,
const TabStripSelectionChange& selection) override;
void OnTabGroupChanged(const TabGroupChange& change) override;
private:
FeaturePromoController* const promo_controller_;
// The IPH backend for the profile.
feature_engagement::Tracker* const tracker_;
GetTabViewCallback get_tab_view_;
// A handle given by |promo_controller_| if we show a context menu
// promo. When destroyed this notifies |promo_controller_| we are
// done.
base::Optional<FeaturePromoController::PromoHandle> promo_handle_for_menu_;
};
#endif // CHROME_BROWSER_UI_VIEWS_TABS_TAB_GROUPS_IPH_CONTROLLER_H_
// Copyright 2020 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/views/tabs/tab_groups_iph_controller.h"
#include <memory>
#include <string>
#include "base/bind.h"
#include "base/callback_list.h"
#include "chrome/browser/feature_engagement/tracker_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/test/test_browser_dialog.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/feature_engagement/test/mock_tracker.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "content/public/test/browser_test.h"
#include "testing/gmock/include/gmock/gmock.h"
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::Ref;
using ::testing::Return;
class TabGroupsIPHControllerBrowserTest : public DialogBrowserTest {
public:
TabGroupsIPHControllerBrowserTest() {
service_manager_subscription_ =
BrowserContextDependencyManager::GetInstance()
->RegisterCreateServicesCallbackForTesting(
base::BindRepeating(RegisterMockTrackerFactory));
}
protected:
void ShowUi(const std::string& name) override {
OpenTabsToTrigger(browser());
}
void OpenTabsToTrigger(Browser* browser) {
// We need to have 6 tabs to trigger our IPH. Browser tests start
// with one tab, so open 5 more.
for (int i = 0; i < 5; ++i)
chrome::NewTab(browser);
}
void SetUpOnMainThread() override {
DialogBrowserTest::SetUpOnMainThread();
mock_tracker_ = static_cast<feature_engagement::test::MockTracker*>(
feature_engagement::TrackerFactory::GetForBrowserContext(
browser()->profile()));
}
feature_engagement::test::MockTracker* mock_tracker_;
private:
static void RegisterMockTrackerFactory(content::BrowserContext* context) {
feature_engagement::TrackerFactory::GetInstance()->SetTestingFactory(
context, base::BindRepeating([](content::BrowserContext*) {
auto mock_tracker =
std::make_unique<feature_engagement::test::MockTracker>();
// Other features may call into the backend.
EXPECT_CALL(*mock_tracker, NotifyEvent(_)).Times(AnyNumber());
EXPECT_CALL(*mock_tracker, ShouldTriggerHelpUI(_))
.Times(AnyNumber())
.WillRepeatedly(Return(false));
return std::unique_ptr<KeyedService>(mock_tracker.release());
}));
}
std::unique_ptr<
BrowserContextDependencyManager::CreateServicesCallbackList::Subscription>
service_manager_subscription_;
};
IN_PROC_BROWSER_TEST_F(TabGroupsIPHControllerBrowserTest, InvokeUi_default) {
// Allow the controller to show the promo.
EXPECT_CALL(*mock_tracker_,
ShouldTriggerHelpUI(
Ref(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature)))
.Times(1)
.WillOnce(Return(true));
// Expect the controller to notify on dismissal.
EXPECT_CALL(
*mock_tracker_,
Dismissed(Ref(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature)))
.Times(1);
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(TabGroupsIPHControllerBrowserTest,
HandlesBrowserShutdown) {
Browser* second_browser = CreateBrowser(browser()->profile());
EXPECT_CALL(*mock_tracker_,
ShouldTriggerHelpUI(
Ref(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature)))
.Times(1)
.WillOnce(Return(true));
EXPECT_CALL(
*mock_tracker_,
Dismissed(Ref(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature)))
.Times(1);
OpenTabsToTrigger(second_browser);
CloseBrowserSynchronously(second_browser);
}
// Copyright 2020 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/views/tabs/tab_groups_iph_controller.h"
#include <memory>
#include <utility>
#include "base/bind.h"
#include "chrome/browser/feature_engagement/tracker_factory.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/test_with_browser_view.h"
#include "chrome/browser/ui/views/in_product_help/feature_promo_controller_views.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/views/chrome_test_widget.h"
#include "components/feature_engagement/public/event_constants.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/feature_engagement/test/mock_tracker.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "ui/views/test/scoped_views_test_helper.h"
#include "ui/views/view.h"
#include "ui/views/widget/unique_widget_ptr.h"
#include "ui/views/widget/widget.h"
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::NiceMock;
using ::testing::Ref;
using ::testing::Return;
class TabGroupsIPHControllerTest : public TestWithBrowserView {
public:
void SetUp() override {
TestWithBrowserView::SetUp();
mock_tracker_ =
static_cast<NiceMock<feature_engagement::test::MockTracker>*>(
feature_engagement::TrackerFactory::GetForBrowserContext(
profile()));
promo_controller_ = browser_view()->feature_promo_controller();
iph_controller_ = browser_view()->tab_groups_iph_controller();
}
void TearDown() override {
iph_controller_ = nullptr;
promo_controller_ = nullptr;
TestWithBrowserView::TearDown();
}
TestingProfile::TestingFactories GetTestingFactories() override {
TestingProfile::TestingFactories factories =
TestWithBrowserView::GetTestingFactories();
factories.emplace_back(feature_engagement::TrackerFactory::GetInstance(),
base::BindRepeating(MakeTestTracker));
return factories;
}
private:
static std::unique_ptr<KeyedService> MakeTestTracker(
content::BrowserContext* context) {
auto tracker =
std::make_unique<NiceMock<feature_engagement::test::MockTracker>>();
// Allow other code to call into the tracker.
EXPECT_CALL(*tracker, NotifyEvent(_)).Times(AnyNumber());
EXPECT_CALL(*tracker, ShouldTriggerHelpUI(_))
.Times(AnyNumber())
.WillRepeatedly(Return(false));
return tracker;
}
protected:
NiceMock<feature_engagement::test::MockTracker>* mock_tracker_;
FeaturePromoController* promo_controller_;
TabGroupsIPHController* iph_controller_;
};
TEST_F(TabGroupsIPHControllerTest, NotifyEventAndTriggerOnSixthTabOpened) {
// TabGroupsIPHController shouldn't issue any calls...yet
EXPECT_CALL(*mock_tracker_,
NotifyEvent(feature_engagement::events::kSixthTabOpened))
.Times(0);
EXPECT_CALL(*mock_tracker_,
ShouldTriggerHelpUI(
Ref(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature)))
.Times(0);
for (int i = 0; i < 5; ++i)
chrome::NewTab(browser());
// Upon opening a sixth tab, our controller should both notify the IPH
// backend and ask to trigger IPH.
EXPECT_CALL(*mock_tracker_,
NotifyEvent(feature_engagement::events::kSixthTabOpened))
.Times(1);
EXPECT_CALL(*mock_tracker_,
ShouldTriggerHelpUI(
Ref(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature)))
.Times(1)
.WillOnce(Return(false));
chrome::NewTab(browser());
}
TEST_F(TabGroupsIPHControllerTest, NotifyEventOnTabGroupCreated) {
// Creating an ungrouped tab shouldn't do anything.
EXPECT_CALL(*mock_tracker_,
NotifyEvent(feature_engagement::events::kTabGroupCreated))
.Times(0);
chrome::NewTab(browser());
// Adding the tab to a new group should issue the relevant event.
EXPECT_CALL(*mock_tracker_,
NotifyEvent(feature_engagement::events::kTabGroupCreated))
.Times(1);
browser()->tab_strip_model()->AddToNewGroup({0});
}
TEST_F(TabGroupsIPHControllerTest, DismissedOnMenuClosed) {
EXPECT_CALL(*mock_tracker_,
ShouldTriggerHelpUI(
Ref(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature)))
.Times(1)
.WillOnce(Return(true));
for (int i = 0; i < 6; ++i)
chrome::NewTab(browser());
EXPECT_TRUE(promo_controller_->BubbleIsShowing(
feature_engagement::kIPHDesktopTabGroupsNewGroupFeature));
iph_controller_->TabContextMenuOpened();
EXPECT_FALSE(promo_controller_->BubbleIsShowing(
feature_engagement::kIPHDesktopTabGroupsNewGroupFeature));
EXPECT_CALL(
*mock_tracker_,
Dismissed(Ref(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature)))
.Times(1);
iph_controller_->TabContextMenuClosed();
EXPECT_FALSE(promo_controller_->BubbleIsShowing(
feature_engagement::kIPHDesktopTabGroupsNewGroupFeature));
}
TEST_F(TabGroupsIPHControllerTest, ShowsContextMenuHighlightIfAppropriate) {
EXPECT_CALL(*mock_tracker_,
ShouldTriggerHelpUI(
Ref(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature)))
.Times(1)
.WillOnce(Return(true));
EXPECT_CALL(
*mock_tracker_,
Dismissed(Ref(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature)))
.Times(1);
EXPECT_FALSE(iph_controller_->ShouldHighlightContextMenuItem());
for (int i = 0; i < 6; ++i)
chrome::NewTab(browser());
EXPECT_TRUE(iph_controller_->ShouldHighlightContextMenuItem());
iph_controller_->TabContextMenuOpened();
iph_controller_->TabContextMenuClosed();
EXPECT_FALSE(iph_controller_->ShouldHighlightContextMenuItem());
}
...@@ -1405,7 +1405,6 @@ if (!is_android) { ...@@ -1405,7 +1405,6 @@ if (!is_android) {
"../browser/ui/views/sharing/shared_clipboard_browsertest.cc", "../browser/ui/views/sharing/shared_clipboard_browsertest.cc",
"../browser/ui/views/sharing/sharing_browsertest.cc", "../browser/ui/views/sharing/sharing_browsertest.cc",
"../browser/ui/views/sharing/sharing_browsertest.h", "../browser/ui/views/sharing/sharing_browsertest.h",
"../browser/ui/views/tabs/tab_groups_iph_controller_browsertest.cc",
"../browser/ui/views/tabs/tab_strip_browsertest.cc", "../browser/ui/views/tabs/tab_strip_browsertest.cc",
"../browser/ui/views/try_chrome_dialog_win/try_chrome_dialog_browsertest.cc", "../browser/ui/views/try_chrome_dialog_win/try_chrome_dialog_browsertest.cc",
"../browser/ui/views/web_apps/web_app_frame_toolbar_browsertest.cc", "../browser/ui/views/web_apps/web_app_frame_toolbar_browsertest.cc",
...@@ -5686,7 +5685,6 @@ test("unit_tests") { ...@@ -5686,7 +5685,6 @@ test("unit_tests") {
"../browser/ui/views/tabs/fake_base_tab_strip_controller.cc", "../browser/ui/views/tabs/fake_base_tab_strip_controller.cc",
"../browser/ui/views/tabs/fake_base_tab_strip_controller.h", "../browser/ui/views/tabs/fake_base_tab_strip_controller.h",
"../browser/ui/views/tabs/stacked_tab_strip_layout_unittest.cc", "../browser/ui/views/tabs/stacked_tab_strip_layout_unittest.cc",
"../browser/ui/views/tabs/tab_groups_iph_controller_unittest.cc",
"../browser/ui/views/tabs/tab_strip_layout_unittest.cc", "../browser/ui/views/tabs/tab_strip_layout_unittest.cc",
"../browser/ui/views/tabs/tab_strip_unittest.cc", "../browser/ui/views/tabs/tab_strip_unittest.cc",
"../browser/ui/views/tabs/tab_unittest.cc", "../browser/ui/views/tabs/tab_unittest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment