Commit 4cbe5b13 authored by Collin Baker's avatar Collin Baker Committed by Commit Bot

Use FeaturePromoController to show Live Caption promo

Bug: 1055150
Change-Id: Iee3d318ff90362a2cc29754b9a118a2a60d5a4c7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2418809
Commit-Queue: Collin Baker <collinbaker@chromium.org>
Commit-Queue: Abigail Klein <abigailbklein@google.com>
Auto-Submit: Collin Baker <collinbaker@chromium.org>
Reviewed-by: default avatarAbigail Klein <abigailbklein@google.com>
Cr-Commit-Position: refs/heads/master@{#808939}
parent 83bcf82e
......@@ -1024,11 +1024,6 @@ static_library("ui") {
"in_product_help/global_media_controls_in_product_help.h",
"in_product_help/global_media_controls_in_product_help_factory.cc",
"in_product_help/global_media_controls_in_product_help_factory.h",
"in_product_help/in_product_help.h",
"in_product_help/live_caption_in_product_help.cc",
"in_product_help/live_caption_in_product_help.h",
"in_product_help/live_caption_in_product_help_factory.cc",
"in_product_help/live_caption_in_product_help_factory.h",
"in_product_help/reopen_tab_in_product_help.cc",
"in_product_help/reopen_tab_in_product_help.h",
"in_product_help/reopen_tab_in_product_help_factory.cc",
......@@ -3576,8 +3571,6 @@ static_library("ui") {
"views/in_product_help/feature_promo_registry.h",
"views/in_product_help/global_media_controls_promo_controller.cc",
"views/in_product_help/global_media_controls_promo_controller.h",
"views/in_product_help/live_caption_promo_controller.cc",
"views/in_product_help/live_caption_promo_controller.h",
"views/in_product_help/reopen_tab_promo_controller.cc",
"views/in_product_help/reopen_tab_promo_controller.h",
"views/infobars/alternate_nav_infobar_view.cc",
......
......@@ -9,7 +9,6 @@
enum class InProductHelpFeature {
kGlobalMediaControls,
kIncognitoWindow,
kLiveCaption,
kReopenTab,
};
......
// 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/in_product_help/live_caption_in_product_help.h"
#include "base/feature_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_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/feature_engagement/public/tracker.h"
#include "media/base/media_switches.h"
LiveCaptionInProductHelp::LiveCaptionInProductHelp(Profile* profile)
: profile_(profile) {}
LiveCaptionInProductHelp::~LiveCaptionInProductHelp() = default;
void LiveCaptionInProductHelp::OnMediaButtonEnabled() {
Browser* browser = BrowserList::GetInstance()->GetLastActive();
if (!browser || browser->profile() != profile_)
return;
if (GetTracker()->ShouldTriggerHelpUI(
feature_engagement::kIPHLiveCaptionFeature)) {
browser->window()->ShowInProductHelpPromo(
InProductHelpFeature::kLiveCaption);
}
}
void LiveCaptionInProductHelp::HelpDismissed() {
GetTracker()->Dismissed(feature_engagement::kIPHLiveCaptionFeature);
}
feature_engagement::Tracker* LiveCaptionInProductHelp::GetTracker() {
return feature_engagement::TrackerFactory::GetForBrowserContext(profile_);
}
// 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_IN_PRODUCT_HELP_LIVE_CAPTION_IN_PRODUCT_HELP_H_
#define CHROME_BROWSER_UI_IN_PRODUCT_HELP_LIVE_CAPTION_IN_PRODUCT_HELP_H_
#include "chrome/browser/ui/global_media_controls/media_toolbar_button_observer.h"
#include "components/keyed_service/core/keyed_service.h"
class Profile;
namespace feature_engagement {
class Tracker;
}
// Listens for the triggering conditions for the global media controls
// in-product help and starts the IPH flow at the appropriate time. This is a
// |Profile|-keyed service since we track interactions per user profile. Hooks
// throughout the browser UI code will fetch this service and notify it of
// interesting user actions.
class LiveCaptionInProductHelp : public KeyedService,
public MediaToolbarButtonObserver {
public:
explicit LiveCaptionInProductHelp(Profile* profile);
~LiveCaptionInProductHelp() override;
LiveCaptionInProductHelp(const LiveCaptionInProductHelp&) = delete;
LiveCaptionInProductHelp& operator=(const LiveCaptionInProductHelp&) = delete;
// MediaToolbarButtonObserver:
void OnMediaDialogOpened() override {}
void OnMediaButtonShown() override {}
void OnMediaButtonHidden() override {}
void OnMediaButtonEnabled() override;
void OnMediaButtonDisabled() override {}
// Must be called when IPH promo finishes showing, whether by use of the
// feature or by timing out.
void HelpDismissed();
private:
feature_engagement::Tracker* GetTracker();
Profile* const profile_;
};
#endif // CHROME_BROWSER_UI_IN_PRODUCT_HELP_LIVE_CAPTION_IN_PRODUCT_HELP_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/in_product_help/live_caption_in_product_help_factory.h"
#include "chrome/browser/feature_engagement/tracker_factory.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/in_product_help/live_caption_in_product_help.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
// static
LiveCaptionInProductHelp* LiveCaptionInProductHelpFactory::GetForProfile(
Profile* profile) {
return static_cast<LiveCaptionInProductHelp*>(
GetInstance()->GetServiceForBrowserContext(profile, true));
}
// static
LiveCaptionInProductHelpFactory*
LiveCaptionInProductHelpFactory::GetInstance() {
static base::NoDestructor<LiveCaptionInProductHelpFactory> factory;
return factory.get();
}
LiveCaptionInProductHelpFactory::LiveCaptionInProductHelpFactory()
: BrowserContextKeyedServiceFactory(
"LiveCaptionInProductHelp",
BrowserContextDependencyManager::GetInstance()) {
DependsOn(feature_engagement::TrackerFactory::GetInstance());
}
LiveCaptionInProductHelpFactory::~LiveCaptionInProductHelpFactory() = default;
content::BrowserContext*
LiveCaptionInProductHelpFactory::GetBrowserContextToUse(
content::BrowserContext* context) const {
return chrome::GetBrowserContextRedirectedInIncognito(context);
}
KeyedService* LiveCaptionInProductHelpFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
return new LiveCaptionInProductHelp(Profile::FromBrowserContext(context));
}
// 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_IN_PRODUCT_HELP_LIVE_CAPTION_IN_PRODUCT_HELP_FACTORY_H_
#define CHROME_BROWSER_UI_IN_PRODUCT_HELP_LIVE_CAPTION_IN_PRODUCT_HELP_FACTORY_H_
#include "base/no_destructor.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
class LiveCaptionInProductHelp;
class Profile;
class LiveCaptionInProductHelpFactory
: public BrowserContextKeyedServiceFactory {
public:
static LiveCaptionInProductHelp* GetForProfile(Profile* profile);
static LiveCaptionInProductHelpFactory* GetInstance();
private:
friend base::NoDestructor<LiveCaptionInProductHelpFactory>;
LiveCaptionInProductHelpFactory();
~LiveCaptionInProductHelpFactory() override;
// BrowserContextKeyedServiceFactory overrides:
content::BrowserContext* GetBrowserContextToUse(
content::BrowserContext* context) const override;
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* profile) const override;
};
#endif // CHROME_BROWSER_UI_IN_PRODUCT_HELP_LIVE_CAPTION_IN_PRODUCT_HELP_FACTORY_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/in_product_help/live_caption_in_product_help.h"
#include "base/bind.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/feature_engagement/tracker_factory.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "chrome/test/base/testing_profile.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/feature_engagement/public/tracker.h"
#include "components/feature_engagement/test/mock_tracker.h"
#include "media/base/media_switches.h"
using ::testing::_;
using ::testing::Return;
using MockTracker = ::testing::NiceMock<feature_engagement::test::MockTracker>;
class LiveCaptionInProductHelpTest : public BrowserWithTestWindowTest {
protected:
void SetUp() override {
BrowserWithTestWindowTest::SetUp();
scoped_feature_list_.InitWithFeatures(
{media::kLiveCaption, feature_engagement::kIPHLiveCaptionFeature}, {});
}
TestingProfile::TestingFactories GetTestingFactories() override {
return {{feature_engagement::TrackerFactory::GetInstance(),
base::BindRepeating(CreateTracker)}};
}
MockTracker* GetMockTracker() {
return static_cast<MockTracker*>(
feature_engagement::TrackerFactory::GetForBrowserContext(profile()));
}
private:
static std::unique_ptr<KeyedService> CreateTracker(
content::BrowserContext* context) {
return std::make_unique<MockTracker>();
}
base::test::ScopedFeatureList scoped_feature_list_;
};
TEST_F(LiveCaptionInProductHelpTest, TriggersAndDismissesIPH) {
LiveCaptionInProductHelp live_caption_iph(profile());
auto* mock_tracker = GetMockTracker();
EXPECT_CALL(*mock_tracker, ShouldTriggerHelpUI(_))
.Times(1)
.WillOnce(Return(true));
EXPECT_CALL(*mock_tracker, Dismissed(_)).Times(1);
BrowserList::SetLastActive(browser());
live_caption_iph.OnMediaButtonEnabled();
live_caption_iph.HelpDismissed();
}
......@@ -3443,9 +3443,6 @@ void BrowserView::ShowInProductHelpPromo(InProductHelpFeature iph_feature) {
if (toolbar_ && toolbar_->media_button())
toolbar_->media_button()->ShowPromo();
break;
case InProductHelpFeature::kLiveCaption:
live_caption_promo_controller_.ShowPromo();
break;
}
}
......
......@@ -36,7 +36,6 @@
#include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
#include "chrome/browser/ui/views/frame/top_controls_slide_controller.h"
#include "chrome/browser/ui/views/frame/web_contents_close_handler.h"
#include "chrome/browser/ui/views/in_product_help/live_caption_promo_controller.h"
#include "chrome/browser/ui/views/in_product_help/reopen_tab_promo_controller.h"
#include "chrome/browser/ui/views/intent_picker_bubble_view.h"
#include "chrome/browser/ui/views/load_complete_listener.h"
......@@ -922,8 +921,6 @@ class BrowserView : public BrowserWindow,
ReopenTabPromoController reopen_tab_promo_controller_{this};
LiveCaptionPromoController live_caption_promo_controller_{this};
ScopedObserver<banners::AppBannerManager, banners::AppBannerManager::Observer>
app_banner_manager_observer_{this};
......
......@@ -4,6 +4,7 @@
#include "chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.h"
#include "base/feature_list.h"
#include "build/build_config.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/themes/theme_properties.h"
......@@ -12,11 +13,12 @@
#include "chrome/browser/ui/global_media_controls/media_toolbar_button_controller.h"
#include "chrome/browser/ui/in_product_help/global_media_controls_in_product_help.h"
#include "chrome/browser/ui/in_product_help/global_media_controls_in_product_help_factory.h"
#include "chrome/browser/ui/in_product_help/live_caption_in_product_help.h"
#include "chrome/browser/ui/in_product_help/live_caption_in_product_help_factory.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/global_media_controls/media_dialog_view.h"
#include "chrome/browser/ui/views/in_product_help/feature_promo_controller_views.h"
#include "chrome/browser/ui/views/in_product_help/global_media_controls_promo_controller.h"
#include "chrome/grit/generated_resources.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/vector_icons/vector_icons.h"
#include "media/base/media_switches.h"
#include "ui/base/l10n/l10n_util.h"
......@@ -39,13 +41,6 @@ MediaToolbarButtonView::MediaToolbarButtonView(const Browser* browser)
if (global_media_controls_in_product_help)
AddObserver(global_media_controls_in_product_help);
if (base::FeatureList::IsEnabled(media::kLiveCaption)) {
LiveCaptionInProductHelp* live_caption_in_product_help =
LiveCaptionInProductHelpFactory::GetForProfile(browser_->profile());
if (live_caption_in_product_help)
AddObserver(live_caption_in_product_help);
}
button_controller()->set_notify_action(
views::ButtonController::NotifyAction::kOnPress);
EnableCanvasFlippingForRTLUI(false);
......@@ -84,9 +79,12 @@ void MediaToolbarButtonView::ButtonPressed(views::Button* sender,
} else {
MediaDialogView::ShowDialog(this, service_);
// Inform observers. Since the promo controller cares about the dialog
// showing, we need to ensure that it's created.
// Ensure we have IPH related objects before calling into them.
EnsurePromoController();
feature_promo_controller_->CloseBubble(
feature_engagement::kIPHLiveCaptionFeature);
for (auto& observer : observers_)
observer.OnMediaDialogOpened();
}
......@@ -104,8 +102,7 @@ void MediaToolbarButtonView::Hide() {
SetVisible(false);
PreferredSizeChanged();
// Inform observers. Since the promo controller cares about hiding, we need to
// ensure that it's created.
// Ensure we have IPH related objects before calling into them.
EnsurePromoController();
for (auto& observer : observers_)
observer.OnMediaButtonHidden();
......@@ -114,6 +111,14 @@ void MediaToolbarButtonView::Hide() {
void MediaToolbarButtonView::Enable() {
SetEnabled(true);
// Ensure we have IPH related objects before calling into them.
EnsurePromoController();
if (base::FeatureList::IsEnabled(media::kLiveCaption)) {
feature_promo_controller_->MaybeShowPromo(
feature_engagement::kIPHLiveCaptionFeature);
}
for (auto& observer : observers_)
observer.OnMediaButtonEnabled();
}
......@@ -121,9 +126,12 @@ void MediaToolbarButtonView::Enable() {
void MediaToolbarButtonView::Disable() {
SetEnabled(false);
// Inform observers. Since the promo controller cares about disabling, we need
// to ensure that it's created.
// Ensure we have IPH related objects before calling into them.
EnsurePromoController();
feature_promo_controller_->CloseBubble(
feature_engagement::kIPHLiveCaptionFeature);
for (auto& observer : observers_)
observer.OnMediaButtonDisabled();
}
......@@ -154,10 +162,14 @@ void MediaToolbarButtonView::OnPromoEnded() {
}
void MediaToolbarButtonView::EnsurePromoController() {
if (promo_controller_)
return;
if (!promo_controller_) {
promo_controller_ = std::make_unique<GlobalMediaControlsPromoController>(
this, browser_->profile());
AddObserver(promo_controller_.get());
}
promo_controller_ = std::make_unique<GlobalMediaControlsPromoController>(
this, browser_->profile());
AddObserver(promo_controller_.get());
if (!feature_promo_controller_) {
feature_promo_controller_ = BrowserView::GetBrowserViewForBrowser(browser_)
->feature_promo_controller();
}
}
......@@ -10,6 +10,7 @@
#include "chrome/browser/ui/views/toolbar/toolbar_button.h"
class Browser;
class FeaturePromoControllerViews;
class GlobalMediaControlsPromoController;
class MediaNotificationService;
class MediaToolbarButtonController;
......@@ -67,6 +68,9 @@ class MediaToolbarButtonView : public ToolbarButton,
// Shows the in-product help bubble.
std::unique_ptr<GlobalMediaControlsPromoController> promo_controller_;
// The window's IPH promo controller.
FeaturePromoControllerViews* feature_promo_controller_ = nullptr;
// True if the in-product help bubble is currently showing.
bool is_promo_showing_ = false;
......
......@@ -31,10 +31,13 @@ class FeaturePromoController {
// longer showing.
virtual bool BubbleIsShowing(const base::Feature& iph_feature) const = 0;
// Close the bubble for |iph_feature| and end the promo. If no promo
// is showing for |iph_feature|, or the promo has continued past the
// bubble, calling this is an error.
virtual void CloseBubble(const base::Feature& iph_feature) = 0;
// If a bubble is showing for |iph_feature| close it and end the
// promo. Does nothing otherwise. Returns true if a bubble was closed
// and false otherwise.
//
// Calling this has no effect if |CloseBubbleAndContinuePromo()| was
// called for |iph_feature|.
virtual bool CloseBubble(const base::Feature& iph_feature) = 0;
class PromoHandle;
......
......@@ -94,11 +94,12 @@ bool FeaturePromoControllerViews::BubbleIsShowing(
return promo_bubble_ && current_iph_feature_ == &iph_feature;
}
void FeaturePromoControllerViews::CloseBubble(
bool FeaturePromoControllerViews::CloseBubble(
const base::Feature& iph_feature) {
DCHECK_EQ(&iph_feature, current_iph_feature_);
DCHECK(promo_bubble_);
if (!BubbleIsShowing(iph_feature))
return false;
promo_bubble_->GetWidget()->Close();
return true;
}
void FeaturePromoControllerViews::UpdateBubbleForAnchorBoundsChange() {
......
......@@ -49,7 +49,7 @@ class FeaturePromoControllerViews : public FeaturePromoController,
// FeaturePromoController:
bool MaybeShowPromo(const base::Feature& iph_feature) override;
bool BubbleIsShowing(const base::Feature& iph_feature) const override;
void CloseBubble(const base::Feature& iph_feature) override;
bool CloseBubble(const base::Feature& iph_feature) override;
PromoHandle CloseBubbleAndContinuePromo(
const base::Feature& iph_feature) override;
......
......@@ -35,6 +35,8 @@ using ::testing::Return;
namespace {
base::Feature kTestIPHFeature{"TestIPHFeature",
base::FEATURE_ENABLED_BY_DEFAULT};
base::Feature kSecondIPHFeature{"SecondIPHFeature",
base::FEATURE_ENABLED_BY_DEFAULT};
} // namespace
class FeaturePromoControllerViewsTest : public TestWithBrowserView {
......@@ -145,7 +147,7 @@ TEST_F(FeaturePromoControllerViewsTest, PromoEndsWhenRequested) {
views::test::WidgetClosingObserver widget_observer(bubble->GetWidget());
EXPECT_CALL(*mock_tracker_, Dismissed(Ref(kTestIPHFeature))).Times(1);
controller_->CloseBubble(kTestIPHFeature);
EXPECT_TRUE(controller_->CloseBubble(kTestIPHFeature));
EXPECT_FALSE(controller_->BubbleIsShowing(kTestIPHFeature));
EXPECT_FALSE(controller_->promo_bubble_for_testing());
......@@ -153,6 +155,24 @@ TEST_F(FeaturePromoControllerViewsTest, PromoEndsWhenRequested) {
widget_observer.Wait();
}
TEST_F(FeaturePromoControllerViewsTest,
CloseBubbleDoesNothingIfPromoNotShowing) {
EXPECT_FALSE(controller_->CloseBubble(kTestIPHFeature));
}
TEST_F(FeaturePromoControllerViewsTest,
CloseBubbleDoesNothingIfDifferentPromoShowing) {
EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature)))
.Times(1)
.WillOnce(Return(true));
ASSERT_TRUE(controller_->MaybeShowPromoWithParams(kTestIPHFeature,
DefaultBubbleParams()));
EXPECT_FALSE(controller_->CloseBubble(kSecondIPHFeature));
EXPECT_TRUE(controller_->BubbleIsShowing(kTestIPHFeature));
EXPECT_TRUE(controller_->promo_bubble_for_testing());
}
TEST_F(FeaturePromoControllerViewsTest, PromoEndsOnBubbleClosure) {
EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature)))
.Times(1)
......
......@@ -7,8 +7,10 @@
#include "base/no_destructor.h"
#include "base/optional.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.h"
#include "chrome/browser/ui/views/in_product_help/feature_promo_bubble_params.h"
#include "chrome/browser/ui/views/tabs/tab_strip.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "chrome/grit/generated_resources.h"
#include "components/feature_engagement/public/feature_constants.h"
......@@ -23,6 +25,11 @@ views::View* GetTabGroupsAnchorView(BrowserView* browser_view) {
kPreferredAnchorTab);
}
// kIPHLiveCaptionFeature:
views::View* GetMediaButton(BrowserView* browser_view) {
return browser_view->toolbar()->media_button();
}
} // namespace
FeaturePromoRegistry::FeaturePromoRegistry() {
......@@ -86,6 +93,17 @@ void FeaturePromoRegistry::RegisterKnownFeatures() {
RegisterFeature(feature_engagement::kIPHDesktopTabGroupsNewGroupFeature,
params, base::BindRepeating(GetTabGroupsAnchorView));
}
{
// kIPHLiveCaptionFeature:
FeaturePromoBubbleParams params;
params.body_string_specifier = IDS_LIVE_CAPTION_PROMO;
params.screenreader_string_specifier = IDS_LIVE_CAPTION_PROMO_SCREENREADER;
params.arrow = views::BubbleBorder::Arrow::TOP_RIGHT;
RegisterFeature(feature_engagement::kIPHLiveCaptionFeature, params,
base::BindRepeating(GetMediaButton));
}
}
FeaturePromoRegistry::FeaturePromoData::FeaturePromoData() = default;
......
// 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/in_product_help/live_caption_promo_controller.h"
#include "chrome/browser/ui/in_product_help/live_caption_in_product_help.h"
#include "chrome/browser/ui/in_product_help/live_caption_in_product_help_factory.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.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/toolbar/toolbar_view.h"
#include "chrome/grit/generated_resources.h"
LiveCaptionPromoController::LiveCaptionPromoController(
BrowserView* browser_view)
: browser_view_(browser_view) {}
LiveCaptionPromoController::~LiveCaptionPromoController() = default;
void LiveCaptionPromoController::ShowPromo() {
FeaturePromoBubbleParams bubble_params;
bubble_params.body_string_specifier = IDS_LIVE_CAPTION_PROMO;
bubble_params.screenreader_string_specifier =
IDS_LIVE_CAPTION_PROMO_SCREENREADER;
bubble_params.anchor_view = browser_view_->toolbar()->media_button();
bubble_params.arrow = views::BubbleBorder::Arrow::TOP_RIGHT;
promo_bubble_ = FeaturePromoBubbleView::Create(std::move(bubble_params));
promo_bubble_->set_close_on_deactivate(false);
widget_observer_.Add(promo_bubble_->GetWidget());
browser_view_->toolbar()->media_button()->AddObserver(this);
}
void LiveCaptionPromoController::PromoEnded() {
LiveCaptionInProductHelpFactory::GetForProfile(
browser_view_->browser()->profile())
->HelpDismissed();
}
void LiveCaptionPromoController::OnMediaDialogOpened() {
promo_bubble_->GetWidget()->CloseNow();
PromoEnded();
}
void LiveCaptionPromoController::OnMediaButtonDisabled() {
promo_bubble_->GetWidget()->CloseNow();
}
void LiveCaptionPromoController::OnWidgetDestroying(views::Widget* widget) {
DCHECK(promo_bubble_);
promo_bubble_ = nullptr;
browser_view_->toolbar()->media_button()->RemoveObserver(this);
widget_observer_.Remove(widget);
}
// 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_IN_PRODUCT_HELP_LIVE_CAPTION_PROMO_CONTROLLER_H_
#define CHROME_BROWSER_UI_VIEWS_IN_PRODUCT_HELP_LIVE_CAPTION_PROMO_CONTROLLER_H_
#include "base/scoped_observer.h"
#include "chrome/browser/ui/global_media_controls/media_toolbar_button_observer.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
class BrowserView;
class FeaturePromoBubbleView;
// Handles display of the live caption in-product help promo. Notifies the
// |LiveCaptionInProductHelp| service when the promo is finished.
class LiveCaptionPromoController : public MediaToolbarButtonObserver,
public views::WidgetObserver {
public:
explicit LiveCaptionPromoController(BrowserView* browser_view);
~LiveCaptionPromoController() override;
LiveCaptionPromoController(const LiveCaptionPromoController&) = delete;
LiveCaptionPromoController& operator=(const LiveCaptionPromoController&) =
delete;
// Shows the IPH promo. Should only be called once.
void ShowPromo();
private:
friend class LiveCaptionPromoControllerTest;
// MediaToolbarButtonObserver:
void OnMediaDialogOpened() override;
void OnMediaButtonShown() override {}
void OnMediaButtonHidden() override {}
void OnMediaButtonEnabled() override {}
void OnMediaButtonDisabled() override;
// views::WidgetObserver:
void OnWidgetDestroying(views::Widget* widget) override;
// Called when the promo flow ends.
void PromoEnded();
BrowserView* const browser_view_;
FeaturePromoBubbleView* promo_bubble_ = nullptr;
ScopedObserver<views::Widget, views::WidgetObserver> widget_observer_{this};
};
#endif // CHROME_BROWSER_UI_VIEWS_IN_PRODUCT_HELP_LIVE_CAPTION_PROMO_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 "base/test/scoped_feature_list.h"
#include "chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.h"
#include "chrome/browser/ui/views/in_product_help/feature_promo_bubble_view.h"
#include "chrome/browser/ui/views/in_product_help/live_caption_promo_controller.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "content/public/test/browser_test.h"
#include "media/base/media_switches.h"
#include "ui/events/base_event_utils.h"
class LiveCaptionPromoControllerTest : public InProcessBrowserTest {
public:
LiveCaptionPromoControllerTest() = default;
~LiveCaptionPromoControllerTest() override = default;
LiveCaptionPromoControllerTest(const LiveCaptionPromoControllerTest&) =
delete;
LiveCaptionPromoControllerTest& operator=(
const LiveCaptionPromoControllerTest&) = delete;
// InProcessBrowserTest:
void SetUp() override {
scoped_feature_list_.InitWithFeatures(
{media::kGlobalMediaControls,
feature_engagement::kIPHLiveCaptionFeature},
{});
InProcessBrowserTest::SetUp();
}
bool PromoBubbleVisible() {
FeaturePromoBubbleView* bubble = GetPromoController()->promo_bubble_;
return bubble && bubble->GetVisible();
}
void ShowPromo() { GetPromoController()->ShowPromo(); }
void DisableMediaButton() { GetPromoController()->OnMediaButtonDisabled(); }
void OpenMediaDialog() { GetPromoController()->OnMediaDialogOpened(); }
private:
LiveCaptionPromoController* GetPromoController() {
if (!controller_) {
controller_ = std::make_unique<LiveCaptionPromoController>(
BrowserView::GetBrowserViewForBrowser(browser()));
}
return controller_.get();
}
base::test::ScopedFeatureList scoped_feature_list_;
std::unique_ptr<LiveCaptionPromoController> controller_;
};
IN_PROC_BROWSER_TEST_F(LiveCaptionPromoControllerTest, ShowPromo) {
EXPECT_FALSE(PromoBubbleVisible());
ShowPromo();
EXPECT_TRUE(PromoBubbleVisible());
}
IN_PROC_BROWSER_TEST_F(LiveCaptionPromoControllerTest, OpenMediaDialog) {
EXPECT_FALSE(PromoBubbleVisible());
ShowPromo();
EXPECT_TRUE(PromoBubbleVisible());
// Promo disappears when media dialog opens.
OpenMediaDialog();
EXPECT_FALSE(PromoBubbleVisible());
}
IN_PROC_BROWSER_TEST_F(LiveCaptionPromoControllerTest, DisableMediaButton) {
EXPECT_FALSE(PromoBubbleVisible());
ShowPromo();
EXPECT_TRUE(PromoBubbleVisible());
// Promo disappears when media button is disabled.
DisableMediaButton();
EXPECT_FALSE(PromoBubbleVisible());
}
......@@ -18,7 +18,7 @@ class MockFeaturePromoController : public FeaturePromoController {
// FeaturePromoController:
MOCK_METHOD(bool, MaybeShowPromo, (const base::Feature&), (override));
MOCK_METHOD(bool, BubbleIsShowing, (const base::Feature&), (const, override));
MOCK_METHOD(void, CloseBubble, (const base::Feature&), (override));
MOCK_METHOD(bool, CloseBubble, (const base::Feature&), (override));
MOCK_METHOD(PromoHandle,
CloseBubbleAndContinuePromo,
(const base::Feature&),
......
......@@ -2133,7 +2133,6 @@ if (!is_android) {
"../browser/ui/views/importer/import_lock_dialog_view_browsertest.cc",
"../browser/ui/views/in_product_help/feature_promo_dialog_browsertest.cc",
"../browser/ui/views/in_product_help/global_media_controls_promo_controller_dialog_browsertest.cc",
"../browser/ui/views/in_product_help/live_caption_promo_controller_browsertest.cc",
"../browser/ui/views/in_product_help/reopen_tab_promo_controller_dialog_browsertest.cc",
"../browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc",
"../browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc",
......@@ -4397,7 +4396,6 @@ test("unit_tests") {
"../browser/ui/hid/hid_chooser_controller_unittest.cc",
"../browser/ui/in_product_help/active_tab_tracker_unittest.cc",
"../browser/ui/in_product_help/global_media_controls_in_product_help_unittest.cc",
"../browser/ui/in_product_help/live_caption_in_product_help_unittest.cc",
"../browser/ui/in_product_help/reopen_tab_in_product_help_trigger_unittest.cc",
"../browser/ui/in_product_help/reopen_tab_in_product_help_unittest.cc",
"../browser/ui/manifest_web_app_browser_controller_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