chromium/ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_coordinator.mm

// 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.

#import "ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_coordinator.h"

#import "base/metrics/histogram_functions.h"
#import "base/metrics/user_metrics.h"
#import "components/feature_engagement/public/event_constants.h"
#import "components/feature_engagement/public/tracker.h"
#import "components/segmentation_platform/public/segmentation_platform_service.h"
#import "ios/chrome/browser/default_browser/model/utils.h"
#import "ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_commands.h"
#import "ios/chrome/browser/default_promo/ui_bundled/generic/default_browser_generic_promo_view_controller.h"
#import "ios/chrome/browser/feature_engagement/model/tracker_factory.h"
#import "ios/chrome/browser/promos_manager/model/promos_manager.h"
#import "ios/chrome/browser/promos_manager/model/promos_manager_factory.h"
#import "ios/chrome/browser/segmentation_platform/model/segmentation_platform_service_factory.h"
#import "ios/chrome/browser/shared/model/browser/browser.h"
#import "ios/chrome/browser/shared/model/profile/profile_ios.h"
#import "ios/chrome/browser/shared/public/commands/command_dispatcher.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/chrome/browser/ui/promos_manager/promos_manager_ui_handler.h"

using base::RecordAction;
using base::UserMetricsAction;

@interface DefaultBrowserGenericPromoCoordinator () <
    ConfirmationAlertActionHandler,
    UIAdaptivePresentationControllerDelegate>
@end

@implementation DefaultBrowserGenericPromoCoordinator {
  // Main view controller for this coordinator.
  DefaultBrowserGenericPromoViewController* _viewController;
  // Default browser promo command handler.
  id<DefaultBrowserGenericPromoCommands> _defaultBrowserPromoHandler;
  // Feature engagement tracker reference.
  feature_engagement::Tracker* _tracker;
  // Contains all the stats that needs to be recorded for all promo actions.
  PromoStatistics* _promoStats;
  // TODO(crbug.com/357836827): Transparent view to block user interaction
  // while waiting for classification results. This ivar is a temporary
  // solution.
  UIView* _transparentView;
}

#pragma mark - ChromeCoordinator

- (void)start {
  [super start];
  [self recordVideoDefaultBrowserPromoShown];

  ChromeBrowserState* browserState = self.browser->GetBrowserState();
  _tracker =
      feature_engagement::TrackerFactory::GetForBrowserState(browserState);

  if (IsSegmentedDefaultBrowserPromoEnabled()) {
    segmentation_platform::SegmentationPlatformService* segmentationService =
        segmentation_platform::SegmentationPlatformServiceFactory::
            GetForBrowserState(browserState);
    segmentation_platform::DeviceSwitcherResultDispatcher* dispatcher =
        segmentation_platform::SegmentationPlatformServiceFactory::
            GetDispatcherForBrowserState(browserState);

    _mediator = [[DefaultBrowserGenericPromoMediator alloc]
           initWithSegmentationService:segmentationService
        deviceSwitcherResultDispatcher:dispatcher];

    // Present a transparent view to block UI interaction until promo presents.
    _transparentView =
        [[UIView alloc] initWithFrame:self.baseViewController.view.bounds];
    _transparentView.backgroundColor = [UIColor colorWithWhite:0 alpha:0];
    [self.baseViewController.view addSubview:_transparentView];

    __weak __typeof(self) weakSelf = self;
    [_mediator retrieveUserSegmentWithCompletion:^{
      [weakSelf didRetrieveUserSegment];
    }];
  } else {
    _mediator = [[DefaultBrowserGenericPromoMediator alloc] init];
    _viewController = [[DefaultBrowserGenericPromoViewController alloc] init];
    _mediator.consumer = _viewController;
    [self showPromo];
  }
}

- (void)stop {
  LogUserInteractionWithFullscreenPromo();

  if (_promoWasFromRemindMeLater && _tracker) {
    _tracker->Dismissed(
        feature_engagement::kIPHiOSPromoDefaultBrowserReminderFeature);
  }

  [self.promosUIHandler promoWasDismissed];
  self.promosUIHandler = nil;

  [self.baseViewController dismissViewControllerAnimated:YES completion:nil];
  _viewController = nil;
  _mediator.consumer = nil;
  [_mediator disconnect];
  _mediator = nil;
  _promoStats = nil;
  _transparentView = nil;

  [super stop];
}

#pragma mark - ConfirmationAlertActionHandler

- (void)confirmationAlertPrimaryAction {
  [_mediator didTapPrimaryActionButton];
  RecordDefaultBrowserPromoLastAction(
      IOSDefaultBrowserPromoAction::kActionButton);
  base::UmaHistogramEnumeration(
      "IOS.DefaultBrowserVideoPromo.Fullscreen",
      IOSDefaultBrowserVideoPromoAction::kPrimaryActionTapped);
  RecordAction(UserMetricsAction(
      "IOS.DefaultBrowserVideoPromo.Fullscreen.OpenSettingsTapped"));
  [_handler hidePromo];
  if (IsDefaultBrowserTriggerCriteraExperimentEnabled()) {
    RecordPromoStatsToUMAForAction(_promoStats,
                                   IOSDefaultBrowserPromoAction::kActionButton);
  }
}

- (void)confirmationAlertSecondaryAction {
  RecordDefaultBrowserPromoLastAction(IOSDefaultBrowserPromoAction::kCancel);
  base::UmaHistogramEnumeration(
      "IOS.DefaultBrowserVideoPromo.Fullscreen",
      IOSDefaultBrowserVideoPromoAction::kSecondaryActionTapped);
  RecordAction(
      UserMetricsAction("IOS.DefaultBrowserVideoPromo.Fullscreen.Dismiss"));
  [_handler hidePromo];
  if (IsDefaultBrowserTriggerCriteraExperimentEnabled()) {
    RecordPromoStatsToUMAForAction(_promoStats,
                                   IOSDefaultBrowserPromoAction::kCancel);
  }
}

- (void)confirmationAlertTertiaryAction {
  RecordDefaultBrowserPromoLastAction(
      IOSDefaultBrowserPromoAction::kRemindMeLater);
  base::UmaHistogramEnumeration(
      "IOS.DefaultBrowserVideoPromo.Fullscreen",
      IOSDefaultBrowserVideoPromoAction::kTertiaryActionTapped);
  RecordAction(UserMetricsAction(
      "IOS.DefaultBrowserVideoPromo.Fullscreen.RemindMeLater"));
  if (_tracker) {
    _tracker->NotifyEvent(
        feature_engagement::events::kDefaultBrowserPromoRemindMeLater);
  }
  PromosManager* promosManager =
      PromosManagerFactory::GetForBrowserState(self.browser->GetBrowserState());
  promosManager->RegisterPromoForSingleDisplay(
      promos_manager::Promo::DefaultBrowserRemindMeLater);

  [_handler hidePromo];
}

#pragma mark - UIAdaptivePresentationControllerDelegate

- (void)presentationControllerDidDismiss:
    (UIPresentationController*)presentationController {
  RecordDefaultBrowserPromoLastAction(IOSDefaultBrowserPromoAction::kDismiss);
  base::UmaHistogramEnumeration("IOS.DefaultBrowserVideoPromo.Fullscreen",
                                IOSDefaultBrowserVideoPromoAction::kSwipeDown);
  RecordAction(
      UserMetricsAction("IOS.DefaultBrowserVideoPromo.Fullscreen.Dismiss"));
  [_handler hidePromo];
  if (IsDefaultBrowserTriggerCriteraExperimentEnabled()) {
    RecordPromoStatsToUMAForAction(_promoStats,
                                   IOSDefaultBrowserPromoAction::kDismiss);
  }
}

#pragma mark - Public

- (id<DefaultBrowserGenericPromoCommands>)defaultBrowserPromoHandler {
  id<DefaultBrowserGenericPromoCommands> handler = HandlerForProtocol(
      self.browser->GetCommandDispatcher(), DefaultBrowserGenericPromoCommands);

  return handler;
}

#pragma mark - Private

- (void)didRetrieveUserSegment {
  [_transparentView removeFromSuperview];
  _transparentView = nil;
  _viewController = [[DefaultBrowserGenericPromoViewController alloc] init];
  _mediator.consumer = _viewController;
  [self showPromo];
}

- (void)showPromo {
  CHECK(_viewController);
  CHECK(!_transparentView);
  RecordAction(
      UserMetricsAction("IOS.DefaultBrowserVideoPromo.Fullscreen.Impression"));
  _viewController.actionHandler = self;
  BOOL hasRemindMeLater =
      base::FeatureList::IsEnabled(
          feature_engagement::kIPHiOSPromoDefaultBrowserReminderFeature) &&
      !_promoWasFromRemindMeLater;
  _viewController.hasRemindMeLater = hasRemindMeLater;
  _viewController.presentationController.delegate = self;
  [self.baseViewController presentViewController:_viewController
                                        animated:YES
                                      completion:nil];
}

// Records that a default browser promo has been shown.
- (void)recordVideoDefaultBrowserPromoShown {
  // Record the current state before updating the local storage.
  RecordPromoDisplayStatsToUMA();

  if (IsDefaultBrowserTriggerCriteraExperimentEnabled()) {
    // `CalculatePromoStatistics` should be called before
    // `LogFullscreenDefaultBrowserPromoDisplayed` which will modify storage
    // data.
    _promoStats = CalculatePromoStatistics();
    RecordPromoStatsToUMAForAppear(_promoStats);
  }

  LogFullscreenDefaultBrowserPromoDisplayed();
  RecordAction(UserMetricsAction("IOS.DefaultBrowserVideoPromo.Appear"));
  base::UmaHistogramEnumeration("IOS.DefaultBrowserPromo.Shown",
                                DefaultPromoTypeForUMA::kGeneral);
}

@end