Skip to content

Commit

Permalink
Add ScalableIphDelegate
Browse files Browse the repository at this point in the history
- ScalableIphDelegate is a class to handle IPH UIs and actions.

Bug: b:284053005
Test: browser_tests --gtest_filter=*ScalableIphBrowserTest*
Change-Id: I0784bd9b5257adf010160c053752650e44d5477c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4575995
Reviewed-by: Xiyuan Xia <xiyuan@chromium.org>
Commit-Queue: Yuki Awano <yawano@google.com>
Reviewed-by: Tao Wu <wutao@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1153595}
  • Loading branch information
Yuki Awano authored and Chromium LUCI CQ committed Jun 6, 2023
1 parent 909adcb commit b21f2b4
Show file tree
Hide file tree
Showing 17 changed files with 536 additions and 20 deletions.
36 changes: 36 additions & 0 deletions chrome/browser/ash/scalable_iph/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,33 @@ source_set("scalable_iph_factory") {
]

deps = [
":scalable_iph_delegate_impl",
"//base",
"//chrome/browser",
"//chrome/browser/profiles:profile",
"//chromeos/ash/components/scalable_iph",
"//chromeos/ash/components/scalable_iph:scalable_iph_delegate",
"//components/feature_engagement/public",
"//components/keyed_service/content",
"//components/keyed_service/core",
"//content/public/browser",
]
}

source_set("scalable_iph_delegate_impl") {
sources = [
"scalable_iph_delegate_impl.cc",
"scalable_iph_delegate_impl.h",
]

deps = [
"//chrome/browser/profiles:profile",
"//chromeos/ash/components/scalable_iph:iph_session",
"//chromeos/ash/components/scalable_iph:scalable_iph_delegate",
"//components/keyed_service/core",
]
}

source_set("browser_test_base") {
testonly = true

Expand All @@ -32,12 +49,15 @@ source_set("browser_test_base") {
]

deps = [
":mock_scalable_iph_delegate",
":scalable_iph_factory",
"//base",
"//chrome/browser",
"//chrome/browser/profiles:profile",
"//chrome/browser/ui",
"//chrome/test:test_support_ui",
"//chromeos/ash/components/scalable_iph",
"//chromeos/ash/components/scalable_iph:scalable_iph_delegate",
"//components/feature_engagement/public",
"//components/feature_engagement/test:test_support",
"//components/keyed_service/content",
Expand All @@ -46,3 +66,19 @@ source_set("browser_test_base") {
"//testing/gmock",
]
}

source_set("mock_scalable_iph_delegate") {
testonly = true

sources = [
"mock_scalable_iph_delegate.cc",
"mock_scalable_iph_delegate.h",
]

deps = [
"//chromeos/ash/components/scalable_iph:iph_session",
"//chromeos/ash/components/scalable_iph:scalable_iph_delegate",
"//components/keyed_service/core",
"//testing/gmock",
]
}
14 changes: 14 additions & 0 deletions chrome/browser/ash/scalable_iph/mock_scalable_iph_delegate.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/scalable_iph/mock_scalable_iph_delegate.h"

namespace ash {
namespace test {

MockScalableIphDelegate::MockScalableIphDelegate() = default;
MockScalableIphDelegate::~MockScalableIphDelegate() = default;

} // namespace test
} // namespace ash
39 changes: 39 additions & 0 deletions chrome/browser/ash/scalable_iph/mock_scalable_iph_delegate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_ASH_SCALABLE_IPH_MOCK_SCALABLE_IPH_DELEGATE_H_
#define CHROME_BROWSER_ASH_SCALABLE_IPH_MOCK_SCALABLE_IPH_DELEGATE_H_

#include <memory>

#include "chromeos/ash/components/scalable_iph/iph_session.h"
#include "chromeos/ash/components/scalable_iph/scalable_iph_delegate.h"
#include "components/keyed_service/core/keyed_service.h"
#include "testing/gmock/include/gmock/gmock.h"

namespace ash {
namespace test {

class MockScalableIphDelegate : public scalable_iph::ScalableIphDelegate {
public:
MockScalableIphDelegate();
~MockScalableIphDelegate() override;

MOCK_METHOD(void,
ShowBubble,
(const scalable_iph::ScalableIphDelegate::BubbleParams& params,
std::unique_ptr<scalable_iph::IphSession> iph_session),
(override));
MOCK_METHOD(
void,
ShowNotification,
(const scalable_iph::ScalableIphDelegate::NotificationParams& params,
std::unique_ptr<scalable_iph::IphSession> iph_session),
(override));
};

} // namespace test
} // namespace ash

#endif // CHROME_BROWSER_ASH_SCALABLE_IPH_MOCK_SCALABLE_IPH_DELEGATE_H_
47 changes: 42 additions & 5 deletions chrome/browser/ash/scalable_iph/scalable_iph_browser_test_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
#include <memory>

#include "base/functional/bind.h"
#include "chrome/browser/ash/scalable_iph/mock_scalable_iph_delegate.h"
#include "chrome/browser/ash/scalable_iph/scalable_iph_factory.h"
#include "chrome/browser/feature_engagement/tracker_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chromeos/ash/components/scalable_iph/scalable_iph.h"
#include "chromeos/ash/components/scalable_iph/scalable_iph_delegate.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/keyed_service/core/keyed_service.h"
#include "content/public/browser/browser_context.h"
Expand All @@ -36,8 +40,8 @@ void ScalableIphBrowserTestBase::SetUp() {
// before command lines are set, etc.
subscription_ =
BrowserContextDependencyManager::GetInstance()
->RegisterCreateServicesCallbackForTesting(
base::BindRepeating(&ScalableIphBrowserTestBase::CreateServices));
->RegisterCreateServicesCallbackForTesting(base::BindRepeating(
&ScalableIphBrowserTestBase::SetTestingFactories));

InProcessBrowserTest::SetUp();
}
Expand All @@ -60,24 +64,51 @@ void ScalableIphBrowserTestBase::SetUpOnMainThread() {

ON_CALL(*mock_tracker_, IsInitialized).WillByDefault(testing::Return(true));

CHECK(ScalableIphFactory::GetInstance()->has_delegate_factory_for_testing())
<< "This test uses MockScalableIphDelegate. A factory for testing must "
"be set.";
scalable_iph::ScalableIph* scalable_iph =
ScalableIphFactory::GetForProfile(browser()->profile());
CHECK(scalable_iph);

mock_delegate_ = static_cast<test::MockScalableIphDelegate*>(
scalable_iph->delegate_for_testing());
CHECK(mock_delegate_);

InProcessBrowserTest::SetUpOnMainThread();
}

void ScalableIphBrowserTestBase::TearDownOnMainThread() {
// We are going to release a reference to a MockTracker below. Verify the
// expectation in advance to have a predictable behavior.
// We are going to release references to mock objects below. Verify the
// expectations in advance to have a predictable behavior.
testing::Mock::VerifyAndClearExpectations(mock_tracker_);
mock_tracker_ = nullptr;
testing::Mock::VerifyAndClearExpectations(mock_delegate_);
mock_delegate_ = nullptr;

InProcessBrowserTest::TearDownOnMainThread();
}

// static
void ScalableIphBrowserTestBase::CreateServices(
void ScalableIphBrowserTestBase::SetTestingFactories(
content::BrowserContext* browser_context) {
feature_engagement::TrackerFactory::GetInstance()->SetTestingFactory(
browser_context,
base::BindRepeating(&ScalableIphBrowserTestBase::CreateMockTracker));

ScalableIphFactory* scalable_iph_factory = ScalableIphFactory::GetInstance();
CHECK(scalable_iph_factory);

// This method can be called more than once for a single browser context.
if (scalable_iph_factory->has_delegate_factory_for_testing()) {
return;
}

// This is NOT a testing factory of a keyed service factory .But the delegate
// factory is called from the factory of `ScalableIphFactory`. Set this at the
// same time.
scalable_iph_factory->SetDelegateFactoryForTesting(
base::BindRepeating(&ScalableIphBrowserTestBase::CreateMockDelegate));
}

// static
Expand All @@ -86,4 +117,10 @@ std::unique_ptr<KeyedService> ScalableIphBrowserTestBase::CreateMockTracker(
return std::make_unique<feature_engagement::test::MockTracker>();
}

// static
std::unique_ptr<scalable_iph::ScalableIphDelegate>
ScalableIphBrowserTestBase::CreateMockDelegate() {
return std::make_unique<test::MockScalableIphDelegate>();
}

} // namespace ash
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "base/callback_list.h"
#include "base/memory/raw_ptr.h"
#include "chrome/browser/ash/scalable_iph/mock_scalable_iph_delegate.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "components/feature_engagement/test/mock_tracker.h"
#include "components/keyed_service/core/keyed_service.h"
Expand All @@ -27,14 +28,18 @@ class ScalableIphBrowserTestBase : public InProcessBrowserTest {
feature_engagement::test::MockTracker* mock_tracker() {
return mock_tracker_;
}
test::MockScalableIphDelegate* mock_delegate() { return mock_delegate_; }

private:
static void CreateServices(content::BrowserContext* browser_context);
static void SetTestingFactories(content::BrowserContext* browser_context);
static std::unique_ptr<KeyedService> CreateMockTracker(
content::BrowserContext* browser_context);
static std::unique_ptr<scalable_iph::ScalableIphDelegate>
CreateMockDelegate();

base::CallbackListSubscription subscription_;
raw_ptr<feature_engagement::test::MockTracker> mock_tracker_;
raw_ptr<test::MockScalableIphDelegate> mock_delegate_;
};

} // namespace ash
Expand Down
36 changes: 35 additions & 1 deletion chrome/browser/ash/scalable_iph/scalable_iph_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/feature_list.h"
#include "chrome/browser/ash/scalable_iph/scalable_iph_browser_test_base.h"
#include "chrome/browser/ash/scalable_iph/scalable_iph_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chromeos/ash/components/scalable_iph/iph_session.h"
#include "chromeos/ash/components/scalable_iph/scalable_iph.h"
#include "chromeos/ash/components/scalable_iph/scalable_iph_delegate.h"
#include "components/feature_engagement/test/mock_tracker.h"
#include "content/public/test/browser_test.h"
#include "testing/gmock/include/gmock/gmock.h"
Expand All @@ -14,6 +17,10 @@ namespace {

using ScalableIphBrowserTest = ash::ScalableIphBrowserTestBase;

BASE_FEATURE(kScalableIphTest,
"ScalableIphTest",
base::FEATURE_DISABLED_BY_DEFAULT);

} // namespace

IN_PROC_BROWSER_TEST_F(ScalableIphBrowserTest, RecordEvent) {
Expand All @@ -24,5 +31,32 @@ IN_PROC_BROWSER_TEST_F(ScalableIphBrowserTest, RecordEvent) {
scalable_iph->RecordEvent(scalable_iph::ScalableIph::Event::kFiveMinTick);
}

IN_PROC_BROWSER_TEST_F(ScalableIphBrowserTest, InvokeIph) {
ON_CALL(*mock_tracker(), ShouldTriggerHelpUI)
.WillByDefault([](const base::Feature& feature) {
return &feature == &kScalableIphTest;
});

// Tracker::Dismissed must be called when an IPH gets dismissed.
EXPECT_CALL(*mock_tracker(), Dismissed(::testing::Ref(kScalableIphTest)));

scalable_iph::ScalableIphDelegate::BubbleParams expected_params;
EXPECT_CALL(*mock_delegate(),
ShowBubble(::testing::Eq(expected_params), ::testing::NotNull()))
.WillOnce(
[](const scalable_iph::ScalableIphDelegate::BubbleParams& params,
std::unique_ptr<scalable_iph::IphSession> session) {
// Simulate that an IPH gets dismissed.
session.reset();
});

scalable_iph::ScalableIph* scalable_iph =
ash::ScalableIphFactory::GetForProfile(browser()->profile());
std::vector<const base::Feature*> features = {&kScalableIphTest};
scalable_iph->OverrideFeatureListForTesting(features);

scalable_iph->RecordEvent(scalable_iph::ScalableIph::Event::kFiveMinTick);
}

// TODO(b/284053005): Add a test case for available profiles.
// TODO(b/284053005): Add a test case for invalid event name.
// TODO(b/284053005): Add a test case for checking trigger condition.
34 changes: 34 additions & 0 deletions chrome/browser/ash/scalable_iph/scalable_iph_delegate_impl.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/scalable_iph/scalable_iph_delegate_impl.h"

#include <memory>

#include "chrome/browser/profiles/profile.h"
#include "chromeos/ash/components/scalable_iph/iph_session.h"
#include "chromeos/ash/components/scalable_iph/scalable_iph_delegate.h"

namespace ash {

ScalableIphDelegateImpl::ScalableIphDelegateImpl(Profile* profile)
: profile_(profile) {}

// Remember NOT to interact with `iph_session` from the destructor. See the
// comment of `ScalableIphDelegate::ShowBubble` for details.
ScalableIphDelegateImpl::~ScalableIphDelegateImpl() = default;

void ScalableIphDelegateImpl::ShowBubble(
const scalable_iph::ScalableIphDelegate::BubbleParams& params,
std::unique_ptr<scalable_iph::IphSession> iph_session) {
// TODO(b/284158855): Add implementation.
}

void ScalableIphDelegateImpl::ShowNotification(
const scalable_iph::ScalableIphDelegate::NotificationParams& params,
std::unique_ptr<scalable_iph::IphSession> iph_session) {
// TODO(b/284158831): Add implementation.
}

} // namespace ash
35 changes: 35 additions & 0 deletions chrome/browser/ash/scalable_iph/scalable_iph_delegate_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_ASH_SCALABLE_IPH_SCALABLE_IPH_DELEGATE_IMPL_H_
#define CHROME_BROWSER_ASH_SCALABLE_IPH_SCALABLE_IPH_DELEGATE_IMPL_H_

#include <memory>

#include "chrome/browser/profiles/profile.h"
#include "chromeos/ash/components/scalable_iph/iph_session.h"
#include "chromeos/ash/components/scalable_iph/scalable_iph_delegate.h"
#include "components/keyed_service/core/keyed_service.h"

namespace ash {

class ScalableIphDelegateImpl : public scalable_iph::ScalableIphDelegate {
public:
explicit ScalableIphDelegateImpl(Profile* profile);
~ScalableIphDelegateImpl() override;

// scalable_iph::ScalableIphDelegate:
void ShowBubble(
const BubbleParams& params,
std::unique_ptr<scalable_iph::IphSession> iph_session) override;
void ShowNotification(
const NotificationParams& params,
std::unique_ptr<scalable_iph::IphSession> iph_session) override;

private:
raw_ptr<Profile> profile_;
};
} // namespace ash

#endif // CHROME_BROWSER_ASH_SCALABLE_IPH_SCALABLE_IPH_DELEGATE_IMPL_H_

0 comments on commit b21f2b4

Please sign in to comment.