blob: 136c6a542f826e4da2afcdf3e88ca4b9796eae37 [file] [log] [blame]
// 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/user_education/feature_promo_controller_views.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/feature_list.h"
#include "base/test/bind.h"
#include "base/test/mock_callback.h"
#include "base/test/task_environment.h"
#include "chrome/browser/feature_engagement/tracker_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/user_education/feature_promo_bubble_params.h"
#include "chrome/browser/ui/user_education/feature_promo_snooze_service.h"
#include "chrome/browser/ui/views/chrome_view_class_properties.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/toolbar/browser_app_menu_button.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "chrome/browser/ui/views/user_education/feature_promo_bubble_owner_impl.h"
#include "chrome/browser/ui/views/user_education/feature_promo_bubble_view.h"
#include "chrome/browser/ui/views/user_education/feature_promo_registry.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/testing_profile.h"
#include "components/feature_engagement/test/mock_tracker.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/view_class_properties.h"
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::NiceMock;
using ::testing::Ref;
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 {
public:
void SetUp() override {
TestWithBrowserView::SetUp();
controller_ = browser_view()->feature_promo_controller();
FeaturePromoControllerViews::BlockActiveWindowCheckForTesting();
mock_tracker_ =
static_cast<NiceMock<feature_engagement::test::MockTracker>*>(
feature_engagement::TrackerFactory::GetForBrowserContext(
profile()));
FeaturePromoRegistry::GetInstance()->ClearFeaturesForTesting();
}
void TearDown() override {
FeaturePromoRegistry::GetInstance()->ReinitializeForTesting();
TestWithBrowserView::TearDown();
}
TestingProfile::TestingFactories GetTestingFactories() override {
TestingProfile::TestingFactories factories =
TestWithBrowserView::GetTestingFactories();
factories.emplace_back(
feature_engagement::TrackerFactory::GetInstance(),
base::BindRepeating(FeaturePromoControllerViewsTest::MakeTestTracker));
return factories;
}
protected:
views::View* GetAnchorView() {
return browser_view()->toolbar()->app_menu_button();
}
FeaturePromoBubbleParams DefaultBubbleParams() {
FeaturePromoBubbleParams params;
params.body_string_specifier = IDS_REOPEN_TAB_PROMO;
params.arrow = FeaturePromoBubbleParams::Arrow::TOP_RIGHT;
return params;
}
FeaturePromoBubbleParams IPHSnoozeBubbleParams() {
FeaturePromoBubbleParams params = DefaultBubbleParams();
params.allow_snooze = true;
return params;
}
FeaturePromoControllerViews* controller_;
NiceMock<feature_engagement::test::MockTracker>* mock_tracker_;
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;
}
};
using BubbleCloseCallback = FeaturePromoControllerViews::BubbleCloseCallback;
TEST_F(FeaturePromoControllerViewsTest, GetForView) {
EXPECT_EQ(controller_,
FeaturePromoControllerViews::GetForView(GetAnchorView()));
// For a view not in the BrowserView's hierarchy, it should return null.
views::View orphan_view;
EXPECT_EQ(nullptr, FeaturePromoControllerViews::GetForView(&orphan_view));
}
TEST_F(FeaturePromoControllerViewsTest, AsksBackendToShowPromo) {
EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature)))
.Times(1)
.WillOnce(Return(false));
base::MockCallback<BubbleCloseCallback> close_callback;
EXPECT_CALL(close_callback, Run()).Times(0);
EXPECT_FALSE(controller_->MaybeShowPromoWithParams(
kTestIPHFeature, DefaultBubbleParams(), GetAnchorView(),
close_callback.Get()));
EXPECT_FALSE(controller_->BubbleIsShowing(kTestIPHFeature));
EXPECT_FALSE(
FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
}
TEST_F(FeaturePromoControllerViewsTest, ShowsBubble) {
EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature)))
.Times(1)
.WillOnce(Return(true));
EXPECT_TRUE(controller_->MaybeShowPromoWithParams(
kTestIPHFeature, DefaultBubbleParams(), GetAnchorView()));
EXPECT_TRUE(controller_->BubbleIsShowing(kTestIPHFeature));
EXPECT_TRUE(FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
}
TEST_F(FeaturePromoControllerViewsTest,
DismissNonCriticalBubbleInRegion_RegionDoesNotOverlap) {
EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature)))
.Times(1)
.WillOnce(Return(true));
EXPECT_TRUE(controller_->MaybeShowPromoWithParams(
kTestIPHFeature, DefaultBubbleParams(), GetAnchorView()));
const gfx::Rect bounds = FeaturePromoBubbleOwnerImpl::GetInstance()
->bubble_for_testing()
->GetWidget()
->GetWindowBoundsInScreen();
EXPECT_FALSE(bounds.IsEmpty());
gfx::Rect non_overlapping_region(bounds.right() + 1, bounds.bottom() + 1, 10,
10);
const bool result =
controller_->DismissNonCriticalBubbleInRegion(non_overlapping_region);
EXPECT_FALSE(result);
EXPECT_TRUE(controller_->BubbleIsShowing(kTestIPHFeature));
}
TEST_F(FeaturePromoControllerViewsTest,
DismissNonCriticalBubbleInRegion_RegionOverlaps) {
EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature)))
.Times(1)
.WillOnce(Return(true));
EXPECT_TRUE(controller_->MaybeShowPromoWithParams(
kTestIPHFeature, DefaultBubbleParams(), GetAnchorView()));
const gfx::Rect bounds = FeaturePromoBubbleOwnerImpl::GetInstance()
->bubble_for_testing()
->GetWidget()
->GetWindowBoundsInScreen();
EXPECT_FALSE(bounds.IsEmpty());
gfx::Rect overlapping_region(bounds.x() + 1, bounds.y() + 1, 10, 10);
const bool result =
controller_->DismissNonCriticalBubbleInRegion(overlapping_region);
EXPECT_TRUE(result);
EXPECT_FALSE(controller_->BubbleIsShowing(kTestIPHFeature));
}
TEST_F(FeaturePromoControllerViewsTest,
DismissNonCriticalBubbleInRegion_CriticalPromo) {
const auto token =
controller_->ShowCriticalPromo(DefaultBubbleParams(), GetAnchorView());
ASSERT_TRUE(token.has_value());
const gfx::Rect bounds = FeaturePromoBubbleOwnerImpl::GetInstance()
->bubble_for_testing()
->GetWidget()
->GetWindowBoundsInScreen();
EXPECT_FALSE(bounds.IsEmpty());
gfx::Rect overlapping_region(bounds.x() + 1, bounds.y() + 1, 10, 10);
const bool result =
controller_->DismissNonCriticalBubbleInRegion(overlapping_region);
EXPECT_FALSE(result);
EXPECT_TRUE(controller_->CriticalPromoIsShowing(token.value()));
}
TEST_F(FeaturePromoControllerViewsTest, SnoozeServiceBlocksPromo) {
EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature)))
.Times(0);
controller_->snooze_service_for_testing()->OnUserDismiss(kTestIPHFeature);
EXPECT_FALSE(controller_->MaybeShowPromoWithParams(
kTestIPHFeature, DefaultBubbleParams(), GetAnchorView()));
EXPECT_FALSE(controller_->BubbleIsShowing(kTestIPHFeature));
EXPECT_FALSE(
FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
controller_->snooze_service_for_testing()->Reset(kTestIPHFeature);
}
TEST_F(FeaturePromoControllerViewsTest, PromoEndsWhenRequested) {
EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature)))
.Times(1)
.WillOnce(Return(true));
EXPECT_CALL(*mock_tracker_, Dismissed(Ref(kTestIPHFeature))).Times(0);
base::MockCallback<BubbleCloseCallback> close_callback;
ASSERT_TRUE(controller_->MaybeShowPromoWithParams(
kTestIPHFeature, DefaultBubbleParams(), GetAnchorView(),
close_callback.Get()));
// Only valid before the widget is closed.
FeaturePromoBubbleView* const bubble =
FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing();
ASSERT_TRUE(bubble);
EXPECT_TRUE(controller_->BubbleIsShowing(kTestIPHFeature));
views::test::WidgetDestroyedWaiter widget_observer(bubble->GetWidget());
EXPECT_CALL(*mock_tracker_, Dismissed(Ref(kTestIPHFeature))).Times(1);
EXPECT_CALL(close_callback, Run()).Times(1);
EXPECT_TRUE(controller_->CloseBubble(kTestIPHFeature));
EXPECT_FALSE(controller_->BubbleIsShowing(kTestIPHFeature));
EXPECT_FALSE(
FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
// Ensure the widget does close.
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(), GetAnchorView()));
EXPECT_FALSE(controller_->CloseBubble(kSecondIPHFeature));
EXPECT_TRUE(controller_->BubbleIsShowing(kTestIPHFeature));
EXPECT_TRUE(FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
}
TEST_F(FeaturePromoControllerViewsTest, PromoEndsOnBubbleClosure) {
EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature)))
.Times(1)
.WillOnce(Return(true));
EXPECT_CALL(*mock_tracker_, Dismissed(Ref(kTestIPHFeature))).Times(0);
base::MockCallback<BubbleCloseCallback> close_callback;
ASSERT_TRUE(controller_->MaybeShowPromoWithParams(
kTestIPHFeature, DefaultBubbleParams(), GetAnchorView(),
close_callback.Get()));
// Only valid before the widget is closed.
FeaturePromoBubbleView* const bubble =
FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing();
ASSERT_TRUE(bubble);
EXPECT_TRUE(controller_->BubbleIsShowing(kTestIPHFeature));
views::test::WidgetDestroyedWaiter widget_observer(bubble->GetWidget());
EXPECT_CALL(*mock_tracker_, Dismissed(Ref(kTestIPHFeature))).Times(1);
EXPECT_CALL(close_callback, Run());
bubble->GetWidget()->Close();
widget_observer.Wait();
EXPECT_FALSE(controller_->BubbleIsShowing(kTestIPHFeature));
EXPECT_FALSE(
FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
}
TEST_F(FeaturePromoControllerViewsTest, ContinuedPromoDefersBackendDismissed) {
EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature)))
.Times(1)
.WillOnce(Return(true));
EXPECT_CALL(*mock_tracker_, Dismissed(Ref(kTestIPHFeature))).Times(0);
base::MockCallback<BubbleCloseCallback> close_callback;
ASSERT_TRUE(controller_->MaybeShowPromoWithParams(
kTestIPHFeature, DefaultBubbleParams(), GetAnchorView(),
close_callback.Get()));
// Only valid before the widget is closed.
FeaturePromoBubbleView* const bubble =
FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing();
ASSERT_TRUE(bubble);
EXPECT_TRUE(controller_->BubbleIsShowing(kTestIPHFeature));
views::test::WidgetDestroyedWaiter widget_observer(bubble->GetWidget());
// First check that CloseBubbleAndContinuePromo() actually closes the
// bubble, but doesn't yet tell the backend the promo finished.
EXPECT_CALL(close_callback, Run()).Times(1);
absl::optional<FeaturePromoController::PromoHandle> promo_handle =
controller_->CloseBubbleAndContinuePromo(kTestIPHFeature);
EXPECT_FALSE(controller_->BubbleIsShowing(kTestIPHFeature));
EXPECT_FALSE(
FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
// Ensure the widget does close.
widget_observer.Wait();
// Check handle destruction causes the backend to be notified.
EXPECT_CALL(*mock_tracker_, Dismissed(Ref(kTestIPHFeature))).Times(1);
promo_handle.reset();
}
TEST_F(FeaturePromoControllerViewsTest,
PropertySetOnAnchorViewWhileBubbleOpen) {
EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature)))
.Times(1)
.WillOnce(Return(true));
EXPECT_FALSE(GetAnchorView()->GetProperty(kHasInProductHelpPromoKey));
ASSERT_TRUE(controller_->MaybeShowPromoWithParams(
kTestIPHFeature, DefaultBubbleParams(), GetAnchorView()));
EXPECT_TRUE(GetAnchorView()->GetProperty(kHasInProductHelpPromoKey));
controller_->CloseBubble(kTestIPHFeature);
EXPECT_FALSE(GetAnchorView()->GetProperty(kHasInProductHelpPromoKey));
}
TEST_F(FeaturePromoControllerViewsTest, GetsParamsFromRegistry) {
FeaturePromoBubbleParams params = DefaultBubbleParams();
FeaturePromoRegistry::GetInstance()->RegisterFeature(
kTestIPHFeature, DefaultBubbleParams(),
base::BindRepeating([](BrowserView* browser_view) {
return static_cast<views::View*>(
browser_view->toolbar()->app_menu_button());
}));
EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature)))
.Times(1)
.WillOnce(Return(true));
ASSERT_TRUE(controller_->MaybeShowPromo(kTestIPHFeature));
EXPECT_EQ(browser_view()->toolbar()->app_menu_button(),
FeaturePromoBubbleOwnerImpl::GetInstance()
->bubble_for_testing()
->GetAnchorView());
}
TEST_F(FeaturePromoControllerViewsTest, TestCanBlockPromos) {
EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature)))
.Times(0);
controller_->BlockPromosForTesting();
EXPECT_FALSE(controller_->MaybeShowPromoWithParams(
kTestIPHFeature, DefaultBubbleParams(), GetAnchorView()));
EXPECT_FALSE(controller_->BubbleIsShowing(kTestIPHFeature));
EXPECT_FALSE(
FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
}
TEST_F(FeaturePromoControllerViewsTest, TestCanStopCurrentPromo) {
EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature)))
.Times(1)
.WillOnce(Return(true));
EXPECT_TRUE(controller_->MaybeShowPromoWithParams(
kTestIPHFeature, DefaultBubbleParams(), GetAnchorView()));
controller_->BlockPromosForTesting();
EXPECT_FALSE(controller_->BubbleIsShowing(kTestIPHFeature));
EXPECT_FALSE(
FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
}
TEST_F(FeaturePromoControllerViewsTest, CriticalPromoBlocksNormalPromo) {
EXPECT_TRUE(
controller_->ShowCriticalPromo(DefaultBubbleParams(), GetAnchorView()));
EXPECT_TRUE(FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature)))
.Times(0);
EXPECT_FALSE(controller_->MaybeShowPromoWithParams(
kTestIPHFeature, DefaultBubbleParams(), GetAnchorView()));
EXPECT_FALSE(controller_->BubbleIsShowing(kTestIPHFeature));
EXPECT_TRUE(FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
}
TEST_F(FeaturePromoControllerViewsTest, CriticalPromoPreemptsNormalPromo) {
EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature)))
.Times(1)
.WillOnce(Return(true));
base::MockCallback<BubbleCloseCallback> close_callback;
EXPECT_TRUE(controller_->MaybeShowPromoWithParams(
kTestIPHFeature, DefaultBubbleParams(), GetAnchorView(),
close_callback.Get()));
EXPECT_TRUE(controller_->BubbleIsShowing(kTestIPHFeature));
EXPECT_TRUE(FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
EXPECT_CALL(*mock_tracker_, Dismissed(Ref(kTestIPHFeature))).Times(1);
EXPECT_CALL(close_callback, Run()).Times(1);
EXPECT_TRUE(
controller_->ShowCriticalPromo(DefaultBubbleParams(), GetAnchorView()));
EXPECT_FALSE(controller_->BubbleIsShowing(kTestIPHFeature));
EXPECT_TRUE(FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
}
TEST_F(FeaturePromoControllerViewsTest, FirstCriticalPromoHasPrecedence) {
EXPECT_TRUE(
controller_->ShowCriticalPromo(DefaultBubbleParams(), GetAnchorView()));
const auto* first_bubble =
FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing();
EXPECT_TRUE(first_bubble);
EXPECT_FALSE(
controller_->ShowCriticalPromo(DefaultBubbleParams(), GetAnchorView()));
EXPECT_EQ(FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing(),
first_bubble);
}
TEST_F(FeaturePromoControllerViewsTest, CloseBubbleForCriticalPromo) {
absl::optional<base::Token> maybe_id =
controller_->ShowCriticalPromo(DefaultBubbleParams(), GetAnchorView());
ASSERT_TRUE(maybe_id);
base::Token id = maybe_id.value();
EXPECT_TRUE(FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
controller_->CloseBubbleForCriticalPromo(id);
EXPECT_FALSE(
FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
}
TEST_F(FeaturePromoControllerViewsTest,
CloseBubbleForCriticalPromoDoesNothingAfterClose) {
absl::optional<base::Token> maybe_id =
controller_->ShowCriticalPromo(DefaultBubbleParams(), GetAnchorView());
ASSERT_TRUE(maybe_id);
base::Token id = maybe_id.value();
auto* bubble =
FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing();
ASSERT_TRUE(bubble);
bubble->GetWidget()->Close();
EXPECT_FALSE(
FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
EXPECT_TRUE(
controller_->ShowCriticalPromo(DefaultBubbleParams(), GetAnchorView()));
EXPECT_TRUE(FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
// Since |id| has expired, this should do nothing.
controller_->CloseBubbleForCriticalPromo(id);
EXPECT_TRUE(FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
}
TEST_F(FeaturePromoControllerViewsTest, ShowNewCriticalPromoAfterClose) {
absl::optional<base::Token> maybe_id =
controller_->ShowCriticalPromo(DefaultBubbleParams(), GetAnchorView());
ASSERT_TRUE(maybe_id);
base::Token id = maybe_id.value();
EXPECT_TRUE(FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
controller_->CloseBubbleForCriticalPromo(id);
EXPECT_FALSE(
FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
EXPECT_TRUE(
controller_->ShowCriticalPromo(DefaultBubbleParams(), GetAnchorView()));
EXPECT_TRUE(FeaturePromoBubbleOwnerImpl::GetInstance()->bubble_for_testing());
}
TEST_F(FeaturePromoControllerViewsTest, FailsIfBubbleIsShowing) {
FeaturePromoBubbleView::CreateParams bubble_params;
bubble_params.anchor_view = GetAnchorView();
bubble_params.body_text = IDS_REOPEN_TAB_PROMO;
EXPECT_TRUE(FeaturePromoBubbleOwnerImpl::GetInstance()->ShowBubble(
std::move(bubble_params), base::DoNothing()));
EXPECT_CALL(*mock_tracker_, ShouldTriggerHelpUI(Ref(kTestIPHFeature)))
.Times(0);
EXPECT_CALL(*mock_tracker_, Dismissed(Ref(kTestIPHFeature))).Times(0);
EXPECT_FALSE(controller_->MaybeShowPromoWithParams(
kTestIPHFeature, DefaultBubbleParams(), GetAnchorView()));
}
// Test that IPH defaults are respected in the Snooze case.
TEST_F(FeaturePromoControllerViewsTest, IPHSnoozeUniqueTimeout) {
FeaturePromoBubbleView::CreateParams bubble_params =
controller_->GetBaseCreateParams(IPHSnoozeBubbleParams(),
GetAnchorView());
EXPECT_EQ(FeaturePromoSnoozeService::kTimeoutNoInteraction,
bubble_params.timeout_no_interaction);
EXPECT_EQ(FeaturePromoSnoozeService::kTimeoutAfterInteraction,
bubble_params.timeout_after_interaction);
}