| // 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/ui/settings/privacy/lockdown_mode/lockdown_mode_view_controller.h" |
| |
| #import "base/apple/foundation_util.h" |
| #import "base/metrics/user_metrics.h" |
| #import "base/metrics/user_metrics_action.h" |
| #import "ios/chrome/browser/net/crurl.h" |
| #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_cell.h" |
| #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_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/ui/settings/elements/info_popover_view_controller.h" |
| #import "ios/chrome/common/string_util.h" |
| #import "ios/chrome/common/ui/colors/semantic_color_names.h" |
| #import "ios/chrome/grit/ios_strings.h" |
| #import "ui/base/l10n/l10n_util_mac.h" |
| |
| namespace { |
| |
| // List of sections. |
| typedef NS_ENUM(NSInteger, SectionIdentifier) { |
| SectionIdentifierLockdownMode = kSectionIdentifierEnumZero, |
| }; |
| |
| typedef NS_ENUM(NSInteger, ItemType) { |
| ItemTypeLockdownModeSwitch = kItemTypeEnumZero, |
| ItemTypeLockdownModeFooter, |
| }; |
| |
| NSString* const kLockdownModeTableViewId = @"kLockdownModeTableViewId"; |
| NSString* const kLockdownModeCellId = @"kLockdownModeCellId"; |
| |
| } // namespace |
| |
| @interface LockdownModeViewController () |
| |
| // The item related to the switch for the lockdown mode setting. |
| @property(nonatomic, strong) TableViewItem* lockdownModeItem; |
| |
| // Boolean related to dismissing settings. |
| @property(nonatomic) BOOL settingsAreDismissed; |
| |
| // Boolean that is set through the model in order to tell the view if OS |
| // Lockdown Mode is enabled. |
| @property(nonatomic) BOOL osLockdownModeEnabled; |
| |
| @end |
| |
| @implementation LockdownModeViewController |
| |
| - (void)viewDidLoad { |
| [super viewDidLoad]; |
| self.tableView.accessibilityIdentifier = kLockdownModeTableViewId; |
| self.title = l10n_util::GetNSString(IDS_IOS_LOCKDOWN_MODE_TITLE); |
| [self loadModel]; |
| } |
| |
| #pragma mark - CollectionViewController |
| |
| - (void)loadModel { |
| [super loadModel]; |
| TableViewModel* model = self.tableViewModel; |
| [model addSectionWithIdentifier:SectionIdentifierLockdownMode]; |
| [model addItem:self.lockdownModeItem |
| toSectionWithIdentifier:SectionIdentifierLockdownMode]; |
| [model setFooter:[self showLockdownModeFooter] |
| forSectionWithIdentifier:SectionIdentifierLockdownMode]; |
| } |
| |
| #pragma mark - LockdownModeConsumer |
| |
| - (void)reloadCellsForItems { |
| if (!self.tableViewModel) { |
| // No need to reconfigure since the model has not been loaded yet. |
| return; |
| } |
| NSArray<TableViewItem*>* items = @[ self.lockdownModeItem ]; |
| [self reloadCellsForItems:items withRowAnimation:UITableViewRowAnimationNone]; |
| } |
| |
| - (void)setBrowserLockdownModeEnabled:(BOOL)enabled { |
| if (!_osLockdownModeEnabled) { |
| TableViewSwitchItem* lockdownModeSwitchItem = |
| base::apple::ObjCCastStrict<TableViewSwitchItem>(self.lockdownModeItem); |
| lockdownModeSwitchItem.on = enabled; |
| } |
| [self reloadCellsForItems]; |
| } |
| |
| - (void)setOSLockdownModeEnabled:(BOOL)enabled { |
| // Cell isn't reloaded because the variable is only set during the initial |
| // view load. This boolean doesn't get changed unless the OS setting is |
| // changed which requires a device restart. |
| _osLockdownModeEnabled = enabled; |
| } |
| |
| #pragma mark - Private |
| |
| // Called when switch is toggled. |
| - (void)lockdownModeSwitchChanged:(UISwitch*)sender { |
| [self.modelDelegate didEnableBrowserLockdownMode:sender.isOn]; |
| } |
| |
| // Removes the view as a result of pressing "Done" button. |
| - (void)dismiss { |
| [self dismissViewControllerAnimated:YES completion:nil]; |
| } |
| |
| // Returns the primary attributed string for the InfoPopOverViewController. |
| - (NSAttributedString*)createPrimaryMessage { |
| NSDictionary* primaryAttributes = @{ |
| NSForegroundColorAttributeName : [UIColor colorNamed:kTextPrimaryColor], |
| NSFontAttributeName : |
| [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline] |
| }; |
| |
| return [[NSAttributedString alloc] |
| initWithString:l10n_util::GetNSString( |
| IDS_IOS_LOCKDOWN_MODE_INFO_BUTTON_TITLE) |
| attributes:primaryAttributes]; |
| } |
| |
| // Returns the secondary attributed string for the InfoPopOverViewController. |
| - (NSAttributedString*)createSecondaryMessage { |
| // Create and format the text. |
| NSDictionary* textAttributes = @{ |
| NSForegroundColorAttributeName : [UIColor colorNamed:kTextSecondaryColor], |
| NSFontAttributeName : |
| [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote] |
| }; |
| |
| NSString* message; |
| message = l10n_util::GetNSString(IDS_IOS_LOCKDOWN_MODE_INFO_BUTTON_SUMMARY); |
| NSAttributedString* attributedString = |
| [[NSAttributedString alloc] initWithString:message |
| attributes:textAttributes]; |
| |
| return attributedString; |
| } |
| |
| #pragma mark - Actions |
| |
| // Called when the user clicks on a managed information button. |
| - (void)didTapUIInfoButton:(UIButton*)buttonView { |
| NSAttributedString* primaryString = [self createPrimaryMessage]; |
| NSAttributedString* secondaryString = [self createSecondaryMessage]; |
| |
| InfoPopoverViewController* bubbleViewController = |
| [[InfoPopoverViewController alloc] |
| initWithPrimaryAttributedString:primaryString |
| secondaryAttributedString:secondaryString |
| icon:nil |
| isPresentingFromButton:YES]; |
| |
| // Disable the button when showing the bubble. |
| buttonView.enabled = NO; |
| |
| // Set the anchor and arrow direction of the bubble. |
| bubbleViewController.popoverPresentationController.sourceView = buttonView; |
| bubbleViewController.popoverPresentationController.sourceRect = |
| buttonView.bounds; |
| bubbleViewController.popoverPresentationController.permittedArrowDirections = |
| UIPopoverArrowDirectionAny; |
| |
| [self presentViewController:bubbleViewController animated:YES completion:nil]; |
| } |
| |
| #pragma mark - UITableViewDataSource |
| |
| - (UITableViewCell*)tableView:(UITableView*)tableView |
| cellForRowAtIndexPath:(NSIndexPath*)indexPath { |
| UITableViewCell* cell = [super tableView:tableView |
| cellForRowAtIndexPath:indexPath]; |
| if ([cell isKindOfClass:[TableViewSwitchCell class]]) { |
| switch ([self.tableViewModel itemTypeForIndexPath:indexPath]) { |
| case ItemTypeLockdownModeSwitch: { |
| TableViewSwitchCell* switchCell = |
| base::apple::ObjCCastStrict<TableViewSwitchCell>(cell); |
| [switchCell.switchView addTarget:self |
| action:@selector(lockdownModeSwitchChanged:) |
| forControlEvents:UIControlEventValueChanged]; |
| break; |
| } |
| } |
| } else if ([cell isKindOfClass:[TableViewInfoButtonCell class]]) { |
| TableViewInfoButtonCell* infoCell = |
| base::apple::ObjCCastStrict<TableViewInfoButtonCell>(cell); |
| [infoCell.trailingButton addTarget:self |
| action:@selector(didTapUIInfoButton:) |
| forControlEvents:UIControlEventTouchUpInside]; |
| } |
| |
| return cell; |
| } |
| |
| #pragma mark - UIViewController |
| |
| - (void)didMoveToParentViewController:(UIViewController*)parent { |
| [super didMoveToParentViewController:parent]; |
| if (!parent) { |
| [self.presentationDelegate lockdownModeViewControllerDidRemove:self]; |
| } |
| } |
| |
| #pragma mark - SettingsControllerProtocol |
| |
| - (void)reportDismissalUserAction { |
| base::RecordAction( |
| base::UserMetricsAction("MobileLockdownModeSettingsClose")); |
| } |
| |
| - (void)reportBackUserAction { |
| base::RecordAction(base::UserMetricsAction("MobileLockdownModeSettingsBack")); |
| } |
| |
| #pragma mark - Properties |
| |
| - (TableViewItem*)lockdownModeItem { |
| if (!_lockdownModeItem) { |
| if (_osLockdownModeEnabled) { |
| TableViewInfoButtonItem* lockdownModeItem = |
| [[TableViewInfoButtonItem alloc] |
| initWithType:ItemTypeLockdownModeSwitch]; |
| lockdownModeItem.statusText = l10n_util::GetNSString(IDS_IOS_SETTING_ON); |
| lockdownModeItem.text = |
| l10n_util::GetNSString(IDS_IOS_LOCKDOWN_MODE_TITLE); |
| lockdownModeItem.detailText = |
| l10n_util::GetNSString(IDS_IOS_LOCKDOWN_MODE_SWITCH_BUTTON_SUMMARY); |
| lockdownModeItem.accessibilityIdentifier = kLockdownModeCellId; |
| _lockdownModeItem = lockdownModeItem; |
| } else { |
| TableViewSwitchItem* lockdownModeItem = |
| [[TableViewSwitchItem alloc] initWithType:ItemTypeLockdownModeSwitch]; |
| lockdownModeItem.text = |
| l10n_util::GetNSString(IDS_IOS_LOCKDOWN_MODE_TITLE); |
| lockdownModeItem.detailText = |
| l10n_util::GetNSString(IDS_IOS_LOCKDOWN_MODE_SWITCH_BUTTON_SUMMARY); |
| lockdownModeItem.accessibilityIdentifier = kLockdownModeCellId; |
| _lockdownModeItem = lockdownModeItem; |
| } |
| } |
| return _lockdownModeItem; |
| } |
| |
| - (TableViewHeaderFooterItem*)showLockdownModeFooter { |
| TableViewLinkHeaderFooterItem* lockdownModeFooterItem = |
| [[TableViewLinkHeaderFooterItem alloc] |
| initWithType:ItemTypeLockdownModeFooter]; |
| lockdownModeFooterItem.text = |
| l10n_util::GetNSString(IDS_IOS_LOCKDOWN_MODE_FOOTER); |
| return lockdownModeFooterItem; |
| } |
| |
| @end |