[iOS][DefaultBrowserPromo] Migrate non-modal promo to the FET

This CL:
- Migrates the default browser non-modal promo to the FET.
- Check FET to determine if promo should/would be shown if migration
flag is enabled.
- Records events to both the FET and UserDefaults in case of reverse
migration.

Bug: 383772478
Change-Id: I4604fb89a59ae7fb68d59d45d1dcc58f94047b00
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6179700
Reviewed-by: Sylvain Defresne <sdefresne@chromium.org>
Commit-Queue: Cheick Cisse <cheickcisse@google.com>
Reviewed-by: Robbie Gibson <rkgibson@google.com>
Reviewed-by: Guillaume Jenkins <gujen@google.com>
Cr-Commit-Position: refs/heads/main@{#1415051}
NOKEYCHECK=True
GitOrigin-RevId: 05785c0b22108c965d578d643c1bcfaa8ea99279
diff --git a/chrome/browser/default_browser/model/BUILD.gn b/chrome/browser/default_browser/model/BUILD.gn
index 2df6c93..57f7d71 100644
--- a/chrome/browser/default_browser/model/BUILD.gn
+++ b/chrome/browser/default_browser/model/BUILD.gn
@@ -85,6 +85,7 @@
     "default_browser_promo_event_exporter.mm",
   ]
   deps = [
+    ":features",
     ":utils",
     "//components/feature_engagement/public",
   ]
diff --git a/chrome/browser/default_browser/model/default_browser_promo_event_exporter.mm b/chrome/browser/default_browser/model/default_browser_promo_event_exporter.mm
index 81e3fb0..5930fd0 100644
--- a/chrome/browser/default_browser/model/default_browser_promo_event_exporter.mm
+++ b/chrome/browser/default_browser/model/default_browser_promo_event_exporter.mm
@@ -4,8 +4,13 @@
 
 #import "ios/chrome/browser/default_browser/model/default_browser_promo_event_exporter.h"
 
+#import <UIKit/UIKit.h>
+
+#import "base/apple/foundation_util.h"
 #import "base/time/time.h"
 #import "components/feature_engagement/public/event_constants.h"
+#import "ios/chrome/browser/default_browser/model/features.h"
+#import "ios/chrome/browser/default_browser/model/utils.h"
 
 namespace {
 
@@ -24,12 +29,16 @@
   std::vector<EventData> events_to_migrate;
 
   // Migrate the FRE promo event.
+  // TODO(crbug.com/382733018): Clean up the default browser promos eligibility
+  // tracking migration code.
   if (!FRETimestampMigrationDone()) {
     AddFREPromoEvent(events_to_migrate);
     LogFRETimestampMigrationDone();
   }
 
   // Migrate promo interest signals
+  // TODO(crbug.com/382733018): Clean up the default browser promos eligibility
+  // tracking migration code.
   if (!IsPromoInterestEventMigrationDone()) {
     AddPromoInterestEvents(
         events_to_migrate, DefaultPromoTypeGeneral,
@@ -46,12 +55,30 @@
     LogPromoInterestEventMigrationDone();
   }
 
+  // TODO(crbug.com/382733018): Clean up the default browser promos eligibility
+  // tracking migration code.
   if (!IsPromoImpressionsMigrationDone()) {
     AddGenericPromoImpressions(events_to_migrate);
     AddTailoredPromoImpressions(events_to_migrate);
     LogPromoImpressionsMigrationDone();
   }
 
+  // Migrate the default browser's non-modal promo events.
+  // TODO(crbug.com/391166425): Clean up the non-modal promo migration code.
+  if (IsNonModalPromoMigrationEnabled() && !IsNonModalPromoMigrationDone()) {
+    NSDate* last_interaction = LastTimeUserInteractedWithNonModalPromo();
+    if (last_interaction && UserInteractionWithNonModalPromoCount() > 0) {
+      const NSInteger count = UserInteractionWithNonModalPromoCount();
+      for (NSInteger i = 0; i < count; ++i) {
+        events_to_migrate.emplace_back(
+            feature_engagement::events::
+                kNonModalDefaultBrowserPromoUrlPasteTrigger,
+            DaysSinceTime(base::Time::FromNSDate(last_interaction)));
+      }
+    }
+    LogNonModalPromoMigrationDone();
+  }
+
   base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
       FROM_HERE,
       base::BindOnce(std::move(callback), std::move(events_to_migrate)));
diff --git a/chrome/browser/default_browser/model/default_browser_promo_event_exporter_unittest.mm b/chrome/browser/default_browser/model/default_browser_promo_event_exporter_unittest.mm
index aa99259..9754857 100644
--- a/chrome/browser/default_browser/model/default_browser_promo_event_exporter_unittest.mm
+++ b/chrome/browser/default_browser/model/default_browser_promo_event_exporter_unittest.mm
@@ -60,7 +60,7 @@
 
   int GetExportEventsCount() { return export_events_.size(); }
 
-  // Initializes the feature engagement tracker  with the default browser
+  // Initializes the feature engagement tracker with the default browser
   // exporter and set basic common conditions for default browser promos.
   void InitTrackerAndSetBasicConditions() {
     // Initialize tracker with the default browser exporter.
@@ -354,3 +354,84 @@
   EXPECT_FALSE(tracker_->WouldTriggerHelpUI(
       feature_engagement::kIPHiOSPromoAllTabsFeature));
 }
+
+// Checks that the event exporter migrates the events.
+TEST_F(DefaultBrowserEventExporterTest, TestNonModalPromoEventsMigration) {
+  // No events to export.
+  RequestExportEventsAndVerifyCallback();
+  EXPECT_EQ(GetExportEventsCount(), 0);
+
+  ClearDefaultBrowserPromoData();
+
+  // Check when there is only 1 event.
+  LogUserInteractionWithNonModalPromo(0);
+  RequestExportEventsAndVerifyCallback();
+  EXPECT_EQ(GetExportEventsCount(), 1);
+  // Check that exporting second time will not have any events.
+  RequestExportEventsAndVerifyCallback();
+  EXPECT_EQ(GetExportEventsCount(), 0);
+
+  // Check when there is only 2 event.
+  ClearDefaultBrowserPromoData();
+  LogUserInteractionWithNonModalPromo(2);
+  RequestExportEventsAndVerifyCallback();
+  EXPECT_EQ(GetExportEventsCount(), 3);
+  // Check that exporting second time will not have any events.
+  RequestExportEventsAndVerifyCallback();
+  EXPECT_EQ(GetExportEventsCount(), 0);
+}
+
+// Checks that none of the promos trigger when there are no events exported.
+TEST_F(DefaultBrowserEventExporterTest, TestNonModalMigrationNoEvents) {
+  LogUserInteractionWithNonModalPromo(1);
+
+  // Initialize tracker.
+  InitTrackerAndSetBasicConditions();
+
+  // None of the promos should trigger.
+  EXPECT_FALSE(tracker_->WouldTriggerHelpUI(
+      feature_engagement::kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature));
+}
+
+// Checks that after migration, the promo can be triggered if the last
+// interaction isn't in cooldown and the interaction count is less than 10.
+TEST_F(DefaultBrowserEventExporterTest, TestNonModalMigrationConditionsMet) {
+  SimulateUserInteractionWithNonModalPromo(kMoreThan30Days,
+                                           /*interaction_count=*/1);
+
+  // Initialize tracker.
+  InitTrackerAndSetBasicConditions();
+
+  EXPECT_TRUE(tracker_->WouldTriggerHelpUI(
+      feature_engagement::kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature));
+}
+
+// Checks that after migration, the promo cannot be triggered if the last
+// interaction is in cooldown and the interaction count is less than 10.
+TEST_F(DefaultBrowserEventExporterTest,
+       TestNonModalMigrationCooldownConditionsNotMet) {
+  // Write to user defaults before creating the tracker.
+  SimulateUserInteractionWithNonModalPromo(kMoreThan3Day,
+                                           /*interaction_count=*/1);
+
+  // Initialize tracker.
+  InitTrackerAndSetBasicConditions();
+
+  EXPECT_FALSE(tracker_->WouldTriggerHelpUI(
+      feature_engagement::kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature));
+}
+
+// Checks that after migration, the promo cannot be triggered if the last
+// interaction is not in cooldown but the interaction count is more than 10.
+TEST_F(DefaultBrowserEventExporterTest,
+       TestNonModalMigrationInteractionConditionNotMet) {
+  // Write to user defaults before creating the tracker.
+  SimulateUserInteractionWithNonModalPromo(kMoreThan3Day,
+                                           /*interaction_count=*/10);
+
+  // Initialize tracker.
+  InitTrackerAndSetBasicConditions();
+
+  EXPECT_FALSE(tracker_->WouldTriggerHelpUI(
+      feature_engagement::kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature));
+}
diff --git a/chrome/browser/default_browser/model/utils.h b/chrome/browser/default_browser/model/utils.h
index 1edb71b..5b0b5af 100644
--- a/chrome/browser/default_browser/model/utils.h
+++ b/chrome/browser/default_browser/model/utils.h
@@ -68,6 +68,10 @@
 // interacted with a non-modal promo.
 extern NSString* const kLastTimeUserInteractedWithNonModalPromo;
 
+// Key in storage containing an int indicating the number of times the
+// user has interacted with a non-modal promo.
+extern NSString* const kUserInteractedWithNonModalPromoCount;
+
 // Key in storage containing an NSDate indicating the last time a user
 // interacted with ANY full screen promo. The string value is kept from when the
 // promos first launched to avoid changing the behavior for users that have
@@ -352,7 +356,7 @@
 // Log to UserDefaults FRE timestamp migration is done.
 void LogFRETimestampMigrationDone();
 
-// Returns whether FRE timestamp migratin is done.
+// Returns whether FRE timestamp migrating is done.
 BOOL FRETimestampMigrationDone();
 
 // Log to UserDefaults promo interest event migration is done.
@@ -371,6 +375,15 @@
 // presented.
 void RecordDefaultBrowserPromoLastAction(IOSDefaultBrowserPromoAction action);
 
+// Log to UserDefaults non-modal promo migration done.
+void LogNonModalPromoMigrationDone();
+
+// Returns whether the non-modal promo migration is done.
+bool IsNonModalPromoMigrationDone();
+
+// Gets the date when the user last interacted with the non-modal promo.
+NSDate* LastTimeUserInteractedWithNonModalPromo();
+
 // Returns the last action, if any, that the user took when a Default Browser
 // Promo was presented.
 std::optional<IOSDefaultBrowserPromoAction> DefaultBrowserPromoLastAction();
diff --git a/chrome/browser/default_browser/model/utils.mm b/chrome/browser/default_browser/model/utils.mm
index 560b7ea..86b9d6c 100644
--- a/chrome/browser/default_browser/model/utils.mm
+++ b/chrome/browser/default_browser/model/utils.mm
@@ -44,11 +44,6 @@
 NSString* const kLastSignificantUserEventAllTabs =
     @"lastSignificantUserEventAllTabs";
 
-// Key in storage containing an int indicating the number of times the
-// user has interacted with a non-modal promo.
-NSString* const kUserInteractedWithNonModalPromoCount =
-    @"userInteractedWithNonModalPromoCount";
-
 // Action string for "Appear" event of the promo.
 const char kAppearAction[] = "Appear";
 
@@ -360,6 +355,8 @@
 NSString* const kLastHTTPURLOpenTime = @"lastHTTPURLOpenTime";
 NSString* const kLastTimeUserInteractedWithNonModalPromo =
     @"lastTimeUserInteractedWithNonModalPromo";
+NSString* const kUserInteractedWithNonModalPromoCount =
+    @"userInteractedWithNonModalPromoCount";
 NSString* const kLastTimeUserInteractedWithFullscreenPromo =
     @"lastTimeUserInteractedWithFullscreenPromo";
 NSString* const kAllTimestampsAppLaunchColdStart =
@@ -396,6 +393,7 @@
     @"promo_impressions_migration_done";
 NSString* const kTimestampTriggerCriteriaExperimentStarted =
     @"TimestampTriggerCriteriaExperimentStarted";
+NSString* const kNonModalPromoMigrationDone = @"kNonModalPromoMigrationDone";
 
 std::vector<base::Time> LoadTimestampsForPromoType(DefaultPromoType type) {
   return LoadActiveTimestampsForKey(StorageKeyForDefaultPromoType(type),
@@ -996,6 +994,18 @@
   return number.boolValue;
 }
 
+void LogNonModalPromoMigrationDone() {
+  NSDictionary<NSString*, NSObject*>* update =
+      @{kNonModalPromoMigrationDone : @YES};
+  UpdateStorageWithDictionary(update);
+}
+
+bool IsNonModalPromoMigrationDone() {
+  NSNumber* number =
+      GetObjectFromStorageForKey<NSNumber>(kNonModalPromoMigrationDone);
+  return number.boolValue;
+}
+
 void RecordDefaultBrowserPromoLastAction(IOSDefaultBrowserPromoAction action) {
   GetApplicationContext()->GetLocalState()->SetInteger(
       prefs::kIosDefaultBrowserPromoLastAction, static_cast<int>(action));
@@ -1011,3 +1021,8 @@
   int last_action_int = last_action->GetValue()->GetInt();
   return static_cast<IOSDefaultBrowserPromoAction>(last_action_int);
 }
+
+NSDate* LastTimeUserInteractedWithNonModalPromo() {
+  return GetObjectFromStorageForKey<NSDate>(
+      kLastTimeUserInteractedWithNonModalPromo);
+}
diff --git a/chrome/browser/default_browser/model/utils_test_support.h b/chrome/browser/default_browser/model/utils_test_support.h
index 4a5d547..8b38865 100644
--- a/chrome/browser/default_browser/model/utils_test_support.h
+++ b/chrome/browser/default_browser/model/utils_test_support.h
@@ -33,4 +33,8 @@
     DefaultPromoType type,
     const base::TimeDelta& timeAgo);
 
+// Overwrite local storage for non-modal promo interaction.
+void SimulateUserInteractionWithNonModalPromo(base::TimeDelta time_ago,
+                                              int interaction_count);
+
 #endif  // IOS_CHROME_BROWSER_DEFAULT_BROWSER_MODEL_UTILS_TEST_SUPPORT_H_
diff --git a/chrome/browser/default_browser/model/utils_test_support.mm b/chrome/browser/default_browser/model/utils_test_support.mm
index d7f325c..7bdd853 100644
--- a/chrome/browser/default_browser/model/utils_test_support.mm
+++ b/chrome/browser/default_browser/model/utils_test_support.mm
@@ -57,3 +57,14 @@
 
   StoreTimestampsForPromoType(type, std::move(times));
 }
+
+void SimulateUserInteractionWithNonModalPromo(base::TimeDelta time_ago,
+                                              int interaction_count) {
+  NSDictionary<NSString*, NSObject*>* values = @{
+    kLastTimeUserInteractedWithNonModalPromo : (base::Time::Now() - time_ago)
+        .ToNSDate(),
+    kUserInteractedWithNonModalPromoCount :
+        [NSNumber numberWithInt:interaction_count]
+  };
+  SetValuesInStorage(values);
+}
diff --git a/chrome/browser/default_promo/ui_bundled/BUILD.gn b/chrome/browser/default_promo/ui_bundled/BUILD.gn
index 61058b4..4396d71 100644
--- a/chrome/browser/default_promo/ui_bundled/BUILD.gn
+++ b/chrome/browser/default_promo/ui_bundled/BUILD.gn
@@ -50,7 +50,9 @@
     ":coordinator",
     "//base",
     "//components/feature_engagement/public",
+    "//components/feature_engagement/public:feature_constants",
     "//ios/chrome/app/strings",
+    "//ios/chrome/browser/default_browser/model:features",
     "//ios/chrome/browser/default_browser/model:utils",
     "//ios/chrome/browser/feature_engagement/model",
     "//ios/chrome/browser/infobars/ui_bundled/banners",
@@ -114,6 +116,7 @@
     "//ios/chrome/browser/signin/model:fake_system_identity",
     "//ios/chrome/test:eg_test_support+eg2",
     "//ios/chrome/test/earl_grey:eg_test_support+eg2",
+    "//ios/chrome/test/earl_grey:switches",
     "//ios/testing/earl_grey:eg_test_support+eg2",
     "//net:test_support",
     "//ui/base",
diff --git a/chrome/browser/default_promo/ui_bundled/DEPS b/chrome/browser/default_promo/ui_bundled/DEPS
index 92390be..145a9b6 100644
--- a/chrome/browser/default_promo/ui_bundled/DEPS
+++ b/chrome/browser/default_promo/ui_bundled/DEPS
@@ -1,8 +1,7 @@
 include_rules = [
-  "+ios/chrome/browser/default_browser/model/promo_statistics.h",
-  "+ios/chrome/browser/default_browser/model/utils.h",
   "+ios/chrome/browser/feature_engagement/model/tracker_factory.h",
   "+ios/chrome/browser/promos_manager/model",
   "+ios/chrome/browser/infobars/ui_bundled",
   "+ios/chrome/browser/promos_manager/ui_bundled",
+  "+ios/chrome/browser/default_browser/model",
 ]
diff --git a/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_coordinator.mm b/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_coordinator.mm
index e495216..6f4b18d 100644
--- a/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_coordinator.mm
+++ b/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_coordinator.mm
@@ -5,7 +5,9 @@
 #import "ios/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_coordinator.h"
 
 #import "base/notreached.h"
+#import "components/feature_engagement/public/feature_constants.h"
 #import "components/feature_engagement/public/tracker.h"
+#import "ios/chrome/browser/default_browser/model/features.h"
 #import "ios/chrome/browser/default_browser/model/utils.h"
 #import "ios/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_commands.h"
 #import "ios/chrome/browser/feature_engagement/model/tracker_factory.h"
@@ -125,6 +127,15 @@
 
 - (void)infobarWasDismissed {
   self.bannerViewController = nil;
+
+  if (IsNonModalPromoMigrationEnabled()) {
+    feature_engagement::Tracker* tracker =
+        feature_engagement::TrackerFactory::GetForProfile(
+            self.browser->GetProfile());
+    tracker->Dismissed(
+        feature_engagement::kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature);
+  }
+
   id<DefaultBrowserPromoNonModalCommands> handler =
       HandlerForProtocol(self.browser->GetCommandDispatcher(),
                          DefaultBrowserPromoNonModalCommands);
diff --git a/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_egtest.mm b/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_egtest.mm
index 4d055b6..897aa26 100644
--- a/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_egtest.mm
+++ b/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_egtest.mm
@@ -5,6 +5,7 @@
 #import "base/functional/bind.h"
 #import "base/ios/ios_util.h"
 #import "base/test/ios/wait_util.h"
+#import "components/feature_engagement/public/feature_constants.h"
 #import "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/infobars/ui_bundled/banners/infobar_banner_constants.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
@@ -13,6 +14,7 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
+#import "ios/chrome/test/earl_grey/test_switches.h"
 #import "ios/testing/earl_grey/app_launch_manager.h"
 #import "ios/testing/earl_grey/earl_grey_test.h"
 #import "net/test/embedded_test_server/embedded_test_server.h"
@@ -46,6 +48,14 @@
 
 - (void)setUp {
   [super setUp];
+
+  AppLaunchConfiguration config;
+  config.relaunch_policy = ForceRelaunchByCleanShutdown;
+  config.additional_args.push_back(
+      std::string("-") + test_switches::kEnableIPH +
+      "=IPH_iOSPromoNonModalUrlPasteDefaultBrowser");
+  [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config];
+
   GREYAssertTrue(self.testServer->Start(), @"Server did not start.");
   [ChromeEarlGrey clearDefaultBrowserPromoData];
 }
diff --git a/chrome/browser/shared/coordinator/DEPS b/chrome/browser/shared/coordinator/DEPS
index ef3a265..71316ff 100644
--- a/chrome/browser/shared/coordinator/DEPS
+++ b/chrome/browser/shared/coordinator/DEPS
@@ -2,6 +2,7 @@
   # TODO(crbug.com/40259387): Remove this include once the folders have been
   # moved.
   "+ios/chrome/browser/ui",
+  "+ios/chrome/browser/feature_engagement/model/tracker_factory.h",
 
   # Use ios/chrome/browser/authentication/ui_bundled/signin_earl_grey.h instead
   "-ios/chrome/browser/authentication/ui_bundled/signin_earl_grey_app_interface.h",
diff --git a/chrome/browser/shared/coordinator/default_browser_promo/BUILD.gn b/chrome/browser/shared/coordinator/default_browser_promo/BUILD.gn
index 2f96ff0..e7dd7b1 100644
--- a/chrome/browser/shared/coordinator/default_browser_promo/BUILD.gn
+++ b/chrome/browser/shared/coordinator/default_browser_promo/BUILD.gn
@@ -9,13 +9,18 @@
   ]
   deps = [
     "//base",
+    "//components/feature_engagement/public",
+    "//components/feature_engagement/public:feature_constants",
+    "//ios/chrome/browser/default_browser/model:features",
     "//ios/chrome/browser/default_browser/model:utils",
     "//ios/chrome/browser/default_promo/ui_bundled:coordinator",
+    "//ios/chrome/browser/feature_engagement/model",
     "//ios/chrome/browser/overlays/model",
     "//ios/chrome/browser/shared/coordinator/scene:observing_scene_agent",
     "//ios/chrome/browser/shared/coordinator/scene:scene_state_header",
     "//ios/chrome/browser/shared/coordinator/scene:scene_state_observer",
     "//ios/chrome/browser/shared/model/browser",
+    "//ios/chrome/browser/shared/model/profile",
     "//ios/chrome/browser/shared/model/web_state_list",
     "//ios/chrome/browser/shared/public/commands",
     "//ios/chrome/browser/shared/public/features",
@@ -31,12 +36,17 @@
     ":default_browser_promo",
     "//base",
     "//base/test:test_support",
+    "//components/feature_engagement/public",
+    "//components/feature_engagement/public:feature_constants",
+    "//components/feature_engagement/test:test_support",
     "//ios/chrome/app:app_internal",
     "//ios/chrome/app/application_delegate:app_state",
     "//ios/chrome/app/application_delegate:test_support",
+    "//ios/chrome/browser/default_browser/model:event_exporter",
     "//ios/chrome/browser/default_browser/model:test_support",
     "//ios/chrome/browser/default_browser/model:utils",
     "//ios/chrome/browser/default_promo/ui_bundled:coordinator",
+    "//ios/chrome/browser/feature_engagement/model",
     "//ios/chrome/browser/infobars/model",
     "//ios/chrome/browser/infobars/model/test",
     "//ios/chrome/browser/overlays/model",
diff --git a/chrome/browser/shared/coordinator/default_browser_promo/non_modal_default_browser_promo_scheduler_scene_agent.mm b/chrome/browser/shared/coordinator/default_browser_promo/non_modal_default_browser_promo_scheduler_scene_agent.mm
index 51874d6..3289b3d 100644
--- a/chrome/browser/shared/coordinator/default_browser_promo/non_modal_default_browser_promo_scheduler_scene_agent.mm
+++ b/chrome/browser/shared/coordinator/default_browser_promo/non_modal_default_browser_promo_scheduler_scene_agent.mm
@@ -6,15 +6,21 @@
 
 #import "base/notreached.h"
 #import "base/timer/timer.h"
+#import "components/feature_engagement/public/event_constants.h"
+#import "components/feature_engagement/public/feature_constants.h"
+#import "components/feature_engagement/public/tracker.h"
+#import "ios/chrome/browser/default_browser/model/features.h"
 #import "ios/chrome/browser/default_browser/model/utils.h"
 #import "ios/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_commands.h"
 #import "ios/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_metrics_util.h"
+#import "ios/chrome/browser/feature_engagement/model/tracker_factory.h"
 #import "ios/chrome/browser/overlays/model/public/overlay_presenter.h"
 #import "ios/chrome/browser/overlays/model/public/overlay_presenter_observer_bridge.h"
 #import "ios/chrome/browser/shared/coordinator/scene/scene_state.h"
 #import "ios/chrome/browser/shared/model/browser/browser_observer_bridge.h"
 #import "ios/chrome/browser/shared/model/browser/browser_provider.h"
 #import "ios/chrome/browser/shared/model/browser/browser_provider_interface.h"
+#import "ios/chrome/browser/shared/model/profile/profile_ios.h"
 #import "ios/chrome/browser/shared/model/web_state_list/active_web_state_observation_forwarder.h"
 #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
 #import "ios/chrome/browser/shared/model/web_state_list/web_state_list_observer_bridge.h"
@@ -105,6 +111,9 @@
 // The trigger reason for the in-progress promo flow.
 @property(nonatomic, assign) PromoReason currentPromoReason;
 
+// The tracker for feature engagement.
+@property(nonatomic, readonly) feature_engagement::Tracker* tracker;
+
 // The browser that this scheduler uses to listen to events, such as page loads
 // and overlay events
 @property(nonatomic, assign) Browser* browser;
@@ -215,6 +224,11 @@
     return false;
   }
 
+  if (IsNonModalPromoMigrationEnabled()) {
+    return self.tracker->WouldTriggerHelpUI(
+        feature_engagement::kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature);
+  }
+
   if (UserInNonModalPromoCooldown()) {
     return false;
   }
@@ -230,6 +244,11 @@
   _userInteractionWithNonModalPromoCount =
       UserInteractionWithNonModalPromoCount();
 
+  if (!IsNonModalPromoMigrationEnabled() && IsNonModalPromoMigrationDone()) {
+    self.tracker->NotifyEvent(feature_engagement::events::
+                                  kNonModalDefaultBrowserPromoUrlPasteTrigger);
+  }
+
   [_handler showDefaultBrowserNonModalPromo];
 }
 
@@ -242,7 +261,7 @@
   if (currentPromoReason != PromoReasonNone && !promoIsShowing) {
     LogNonModalPromoAction(NonModalPromoAction::kBackgroundCancel,
                            MetricTypeForPromoReason(currentPromoReason),
-                           _userInteractionWithNonModalPromoCount);
+                           [self nonModalPromoInteractionCount]);
   }
   [self cancelShowPromoTimer];
   [self dismissPromoAnimated:NO];
@@ -251,7 +270,7 @@
 - (void)logPromoAppear:(PromoReason)currentPromoReason {
   LogNonModalPromoAction(NonModalPromoAction::kAppear,
                          MetricTypeForPromoReason(currentPromoReason),
-                         _userInteractionWithNonModalPromoCount);
+                         [self nonModalPromoInteractionCount]);
 }
 
 - (void)logPromoAction:(PromoReason)currentPromoReason
@@ -260,7 +279,7 @@
       IOSDefaultBrowserPromoAction::kActionButton);
   LogNonModalPromoAction(NonModalPromoAction::kAccepted,
                          MetricTypeForPromoReason(currentPromoReason),
-                         _userInteractionWithNonModalPromoCount);
+                         [self nonModalPromoInteractionCount]);
   LogNonModalTimeOnScreen(promoShownTime);
   LogUserInteractionWithNonModalPromo(_userInteractionWithNonModalPromoCount);
 
@@ -275,7 +294,7 @@
   RecordDefaultBrowserPromoLastAction(IOSDefaultBrowserPromoAction::kDismiss);
   LogNonModalPromoAction(NonModalPromoAction::kDismiss,
                          MetricTypeForPromoReason(currentPromoReason),
-                         _userInteractionWithNonModalPromoCount);
+                         [self nonModalPromoInteractionCount]);
   LogNonModalTimeOnScreen(promoShownTime);
   LogUserInteractionWithNonModalPromo(_userInteractionWithNonModalPromoCount);
 }
@@ -284,7 +303,7 @@
          promoShownTime:(base::TimeTicks)promoShownTime {
   LogNonModalPromoAction(NonModalPromoAction::kTimeout,
                          MetricTypeForPromoReason(currentPromoReason),
-                         _userInteractionWithNonModalPromoCount);
+                         [self nonModalPromoInteractionCount]);
   LogNonModalTimeOnScreen(promoShownTime);
   LogUserInteractionWithNonModalPromo(_userInteractionWithNonModalPromoCount);
 }
@@ -335,6 +354,12 @@
   }
 }
 
+- (feature_engagement::Tracker*)tracker {
+  CHECK(_browser);
+  return feature_engagement::TrackerFactory::GetForProfile(
+      _browser->GetProfile());
+}
+
 #pragma mark - WebStateListObserving
 
 - (void)didChangeWebStateList:(WebStateList*)webStateList
@@ -489,6 +514,14 @@
   if (![self promoCanBeDisplayed] || self.promoIsShowing) {
     return;
   }
+
+  if (IsNonModalPromoMigrationEnabled() &&
+      !self.tracker->ShouldTriggerHelpUI(
+          feature_engagement::
+              kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)) {
+    return;
+  }
+
   _showPromoTimer = nullptr;
   [self notifyHandlerShowPromo];
   self.promoIsShowing = YES;
@@ -522,4 +555,24 @@
   }
 }
 
+- (int)nonModalPromoInteractionCount {
+  if (!IsNonModalPromoMigrationEnabled()) {
+    return _userInteractionWithNonModalPromoCount;
+  }
+
+  unsigned int interactions = 0;
+  std::vector<std::pair<feature_engagement::EventConfig, int>> events =
+      self.tracker->ListEvents(
+          feature_engagement::
+              kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature);
+  for (const auto& event : events) {
+    if (event.first.name == feature_engagement::events::
+                                kNonModalDefaultBrowserPromoUrlPasteTrigger) {
+      interactions = event.second;
+      break;
+    }
+  }
+  return interactions;
+}
+
 @end
diff --git a/chrome/browser/shared/coordinator/default_browser_promo/non_modal_default_browser_promo_scheduler_scene_agent_unittest.mm b/chrome/browser/shared/coordinator/default_browser_promo/non_modal_default_browser_promo_scheduler_scene_agent_unittest.mm
index 29a4486..07943cb 100644
--- a/chrome/browser/shared/coordinator/default_browser_promo/non_modal_default_browser_promo_scheduler_scene_agent_unittest.mm
+++ b/chrome/browser/shared/coordinator/default_browser_promo/non_modal_default_browser_promo_scheduler_scene_agent_unittest.mm
@@ -10,12 +10,18 @@
 #import "base/test/scoped_feature_list.h"
 #import "base/test/task_environment.h"
 #import "base/time/time.h"
+#import "components/feature_engagement/public/event_constants.h"
+#import "components/feature_engagement/public/feature_constants.h"
+#import "components/feature_engagement/test/mock_tracker.h"
+#import "components/feature_engagement/test/test_tracker.h"
 #import "ios/chrome/app/application_delegate/app_state.h"
 #import "ios/chrome/app/application_delegate/fake_startup_information.h"
+#import "ios/chrome/browser/default_browser/model/default_browser_promo_event_exporter.h"
 #import "ios/chrome/browser/default_browser/model/utils.h"
 #import "ios/chrome/browser/default_browser/model/utils_test_support.h"
 #import "ios/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_commands.h"
 #import "ios/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_metrics_util.h"
+#import "ios/chrome/browser/feature_engagement/model/tracker_factory.h"
 #import "ios/chrome/browser/infobars/model/infobar_ios.h"
 #import "ios/chrome/browser/infobars/model/infobar_manager_impl.h"
 #import "ios/chrome/browser/infobars/model/test/fake_infobar_ios.h"
@@ -45,20 +51,31 @@
 
 namespace {
 
+std::unique_ptr<KeyedService> BuildFeatureEngagementMockTracker(
+    web::BrowserState* context) {
+  return std::make_unique<feature_engagement::test::MockTracker>();
+}
+
 class NonModalDefaultBrowserPromoSchedulerSceneAgentTest : public PlatformTest {
  protected:
   NonModalDefaultBrowserPromoSchedulerSceneAgentTest() {}
 
   void SetUp() override {
     TestProfileIOS::Builder builder;
-    std::unique_ptr<TestProfileIOS> profile = std::move(builder).Build();
+    builder.AddTestingFactory(
+        feature_engagement::TrackerFactory::GetInstance(),
+        base::BindRepeating(&BuildFeatureEngagementMockTracker));
+    profile_ = std::move(builder).Build();
+
+    mock_tracker_ = static_cast<feature_engagement::test::MockTracker*>(
+        feature_engagement::TrackerFactory::GetForProfile(profile_.get()));
 
     FakeStartupInformation* startup_information =
         [[FakeStartupInformation alloc] init];
     app_state_ =
         [[AppState alloc] initWithStartupInformation:startup_information];
     scene_state_ = [[FakeSceneState alloc] initWithAppState:app_state_
-                                                    profile:profile.get()];
+                                                    profile:profile_.get()];
     scene_state_.scene = static_cast<UIWindowScene*>(
         [[[UIApplication sharedApplication] connectedScenes] anyObject]);
 
@@ -107,16 +124,23 @@
         ->SetPresentationContext(nullptr);
   }
 
+  base::RepeatingCallback<void(bool)> BoolArgumentQuitClosure() {
+    return base::IgnoreArgs<bool>(run_loop_.QuitClosure());
+  }
+
   base::test::TaskEnvironment task_env_{
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
   base::test::ScopedFeatureList feature_list_;
   IOSChromeScopedTestingLocalState scoped_testing_local_state_;
+  std::unique_ptr<TestProfileIOS> profile_;
   raw_ptr<web::FakeWebState> test_web_state_;
   raw_ptr<Browser> browser_;
+  raw_ptr<feature_engagement::test::MockTracker> mock_tracker_;
   FakeOverlayPresentationContext overlay_presentation_context_;
   id promo_commands_handler_;
   NonModalDefaultBrowserPromoSchedulerSceneAgent* scheduler_;
   id application_ = nil;
+  base::RunLoop run_loop_;
   AppState* app_state_;
   FakeSceneState* scene_state_;
 };
@@ -124,6 +148,18 @@
 // Tests that the omnibox paste event triggers the promo to show.
 TEST_F(NonModalDefaultBrowserPromoSchedulerSceneAgentTest,
        TestOmniboxPasteShowsPromo) {
+  // Mock the FET tracker.
+  EXPECT_CALL(*mock_tracker_,
+              WouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(*mock_tracker_,
+              ShouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+
   [scheduler_ logUserPastedInOmnibox];
 
   // Finish loading the page.
@@ -147,6 +183,18 @@
 // promo.
 TEST_F(NonModalDefaultBrowserPromoSchedulerSceneAgentTest,
        TestFirstPartySchemeShowsPromo) {
+  // Mock the FET tracker.
+  EXPECT_CALL(*mock_tracker_,
+              WouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(*mock_tracker_,
+              ShouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+
   [scheduler_ logUserEnteredAppViaFirstPartyScheme];
 
   // Finish loading the page.
@@ -169,6 +217,18 @@
 // Tests that the completed share event triggers the promo.
 TEST_F(NonModalDefaultBrowserPromoSchedulerSceneAgentTest,
        TestShareCompletedShowsPromo) {
+  // Mock the FET tracker.
+  EXPECT_CALL(*mock_tracker_,
+              WouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(*mock_tracker_,
+              ShouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+
   [scheduler_ logUserFinishedActivityFlow];
 
   // Finish loading the page.
@@ -187,6 +247,18 @@
 // the event is stored.
 TEST_F(NonModalDefaultBrowserPromoSchedulerSceneAgentTest,
        TestTimeoutDismissesPromo) {
+  // Mock the FET tracker.
+  EXPECT_CALL(*mock_tracker_,
+              WouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(*mock_tracker_,
+              ShouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+
   [scheduler_ logUserPastedInOmnibox];
 
   // Finish loading the page.
@@ -214,6 +286,18 @@
 // Tests that if the user takes the promo action, that is handled correctly.
 TEST_F(NonModalDefaultBrowserPromoSchedulerSceneAgentTest,
        TestActionDismissesPromo) {
+  // Mock the FET tracker.
+  EXPECT_CALL(*mock_tracker_,
+              WouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(*mock_tracker_,
+              ShouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+
   [scheduler_ logUserPastedInOmnibox];
 
   // Finish loading the page.
@@ -237,12 +321,45 @@
 
   // Check that NSUserDefaults has been updated.
   EXPECT_EQ(UserInteractionWithNonModalPromoCount(), 1);
+
+  // Check that the FET has been updated.
+  std::unique_ptr<feature_engagement::Tracker> tracker =
+      feature_engagement::CreateTestTracker(
+          std::make_unique<DefaultBrowserEventExporter>());
+  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
+  run_loop_.Run();
+  unsigned int interactions = 0;
+  std::vector<std::pair<feature_engagement::EventConfig, int>> events =
+      tracker->ListEvents(
+          feature_engagement::
+              kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature);
+  for (const auto& event : events) {
+    if (event.first.name == feature_engagement::events::
+                                kNonModalDefaultBrowserPromoUrlPasteTrigger) {
+      interactions = event.second;
+      break;
+    }
+  }
+
+  EXPECT_EQ((int)interactions, 1);
 }
 
 // Tests that if the user manages to trigger multiple interactions, the
 // interactions count is only incremented once.
 TEST_F(NonModalDefaultBrowserPromoSchedulerSceneAgentTest,
        TestMultipleInteractionsOnlyIncrementsCountOnce) {
+  // Mock the FET tracker.
+  EXPECT_CALL(*mock_tracker_,
+              WouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(*mock_tracker_,
+              ShouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+
   [scheduler_ logUserPastedInOmnibox];
 
   // Finish loading the page.
@@ -263,12 +380,44 @@
 
   // Check that NSUserDefaults has been updated, incremented only by 1.
   EXPECT_EQ(UserInteractionWithNonModalPromoCount(), 1);
+
+  // Check that the FET has been updated.
+  std::unique_ptr<feature_engagement::Tracker> tracker =
+      feature_engagement::CreateTestTracker(
+          std::make_unique<DefaultBrowserEventExporter>());
+  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
+  run_loop_.Run();
+  unsigned int interactions = 0;
+  std::vector<std::pair<feature_engagement::EventConfig, int>> events =
+      tracker->ListEvents(
+          feature_engagement::
+              kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature);
+  for (const auto& event : events) {
+    if (event.first.name == feature_engagement::events::
+                                kNonModalDefaultBrowserPromoUrlPasteTrigger) {
+      interactions = event.second;
+      break;
+    }
+  }
+
+  EXPECT_EQ((int)interactions, 1);
 }
 
 // Tests that if the user switches to a different tab before the post-load timer
 // finishes, the promo does not show.
 TEST_F(NonModalDefaultBrowserPromoSchedulerSceneAgentTest,
        TestTabSwitchPreventsPromoShown) {
+  // Mock the FET tracker.
+  EXPECT_CALL(*mock_tracker_,
+              WouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(*mock_tracker_,
+              ShouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
   [scheduler_ logUserPastedInOmnibox];
 
   // Finish loading the page.
@@ -290,6 +439,17 @@
 // Tests that if a message is triggered on page load, the promo is not shown.
 TEST_F(NonModalDefaultBrowserPromoSchedulerSceneAgentTest,
        TestMessagePreventsPromoShown) {
+  // Mock the FET tracker.
+  EXPECT_CALL(*mock_tracker_,
+              WouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(*mock_tracker_,
+              ShouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
   [scheduler_ logUserPastedInOmnibox];
 
   // Finish loading the page.
@@ -325,6 +485,18 @@
 // does not update the shown promo count.
 TEST_F(NonModalDefaultBrowserPromoSchedulerSceneAgentTest,
        TestBackgroundingDismissesPromo) {
+  // Mock the FET tracker.
+  EXPECT_CALL(*mock_tracker_,
+              WouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(*mock_tracker_,
+              ShouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+
   [scheduler_ logUserPastedInOmnibox];
 
   // Finish loading the page.
@@ -347,12 +519,45 @@
 
   // Check that NSUserDefaults has not been updated.
   EXPECT_EQ(UserInteractionWithNonModalPromoCount(), 0);
+
+  // Check that the FET has been updated.
+  std::unique_ptr<feature_engagement::Tracker> tracker =
+      feature_engagement::CreateTestTracker(
+          std::make_unique<DefaultBrowserEventExporter>());
+  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
+  run_loop_.Run();
+  unsigned int interactions = 0;
+  std::vector<std::pair<feature_engagement::EventConfig, int>> events =
+      tracker->ListEvents(
+          feature_engagement::
+              kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature);
+  for (const auto& event : events) {
+    if (event.first.name == feature_engagement::events::
+                                kNonModalDefaultBrowserPromoUrlPasteTrigger) {
+      interactions = event.second;
+      break;
+    }
+  }
+
+  EXPECT_EQ((int)interactions, 0);
 }
 
 // Tests that entering the tab grid with the promo showing hides the promo but
 // does not update the shown promo count.
 TEST_F(NonModalDefaultBrowserPromoSchedulerSceneAgentTest,
        TestTabGridDismissesPromo) {
+  // Mock the FET tracker.
+  EXPECT_CALL(*mock_tracker_,
+              WouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(*mock_tracker_,
+              ShouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+
   [scheduler_ logUserPastedInOmnibox];
 
   // Finish loading the page.
@@ -374,11 +579,44 @@
 
   // Check that NSUserDefaults has not been updated.
   EXPECT_EQ(UserInteractionWithNonModalPromoCount(), 0);
+
+  // Check that the FET has been updated.
+  std::unique_ptr<feature_engagement::Tracker> tracker =
+      feature_engagement::CreateTestTracker(
+          std::make_unique<DefaultBrowserEventExporter>());
+  tracker->AddOnInitializedCallback(BoolArgumentQuitClosure());
+  run_loop_.Run();
+  unsigned int interactions = 0;
+  std::vector<std::pair<feature_engagement::EventConfig, int>> events =
+      tracker->ListEvents(
+          feature_engagement::
+              kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature);
+  for (const auto& event : events) {
+    if (event.first.name == feature_engagement::events::
+                                kNonModalDefaultBrowserPromoUrlPasteTrigger) {
+      interactions = event.second;
+      break;
+    }
+  }
+
+  EXPECT_EQ((int)interactions, 0);
 }
 
 // Tests background cancel metric logs correctly.
 TEST_F(NonModalDefaultBrowserPromoSchedulerSceneAgentTest,
        TestBackgroundCancelMetric) {
+  // Mock the FET tracker.
+  EXPECT_CALL(*mock_tracker_,
+              WouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(*mock_tracker_,
+              ShouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+
   base::HistogramTester histogram_tester;
   histogram_tester.ExpectUniqueSample(
       "IOS.DefaultBrowserPromo.NonModal.VisitPastedLink",
@@ -400,6 +638,18 @@
 // Tests background cancel metric is not logged after a promo is shown.
 TEST_F(NonModalDefaultBrowserPromoSchedulerSceneAgentTest,
        TestBackgroundCancelMetricNotLogAfterPromoShown) {
+  // Mock the FET tracker.
+  EXPECT_CALL(*mock_tracker_,
+              WouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(*mock_tracker_,
+              ShouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+
   base::HistogramTester histogram_tester;
   histogram_tester.ExpectUniqueSample(
       "IOS.DefaultBrowserPromo.NonModal.VisitPastedLink",
@@ -431,6 +681,18 @@
 // Tests background cancel metric is not logged after a promo is dismissed.
 TEST_F(NonModalDefaultBrowserPromoSchedulerSceneAgentTest,
        TestBackgroundCancelMetricNotLogAfterPromoDismiss) {
+  // Mock the FET tracker.
+  EXPECT_CALL(*mock_tracker_,
+              WouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(*mock_tracker_,
+              ShouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+
   base::HistogramTester histogram_tester;
   histogram_tester.ExpectUniqueSample(
       "IOS.DefaultBrowserPromo.NonModal.VisitPastedLink",
@@ -477,6 +739,17 @@
   NSUserDefaults* standardDefaults = [NSUserDefaults standardUserDefaults];
   [standardDefaults setObject:[NSDate date]
                        forKey:@"lastTimeUserInteractedWithFullscreenPromo"];
+  // Mock the FET tracker.
+  EXPECT_CALL(*mock_tracker_,
+              WouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(false));
+  EXPECT_CALL(*mock_tracker_,
+              ShouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(false));
 
   [scheduler_ logUserPastedInOmnibox];
 
@@ -525,6 +798,18 @@
 // crbug.com/1224427
 TEST_F(NonModalDefaultBrowserPromoSchedulerSceneAgentTest,
        NoDCHECKIfPromoNotShown) {
+  // Mock the FET tracker.
+  EXPECT_CALL(*mock_tracker_,
+              WouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+  EXPECT_CALL(*mock_tracker_,
+              ShouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(true));
+
   [scheduler_ logUserPastedInOmnibox];
 
   // Switch to a new tab before loading a page. This will prevent the promo from
@@ -556,6 +841,18 @@
     LogUserInteractionWithNonModalPromo(i);
   }
 
+  // Mock the FET tracker.
+  EXPECT_CALL(*mock_tracker_,
+              WouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(false));
+  EXPECT_CALL(*mock_tracker_,
+              ShouldTriggerHelpUI(testing::Ref(
+                  feature_engagement::
+                      kIPHiOSPromoNonModalUrlPasteDefaultBrowserFeature)))
+      .WillRepeatedly(testing::Return(false));
+
   base::HistogramTester histogram_tester;
   [scheduler_ logUserPastedInOmnibox];