blob: 4184664ae34cf4148ef6f2f09762fdf7193f2528 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// 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_table_view_controller.h"
#include "base/check_op.h"
#include "base/feature_list.h"
#include "base/metrics/user_metrics.h"
#include "base/metrics/user_metrics_action.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/strings/grit/components_strings.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#include "ios/chrome/browser/content_settings/host_content_settings_map_factory.h"
#import "ios/chrome/browser/ui/settings/block_popups_table_view_controller.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/ui/table_view/cells/table_view_detail_icon_item.h"
#import "ios/chrome/browser/ui/table_view/cells/table_view_multi_detail_text_item.h"
#include "ios/chrome/browser/ui/ui_feature_flags.h"
#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h"
#include "ios/chrome/grit/ios_strings.h"
#include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
#include "ios/public/provider/chrome/browser/mailto/mailto_handler_provider.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/l10n/l10n_util_mac.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
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,
};
typedef NS_ENUM(NSInteger, ItemType) {
ItemTypeSettingsBlockPopups = kItemTypeEnumZero,
ItemTypeSettingsComposeEmail,
};
} // 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;
}
// Returns the value for the default setting with ID |settingID|.
- (ContentSetting)getContentSetting:(ContentSettingsType)settingID;
// Helpers to create collection view items.
- (id)blockPopupsItem;
- (id)composeEmailItem;
@end
@implementation ContentSettingsTableViewController {
ChromeBrowserState* _browserState; // weak
}
- (instancetype)initWithBrowserState:(ChromeBrowserState*)browserState {
DCHECK(browserState);
UITableViewStyle style = base::FeatureList::IsEnabled(kSettingsRefresh)
? UITableViewStylePlain
: UITableViewStyleGrouped;
self = [super initWithStyle:style];
if (self) {
_browserState = browserState;
self.title = l10n_util::GetNSString(IDS_IOS_CONTENT_SETTINGS_TITLE);
HostContentSettingsMap* settingsMap =
ios::HostContentSettingsMapFactory::GetForBrowserState(browserState);
_disablePopupsSetting = [[ContentSettingBackedBoolean alloc]
initWithHostContentSettingsMap:settingsMap
settingID:ContentSettingsType::POPUPS
inverted:YES];
[_disablePopupsSetting 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 - ChromeTableViewController
- (void)loadModel {
[super loadModel];
TableViewModel* model = self.tableViewModel;
[model addSectionWithIdentifier:SectionIdentifierSettings];
[model addItem:[self blockPopupsItem]
toSectionWithIdentifier:SectionIdentifierSettings];
MailtoHandlerProvider* provider =
ios::GetChromeBrowserProvider()->GetMailtoHandlerProvider();
NSString* settingsTitle = provider->MailtoHandlerSettingsTitle();
// 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];
}
}
}
#pragma mark - SettingsControllerProtocol
- (void)reportDismissalUserAction {
base::RecordAction(base::UserMetricsAction("MobileContentSettingsClose"));
}
- (void)reportBackUserAction {
base::RecordAction(base::UserMetricsAction("MobileContentSettingsBack"));
}
#pragma mark - ContentSettingsTableViewController
- (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 {
_composeEmailDetailItem = [[TableViewDetailIconItem alloc]
initWithType:ItemTypeSettingsComposeEmail];
// Use the handler's preferred title string for the compose email item.
MailtoHandlerProvider* provider =
ios::GetChromeBrowserProvider()->GetMailtoHandlerProvider();
NSString* settingsTitle = provider->MailtoHandlerSettingsTitle();
DCHECK([settingsTitle length]);
// .detailText can display the selected mailto handling app, but the current
// MailtoHandlerProvider does not expose this through its API.
_composeEmailDetailItem.text = settingsTitle;
_composeEmailDetailItem.accessoryType =
UITableViewCellAccessoryDisclosureIndicator;
_composeEmailDetailItem.accessibilityTraits |= UIAccessibilityTraitButton;
_composeEmailDetailItem.accessibilityIdentifier = kSettingsDefaultAppsCellId;
return _composeEmailDetailItem;
}
- (TableViewItem*)openedInAnotherWindowItem {
_openedInAnotherWindowItem = [[TableViewMultiDetailTextItem alloc]
initWithType:ItemTypeSettingsComposeEmail];
// Use the handler's preferred title string for the compose email item.
MailtoHandlerProvider* provider =
ios::GetChromeBrowserProvider()->GetMailtoHandlerProvider();
NSString* settingsTitle = provider->MailtoHandlerSettingsTitle();
DCHECK([settingsTitle length]);
// .detailText can display the selected mailto handling app, but the current
// MailtoHandlerProvider 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;
}
- (ContentSetting)getContentSetting:(ContentSettingsType)settingID {
return ios::HostContentSettingsMapFactory::GetForBrowserState(_browserState)
->GetDefaultContentSetting(settingID, NULL);
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView*)tableView
didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
NSInteger itemType = [self.tableViewModel itemTypeForIndexPath:indexPath];
switch (itemType) {
case ItemTypeSettingsBlockPopups: {
BlockPopupsTableViewController* controller =
[[BlockPopupsTableViewController alloc]
initWithBrowserState:_browserState];
controller.dispatcher = self.dispatcher;
[self.navigationController pushViewController:controller animated:YES];
break;
}
case ItemTypeSettingsComposeEmail: {
if (openedMailTo)
break;
MailtoHandlerProvider* provider =
ios::GetChromeBrowserProvider()->GetMailtoHandlerProvider();
UIViewController* controller =
provider->MailtoHandlerSettingsController();
if (controller) {
[self.navigationController pushViewController:controller animated:YES];
openedMailTo = YES;
[[NSNotificationCenter defaultCenter]
postNotificationName:kMailToInstanceChanged
object:nil];
}
break;
}
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#pragma mark - BooleanObserver
- (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean {
DCHECK_EQ(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 ]];
}
#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 {
// 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;
MailtoHandlerProvider* provider =
ios::GetChromeBrowserProvider()->GetMailtoHandlerProvider();
NSString* mailToTitle = provider->MailtoHandlerSettingsTitle();
if ([top isEqualToString:mailToTitle]) {
openedMailTo = NO;
[[NSNotificationCenter defaultCenter]
postNotificationName:kMailToInstanceChanged
object:nil];
}
}
@end