blob: 8a905cfd9733f61a949147fecf98d72597ac0669 [file] [log] [blame]
// 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 <optional>
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "base/time/time_override.h"
#include "chrome/browser/privacy_sandbox/tracking_protection_notice_factory.h"
#include "chrome/browser/privacy_sandbox/tracking_protection_onboarding_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tpcd/experiment/tpcd_experiment_features.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/hats/hats_service.h"
#include "chrome/browser/ui/hats/hats_service_factory.h"
#include "chrome/browser/ui/hats/mock_hats_service.h"
#include "chrome/browser/ui/hats/survey_config.h"
#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
#include "chrome/common/chrome_features.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chrome/test/user_education/interactive_feature_promo_test.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/common/features.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/privacy_sandbox/privacy_sandbox_features.h"
#include "components/privacy_sandbox/privacy_sandbox_prefs.h"
#include "components/privacy_sandbox/tracking_protection_onboarding.h"
#include "components/user_education/views/help_bubble_factory_views.h"
#include "components/user_education/views/help_bubble_view.h"
#include "components/version_info/channel.h"
#include "content/public/common/content_features.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "net/dns/mock_host_resolver.h"
#include "ui/views/interaction/interaction_test_util_views.h"
namespace privacy_sandbox {
namespace {
using ::testing::_;
using NoticeAction =
privacy_sandbox::TrackingProtectionOnboarding::NoticeAction;
using NoticeType = privacy_sandbox::TrackingProtectionOnboarding::NoticeType;
using SentimentSurveyGroup =
privacy_sandbox::TrackingProtectionOnboarding::SentimentSurveyGroup;
BrowserFeaturePromoController* GetFeaturePromoController(Browser* browser) {
auto* promo_controller = static_cast<BrowserFeaturePromoController*>(
browser->window()->GetFeaturePromoController());
return promo_controller;
}
enum class PromoButton { kDefault, kNonDefault };
void PressPromoButton(Browser* browser,
PromoButton button = PromoButton::kDefault) {
auto* const promo_controller = GetFeaturePromoController(browser);
auto* promo_bubble = promo_controller->promo_bubble_for_testing()
->AsA<user_education::HelpBubbleViews>()
->bubble_view();
switch (button) {
case PromoButton::kDefault:
views::test::InteractionTestUtilSimulatorViews::PressButton(
promo_bubble->GetDefaultButtonForTesting(),
ui::test::InteractionTestUtil::InputType::kMouse);
return;
case PromoButton::kNonDefault:
views::test::InteractionTestUtilSimulatorViews::PressButton(
promo_bubble->GetNonDefaultButtonForTesting(0),
ui::test::InteractionTestUtil::InputType::kMouse);
return;
}
}
base::test::FeatureRefAndParams ModeBFeatures() {
return {features::kCookieDeprecationFacilitatedTesting,
{{tpcd::experiment::kDisable3PCookiesName, "true"},
{features::kCookieDeprecationTestingDisableAdsAPIsName, "false"},
{tpcd::experiment::kForceEligibleForTestingName, "true"}}};
}
base::test::FeatureRefAndParams ModeBPrimeFeatures() {
return {features::kCookieDeprecationFacilitatedTesting,
{{tpcd::experiment::kDisable3PCookiesName, "true"},
{features::kCookieDeprecationTestingDisableAdsAPIsName, "true"},
{tpcd::experiment::kForceEligibleForTestingName, "true"}}};
}
base::test::FeatureRefAndParams ControlFeatures() {
return {features::kCookieDeprecationFacilitatedTesting,
{{tpcd::experiment::kDisable3PCookiesName, "false"},
{tpcd::experiment::kForceEligibleForTestingName, "true"}}};
}
base::test::FeatureRefAndParams ControlFeaturesWithSilentOnboarding() {
return {features::kCookieDeprecationFacilitatedTesting,
{
{tpcd::experiment::kDisable3PCookiesName, "false"},
{tpcd::experiment::kForceEligibleForTestingName, "true"},
{tpcd::experiment::kEnableSilentOnboardingName, "true"},
}};
}
std::vector<base::test::FeatureRefAndParams> HatsImmediateControlFeatures() {
return {
ControlFeatures(),
{features::kTrackingProtectionSentimentSurvey,
{{"tracking-protection-immediate-over-delayed-probability", "1"},
{"tracking-protection-control-immediate-probability", "1.0"},
{"tracking-protection-control-immediate-trigger-id", "trigger-1"}}}};
}
std::vector<base::test::FeatureRefAndParams>
HatsImmediateControlFeaturesWithSilentOnboarding() {
return {
ControlFeaturesWithSilentOnboarding(),
{features::kTrackingProtectionSentimentSurvey,
{{"tracking-protection-immediate-over-delayed-probability", "1"},
{"tracking-protection-control-immediate-probability", "1.0"},
{"tracking-protection-control-immediate-trigger-id", "trigger-1"}}}};
}
std::vector<base::test::FeatureRefAndParams> HatsDelayedControlFeatures() {
return {ControlFeatures(),
{features::kTrackingProtectionSentimentSurvey,
{{"tracking-protection-immediate-over-delayed-probability", "0"},
{"tracking-protection-control-delayed-probability", "1.0"},
{"tracking-protection-control-delayed-trigger-id", "trigger-1"}}}};
}
std::vector<base::test::FeatureRefAndParams> HatsImmediateModeBFeatures() {
return {
ModeBFeatures(),
{features::kTrackingProtectionSentimentSurvey,
{{"tracking-protection-immediate-over-delayed-probability", "1"},
{"tracking-protection-treatment-immediate-probability", "1.0"},
{"tracking-protection-treatment-immediate-trigger-id", "trigger-1"}}}};
}
std::vector<base::test::FeatureRefAndParams> HatsDelayedModeBFeatures() {
return {
ModeBFeatures(),
{features::kTrackingProtectionSentimentSurvey,
{{"tracking-protection-immediate-over-delayed-probability", "0"},
{"tracking-protection-treatment-delayed-probability", "1.0"},
{"tracking-protection-treatment-delayed-trigger-id", "trigger-1"}}}};
}
std::vector<base::test::FeatureRefAndParams> HatsImmediateModeBPrimeFeatures() {
return {
ModeBPrimeFeatures(),
{features::kTrackingProtectionSentimentSurvey,
{{"tracking-protection-immediate-over-delayed-probability", "1"},
{"tracking-protection-treatment-immediate-probability", "1.0"},
{"tracking-protection-treatment-immediate-trigger-id", "trigger-1"}}}};
}
std::vector<base::test::FeatureRefAndParams> HatsDelayedModeBPrimeFeatures() {
return {
ModeBPrimeFeatures(),
{features::kTrackingProtectionSentimentSurvey,
{{"tracking-protection-immediate-over-delayed-probability", "0"},
{"tracking-protection-treatment-delayed-probability", "1.0"},
{"tracking-protection-treatment-delayed-trigger-id", "trigger-1"}}}};
}
void ExpectSurveyGroupHistogramEmitted(
TrackingProtectionOnboarding::SentimentSurveyGroup group,
base::HistogramTester* histogram_tester) {
TrackingProtectionOnboarding::SentimentSurveyGroupMetrics metric_group;
switch (group) {
case TrackingProtectionOnboarding::SentimentSurveyGroup::kNotSet:
return;
case TrackingProtectionOnboarding::SentimentSurveyGroup::kControlImmediate:
metric_group = TrackingProtectionOnboarding::SentimentSurveyGroupMetrics::
kControlImmediate;
break;
case TrackingProtectionOnboarding::SentimentSurveyGroup::kControlDelayed:
metric_group = TrackingProtectionOnboarding::SentimentSurveyGroupMetrics::
kControlDelayed;
break;
case TrackingProtectionOnboarding::SentimentSurveyGroup::
kTreatmentImmediate:
metric_group = TrackingProtectionOnboarding::SentimentSurveyGroupMetrics::
kTreatmentImmediate;
break;
case TrackingProtectionOnboarding::SentimentSurveyGroup::kTreatmentDelayed:
metric_group = TrackingProtectionOnboarding::SentimentSurveyGroupMetrics::
kTreatmentDelayed;
}
histogram_tester->ExpectBucketCount(
"PrivacySandbox.TrackingProtection.SentimentSurvey."
"HatsGroupRegisteredAndEligible",
metric_group, 1);
}
} // namespace
class TrackingProtectionBaseNoticeBrowserTest
: public InteractiveFeaturePromoTest {
protected:
explicit TrackingProtectionBaseNoticeBrowserTest(
const std::vector<base::test::FeatureRef>& enabled_features,
const std::vector<base::test::FeatureRef>& disabled_features = {})
: InteractiveFeaturePromoTest(
UseDefaultTrackerAllowingPromos(enabled_features)) {
disabled_features_.InitWithFeatures({}, disabled_features);
}
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
https_server_.AddDefaultHandlers(GetChromeTestDataDir());
content::SetupCrossSiteRedirector(&https_server_);
ASSERT_TRUE(https_server_.Start());
ASSERT_TRUE(embedded_test_server()->Start());
InteractiveFeaturePromoTest::SetUpOnMainThread();
}
privacy_sandbox::TrackingProtectionOnboarding* onboarding_service() {
return TrackingProtectionOnboardingFactory::GetForProfile(
browser()->profile());
}
privacy_sandbox::TrackingProtectionNoticeService* notice_service() {
return TrackingProtectionNoticeFactory::GetForProfile(browser()->profile());
}
virtual std::vector<base::test::FeatureRef> EnabledFeatures() = 0;
virtual std::vector<base::test::FeatureRef> DisabledFeatures() = 0;
net::EmbeddedTestServer https_server_{net::EmbeddedTestServer::TYPE_HTTPS};
base::HistogramTester histogram_tester_;
private:
base::test::ScopedFeatureList disabled_features_;
};
class TrackingProtectionOnboardingNoticeBrowserTest
: public TrackingProtectionBaseNoticeBrowserTest {
protected:
TrackingProtectionOnboardingNoticeBrowserTest()
: TrackingProtectionBaseNoticeBrowserTest(EnabledFeatures(),
DisabledFeatures()) {}
std::vector<base::test::FeatureRef> EnabledFeatures() override {
return {feature_engagement::kIPHTrackingProtectionOnboardingFeature,
feature_engagement::kIPHTrackingProtectionOffboardingFeature};
}
std::vector<base::test::FeatureRef> DisabledFeatures() override {
return {privacy_sandbox::kTrackingProtectionOnboardingRollback,
features::kCookieDeprecationFacilitatedTesting};
}
bool IsOnboardingPromoActive(Browser* browser) {
return GetFeaturePromoController(browser)->IsPromoActive(
feature_engagement::kIPHTrackingProtectionOnboardingFeature);
}
};
// Navigation
// Profile marked eligible, then the user navigates to a new Secure HTTPS tab
// with the lock button.
// Should be shown the notice
IN_PROC_BROWSER_TEST_F(TrackingProtectionOnboardingNoticeBrowserTest,
NewTabEligiblePage) {
// Setup
onboarding_service()->MaybeMarkEligible();
browser()->window()->Activate();
// Action: Navigate to an HTTPS eligible page in current tab.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
// Profile is onboarded
EXPECT_EQ(onboarding_service()->GetOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::OnboardingStatus::
kOnboarded);
// Notice is showing.
EXPECT_TRUE(IsOnboardingPromoActive(browser()));
}
// Profile marked eligible, the user navigates to a new Secure HTTPS tab
// with the lock button. Is shown the notice, navigates to another eligible
// page.
// Notice should remain on the page.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOnboardingNoticeBrowserTest,
SecondEligibleNavigation) {
// Setup
onboarding_service()->MaybeMarkEligible();
browser()->window()->Activate();
// Action: Navigate to an HTTPS eligible page in current tab.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Then navigate to another eligible page.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("b.test", "/empty.html"), 1,
WindowOpenDisposition::CURRENT_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
// Notice is showing.
EXPECT_TRUE(IsOnboardingPromoActive(browser()));
}
// User is shown the notice, but was marked as Acked somehow.
// Hide the notice
IN_PROC_BROWSER_TEST_F(TrackingProtectionOnboardingNoticeBrowserTest,
NoticeWasShowingWhenAckPrefUpdated) {
// Setup
onboarding_service()->MaybeMarkEligible();
browser()->window()->Activate();
// Action: Navigate to an HTTPS eligible page in current tab.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Simulate backend ack
onboarding_service()->OnboardingNoticeActionTaken(
privacy_sandbox::TrackingProtectionOnboarding::NoticeAction::kGotIt);
// Then navigate to another eligible page.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("b.test", "/empty.html"), 1,
WindowOpenDisposition::CURRENT_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
// Notice is no longer showing.
EXPECT_FALSE(IsOnboardingPromoActive(browser()));
}
// Profile Marked eligible, added navigation to a new eligible background tab
// Current tab is eligible.
// Does not show the notice as the current tab was created before eligibility,
// therefore not tracked, and the new navigation happened in an inactive tab.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOnboardingNoticeBrowserTest,
NewBackgroundTabEligiblePage) {
// Setup
onboarding_service()->MaybeMarkEligible();
browser()->window()->Activate();
// Action: Navigate to an HTTPS eligible page in current tab and New
// background tab.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::CURRENT_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_BACKGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
// Profile is onboarded
EXPECT_EQ(onboarding_service()->GetOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::OnboardingStatus::
kEligible);
// Notice is showing.
EXPECT_FALSE(IsOnboardingPromoActive(browser()));
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Onboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kInactiveWebcontentUpdated,
1);
}
// Profile Marked eligible, added navigation to a new Ineligible Foreground tab
// Does not show the notice as the page isn't eligible.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOnboardingNoticeBrowserTest,
NewTabIneligiblePage) {
// Setup
onboarding_service()->MaybeMarkEligible();
browser()->window()->Activate();
// Action: Navigate to an HTTP ineligible page in current tab. ( No lock icon)
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), embedded_test_server()->GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
// Profile stays Eligible
EXPECT_EQ(onboarding_service()->GetOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::OnboardingStatus::
kEligible);
// Notice is not showing.
EXPECT_FALSE(IsOnboardingPromoActive(browser()));
}
// Switching between eligible/ineligible tabs shows/hides the notice
// accordingly.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOnboardingNoticeBrowserTest,
SwitchesTabs) {
// Setup
browser()->window()->Activate();
// Navigate to an HTTPS eligible page in current tab
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::CURRENT_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Creates new background tab and navigates to Ineligible page.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), embedded_test_server()->GetURL("b.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_BACKGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Action: Profile becomes eligible.
onboarding_service()->MaybeMarkEligible();
// Verification
// Notice is not yet showing.
EXPECT_FALSE(IsOnboardingPromoActive(browser()));
// This selects the second tab (ineligible). Promo shouldn't show, and profile
// not yet onboarded.
browser()->tab_strip_model()->SelectNextTab();
EXPECT_FALSE(IsOnboardingPromoActive(browser()));
EXPECT_EQ(onboarding_service()->GetOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::OnboardingStatus::
kEligible);
// Goes back to eligible tab. Promo will show, and profile is onboarded.
browser()->tab_strip_model()->SelectPreviousTab();
EXPECT_TRUE(IsOnboardingPromoActive(browser()));
EXPECT_EQ(onboarding_service()->GetOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::OnboardingStatus::
kOnboarded);
// Goes to the ineligible tab again. Notice should hide, and profile remain
// onboarded.
browser()->tab_strip_model()->SelectNextTab();
EXPECT_FALSE(IsOnboardingPromoActive(browser()));
EXPECT_EQ(onboarding_service()->GetOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::OnboardingStatus::
kOnboarded);
}
// Popup to eligible page does not show the notice.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOnboardingNoticeBrowserTest,
NewPopupEligiblePage) {
// Setup
onboarding_service()->MaybeMarkEligible();
browser()->window()->Activate();
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_POPUP,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
// Profile is not onboarded - remains eligible.
EXPECT_EQ(onboarding_service()->GetOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::OnboardingStatus::
kEligible);
// Notice is Not showing.
EXPECT_FALSE(IsOnboardingPromoActive(browser()));
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Onboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kBrowserTypeNonNormal,
1);
}
// New Browser Window picks up the promo if it navigates to an eligible page.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOnboardingNoticeBrowserTest,
NewWindowEligiblePage) {
// Setup
onboarding_service()->MaybeMarkEligible();
browser()->window()->Activate();
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_WINDOW,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Notice is showing on the new active window.
EXPECT_TRUE(IsOnboardingPromoActive(BrowserList::GetInstance()->get(1)));
// These histograms are emitted due to the location icon is not secure/visible
// due to the first page load being a non secure page.
// Once the navigation to empty.html goes through, the promo is then active
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Onboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kLocationIconNonVisible,
1);
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Onboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kLocationIconNonSecure,
1);
}
// The promo will only show on a single window.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOnboardingNoticeBrowserTest,
FirstWindowEligibleSecondWindowEligible) {
// Setup
onboarding_service()->MaybeMarkEligible();
browser()->window()->Activate();
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Promo shown on first window as expected.
EXPECT_TRUE(IsOnboardingPromoActive(browser()));
// Open new eligible window.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("b.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_WINDOW,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
EXPECT_TRUE(IsOnboardingPromoActive(browser()));
// Doesn't create a second notice on the second window.
EXPECT_FALSE(IsOnboardingPromoActive(BrowserList::GetInstance()->get(1)));
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Onboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kNoticeRequestedButNotShown,
1);
}
// Notice Acknowledgement
// Profile marked Onboarded, but not yet acknowledged still shows the notice.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOnboardingNoticeBrowserTest,
OnboardedNotAck) {
// Setup
onboarding_service()->MaybeMarkEligible();
// Telling the OnboardingService that the notice has been shown so it marks
// the profile as Onboarded.
onboarding_service()->OnboardingNoticeShown();
// Action: Navigate to an HTTPS eligible page in current tab.
browser()->window()->Activate();
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
// Notice is showing.
EXPECT_TRUE(IsOnboardingPromoActive(browser()));
}
// Profile marked Onboarded and Ack no longer shows the notice.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOnboardingNoticeBrowserTest,
AcknowledgesTheNotice) {
// Action
onboarding_service()->MaybeMarkEligible();
// Navigates to eligible page.
browser()->window()->Activate();
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
PressPromoButton(browser(), PromoButton::kNonDefault);
// Verification - Notice acknowledged.
EXPECT_FALSE(IsOnboardingPromoActive(browser()));
EXPECT_FALSE(onboarding_service()->ShouldShowOnboardingNotice());
}
// Profile marked Onboarded and Ack, then onboarding prefs reset, then profile
// marked eligible again. Shouldn't show the notice again, but will be
// considered onboarded.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOnboardingNoticeBrowserTest,
TreatsAsShownIfPreviouslyDismissed) {
// Setup
onboarding_service()->channel_ = version_info::Channel::CANARY;
// Action Onboarding and ack the user
onboarding_service()->MaybeMarkEligible();
browser()->window()->Activate();
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Notice should be showing at this point.
EXPECT_TRUE(IsOnboardingPromoActive(browser()));
// Ack the notice.
PressPromoButton(browser(), PromoButton::kNonDefault);
// Then reset the user prefs.
onboarding_service()->MaybeResetOnboardingPrefs();
// Then mark as eligible again
onboarding_service()->MaybeMarkEligible();
EXPECT_EQ(onboarding_service()->GetOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::OnboardingStatus::
kEligible);
// Navigates to any page.
browser()->window()->Activate();
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification - Notice not shown again, but the profile is onboarded.
EXPECT_FALSE(IsOnboardingPromoActive(browser()));
EXPECT_FALSE(onboarding_service()->ShouldShowOnboardingNotice());
EXPECT_EQ(onboarding_service()->GetOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::OnboardingStatus::
kOnboarded);
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Onboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kPromoPreviouslyDismissed,
1);
}
// Observation
// Profile is ineligible. Notice Service is not observing tab changes.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOnboardingNoticeBrowserTest,
DoesntStartObserving) {
EXPECT_FALSE(TabStripModelObserver::IsObservingAny(notice_service()));
EXPECT_FALSE(privacy_sandbox::TrackingProtectionNoticeService::TabHelper::
IsHelperNeeded(browser()->profile()));
}
// Profile is eligible. Notice service is observing tab changes.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOnboardingNoticeBrowserTest,
StartsObserving) {
// Action
onboarding_service()->MaybeMarkEligible();
browser()->window()->Activate();
// Verification
EXPECT_TRUE(TabStripModelObserver::IsObservingAny(notice_service()));
EXPECT_TRUE(privacy_sandbox::TrackingProtectionNoticeService::TabHelper::
IsHelperNeeded(browser()->profile()));
}
// Notice is acknowledged. Notice Service stops observing tab changes.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOnboardingNoticeBrowserTest,
StopsObserving) {
// Action
onboarding_service()->MaybeMarkEligible();
// Navigates to eligible page.
browser()->window()->Activate();
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
PressPromoButton(browser());
// Verification - Observation stops
EXPECT_FALSE(TabStripModelObserver::IsObservingAny(notice_service()));
EXPECT_FALSE(privacy_sandbox::TrackingProtectionNoticeService::TabHelper::
IsHelperNeeded(browser()->profile()));
// Once the notice object is created, the tab strip tracker is initialized but
// in this test we press the promo button, which also causes the
// tracker to be reset again.
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.NoticeService."
"IsObservingTabStripModel",
true, 1);
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.NoticeService."
"IsObservingTabStripModel",
false, 1);
}
class TrackingProtectionOffboardingNoticeBrowserTest
: public TrackingProtectionBaseNoticeBrowserTest {
protected:
TrackingProtectionOffboardingNoticeBrowserTest()
: TrackingProtectionBaseNoticeBrowserTest(EnabledFeatures(),
DisabledFeatures()) {}
std::vector<base::test::FeatureRef> EnabledFeatures() override {
return {privacy_sandbox::kTrackingProtectionOnboardingRollback,
feature_engagement::kIPHTrackingProtectionOnboardingFeature,
feature_engagement::kIPHTrackingProtectionOffboardingFeature};
}
std::vector<base::test::FeatureRef> DisabledFeatures() override {
// This feature is irrelevant for these tests, disabling to avoid
// interplaying with the tests.
return {features::kCookieDeprecationFacilitatedTesting};
}
bool IsOnboardingPromoActive(Browser* browser) {
return GetFeaturePromoController(browser)->IsPromoActive(
feature_engagement::kIPHTrackingProtectionOnboardingFeature);
}
bool IsOffboardingPromoActive(Browser* browser) {
return GetFeaturePromoController(browser)->IsPromoActive(
feature_engagement::kIPHTrackingProtectionOffboardingFeature);
}
};
// Profile marked Ineligible.
// The user navigates to a new Secure HTTPS tab with the lock button.
// Offboarding notice should not be show.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOffboardingNoticeBrowserTest,
IneligibleProfile) {
// Setup
browser()->window()->Activate();
// Action: Navigate to an HTTPS eligible page in current tab.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
// Profile stays Ineligible
EXPECT_EQ(onboarding_service()->GetOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::OnboardingStatus::
kIneligible);
// Notice is not showing.
EXPECT_FALSE(IsOffboardingPromoActive(browser()));
}
// Profile marked Eligible, then browser restarted.
// The user navigates to a new Secure HTTPS tab with the lock button.
// Offboarding notice should not be show.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOffboardingNoticeBrowserTest,
PRE_EligibleProfile) {
onboarding_service()->MaybeMarkEligible();
}
IN_PROC_BROWSER_TEST_F(TrackingProtectionOffboardingNoticeBrowserTest,
EligibleProfile) {
// Setup
browser()->window()->Activate();
// Action: Navigate to an HTTPS eligible page in current tab.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
// Profile stays eligible
EXPECT_EQ(onboarding_service()->GetOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::OnboardingStatus::
kEligible);
// Notice is not showing.
EXPECT_FALSE(IsOffboardingPromoActive(browser()));
}
// Profile marked Onboarded, then browser restarted.
// The user navigates to a new Secure HTTPS tab with the lock button.
// Offboarding notice should show.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOffboardingNoticeBrowserTest,
PRE_OnboardedProfile) {
onboarding_service()->MaybeMarkEligible();
onboarding_service()->NoticeShown(NoticeType::kOnboarding);
}
IN_PROC_BROWSER_TEST_F(TrackingProtectionOffboardingNoticeBrowserTest,
OnboardedProfile) {
// Setup
browser()->window()->Activate();
// Action: Navigate to an HTTPS eligible page in current tab.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
// Profile is offboarded
EXPECT_EQ(onboarding_service()->GetOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::OnboardingStatus::
kOffboarded);
// Notice is showing.
EXPECT_TRUE(IsOffboardingPromoActive(browser()));
}
// Profile marked Offboarded, then browser restarted.
// The user navigates to a new Secure HTTPS tab with the lock button.
// Offboarding notice should not show.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOffboardingNoticeBrowserTest,
PRE_OffboardedProfile) {
onboarding_service()->NoticeShown(NoticeType::kOffboarding);
}
IN_PROC_BROWSER_TEST_F(TrackingProtectionOffboardingNoticeBrowserTest,
OffboardedProfile) {
// Setup
browser()->window()->Activate();
// Action: Navigate to an HTTPS eligible page in current tab.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
// Profile is offboarded
EXPECT_EQ(onboarding_service()->GetOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::OnboardingStatus::
kOffboarded);
// Notice is not showing.
EXPECT_FALSE(IsOffboardingPromoActive(browser()));
}
// Once hidden, the offboarding notice doesn't reappear.
IN_PROC_BROWSER_TEST_F(TrackingProtectionOffboardingNoticeBrowserTest,
PRE_NoticeDoesntReshow) {
onboarding_service()->MaybeMarkEligible();
onboarding_service()->NoticeShown(NoticeType::kOnboarding);
}
IN_PROC_BROWSER_TEST_F(TrackingProtectionOffboardingNoticeBrowserTest,
NoticeDoesntReshow) {
// Setup
browser()->window()->Activate();
// Navigate to an HTTPS eligible page in current tab
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::CURRENT_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Creates new background tab and navigates to Ineligible page.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), embedded_test_server()->GetURL("b.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_BACKGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
// Profile is offboarded
EXPECT_EQ(onboarding_service()->GetOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::OnboardingStatus::
kOffboarded);
// Notice is showing.
EXPECT_TRUE(IsOffboardingPromoActive(browser()));
// This selects the second tab (ineligible). Promo shouldn't show.
browser()->tab_strip_model()->SelectNextTab();
EXPECT_FALSE(IsOffboardingPromoActive(browser()));
EXPECT_EQ(onboarding_service()->GetOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::OnboardingStatus::
kOffboarded);
// Goes back to eligible tab. Promo will not show.
browser()->tab_strip_model()->SelectPreviousTab();
EXPECT_FALSE(IsOffboardingPromoActive(browser()));
}
IN_PROC_BROWSER_TEST_F(TrackingProtectionOnboardingNoticeBrowserTest,
NoticeServiceEventHistogramCheck) {
// Setup
onboarding_service()->MaybeMarkEligible();
browser()->window()->Activate();
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Onboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kNoticeObjectCreated,
1);
// Action: Navigate to an HTTPS eligible page in current tab.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// On the first load the OnTabStripModelChanged is invoked causing the
// MaybeUpdateNoticeVisibility function to be called. Then once the navigation
// goes through which also calls the MaybeUpdateNoticeVisibility which is why
// there are two histograms emitted for kUpdateNoticeVisibility.
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Onboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kUpdateNoticeVisibility,
2);
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Onboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kActiveTabChanged,
1);
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Onboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kNoticeRequestedAndShown,
1);
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Onboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kNavigationFinished,
1);
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("b.test", "/empty.html"), 1,
WindowOpenDisposition::CURRENT_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Onboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kNoticeAlreadyShowing,
1);
// Acknowledging the notice with the "Got It" button. Then navigating to a
// different page with the same tab to see that the promo is still showing due
// to the status of the notice not being updated yet.
onboarding_service()->OnboardingNoticeActionTaken(
privacy_sandbox::TrackingProtectionOnboarding::NoticeAction::kGotIt);
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("c.test", "/empty.html"), 1,
WindowOpenDisposition::CURRENT_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Onboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kNoticeShowingButShouldnt,
1);
}
#if !BUILDFLAG(IS_CHROMEOS_LACROS)
IN_PROC_BROWSER_TEST_F(TrackingProtectionOffboardingNoticeBrowserTest,
PRE_NoticeServiceEventHistogramCheck) {
onboarding_service()->MaybeMarkEligible();
onboarding_service()->NoticeShown(NoticeType::kOnboarding);
}
IN_PROC_BROWSER_TEST_F(TrackingProtectionOffboardingNoticeBrowserTest,
NoticeServiceEventHistogramCheck) {
// Setup
browser()->window()->Activate();
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Offboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kNoticeObjectCreated,
1);
// On the first load the OnTabStripModelChanged is invoked causing the
// MaybeUpdateNoticeVisibility function to be called. Then once the navigation
// goes through which also calls the MaybeUpdateNoticeVisibility which is why
// there are two histograms emitted for kUpdateNoticeVisibility.
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Offboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kUpdateNoticeVisibility,
2);
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Offboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kActiveTabChanged,
1);
// Action: Navigate to an HTTPS eligible page in current tab.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
// Profile is offboarded
EXPECT_EQ(onboarding_service()->GetOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::OnboardingStatus::
kOffboarded);
// Notice is showing.
EXPECT_TRUE(IsOffboardingPromoActive(browser()));
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Offboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kNoticeRequestedAndShown,
1);
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("b.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_POPUP,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// This selects the second tab (ineligible). Promo shouldn't show.
browser()->tab_strip_model()->SelectNextTab();
EXPECT_FALSE(IsOffboardingPromoActive(browser()));
EXPECT_EQ(onboarding_service()->GetOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::OnboardingStatus::
kOffboarded);
// Goes back to eligible tab. Promo will not show.
browser()->tab_strip_model()->SelectPreviousTab();
EXPECT_FALSE(IsOffboardingPromoActive(browser()));
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Offboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kNavigationFinished,
2);
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Offboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kNoticeShowingButShouldnt,
1);
}
#endif // !BUILDFLAG(IS_CHROMEOS_LACROS)
IN_PROC_BROWSER_TEST_F(TrackingProtectionOffboardingNoticeBrowserTest,
PRE_NoticeServiceEventHistogramCheckNonNormal) {
onboarding_service()->MaybeMarkEligible();
onboarding_service()->NoticeShown(NoticeType::kOnboarding);
}
IN_PROC_BROWSER_TEST_F(TrackingProtectionOffboardingNoticeBrowserTest,
NoticeServiceEventHistogramCheckNonNormal) {
browser()->window()->Activate();
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_POPUP,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.Offboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kBrowserTypeNonNormal,
1);
}
IN_PROC_BROWSER_TEST_F(TrackingProtectionOffboardingNoticeBrowserTest,
PRE_IsObserving) {
onboarding_service()->MaybeMarkEligible();
onboarding_service()->NoticeShown(NoticeType::kOnboarding);
}
IN_PROC_BROWSER_TEST_F(TrackingProtectionOffboardingNoticeBrowserTest,
IsObserving) {
browser()->window()->Activate();
// Once the notice object is created, the tab strip tracker is initialized
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.NoticeService."
"IsObservingTabStripModel",
true, 1);
}
IN_PROC_BROWSER_TEST_F(TrackingProtectionOffboardingNoticeBrowserTest,
PRE_StopsObserving) {
onboarding_service()->MaybeMarkEligible();
onboarding_service()->NoticeShown(NoticeType::kOnboarding);
}
IN_PROC_BROWSER_TEST_F(TrackingProtectionOffboardingNoticeBrowserTest,
StopsObserving) {
// Navigates to eligible page.
browser()->window()->Activate();
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
EXPECT_TRUE(TabStripModelObserver::IsObservingAny(notice_service()));
PressPromoButton(browser());
// Verification - Observation stops
EXPECT_FALSE(TabStripModelObserver::IsObservingAny(notice_service()));
EXPECT_FALSE(privacy_sandbox::TrackingProtectionNoticeService::TabHelper::
IsHelperNeeded(browser()->profile()));
}
struct TrackingProtectionSurveyTestData {
// Inputs
std::vector<base::test::FeatureRefAndParams> features;
bool has_cookie_controls_3pc_blocked = false;
bool has_tracking_protection_3pc_blocked = false;
bool has_topics_enabled = false;
bool has_fledge_enabled = false;
bool has_measurement_enabled = false;
std::optional<bool> should_silently_onboard = std::nullopt;
std::optional<NoticeAction> ack_action = std::nullopt;
base::TimeDelta to_start_survey;
base::TimeDelta after_end_of_survey;
// Expectations
std::string trigger_id;
SentimentSurveyGroup group;
bool is_b_prime = false;
};
class TrackingProtectionHatsBaseTest : public InProcessBrowserTest {
protected:
explicit TrackingProtectionHatsBaseTest(
const std::vector<base::test::FeatureRefAndParams>&
allow_and_enable_features) {
feature_list_.InitWithFeaturesAndParameters(
allow_and_enable_features,
{content_settings::features::kTrackingProtection3pcd});
}
void SetUpOnMainThread() override {
mock_hats_service_ = static_cast<MockHatsService*>(
HatsServiceFactory::GetInstance()->SetTestingFactoryAndUse(
browser()->profile(), base::BindRepeating(&BuildMockHatsService)));
EXPECT_CALL(*mock_hats_service_, CanShowAnySurvey(testing::_))
.WillRepeatedly(testing::Return(true));
host_resolver()->AddRule("*", "127.0.0.1");
https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
https_server_.AddDefaultHandlers(GetChromeTestDataDir());
content::SetupCrossSiteRedirector(&https_server_);
ASSERT_TRUE(https_server_.Start());
ASSERT_TRUE(embedded_test_server()->Start());
}
privacy_sandbox::TrackingProtectionOnboarding* onboarding_service() {
return TrackingProtectionOnboardingFactory::GetForProfile(
browser()->profile());
}
virtual std::vector<base::test::FeatureRefAndParams>
EnabledFeaturesWithParams() = 0;
net::EmbeddedTestServer https_server_{net::EmbeddedTestServer::TYPE_HTTPS};
raw_ptr<MockHatsService, DanglingUntriaged> mock_hats_service_;
base::test::ScopedFeatureList feature_list_;
};
class TrackingProtectionHatsBrowserTest
: public TrackingProtectionHatsBaseTest,
public testing::WithParamInterface<TrackingProtectionSurveyTestData> {
protected:
TrackingProtectionHatsBrowserTest()
: TrackingProtectionHatsBaseTest(EnabledFeaturesWithParams()) {}
base::HistogramTester histogram_tester_;
std::vector<base::test::FeatureRefAndParams> EnabledFeaturesWithParams()
override {
return GetParam().features;
}
};
base::Time Now() {
static base::Time now = base::subtle::TimeNowIgnoringOverride();
return now;
}
IN_PROC_BROWSER_TEST_P(TrackingProtectionHatsBrowserTest,
CallHatsServiceWithProductData) {
TrackingProtectionSurveyTestData params = GetParam();
// Setup
if (params.has_cookie_controls_3pc_blocked) {
browser()->profile()->GetPrefs()->SetInteger(
prefs::kCookieControlsMode,
static_cast<int>(
content_settings::CookieControlsMode::kBlockThirdParty));
}
browser()->profile()->GetPrefs()->SetBoolean(
prefs::kBlockAll3pcToggleEnabled,
params.has_tracking_protection_3pc_blocked);
browser()->profile()->GetPrefs()->SetBoolean(
prefs::kPrivacySandboxM1TopicsEnabled, params.has_topics_enabled);
browser()->profile()->GetPrefs()->SetBoolean(
prefs::kPrivacySandboxM1FledgeEnabled, params.has_fledge_enabled);
browser()->profile()->GetPrefs()->SetBoolean(
prefs::kPrivacySandboxM1AdMeasurementEnabled,
params.has_measurement_enabled);
if (params.should_silently_onboard) {
{
base::subtle::ScopedTimeClockOverrides override([]() { return Now(); },
nullptr, nullptr);
onboarding_service()->MaybeMarkSilentEligible();
onboarding_service()->SilentOnboardingNoticeShown();
}
}
// Ack if necessary.
if (params.ack_action.has_value()) {
// Onboarding first
{
base::subtle::ScopedTimeClockOverrides override([]() { return Now(); },
nullptr, nullptr);
onboarding_service()->OnboardingNoticeShown();
}
// Ack after 65 seconds
{
base::subtle::ScopedTimeClockOverrides override(
[]() { return Now() + base::Seconds(65); }, nullptr, nullptr);
onboarding_service()->OnboardingNoticeActionTaken(
params.ack_action.value());
}
}
// Navigation to first NTP, triggering group registration.
browser()->window()->Activate();
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(),
GURL(chrome::kChromeUINewTabURL)));
// Verification
// After the start delay, a survey should be required.
{
base::subtle::ScopedTimeClockOverrides override(
[]() { return Now() + GetParam().to_start_survey; }, nullptr, nullptr);
EXPECT_EQ(onboarding_service()->GetEligibleSurveyGroup(), params.group);
SurveyBitsData product_bits{
{"3P cookies blocked", params.has_cookie_controls_3pc_blocked ||
params.has_tracking_protection_3pc_blocked},
{"Fledge enabled", params.has_fledge_enabled},
{"Is Mode B'", params.is_b_prime},
{"Measurement enabled", params.has_measurement_enabled},
{"Onboarding Settings Clicked",
params.ack_action == NoticeAction::kSettings},
{"Topics enabled", params.has_topics_enabled}};
SurveyStringData product_strings{
{"Seconds to acknowledge", params.ack_action.has_value()
? "65" // 65 seconds to ack above.
: "-1"}};
EXPECT_CALL(
*mock_hats_service_,
LaunchSurvey(params.trigger_id, _, _, product_bits, product_strings));
// Navigation actually triggering the survey;
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(),
GURL(chrome::kChromeUINewTabURL)));
ExpectSurveyGroupHistogramEmitted(params.group, &histogram_tester_);
testing::Mock::VerifyAndClearExpectations(mock_hats_service_);
}
// After the end date, the survey should no longer trigger.
{
base::subtle::ScopedTimeClockOverrides override(
[]() { return Now() + GetParam().after_end_of_survey; }, nullptr,
nullptr);
EXPECT_EQ(onboarding_service()->GetEligibleSurveyGroup(),
SentimentSurveyGroup::kNotSet);
EXPECT_CALL(*mock_hats_service_, LaunchSurvey).Times(0);
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(),
GURL(chrome::kChromeUINewTabURL)));
testing::Mock::VerifyAndClearExpectations(mock_hats_service_);
}
}
INSTANTIATE_TEST_SUITE_P(
,
TrackingProtectionHatsBrowserTest,
testing::Values(
// Immediate Control only measuerement enabled.
TrackingProtectionSurveyTestData{
.features = HatsImmediateControlFeatures(),
.has_cookie_controls_3pc_blocked = false,
.has_topics_enabled = false,
.has_fledge_enabled = false,
.has_measurement_enabled = true,
.to_start_survey = base::Minutes(5),
.after_end_of_survey = base::Minutes(65),
.trigger_id = kHatsSurveyTriggerTrackingProtectionControlImmediate,
.group = SentimentSurveyGroup::kControlImmediate,
},
// Immediate Control Only fledge enabled
TrackingProtectionSurveyTestData{
.features = HatsImmediateControlFeatures(),
.has_cookie_controls_3pc_blocked = false,
.has_topics_enabled = false,
.has_fledge_enabled = true,
.has_measurement_enabled = false,
.to_start_survey = base::Minutes(5),
.after_end_of_survey = base::Minutes(65),
.trigger_id = kHatsSurveyTriggerTrackingProtectionControlImmediate,
.group = SentimentSurveyGroup::kControlImmediate,
},
// Immediate Control Only topics Enabled
TrackingProtectionSurveyTestData{
.features = HatsImmediateControlFeatures(),
.has_cookie_controls_3pc_blocked = false,
.has_topics_enabled = true,
.has_fledge_enabled = false,
.has_measurement_enabled = false,
.to_start_survey = base::Minutes(5),
.after_end_of_survey = base::Minutes(65),
.trigger_id = kHatsSurveyTriggerTrackingProtectionControlImmediate,
.group = SentimentSurveyGroup::kControlImmediate,
},
// Immediate Control No Ads API Enabled
TrackingProtectionSurveyTestData{
.features = HatsImmediateControlFeatures(),
.has_cookie_controls_3pc_blocked = true,
.has_topics_enabled = false,
.has_fledge_enabled = false,
.has_measurement_enabled = false,
.to_start_survey = base::Minutes(5),
.after_end_of_survey = base::Minutes(65),
.trigger_id = kHatsSurveyTriggerTrackingProtectionControlImmediate,
.group = SentimentSurveyGroup::kControlImmediate,
},
// Immediate Control with silent onbaording. No Ads API Enabled
TrackingProtectionSurveyTestData{
.features = HatsImmediateControlFeaturesWithSilentOnboarding(),
.has_cookie_controls_3pc_blocked = true,
.has_topics_enabled = false,
.has_fledge_enabled = false,
.has_measurement_enabled = false,
.should_silently_onboard = true,
.to_start_survey = base::Minutes(5),
.after_end_of_survey = base::Minutes(65),
.trigger_id = kHatsSurveyTriggerTrackingProtectionControlImmediate,
.group = SentimentSurveyGroup::kControlImmediate,
},
// Delayed Control No Ads API Enabled
TrackingProtectionSurveyTestData{
.features = HatsDelayedControlFeatures(),
.has_cookie_controls_3pc_blocked = true,
.has_topics_enabled = false,
.has_fledge_enabled = false,
.has_measurement_enabled = false,
.to_start_survey = base::Days(14) + base::Minutes(5),
.after_end_of_survey = base::Days(16),
.trigger_id = kHatsSurveyTriggerTrackingProtectionControlDelayed,
.group = SentimentSurveyGroup::kControlDelayed,
},
// Immediate Mode B acked with "Settings" button
TrackingProtectionSurveyTestData{
.features = HatsImmediateModeBFeatures(),
.has_tracking_protection_3pc_blocked = true,
.has_topics_enabled = false,
.has_fledge_enabled = false,
.has_measurement_enabled = false,
.ack_action = NoticeAction::kSettings,
.to_start_survey = base::Minutes(5),
.after_end_of_survey = base::Minutes(65),
.trigger_id =
kHatsSurveyTriggerTrackingProtectionTreatmentImmediate,
.group = SentimentSurveyGroup::kTreatmentImmediate,
},
// Immediate Mode B Acked with "Got It" button
TrackingProtectionSurveyTestData{
.features = HatsImmediateModeBFeatures(),
.has_tracking_protection_3pc_blocked = true,
.has_topics_enabled = false,
.has_fledge_enabled = false,
.has_measurement_enabled = false,
.ack_action = NoticeAction::kGotIt,
.to_start_survey = base::Minutes(5),
.after_end_of_survey = base::Minutes(65),
.trigger_id =
kHatsSurveyTriggerTrackingProtectionTreatmentImmediate,
.group = SentimentSurveyGroup::kTreatmentImmediate,
},
// Delayed Mode B Acked with "Got It" button
TrackingProtectionSurveyTestData{
.features = HatsDelayedModeBFeatures(),
.has_tracking_protection_3pc_blocked = true,
.has_topics_enabled = false,
.has_fledge_enabled = false,
.has_measurement_enabled = false,
.ack_action = NoticeAction::kGotIt,
.to_start_survey = base::Days(14) + base::Minutes(5),
.after_end_of_survey = base::Days(16),
.trigger_id = kHatsSurveyTriggerTrackingProtectionTreatmentDelayed,
.group = SentimentSurveyGroup::kTreatmentDelayed,
},
// Immediate Mode B Prime
TrackingProtectionSurveyTestData{
.features = HatsImmediateModeBPrimeFeatures(),
.has_tracking_protection_3pc_blocked = true,
.has_topics_enabled = false,
.has_fledge_enabled = false,
.has_measurement_enabled = false,
.ack_action = NoticeAction::kGotIt,
.to_start_survey = base::Minutes(5),
.after_end_of_survey = base::Minutes(65),
.trigger_id =
kHatsSurveyTriggerTrackingProtectionTreatmentImmediate,
.group = SentimentSurveyGroup::kTreatmentImmediate,
.is_b_prime = true,
},
// Delayed Mode B Prime
TrackingProtectionSurveyTestData{
.features = HatsDelayedModeBPrimeFeatures(),
.has_tracking_protection_3pc_blocked = true,
.has_topics_enabled = false,
.has_fledge_enabled = false,
.has_measurement_enabled = false,
.ack_action = NoticeAction::kGotIt,
.to_start_survey = base::Days(14) + base::Minutes(5),
.after_end_of_survey = base::Days(16),
.trigger_id = kHatsSurveyTriggerTrackingProtectionTreatmentDelayed,
.group = SentimentSurveyGroup::kTreatmentDelayed,
.is_b_prime = true,
}));
class TrackingProtectionHatsIneligibleClientBrowserTest
: public TrackingProtectionHatsBaseTest {
protected:
TrackingProtectionHatsIneligibleClientBrowserTest()
: TrackingProtectionHatsBaseTest(EnabledFeaturesWithParams()) {}
std::vector<base::test::FeatureRefAndParams> EnabledFeaturesWithParams()
override {
return {
{features::kCookieDeprecationFacilitatedTesting,
{{tpcd::experiment::kDisable3PCookiesName, "false"},
{tpcd::experiment::kForceEligibleForTestingName, "false"}}},
{features::kTrackingProtectionSentimentSurvey,
{{"tracking-protection-immediate-over-delayed-probability", "1"},
{"tracking-protection-control-immediate-probability", "1.0"},
{"tracking-protection-control-immediate-trigger-id", "trigger-1"}}}};
}
};
IN_PROC_BROWSER_TEST_F(TrackingProtectionHatsIneligibleClientBrowserTest,
IneligibleClientDoesntSurvey) {
// Navigation to first NTP, triggering group registration.
browser()->window()->Activate();
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(),
GURL(chrome::kChromeUINewTabURL)));
// Verification
// After the start delay, a survey should not be required.
{
base::subtle::ScopedTimeClockOverrides override(
[]() { return Now() + base::Minutes(5); }, nullptr, nullptr);
EXPECT_EQ(onboarding_service()->GetEligibleSurveyGroup(),
SentimentSurveyGroup::kNotSet);
// Navigation will not trigger the survey.
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(),
GURL(chrome::kChromeUINewTabURL)));
EXPECT_CALL(*mock_hats_service_, LaunchSurvey).Times(0);
testing::Mock::VerifyAndClearExpectations(mock_hats_service_);
}
}
class TrackingProtectionSilentOnboardingNoticeBrowserTest
: public TrackingProtectionOnboardingNoticeBrowserTest {};
// Navigation
// Profile marked eligible, then the user navigates to a new Secure HTTPS tab
// with the lock button.
// Should be shown the notice
IN_PROC_BROWSER_TEST_F(TrackingProtectionSilentOnboardingNoticeBrowserTest,
NewTabEligiblePage) {
// Setup
onboarding_service()->MaybeMarkSilentEligible();
browser()->window()->Activate();
// Action: Navigate to an HTTPS eligible page in current tab.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
// Profile is Onboarded
EXPECT_EQ(onboarding_service()->GetSilentOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::
SilentOnboardingStatus::kOnboarded);
}
// Profile Marked eligible, added navigation to a new eligible background tab
// Current tab is eligible.
// Does not show the notice as the current tab was created before eligibility,
// therefore not tracked, and the new navigation happened in an inactive tab.
IN_PROC_BROWSER_TEST_F(TrackingProtectionSilentOnboardingNoticeBrowserTest,
NewBackgroundTabEligiblePage) {
// Setup
onboarding_service()->MaybeMarkSilentEligible();
browser()->window()->Activate();
// Action: Navigate to an HTTPS eligible page in current tab and New
// background tab.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::CURRENT_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_BACKGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
// Profile stays Eligible
EXPECT_EQ(onboarding_service()->GetSilentOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::
SilentOnboardingStatus::kEligible);
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.SilentOnboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kInactiveWebcontentUpdated,
1);
}
// Profile Marked eligible, added navigation to a new Ineligible Foreground tab
// Does not silently onboard the profile as the page isn't eligible.
IN_PROC_BROWSER_TEST_F(TrackingProtectionSilentOnboardingNoticeBrowserTest,
NewTabIneligiblePage) {
// Setup
onboarding_service()->MaybeMarkSilentEligible();
browser()->window()->Activate();
// Action: Navigate to an HTTP ineligible page in current tab. ( No lock icon)
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), embedded_test_server()->GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
// Profile stays Eligible
EXPECT_EQ(onboarding_service()->GetSilentOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::
SilentOnboardingStatus::kEligible);
}
// Switching between eligible/ineligible tabs silently onboards the profile
// accordingly.
IN_PROC_BROWSER_TEST_F(TrackingProtectionSilentOnboardingNoticeBrowserTest,
SwitchesTabs) {
// Setup
browser()->window()->Activate();
// Navigate to an HTTPS eligible page in current tab
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::CURRENT_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Creates new background tab and navigates to Ineligible page.
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), embedded_test_server()->GetURL("b.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_BACKGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Action: Profile becomes eligible.
onboarding_service()->MaybeMarkSilentEligible();
// This selects the second tab (ineligible). Promo shouldn't show, and profile
// not yet onboarded.
browser()->tab_strip_model()->SelectNextTab();
EXPECT_EQ(onboarding_service()->GetSilentOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::
SilentOnboardingStatus::kEligible);
// Goes back to eligible tab. Promo will show, and profile is onboarded.
browser()->tab_strip_model()->SelectPreviousTab();
EXPECT_EQ(onboarding_service()->GetSilentOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::
SilentOnboardingStatus::kOnboarded);
// Goes to the ineligible tab again. Profile remains onboarded.
browser()->tab_strip_model()->SelectNextTab();
EXPECT_EQ(onboarding_service()->GetSilentOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::
SilentOnboardingStatus::kOnboarded);
}
// Popup to eligible page does not show the notice.
IN_PROC_BROWSER_TEST_F(TrackingProtectionSilentOnboardingNoticeBrowserTest,
NewPopupEligiblePage) {
// Setup
onboarding_service()->MaybeMarkSilentEligible();
browser()->window()->Activate();
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_POPUP,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification
// Profile is not onboarded - remains eligible.
EXPECT_EQ(onboarding_service()->GetSilentOnboardingStatus(),
privacy_sandbox::TrackingProtectionOnboarding::
SilentOnboardingStatus::kEligible);
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.SilentOnboarding.NoticeServiceEvent",
privacy_sandbox::TrackingProtectionNoticeService::
TrackingProtectionMetricsNoticeEvent::kBrowserTypeNonNormal,
1);
}
// Observation
// Profile is ineligible. Notice Service is not observing tab changes.
IN_PROC_BROWSER_TEST_F(TrackingProtectionSilentOnboardingNoticeBrowserTest,
DoesntStartObserving) {
EXPECT_FALSE(TabStripModelObserver::IsObservingAny(notice_service()));
EXPECT_FALSE(privacy_sandbox::TrackingProtectionNoticeService::TabHelper::
IsHelperNeeded(browser()->profile()));
}
// Profile is eligible. Notice service is observing tab changes.
IN_PROC_BROWSER_TEST_F(TrackingProtectionSilentOnboardingNoticeBrowserTest,
StartsObserving) {
// Action
onboarding_service()->MaybeMarkSilentEligible();
browser()->window()->Activate();
// Verification
EXPECT_TRUE(TabStripModelObserver::IsObservingAny(notice_service()));
EXPECT_TRUE(privacy_sandbox::TrackingProtectionNoticeService::TabHelper::
IsHelperNeeded(browser()->profile()));
}
// Notice is shown. Notice Service stops observing tab changes.
IN_PROC_BROWSER_TEST_F(TrackingProtectionSilentOnboardingNoticeBrowserTest,
StopsObserving) {
// Action
onboarding_service()->MaybeMarkSilentEligible();
// Navigates to eligible page.
browser()->window()->Activate();
ui_test_utils::NavigateToURLWithDispositionBlockUntilNavigationsComplete(
browser(), https_server_.GetURL("a.test", "/empty.html"), 1,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Verification - Observation stops
EXPECT_FALSE(TabStripModelObserver::IsObservingAny(notice_service()));
EXPECT_FALSE(privacy_sandbox::TrackingProtectionNoticeService::TabHelper::
IsHelperNeeded(browser()->profile()));
// Once the notice object is created, the tab strip tracker is initialized but
// in this test we press the promo button, which also causes the
// tracker to be reset again.
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.NoticeService."
"IsObservingTabStripModel",
true, 1);
histogram_tester_.ExpectBucketCount(
"PrivacySandbox.TrackingProtection.NoticeService."
"IsObservingTabStripModel",
false, 1);
}
// Profile is onboarded. Notice Service is not observing tab changes.
IN_PROC_BROWSER_TEST_F(TrackingProtectionSilentOnboardingNoticeBrowserTest,
OnboardedProfileDoesntStartObserving) {
onboarding_service()->MaybeMarkSilentEligible();
// Telling the OnboardingService that the notice has been shown so it marks
// the profile as Onboarded.
onboarding_service()->SilentOnboardingNoticeShown();
EXPECT_FALSE(TabStripModelObserver::IsObservingAny(notice_service()));
EXPECT_FALSE(privacy_sandbox::TrackingProtectionNoticeService::TabHelper::
IsHelperNeeded(browser()->profile()));
}
} // namespace privacy_sandbox