chromium/ios/chrome/browser/ui/settings/privacy/privacy_safe_browsing_coordinator.mm

// Copyright 2022 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/ui/settings/privacy/privacy_safe_browsing_coordinator.h"

#import "base/apple/foundation_util.h"
#import "base/metrics/user_metrics.h"
#import "base/metrics/user_metrics_action.h"
#import "components/safe_browsing/core/common/safe_browsing_settings_metrics.h"
#import "components/strings/grit/components_strings.h"
#import "ios/chrome/browser/shared/coordinator/alert/alert_coordinator.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/model/url/chrome_url_constants.h"
#import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/chrome/browser/shared/ui/table_view/legacy_chrome_table_view_styler.h"
#import "ios/chrome/browser/shared/ui/table_view/table_view_utils.h"
#import "ios/chrome/browser/signin/model/chrome_account_manager_service_factory.h"
#import "ios/chrome/browser/ui/settings/privacy/privacy_safe_browsing_mediator.h"
#import "ios/chrome/browser/ui/settings/privacy/privacy_safe_browsing_navigation_commands.h"
#import "ios/chrome/browser/ui/settings/privacy/privacy_safe_browsing_view_controller.h"
#import "ios/chrome/browser/ui/settings/privacy/safe_browsing/safe_browsing_enhanced_protection_coordinator.h"
#import "ios/chrome/browser/ui/settings/privacy/safe_browsing/safe_browsing_standard_protection_coordinator.h"
#import "ios/chrome/common/ui/colors/semantic_color_names.h"
#import "ios/chrome/grit/ios_strings.h"
#import "ui/base/l10n/l10n_util.h"

// Currently takes into account a view controller delegate and not a command
// handler to communicate with the mediator since there's currently no needed
// functionality that requires this.
@interface PrivacySafeBrowsingCoordinator () <
    PrivacySafeBrowsingNavigationCommands,
    PrivacySafeBrowsingViewControllerPresentationDelegate,
    SafeBrowsingEnhancedProtectionCoordinatorDelegate,
    SafeBrowsingStandardProtectionCoordinatorDelegate>

// View controller presented by this coordinator.
@property(nonatomic, strong) PrivacySafeBrowsingViewController* viewController;
// Safe Browsing settings mediator.
@property(nonatomic, strong) PrivacySafeBrowsingMediator* mediator;
// Coordinator for No Protection Safe Browsing Pop Up.
@property(nonatomic, strong) AlertCoordinator* alertCoordinator;
// Coordinator for Privacy Safe Browsing Enhanced Protection settings.
@property(nonatomic, strong) SafeBrowsingEnhancedProtectionCoordinator*
    safeBrowsingEnhancedProtectionCoordinator;
// Coordinator for Privacy Safe Browsing Standard Protection settings.
@property(nonatomic, strong) SafeBrowsingStandardProtectionCoordinator*
    safeBrowsingStandardProtectionCoordinator;

@end

@implementation PrivacySafeBrowsingCoordinator

@synthesize baseNavigationController = _baseNavigationController;

- (instancetype)initWithBaseNavigationController:
                    (UINavigationController*)navigationController
                                         browser:(Browser*)browser {
  self = [super initWithBaseViewController:navigationController
                                   browser:browser];
  if (self) {
    _baseNavigationController = navigationController;
  }
  return self;
}

- (void)start {
  self.viewController = [[PrivacySafeBrowsingViewController alloc]
      initWithStyle:ChromeTableViewStyle()];
  self.viewController.styler.cellHighlightColor =
      [UIColor colorNamed:kTextfieldHighlightBackgroundColor];
  self.viewController.presentationDelegate = self;
  self.mediator = [[PrivacySafeBrowsingMediator alloc]
      initWithUserPrefService:self.browser->GetBrowserState()->GetPrefs()];
  self.mediator.consumer = self.viewController;
  self.mediator.handler = self;
  self.viewController.modelDelegate = self.mediator;
  DCHECK(self.baseNavigationController);
  safe_browsing::LogShowEnhancedProtectionAction();
  [self.baseNavigationController pushViewController:self.viewController
                                           animated:YES];
}

- (void)stop {
  [self stopSafeBrowsingEnhancedProtectionCoordinator];
  [self stopSafeBrowsingStandardProtectionCoordinator];
  [super stop];
}

- (void)setOpenedFromPromoInteraction:(BOOL)openedFromPromoInteraction {
  _openedFromPromoInteraction = openedFromPromoInteraction;
  self.mediator.openedFromPromoInteraction = _openedFromPromoInteraction;
}

#pragma mark - SafeBrowsingViewControllerPresentationDelegate

- (void)privacySafeBrowsingViewControllerDidRemove:
    (PrivacySafeBrowsingViewController*)controller {
  DCHECK_EQ(self.viewController, controller);
  [self.delegate privacySafeBrowsingCoordinatorDidRemove:self];
}

#pragma mark - PrivacySafeBrowsingNavigationCommands

- (void)showSafeBrowsingEnhancedProtection {
  // Asynchronized UI sequences can cause coordinators to exist when
  // re-initializing a new coordinator. To ensure that the object is reset
  // properly, we forcefully stop the coordinator so that we can properly
  // initialize a new one.
  if (self.safeBrowsingEnhancedProtectionCoordinator) {
    [self stopSafeBrowsingEnhancedProtectionCoordinator];
  }
  self.safeBrowsingEnhancedProtectionCoordinator =
      [[SafeBrowsingEnhancedProtectionCoordinator alloc]
          initWithBaseNavigationController:self.baseNavigationController
                                   browser:self.browser];
  self.safeBrowsingEnhancedProtectionCoordinator.delegate = self;
  [self.safeBrowsingEnhancedProtectionCoordinator start];
}

- (void)showSafeBrowsingStandardProtection {
  // Asynchronized UI sequences can cause coordinators to exist when
  // re-initializing a new coordinator. To ensure that the object is reset
  // properly, we forcefully stop the coordinator so that we can properly
  // initialize a new one.
  if (self.safeBrowsingStandardProtectionCoordinator) {
    [self stopSafeBrowsingStandardProtectionCoordinator];
  }
  self.safeBrowsingStandardProtectionCoordinator =
      [[SafeBrowsingStandardProtectionCoordinator alloc]
          initWithBaseNavigationController:self.baseNavigationController
                                   browser:self.browser];
  self.safeBrowsingStandardProtectionCoordinator.delegate = self;
  [self.safeBrowsingStandardProtectionCoordinator start];
}

- (void)showSafeBrowsingNoProtectionPopUp:(TableViewItem*)item {
  DCHECK(!self.alertCoordinator);
  self.alertCoordinator = [[AlertCoordinator alloc]
      initWithBaseViewController:self.viewController
                         browser:self.browser
                           title:
                               l10n_util::GetNSString(
                                   IDS_IOS_SAFE_BROWSING_NO_PROTECTION_CONFIRMATION_DIALOG_TITLE)
                         message:
                             l10n_util::GetNSString(
                                 IDS_IOS_SAFE_BROWSING_NO_PROTECTION_CONFIRMATION_DIALOG_MESSAGE)];

  __weak __typeof__(self) weakSelf = self;
  NSString* actionTitle = l10n_util::GetNSString(
      IDS_IOS_SAFE_BROWSING_NO_PROTECTION_CONFIRMATION_DIALOG_CONFIRM);
  [self.alertCoordinator addItemWithTitle:actionTitle
                                   action:^{
                                     base::RecordAction(base::UserMetricsAction(
                                         "SafeBrowsing.Settings."
                                         "DisableSafeBrowsingDialogConfirmed"));
                                     [weakSelf.mediator selectSettingItem:item];
                                     [weakSelf.alertCoordinator stop];
                                     weakSelf.alertCoordinator = nil;
                                   }
                                    style:UIAlertActionStyleDefault];

  [self.alertCoordinator
      addItemWithTitle:l10n_util::GetNSString(IDS_CANCEL)
                action:^{
                  base::RecordAction(base::UserMetricsAction(
                      "SafeBrowsing.Settings.DisableSafeBrowsingDialogDenied"));
                  [weakSelf.mediator selectSettingItem:nil];
                  [weakSelf.alertCoordinator stop];
                  weakSelf.alertCoordinator = nil;
                }
                 style:UIAlertActionStyleCancel];

  [self.alertCoordinator start];
}

#pragma mark - SafeBrowsingEnhancedProtectionCoordinatorDelegate

- (void)safeBrowsingEnhancedProtectionCoordinatorDidRemove:
    (SafeBrowsingEnhancedProtectionCoordinator*)coordinator {
  DCHECK_EQ(self.safeBrowsingEnhancedProtectionCoordinator, coordinator);
  [self stopSafeBrowsingEnhancedProtectionCoordinator];
}

#pragma mark - SafeBrowsingStandardProtectionCoordinatorDelegate

- (void)safeBrowsingStandardProtectionCoordinatorDidRemove:
    (SafeBrowsingStandardProtectionCoordinator*)coordinator {
  DCHECK_EQ(self.safeBrowsingStandardProtectionCoordinator, coordinator);
  [self stopSafeBrowsingStandardProtectionCoordinator];
}

#pragma mark - Private

- (void)stopSafeBrowsingStandardProtectionCoordinator {
  [self.safeBrowsingStandardProtectionCoordinator stop];
  self.safeBrowsingStandardProtectionCoordinator.delegate = nil;
  self.safeBrowsingStandardProtectionCoordinator = nil;
}

#pragma mark - Private

- (void)stopSafeBrowsingEnhancedProtectionCoordinator {
  [self.safeBrowsingEnhancedProtectionCoordinator stop];
  self.safeBrowsingEnhancedProtectionCoordinator.delegate = nil;
  self.safeBrowsingEnhancedProtectionCoordinator = nil;
}

@end