Commit dbdb5e96 authored by Collin Baker's avatar Collin Baker Committed by Commit Bot

Implement display of reopen tab in-product help

This adds a class, ReopenTabPromoController, that manages display of
the reopen tab in-product help promo, and expands the interfaces of
AppMenu and AppMenuButton to allow this.

Change-Id: I78431981a21d432778aceb65d3aa17642164bc14
Bug: 887991
Reviewed-on: https://chromium-review.googlesource.com/c/1334937
Commit-Queue: Collin Baker <collinbaker@chromium.org>
Reviewed-by: default avatarPeter Boström <pbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#609405}
parent f3b33a18
......@@ -5080,6 +5080,9 @@ the Bookmarks menu.">
<message name="IDS_NEWTAB_PROMO_2" desc="Variations option 3. Text shown on promotional UI appearing next to the New Tab button, which encourages users to use it.">
Open a new tab to browse two sites at once
</message>
<message name="IDS_REOPEN_TAB_PROMO" desc="Text shown on promotional UI appearing next to the app menu button">
Reopen a tab if you accidentally closed it
</message>
<!-- Browser Hung Plugin Detector -->
<if expr="is_win">
......
6e3827c2634ca8ef00f34a4df80367296252542b
\ No newline at end of file
......@@ -3298,6 +3298,8 @@ jumbo_split_static_library("ui") {
"in_product_help/reopen_tab_in_product_help_factory.h",
"in_product_help/reopen_tab_in_product_help_trigger.cc",
"in_product_help/reopen_tab_in_product_help_trigger.h",
"views/feature_promos/reopen_tab_promo_controller.cc",
"views/feature_promos/reopen_tab_promo_controller.h",
]
}
......
// Copyright 2018 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/feature_promos/reopen_tab_promo_controller.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/ui/in_product_help/reopen_tab_in_product_help.h"
#include "chrome/browser/ui/in_product_help/reopen_tab_in_product_help_factory.h"
#include "chrome/browser/ui/toolbar/app_menu_model.h"
#include "chrome/browser/ui/views/feature_promos/feature_promo_bubble_view.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/toolbar/app_menu.h"
#include "chrome/browser/ui/views/toolbar/browser_app_menu_button.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "chrome/grit/generated_resources.h"
#include "ui/views/controls/menu/menu_item_view.h"
ReopenTabPromoController::ReopenTabPromoController(BrowserView* browser_view)
: iph_service_(ReopenTabInProductHelpFactory::GetForProfile(
browser_view->browser()->profile())),
browser_view_(browser_view) {
// Check that the app menu button exists. It should only not exist when there
// is no tab strip, in which case this shouldn't trigger in the first place.
BrowserAppMenuButton* app_menu_button =
browser_view_->toolbar()->app_menu_button();
DCHECK(app_menu_button);
}
void ReopenTabPromoController::ShowPromo() {
// Here, we start the promo display. We highlight the app menu button and open
// the promo bubble.
BrowserAppMenuButton* app_menu_button =
browser_view_->toolbar()->app_menu_button();
app_menu_button->AddMenuListener(this);
app_menu_button->SetHighlighted(true);
promo_bubble_ = FeaturePromoBubbleView::CreateOwned(
app_menu_button, views::BubbleBorder::Arrow::TOP_RIGHT,
IDS_REOPEN_TAB_PROMO, FeaturePromoBubbleView::ActivationAction::ACTIVATE);
promo_bubble_->GetWidget()->AddObserver(this);
}
void ReopenTabPromoController::OnMenuOpened() {
// The user followed the promo and opened the menu. Now, we highlight the
// history item and observe for the history submenu opening.
BrowserAppMenuButton* app_menu_button =
browser_view_->toolbar()->app_menu_button();
app_menu_button->RemoveMenuListener(this);
AppMenu* app_menu = app_menu_button->app_menu();
app_menu->AddObserver(this);
views::MenuItemView* recent_tabs_menu_item =
app_menu->root_menu_item()->GetMenuItemByID(IDC_RECENT_TABS_MENU);
recent_tabs_menu_item->SetForcedVisualSelection(true);
}
void ReopenTabPromoController::OnWidgetDestroying(views::Widget* widget) {
DCHECK(promo_bubble_);
// If the menu isn't showing, that means the promo bubble timed out. We should
// notify our IPH service that help was dismissed.
if (!browser_view_->toolbar()->app_menu_button()->IsMenuShowing()) {
BrowserAppMenuButton* app_menu_button =
browser_view_->toolbar()->app_menu_button();
app_menu_button->RemoveMenuListener(this);
app_menu_button->SetHighlighted(false);
iph_service_->HelpDismissed();
}
}
void ReopenTabPromoController::AppMenuClosed() {
// The menu was opened then closed, whether by clicking away or by clicking a
// menu item. We notify the service regardless of whether IPH succeeded.
// Success is determined by whether the reopen tab event was sent.
iph_service_->HelpDismissed();
AppMenu* app_menu = browser_view_->toolbar()->app_menu_button()->app_menu();
app_menu->RemoveObserver(this);
}
void ReopenTabPromoController::OnShowSubmenu() {
// Check if the last opened tab menu item exists (it will if the history
// submenu was opened). If so, highlight it.
views::MenuItemView* root_menu_item =
browser_view_->toolbar()->app_menu_button()->app_menu()->root_menu_item();
views::MenuItemView* last_tab_menu_item =
root_menu_item->GetMenuItemByID(AppMenuModel::kMinRecentTabsCommandId);
if (last_tab_menu_item) {
// The history submenu was shown. Highlight the last-closed tab item.
last_tab_menu_item->SetForcedVisualSelection(true);
}
}
// Copyright 2018 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_FEATURE_PROMOS_REOPEN_TAB_PROMO_CONTROLLER_H_
#define CHROME_BROWSER_UI_VIEWS_FEATURE_PROMOS_REOPEN_TAB_PROMO_CONTROLLER_H_
#include "chrome/browser/ui/views/toolbar/app_menu_observer.h"
#include "ui/views/controls/menu/menu_listener.h"
#include "ui/views/widget/widget_observer.h"
class BrowserView;
class FeaturePromoBubbleView;
class ReopenTabInProductHelp;
// Handles display of the reopen tab in-product help promo, including showing
// the promo bubble and highlighting the appropriate app menu items. Notifies
// the |ReopenTabInProductHelp| service when the promo is finished.
class ReopenTabPromoController : public AppMenuObserver,
public views::MenuListener,
public views::WidgetObserver {
public:
explicit ReopenTabPromoController(BrowserView* browser_view);
~ReopenTabPromoController() override = default;
void ShowPromo();
private:
// views::MenuListener:
void OnMenuOpened() override;
// views::WidgetObserver:
void OnWidgetDestroying(views::Widget* widget) override;
// AppMenuObserver:
void AppMenuClosed() override;
void OnShowSubmenu() override;
ReopenTabInProductHelp* const iph_service_;
BrowserView* const browser_view_;
FeaturePromoBubbleView* promo_bubble_ = nullptr;
};
#endif // CHROME_BROWSER_UI_VIEWS_FEATURE_PROMOS_REOPEN_TAB_PROMO_CONTROLLER_H_
......@@ -43,7 +43,7 @@ class AppMenuButton : public views::MenuButton {
// Removes a menu listener.
void RemoveMenuListener(views::MenuListener* listener);
AppMenu* app_menu_for_testing() { return menu_.get(); }
AppMenu* app_menu() { return menu_.get(); }
protected:
// Create (but don't show) the menu. |menu_model| should be a newly created
......
......@@ -778,8 +778,7 @@ class HostedAppNonClientFrameViewAshTest
}
AppMenu* GetAppMenu() {
return hosted_app_button_container_->app_menu_button_
->app_menu_for_testing();
return hosted_app_button_container_->app_menu_button_->app_menu();
}
SkColor GetActiveColor() {
......
......@@ -100,6 +100,7 @@
#include "chrome/browser/ui/views/tabs/tab.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_app_menu_button.h"
#include "chrome/browser/ui/views/toolbar/reload_button.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "chrome/browser/ui/views/translate/translate_bubble_view.h"
......@@ -194,6 +195,7 @@
#if BUILDFLAG(ENABLE_DESKTOP_IN_PRODUCT_HELP)
#include "chrome/browser/ui/in_product_help/reopen_tab_in_product_help.h"
#include "chrome/browser/ui/in_product_help/reopen_tab_in_product_help_factory.h"
#include "chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.h"
#endif // BUILDFLAG(ENABLE_DESKTOP_IN_PRODUCT_HELP)
#if BUILDFLAG(ENABLE_ONE_CLICK_SIGNIN)
......@@ -2958,9 +2960,11 @@ bool BrowserView::IsVisibleOnAllWorkspaces() const {
void BrowserView::ShowInProductHelpPromo(InProductHelpFeature iph_feature) {
switch (iph_feature) {
case InProductHelpFeature::kReopenTab:
// TODO(collinbaker): start in-product help flow here.
ReopenTabInProductHelpFactory::GetForProfile(browser()->profile())
->HelpDismissed();
if (!reopen_tab_promo_controller_) {
reopen_tab_promo_controller_ =
std::make_unique<ReopenTabPromoController>(this);
}
reopen_tab_promo_controller_->ShowPromo();
break;
}
}
......
......@@ -61,6 +61,7 @@ class ExclusiveAccessBubbleViews;
class FullscreenControlHost;
class InfoBarContainerView;
class LocationBarView;
class ReopenTabPromoController;
class StatusBubbleViews;
class TabStrip;
class ToolbarButtonProvider;
......@@ -806,6 +807,10 @@ class BrowserView : public BrowserWindow,
std::unique_ptr<FullscreenControlHost> fullscreen_control_host_;
#if BUILDFLAG(ENABLE_DESKTOP_IN_PRODUCT_HELP)
std::unique_ptr<ReopenTabPromoController> reopen_tab_promo_controller_;
#endif
struct ResizeSession {
// The time when user started resizing the window.
base::TimeTicks begin_timestamp;
......
......@@ -57,7 +57,7 @@ BrowserAppMenuButton* AppMenuTestApiViews::GetAppMenuButton() {
}
AppMenu* AppMenuTestApiViews::GetAppMenu() {
return GetAppMenuButton()->app_menu_for_testing();
return GetAppMenuButton()->app_menu();
}
} // namespace
......
......@@ -1025,6 +1025,11 @@ bool AppMenu::GetAccelerator(int command_id,
}
void AppMenu::WillShowMenu(MenuItemView* menu) {
if (menu != root_) {
for (AppMenuObserver& observer : observer_list_)
observer.OnShowSubmenu();
}
if (menu == bookmark_menu_)
CreateBookmarkMenu();
else if (bookmark_menu_delegate_)
......@@ -1051,6 +1056,9 @@ bool AppMenu::ShouldCloseOnDragComplete() {
}
void AppMenu::OnMenuClosed(views::MenuItemView* menu) {
for (AppMenuObserver& observer : observer_list_)
observer.AppMenuClosed();
if (bookmark_menu_delegate_.get()) {
BookmarkModel* model =
BookmarkModelFactory::GetForBrowserContext(browser_->profile());
......
......@@ -57,6 +57,8 @@ class AppMenu : public views::MenuDelegate,
bool for_drop() const { return (run_flags_ & FOR_DROP) != 0; }
views::MenuItemView* root_menu_item() { return root_; }
void AddObserver(AppMenuObserver* observer);
void RemoveObserver(AppMenuObserver* observer);
......
......@@ -8,7 +8,11 @@
class AppMenuObserver {
public:
// Invoked when the AppMenu is about to be destroyed (from its destructor).
virtual void AppMenuDestroyed() = 0;
virtual void AppMenuDestroyed() {}
virtual void AppMenuClosed() {}
virtual void OnShowSubmenu() {}
protected:
virtual ~AppMenuObserver() {}
......
......@@ -51,7 +51,7 @@ void TestOverflowedToolbarAction(Browser* browser,
// A bunch of plumbing to safely get at the overflowed toolbar action.
BrowserAppMenuButton* app_menu_button = GetAppButtonFromBrowser(browser);
EXPECT_TRUE(app_menu_button->IsMenuShowing());
AppMenu* app_menu = app_menu_button->app_menu_for_testing();
AppMenu* app_menu = app_menu_button->app_menu();
ASSERT_TRUE(app_menu);
ExtensionToolbarMenuView* menu_view =
app_menu->extension_toolbar_for_testing();
......@@ -92,7 +92,7 @@ void TestWhileContextMenuOpen(Browser* browser,
// Get the overflow container.
BrowserAppMenuButton* app_menu_button = GetAppButtonFromBrowser(browser);
AppMenu* app_menu = app_menu_button->app_menu_for_testing();
AppMenu* app_menu = app_menu_button->app_menu();
ASSERT_TRUE(app_menu);
ExtensionToolbarMenuView* menu_view =
app_menu->extension_toolbar_for_testing();
......
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