chromium/ios/chrome/browser/ui/settings/content_settings/content_settings_table_view_controller.mm

// Copyright 2013 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/content_settings/content_settings_table_view_controller.h"

#import "base/apple/foundation_util.h"
#import "base/check_op.h"
#import "base/feature_list.h"
#import "base/memory/raw_ptr.h"
#import "base/metrics/user_metrics.h"
#import "base/metrics/user_metrics_action.h"
#import "components/content_settings/core/browser/host_content_settings_map.h"
#import "components/content_settings/core/common/content_settings.h"
#import "components/content_settings/core/common/content_settings_types.h"
#import "components/strings/grit/components_strings.h"
#import "ios/chrome/browser/content_settings/model/host_content_settings_map_factory.h"
#import "ios/chrome/browser/mailto_handler/model/mailto_handler_service.h"
#import "ios/chrome/browser/mailto_handler/model/mailto_handler_service_factory.h"
#import "ios/chrome/browser/ntp/ui_bundled/new_tab_page_feature.h"
#import "ios/chrome/browser/shared/model/browser/browser.h"
#import "ios/chrome/browser/shared/model/prefs/pref_backed_boolean.h"
#import "ios/chrome/browser/shared/model/prefs/pref_names.h"
#import "ios/chrome/browser/shared/model/profile/profile_ios.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/chrome/browser/shared/ui/table_view/cells/table_view_detail_icon_item.h"
#import "ios/chrome/browser/shared/ui/table_view/cells/table_view_multi_detail_text_item.h"
#import "ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_cell.h"
#import "ios/chrome/browser/shared/ui/table_view/cells/table_view_switch_item.h"
#import "ios/chrome/browser/shared/ui/table_view/table_view_utils.h"
#import "ios/chrome/browser/ui/settings/content_settings/block_popups_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/content_settings/default_page_mode_coordinator.h"
#import "ios/chrome/browser/ui/settings/content_settings/web_inspector_state_coordinator.h"
#import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
#import "ios/chrome/browser/ui/settings/settings_table_view_controller_constants.h"
#import "ios/chrome/browser/ui/settings/utils/content_setting_backed_boolean.h"
#import "ios/chrome/browser/web/model/annotations/annotations_util.h"
#import "ios/chrome/grit/ios_strings.h"
#import "ios/web/common/features.h"
#import "ui/base/l10n/l10n_util.h"
#import "ui/base/l10n/l10n_util_mac.h"

namespace {

// Is YES when one window has mailTo controller opened.
BOOL openedMailTo = NO;

// Notification name of changes to openedMailTo state.
NSString* kMailToInstanceChanged = @"MailToInstanceChanged";

typedef NS_ENUM(NSInteger, SectionIdentifier) {
  SectionIdentifierSettings = kSectionIdentifierEnumZero,
  SectionIdentifierDeveloperTools,
};

typedef NS_ENUM(NSInteger, ItemType) {
  ItemTypeSettingsBlockPopups = kItemTypeEnumZero,
  ItemTypeSettingsComposeEmail,
  ItemTypeSettingsShowLinkPreview,
  ItemTypeSettingsDefaultSiteMode,
  ItemTypeSettingsDetectAddresses,
  ItemTypeSettingsDetectUnits,
  ItemTypeSettingsWebInspector,
};

}  // namespace

@interface ContentSettingsTableViewController () <BooleanObserver> {
  // The observable boolean that binds to the "Disable Popups" setting state.
  ContentSettingBackedBoolean* _disablePopupsSetting;

  // Updatable Items
  TableViewDetailIconItem* _blockPopupsDetailItem;
  TableViewDetailIconItem* _composeEmailDetailItem;
  TableViewMultiDetailTextItem* _openedInAnotherWindowItem;
  TableViewDetailIconItem* _defaultSiteMode;
  TableViewDetailIconItem* _webInspectorStateItem;
}

// PrefBackedBoolean for "Show Link Preview" setting state.
@property(nonatomic, strong, readonly) PrefBackedBoolean* linkPreviewEnabled;

// PrefBackedBoolean for "Detect addresses" setting state.
@property(nonatomic, strong, readonly)
    PrefBackedBoolean* detectAddressesEnabled;

// PrefBackedBoolean for "Detect units" setting state.
@property(nonatomic, strong, readonly) PrefBackedBoolean* detectUnitsEnabled;

// The item related to the switch for the "Show Link Preview" setting.
@property(nonatomic, strong) TableViewSwitchItem* linkPreviewItem;

// The item related to the switch for the "Detect Addresses" setting.
@property(nonatomic, strong) TableViewSwitchItem* detectAddressesItem;

// The item related to the switch for the "Detect units" setting.
@property(nonatomic, strong) TableViewSwitchItem* detectUnitsItem;

// The item related to the default mode used to load the pages.
@property(nonatomic, strong) TableViewDetailIconItem* defaultModeItem;

// The item related to the switch for the "Web Inspector" setting.
@property(nonatomic, strong) TableViewDetailIconItem* webInspectorItem;

// The coordinator showing the view to choose the defaultMode.
@property(nonatomic, strong)
    DefaultPageModeCoordinator* defaultModeViewCoordinator;

// The coordinator showing the view to enable or disable Web Inspector.
@property(nonatomic, strong)
    WebInspectorStateCoordinator* webInspectorStateViewCoordinator;

// The setting used to store the default mode.
@property(nonatomic, strong) ContentSettingBackedBoolean* requestDesktopSetting;

// PrefBackedBoolean for Web Inspector setting state.
@property(nonatomic, strong) PrefBackedBoolean* webInspectorEnabled;

// Helpers to create collection view items.
- (id)blockPopupsItem;
- (id)composeEmailItem;

@end

@implementation ContentSettingsTableViewController {
  raw_ptr<Browser> _browser;  // weak
}

- (instancetype)initWithBrowser:(Browser*)browser {
  DCHECK(browser);

  self = [super initWithStyle:ChromeTableViewStyle()];
  if (self) {
    _browser = browser;
    self.title = l10n_util::GetNSString(IDS_IOS_CONTENT_SETTINGS_TITLE);

    ChromeBrowserState* browserState = browser->GetBrowserState();

    HostContentSettingsMap* settingsMap =
        ios::HostContentSettingsMapFactory::GetForBrowserState(browserState);
    _disablePopupsSetting = [[ContentSettingBackedBoolean alloc]
        initWithHostContentSettingsMap:settingsMap
                             settingID:ContentSettingsType::POPUPS
                              inverted:YES];
    [_disablePopupsSetting setObserver:self];

    _linkPreviewEnabled = [[PrefBackedBoolean alloc]
        initWithPrefService:browserState->GetPrefs()
                   prefName:prefs::kLinkPreviewEnabled];
    [_linkPreviewEnabled setObserver:self];

    _detectAddressesEnabled = [[PrefBackedBoolean alloc]
        initWithPrefService:browserState->GetPrefs()
                   prefName:prefs::kDetectAddressesEnabled];
    [_detectAddressesEnabled setObserver:self];

    _detectUnitsEnabled = [[PrefBackedBoolean alloc]
        initWithPrefService:browserState->GetPrefs()
                   prefName:prefs::kDetectUnitsEnabled];
    [_detectUnitsEnabled setObserver:self];

    _requestDesktopSetting = [[ContentSettingBackedBoolean alloc]
        initWithHostContentSettingsMap:settingsMap
                             settingID:ContentSettingsType::REQUEST_DESKTOP_SITE
                              inverted:NO];
    [_requestDesktopSetting setObserver:self];

    if (web::features::IsWebInspectorSupportEnabled()) {
      _webInspectorEnabled = [[PrefBackedBoolean alloc]
          initWithPrefService:browserState->GetPrefs()
                     prefName:prefs::kWebInspectorEnabled];
      [_webInspectorEnabled setObserver:self];
    }
  }
  return self;
}

#pragma mark - UIViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  self.tableView.rowHeight = UITableViewAutomaticDimension;
  [self loadModel];
}

- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
  [[NSNotificationCenter defaultCenter]
      addObserver:self
         selector:@selector(mailToControllerChanged)
             name:kMailToInstanceChanged
           object:nil];
  [self checkMailToOwnership];
}

- (void)viewWillDisappear:(BOOL)animated {
  [super viewWillDisappear:animated];
  [self checkMailToOwnership];
  [[NSNotificationCenter defaultCenter] removeObserver:self
                                                  name:kMailToInstanceChanged
                                                object:nil];
}

#pragma mark - LegacyChromeTableViewController

- (void)loadModel {
  [super loadModel];

  if (!_browser)
    return;

  TableViewModel* model = self.tableViewModel;
  [model addSectionWithIdentifier:SectionIdentifierSettings];
  [model addItem:[self blockPopupsItem]
      toSectionWithIdentifier:SectionIdentifierSettings];
  NSString* settingsTitle = MailtoHandlerServiceFactory::GetForBrowserState(
                                _browser->GetBrowserState())
                                ->SettingsTitle();
  // Display email settings only on one window at a time, by checking
  // if this is the current owner.
  _openedInAnotherWindowItem = nil;
  _composeEmailDetailItem = nil;
  if (settingsTitle) {
    if (!openedMailTo) {
      [model addItem:[self composeEmailItem]
          toSectionWithIdentifier:SectionIdentifierSettings];
    } else {
      [model addItem:[self openedInAnotherWindowItem]
          toSectionWithIdentifier:SectionIdentifierSettings];
    }
  }

  if (IsDiscoverFeedPreviewEnabled()) {
    [model addItem:[self linkPreviewItem]
        toSectionWithIdentifier:SectionIdentifierSettings];
  }

  self.defaultModeItem = [self defaultSiteMode];
  [model addItem:self.defaultModeItem
      toSectionWithIdentifier:SectionIdentifierSettings];

  if (IsAddressDetectionEnabled()) {
    [model addItem:[self detectAddressItem]
        toSectionWithIdentifier:SectionIdentifierSettings];
  }

  if (base::FeatureList::IsEnabled(web::features::kEnableMeasurements)) {
    [model addItem:[self detectUnitItem]
        toSectionWithIdentifier:SectionIdentifierSettings];
  }
  if (web::features::IsWebInspectorSupportEnabled()) {
    self.webInspectorItem = [self webInspectorStateItem];
    [model addSectionWithIdentifier:SectionIdentifierDeveloperTools];
    [model addItem:self.webInspectorItem
        toSectionWithIdentifier:SectionIdentifierDeveloperTools];
  }
}

#pragma mark - SettingsControllerProtocol

- (void)reportDismissalUserAction {
  base::RecordAction(base::UserMetricsAction("MobileContentSettingsClose"));
}

- (void)reportBackUserAction {
  base::RecordAction(base::UserMetricsAction("MobileContentSettingsBack"));
}

#pragma mark - ContentSettingsTableViewController

- (TableViewDetailIconItem*)defaultSiteMode {
  _defaultSiteMode = [[TableViewDetailIconItem alloc]
      initWithType:ItemTypeSettingsDefaultSiteMode];
  _defaultSiteMode.text =
      l10n_util::GetNSString(IDS_IOS_DEFAULT_PAGE_MODE_LABEL);
  _defaultSiteMode.detailText = [self defaultModeDescription];
  _defaultSiteMode.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
  _defaultSiteMode.accessibilityIdentifier = kSettingsDefaultSiteModeCellId;
  return _defaultSiteMode;
}

- (TableViewItem*)blockPopupsItem {
  _blockPopupsDetailItem = [[TableViewDetailIconItem alloc]
      initWithType:ItemTypeSettingsBlockPopups];
  NSString* subtitle = [_disablePopupsSetting value]
                           ? l10n_util::GetNSString(IDS_IOS_SETTING_ON)
                           : l10n_util::GetNSString(IDS_IOS_SETTING_OFF);
  _blockPopupsDetailItem.text = l10n_util::GetNSString(IDS_IOS_BLOCK_POPUPS);
  _blockPopupsDetailItem.detailText = subtitle;
  _blockPopupsDetailItem.accessoryType =
      UITableViewCellAccessoryDisclosureIndicator;
  _blockPopupsDetailItem.accessibilityTraits |= UIAccessibilityTraitButton;
  _blockPopupsDetailItem.accessibilityIdentifier = kSettingsBlockPopupsCellId;
  return _blockPopupsDetailItem;
}

- (TableViewItem*)composeEmailItem {
  if (!_browser)
    return nil;

  _composeEmailDetailItem = [[TableViewDetailIconItem alloc]
      initWithType:ItemTypeSettingsComposeEmail];
  // Use the handler's preferred title string for the compose email item.
  NSString* settingsTitle = MailtoHandlerServiceFactory::GetForBrowserState(
                                _browser->GetBrowserState())
                                ->SettingsTitle();
  DCHECK([settingsTitle length]);
  // .detailText can display the selected mailto handling app, but the current
  // MailtoHandlerService does not expose this through its API.
  _composeEmailDetailItem.text = settingsTitle;
  _composeEmailDetailItem.accessoryType =
      UITableViewCellAccessoryDisclosureIndicator;
  _composeEmailDetailItem.accessibilityTraits |= UIAccessibilityTraitButton;
  _composeEmailDetailItem.accessibilityIdentifier = kSettingsDefaultAppsCellId;
  return _composeEmailDetailItem;
}

- (TableViewItem*)openedInAnotherWindowItem {
  if (!_browser)
    return nil;

  _openedInAnotherWindowItem = [[TableViewMultiDetailTextItem alloc]
      initWithType:ItemTypeSettingsComposeEmail];
  // Use the handler's preferred title string for the compose email item.
  NSString* settingsTitle = MailtoHandlerServiceFactory::GetForBrowserState(
                                _browser->GetBrowserState())
                                ->SettingsTitle();
  DCHECK([settingsTitle length]);
  // .detailText can display the selected mailto handling app, but the current
  // MailtoHandlerService does not expose this through its API.
  _openedInAnotherWindowItem.text = settingsTitle;

  _openedInAnotherWindowItem.trailingDetailText =
      l10n_util::GetNSString(IDS_IOS_SETTING_OPENED_IN_ANOTHER_WINDOW);
  _openedInAnotherWindowItem.accessibilityTraits |=
      UIAccessibilityTraitButton | UIAccessibilityTraitNotEnabled;
  _openedInAnotherWindowItem.accessibilityIdentifier =
      kSettingsDefaultAppsCellId;
  return _openedInAnotherWindowItem;
}

- (TableViewSwitchItem*)linkPreviewItem {
  if (!_linkPreviewItem) {
    _linkPreviewItem = [[TableViewSwitchItem alloc]
        initWithType:ItemTypeSettingsShowLinkPreview];

    _linkPreviewItem.text = l10n_util::GetNSString(IDS_IOS_SHOW_LINK_PREVIEWS);
    _linkPreviewItem.on = [self.linkPreviewEnabled value];
    _linkPreviewItem.accessibilityIdentifier = kSettingsShowLinkPreviewCellId;
  }
  return _linkPreviewItem;
}

- (TableViewSwitchItem*)detectAddressItem {
  if (!_detectAddressesItem) {
    _detectAddressesItem = [[TableViewSwitchItem alloc]
        initWithType:ItemTypeSettingsDetectAddresses];

    _detectAddressesItem.text =
        l10n_util::GetNSString(IDS_IOS_DETECT_ADDRESSES_SETTING_TITLE);
    _detectAddressesItem.detailText =
        l10n_util::GetNSString(IDS_IOS_DETECT_ADDRESSES_SETTING_DESCRIPTION);
    _detectAddressesItem.on = [self.detectAddressesEnabled value];
    _detectAddressesItem.accessibilityIdentifier =
        kSettingsDetectAddressesCellId;
  }
  return _detectAddressesItem;
}

- (TableViewSwitchItem*)detectUnitItem {
  if (!_detectUnitsItem) {
    _detectUnitsItem =
        [[TableViewSwitchItem alloc] initWithType:ItemTypeSettingsDetectUnits];

    _detectUnitsItem.text =
        l10n_util::GetNSString(IDS_IOS_DETECT_UNITS_SETTING_TITLE);
    _detectUnitsItem.detailText =
        l10n_util::GetNSString(IDS_IOS_DETECT_UNITS_SETTING_DESCRIPTION);
    _detectUnitsItem.on = [self.detectUnitsEnabled value];
    _detectUnitsItem.accessibilityIdentifier = kSettingsDetectUnitsCellId;
  }
  return _detectUnitsItem;
}

- (TableViewDetailIconItem*)webInspectorStateItem {
  _webInspectorStateItem = [[TableViewDetailIconItem alloc]
      initWithType:ItemTypeSettingsWebInspector];
  _webInspectorStateItem.text =
      l10n_util::GetNSString(IDS_IOS_WEB_INSPECTOR_LABEL);
  _webInspectorStateItem.detailText = [self webInspectorStateDescription];
  _webInspectorStateItem.accessoryType =
      UITableViewCellAccessoryDisclosureIndicator;
  _webInspectorStateItem.accessibilityIdentifier = kSettingsWebInspectorCellId;
  return _webInspectorStateItem;
}

#pragma mark - UITableViewDataSource

- (UITableViewCell*)tableView:(UITableView*)tableView
        cellForRowAtIndexPath:(NSIndexPath*)indexPath {
  UITableViewCell* cell = [super tableView:tableView
                     cellForRowAtIndexPath:indexPath];
  NSInteger itemType = [self.tableViewModel itemTypeForIndexPath:indexPath];

  if (itemType == ItemTypeSettingsShowLinkPreview) {
    TableViewSwitchCell* switchCell =
        base::apple::ObjCCastStrict<TableViewSwitchCell>(cell);
    [switchCell.switchView addTarget:self
                              action:@selector(showLinkPreviewSwitchToggled:)
                    forControlEvents:UIControlEventValueChanged];
  }

  if (itemType == ItemTypeSettingsDetectAddresses) {
    TableViewSwitchCell* switchCell =
        base::apple::ObjCCastStrict<TableViewSwitchCell>(cell);
    [switchCell.switchView addTarget:self
                              action:@selector(detectAddressesSwitchToggled:)
                    forControlEvents:UIControlEventValueChanged];
  }

  if (itemType == ItemTypeSettingsDetectUnits) {
    TableViewSwitchCell* switchCell =
        base::apple::ObjCCastStrict<TableViewSwitchCell>(cell);
    [switchCell.switchView addTarget:self
                              action:@selector(detectUnitsSwitchToggled:)
                    forControlEvents:UIControlEventValueChanged];
  }
  return cell;
}

#pragma mark - UITableViewDelegate

- (void)tableView:(UITableView*)tableView
    didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
  [super tableView:tableView didSelectRowAtIndexPath:indexPath];
  if (!_browser)
    return;

  NSInteger itemType = [self.tableViewModel itemTypeForIndexPath:indexPath];
  switch (itemType) {
    case ItemTypeSettingsBlockPopups: {
      BlockPopupsTableViewController* controller =
          [[BlockPopupsTableViewController alloc]
              initWithBrowserState:_browser->GetBrowserState()];
      [self configureHandlersForRootViewController:controller];
      [self.navigationController pushViewController:controller animated:YES];
      break;
    }
    case ItemTypeSettingsComposeEmail: {
      if (openedMailTo)
        break;

      UIViewController* controller =
          MailtoHandlerServiceFactory::GetForBrowserState(
              _browser->GetBrowserState())
              ->CreateSettingsController();
      if (controller) {
        [self.navigationController pushViewController:controller animated:YES];
        openedMailTo = YES;
        [[NSNotificationCenter defaultCenter]
            postNotificationName:kMailToInstanceChanged
                          object:nil];
      }
      break;
    }
    case ItemTypeSettingsDefaultSiteMode: {
      self.defaultModeViewCoordinator = [[DefaultPageModeCoordinator alloc]
          initWithBaseNavigationController:self.navigationController
                                   browser:_browser];
      [self.defaultModeViewCoordinator start];
      break;
    }
    case ItemTypeSettingsWebInspector: {
      self.webInspectorStateViewCoordinator =
          [[WebInspectorStateCoordinator alloc]
              initWithBaseNavigationController:self.navigationController
                                       browser:_browser];
      [self.webInspectorStateViewCoordinator start];
      break;
    }
  }
  [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

#pragma mark - BooleanObserver

- (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean {
  if (observableBoolean == _disablePopupsSetting) {
    NSString* subtitle = [_disablePopupsSetting value]
                             ? l10n_util::GetNSString(IDS_IOS_SETTING_ON)
                             : l10n_util::GetNSString(IDS_IOS_SETTING_OFF);
    // Update the item.
    _blockPopupsDetailItem.detailText = subtitle;

    // Update the cell.
    [self reconfigureCellsForItems:@[ _blockPopupsDetailItem ]];
  } else if (observableBoolean == self.linkPreviewEnabled) {
    self.linkPreviewItem.on = [self.linkPreviewEnabled value];
    [self reconfigureCellsForItems:@[ self.linkPreviewItem ]];
  } else if (observableBoolean == self.requestDesktopSetting &&
             self.defaultModeItem) {
    self.defaultModeItem.detailText = [self defaultModeDescription];
    [self reconfigureCellsForItems:@[ self.defaultModeItem ]];
  } else if (web::features::IsWebInspectorSupportEnabled() &&
             observableBoolean == self.webInspectorEnabled) {
    self.webInspectorItem.detailText = [self webInspectorStateDescription];
    [self reconfigureCellsForItems:@[ self.webInspectorItem ]];
  } else if (observableBoolean == self.detectAddressesEnabled) {
    self.detectAddressItem.on = [self.detectAddressesEnabled value];
    [self reconfigureCellsForItems:@[ self.detectAddressItem ]];
  } else if (observableBoolean == self.detectUnitsEnabled) {
    self.detectUnitsItem.on = [self.detectUnitsEnabled value];
    [self reconfigureCellsForItems:@[ self.detectUnitsItem ]];
  } else {
    NOTREACHED_IN_MIGRATION();
  }
}

#pragma mark - Switch Actions

- (void)showLinkPreviewSwitchToggled:(UISwitch*)sender {
  BOOL newSwitchValue = sender.isOn;
  self.linkPreviewItem.on = newSwitchValue;
  [self.linkPreviewEnabled setValue:newSwitchValue];
}

- (void)detectAddressesSwitchToggled:(UISwitch*)sender {
  BOOL newSwitchValue = sender.isOn;
  self.detectAddressesItem.on = newSwitchValue;
  [self.detectAddressesEnabled setValue:newSwitchValue];
}

- (void)detectUnitsSwitchToggled:(UISwitch*)sender {
  BOOL newSwitchValue = sender.isOn;
  self.detectUnitsItem.on = newSwitchValue;
  [self.detectUnitsEnabled setValue:newSwitchValue];
}

#pragma mark - Private

// Called to reload data when another window has mailTo settings opened.
- (void)mailToControllerChanged {
  [self reloadData];
}

// Verifies using the navigation stack if this is a return from mailTo settings
// and this instance should reset `openedMailTo`.
- (void)checkMailToOwnership {
  if (!_browser)
    return;

  // Since this doesn't know or have access to the mailTo controller code,
  // it detects if the flow is coming back from it, based on the navigation
  // bar stack items.
  NSString* top = self.navigationController.navigationBar.topItem.title;
  NSString* mailToTitle = MailtoHandlerServiceFactory::GetForBrowserState(
                              _browser->GetBrowserState())
                              ->SettingsTitle();
  if ([top isEqualToString:mailToTitle]) {
    openedMailTo = NO;
    [[NSNotificationCenter defaultCenter]
        postNotificationName:kMailToInstanceChanged
                      object:nil];
  }
}

// Returns the string for the default mode.
- (NSString*)defaultModeDescription {
  return self.requestDesktopSetting.value
             ? l10n_util::GetNSString(IDS_IOS_DEFAULT_PAGE_MODE_DESKTOP)
             : l10n_util::GetNSString(IDS_IOS_DEFAULT_PAGE_MODE_MOBILE);
}

// Returns the string description for the current WebInspectorState.
- (NSString*)webInspectorStateDescription {
  return self.webInspectorEnabled.value
             ? l10n_util::GetNSString(IDS_IOS_SETTING_ON)
             : l10n_util::GetNSString(IDS_IOS_SETTING_OFF);
}

- (void)settingsWillBeDismissed {
  // TODO(crbug.com/40272467)
  DUMP_WILL_BE_CHECK(_browser);
  [_disablePopupsSetting stop];
  _disablePopupsSetting.observer = nil;
  _disablePopupsSetting = nil;
  [_requestDesktopSetting stop];
  _requestDesktopSetting.observer = nil;
  _requestDesktopSetting = nil;
  [_linkPreviewEnabled stop];
  _linkPreviewEnabled.observer = nil;
  _linkPreviewEnabled = nil;
  [_webInspectorEnabled stop];
  _webInspectorEnabled.observer = nil;
  [self.webInspectorStateViewCoordinator stop];
  self.webInspectorStateViewCoordinator = nil;
  [self.defaultModeViewCoordinator stop];
  self.defaultModeViewCoordinator = nil;
  _browser = nullptr;
  [self.defaultModeViewCoordinator stop];
  self.defaultModeViewCoordinator = nil;
}

@end