[go: nahoru, domu]

blob: 45872d0a0157831737f8791ff672c23d95725248 [file] [log] [blame]
// 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_mediator.h"
#import "base/apple/foundation_util.h"
#import "base/auto_reset.h"
#import "base/metrics/user_metrics.h"
#import "base/metrics/user_metrics_action.h"
#import "base/notreached.h"
#import "components/prefs/pref_service.h"
#import "components/safe_browsing/core/common/features.h"
#import "components/safe_browsing/core/common/safe_browsing_prefs.h"
#import "ios/chrome/browser/policy/policy_util.h"
#import "ios/chrome/browser/settings/sync/utils/sync_util.h"
#import "ios/chrome/browser/shared/model/application_context/application_context.h"
#import "ios/chrome/browser/shared/model/prefs/pref_names.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/chrome/browser/shared/ui/list_model/list_model.h"
#import "ios/chrome/browser/shared/ui/symbols/symbols.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_info_button_item_delegate.h"
#import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
#import "ios/chrome/browser/ui/settings/cells/settings_image_detail_text_item.h"
#import "ios/chrome/browser/ui/settings/privacy/privacy_constants.h"
#import "ios/chrome/browser/ui/settings/privacy/privacy_safe_browsing_consumer.h"
#import "ios/chrome/browser/ui/settings/privacy/privacy_safe_browsing_navigation_commands.h"
#import "ios/chrome/browser/ui/settings/utils/observable_boolean.h"
#import "ios/chrome/browser/ui/settings/utils/pref_backed_boolean.h"
#import "ios/chrome/common/ui/colors/semantic_color_names.h"
#import "ios/chrome/grit/ios_chromium_strings.h"
#import "ios/chrome/grit/ios_strings.h"
#import "ui/base/l10n/l10n_util.h"
using ItemArray = NSArray<TableViewItem*>*;
namespace {
// The size of the symbol image.
CGFloat kSymbolImagePointSize = 17.;
// List of item types.
typedef NS_ENUM(NSInteger, ItemType) {
ItemTypeSafeBrowsingStandardProtection = kItemTypeEnumZero,
ItemTypeSafeBrowsingEnhancedProtection,
ItemTypeSafeBrowsingNoProtection,
};
} // namespace
@interface PrivacySafeBrowsingMediator () <BooleanObserver,
TableViewInfoButtonItemDelegate>
// Preference value for the enhanced safe browsing feature.
@property(nonatomic, strong, readonly)
PrefBackedBoolean* safeBrowsingEnhancedProtectionPreference;
// Preference value for the standard safe browsing feature.
@property(nonatomic, strong, readonly)
PrefBackedBoolean* safeBrowsingStandardProtectionPreference;
// All the items for the safe browsing section.
@property(nonatomic, strong, readonly) ItemArray safeBrowsingItems;
// User pref service used to check if a specific pref is managed by enterprise
// policies.
@property(nonatomic, assign, readonly) PrefService* userPrefService;
// Boolean to check if safe browsing is controlled by enterprise.
@property(nonatomic, readonly) BOOL enterpriseEnabled;
@end
@implementation PrivacySafeBrowsingMediator
@synthesize safeBrowsingItems = _safeBrowsingItems;
- (instancetype)initWithUserPrefService:(PrefService*)userPrefService {
self = [super init];
if (self) {
DCHECK(userPrefService);
_userPrefService = userPrefService;
_safeBrowsingEnhancedProtectionPreference = [[PrefBackedBoolean alloc]
initWithPrefService:userPrefService
prefName:prefs::kSafeBrowsingEnhanced];
_safeBrowsingEnhancedProtectionPreference.observer = self;
_safeBrowsingStandardProtectionPreference = [[PrefBackedBoolean alloc]
initWithPrefService:userPrefService
prefName:prefs::kSafeBrowsingEnabled];
_safeBrowsingStandardProtectionPreference.observer = self;
}
return self;
}
- (void)selectSettingItem:(TableViewItem*)item {
// If item is already selected or if we cancel turning off Safe Browsing,
// don't do anything and keep the current selected choice.
ItemType type = static_cast<ItemType>(item.type);
if (item == nil || [self shouldItemTypeHaveCheckmark:type]) {
[self updatePrivacySafeBrowsingSectionAndNotifyConsumer:YES];
return;
}
// Show checkmark for selected item and update associated preference value by
// setting the SafeBrowsingState.
safe_browsing::SafeBrowsingState safeBrowsingState =
safe_browsing::SafeBrowsingState::NO_SAFE_BROWSING;
switch (type) {
case ItemTypeSafeBrowsingEnhancedProtection:
safeBrowsingState = safe_browsing::SafeBrowsingState::ENHANCED_PROTECTION;
break;
case ItemTypeSafeBrowsingStandardProtection:
safeBrowsingState = safe_browsing::SafeBrowsingState::STANDARD_PROTECTION;
break;
case ItemTypeSafeBrowsingNoProtection:
safeBrowsingState = safe_browsing::SafeBrowsingState::NO_SAFE_BROWSING;
break;
default:
NOTREACHED();
break;
}
safe_browsing::SetSafeBrowsingState(self.userPrefService, safeBrowsingState);
[self updatePrivacySafeBrowsingSectionAndNotifyConsumer:YES];
}
#pragma mark - Properties
- (ItemArray)safeBrowsingItems {
if (!_safeBrowsingItems) {
NSMutableArray* items = [NSMutableArray array];
NSInteger enhancedProtectionSummary;
if (base::FeatureList::IsEnabled(
safe_browsing::kFriendlierSafeBrowsingSettingsEnhancedProtection)) {
enhancedProtectionSummary =
IDS_IOS_PRIVACY_SAFE_BROWSING_ENHANCED_PROTECTION_FRIENDLIER_SUMMARY;
} else {
enhancedProtectionSummary =
IDS_IOS_PRIVACY_SAFE_BROWSING_ENHANCED_PROTECTION_SUMMARY;
}
NSInteger standardProtectionSummary;
if (base::FeatureList::IsEnabled(
safe_browsing::kFriendlierSafeBrowsingSettingsStandardProtection)) {
standardProtectionSummary =
IDS_IOS_PRIVACY_SAFE_BROWSING_STANDARD_PROTECTION_FRIENDLIER_SUMMARY;
} else {
standardProtectionSummary =
IDS_IOS_PRIVACY_SAFE_BROWSING_STANDARD_PROTECTION_SUMMARY;
}
TableViewInfoButtonItem* safeBrowsingEnhancedProtectionItem = [self
infoButtonItemType:ItemTypeSafeBrowsingEnhancedProtection
titleId:
IDS_IOS_PRIVACY_SAFE_BROWSING_ENHANCED_PROTECTION_TITLE
detailText:enhancedProtectionSummary
accessibilityIdentifier:kSettingsSafeBrowsingEnhancedProtectionCellId];
[items addObject:safeBrowsingEnhancedProtectionItem];
TableViewInfoButtonItem* safeBrowsingStandardProtectionItem = [self
infoButtonItemType:ItemTypeSafeBrowsingStandardProtection
titleId:
IDS_IOS_PRIVACY_SAFE_BROWSING_STANDARD_PROTECTION_TITLE
detailText:standardProtectionSummary
accessibilityIdentifier:kSettingsSafeBrowsingStandardProtectionCellId];
[items addObject:safeBrowsingStandardProtectionItem];
NSInteger noProtectionSummary;
if (base::FeatureList::IsEnabled(
safe_browsing::kFriendlierSafeBrowsingSettingsEnhancedProtection)) {
noProtectionSummary =
IDS_IOS_PRIVACY_SAFE_BROWSING_NO_PROTECTION_FRIENDLIER_SUMMARY;
} else {
noProtectionSummary = IDS_IOS_PRIVACY_SAFE_BROWSING_NO_PROTECTION_SUMMARY;
}
if (self.enterpriseEnabled) {
TableViewInfoButtonItem* safeBrowsingNoProtectionItem = [self
infoButtonItemType:ItemTypeSafeBrowsingNoProtection
titleId:
IDS_IOS_PRIVACY_SAFE_BROWSING_NO_PROTECTION_TITLE
detailText:noProtectionSummary
accessibilityIdentifier:kSettingsSafeBrowsingNoProtectionCellId];
[items addObject:safeBrowsingNoProtectionItem];
} else {
TableViewInfoButtonItem* safeBrowsingNoProtectionItem = [self
infoButtonItemType:ItemTypeSafeBrowsingNoProtection
titleId:
IDS_IOS_PRIVACY_SAFE_BROWSING_NO_PROTECTION_TITLE
detailText:noProtectionSummary
accessibilityIdentifier:kSettingsSafeBrowsingNoProtectionCellId];
safeBrowsingNoProtectionItem.infoButtonIsHidden = YES;
[items addObject:safeBrowsingNoProtectionItem];
}
_safeBrowsingItems = items;
}
return _safeBrowsingItems;
}
- (void)setConsumer:(id<PrivacySafeBrowsingConsumer>)consumer {
if (_consumer == consumer)
return;
_consumer = consumer;
[_consumer setSafeBrowsingItems:self.safeBrowsingItems];
[_consumer setEnterpriseEnabled:self.enterpriseEnabled];
}
- (BOOL)enterpriseEnabled {
return self.userPrefService->IsManagedPreference(prefs::kSafeBrowsingEnabled);
}
#pragma mark - Private
// Creates item with an image checkmark and an info button.
- (TableViewInfoButtonItem*)infoButtonItemType:(NSInteger)type
titleId:(NSInteger)titleId
detailText:(NSInteger)detailText
accessibilityIdentifier:
(NSString*)accessibilityIdentifier {
TableViewInfoButtonItem* infoButtonItem =
[[TableViewInfoButtonItem alloc] initWithType:type];
infoButtonItem.text = l10n_util::GetNSString(titleId);
infoButtonItem.detailText = l10n_util::GetNSString(detailText);
// If Safe Browsing is controlled by enterprise, make non-selected options
// greyed out.
if (self.enterpriseEnabled && ![self shouldItemTypeHaveCheckmark:type]) {
infoButtonItem.textColor =
[[UIColor colorNamed:kTextPrimaryColor] colorWithAlphaComponent:0.4f];
infoButtonItem.detailTextColor =
[[UIColor colorNamed:kTextSecondaryColor] colorWithAlphaComponent:0.4f];
infoButtonItem.accessibilityHint = l10n_util::GetNSString(
IDS_IOS_TOGGLE_SETTING_MANAGED_ACCESSIBILITY_HINT);
} else {
infoButtonItem.accessibilityActivationPointOnButton = NO;
infoButtonItem.accessibilityHint = l10n_util::GetNSString(
IDS_IOS_TABLE_VIEW_INFO_BUTTON_ITEM_ACCESSIBILITY_TAP);
}
UIImageConfiguration* configuration = [UIImageSymbolConfiguration
configurationWithPointSize:kSymbolImagePointSize
weight:UIImageSymbolWeightSemibold
scale:UIImageSymbolScaleMedium];
infoButtonItem.iconImage =
DefaultSymbolWithConfiguration(kCheckmarkSymbol, configuration);
infoButtonItem.iconTintColor = [self shouldItemTypeHaveCheckmark:type]
? [UIColor colorNamed:kBlueColor]
: [UIColor clearColor];
infoButtonItem.accessibilityIdentifier = accessibilityIdentifier;
infoButtonItem.accessibilityDelegate = self;
return infoButtonItem;
}
// Returns whether an ItemType should have a checkmark based on its
// SafeBrowsingState.
- (BOOL)shouldItemTypeHaveCheckmark:(NSInteger)itemType {
ItemType type = static_cast<ItemType>(itemType);
safe_browsing::SafeBrowsingState safeBrowsingState =
safe_browsing::GetSafeBrowsingState(*self.userPrefService);
switch (type) {
case ItemTypeSafeBrowsingEnhancedProtection:
return safeBrowsingState ==
safe_browsing::SafeBrowsingState::ENHANCED_PROTECTION;
case ItemTypeSafeBrowsingStandardProtection:
return safeBrowsingState ==
safe_browsing::SafeBrowsingState::STANDARD_PROTECTION;
case ItemTypeSafeBrowsingNoProtection:
return safeBrowsingState ==
safe_browsing::SafeBrowsingState::NO_SAFE_BROWSING;
default:
NOTREACHED();
return NO;
}
}
// Updates the privacy safe browsing section according to the user consent. If
// `notifyConsumer` is YES, the consumer is notified about model changes.
- (void)updatePrivacySafeBrowsingSectionAndNotifyConsumer:(BOOL)notifyConsumer {
for (TableViewItem* item in self.safeBrowsingItems) {
TableViewInfoButtonItem* infoButtonItem =
base::apple::ObjCCast<TableViewInfoButtonItem>(item);
ItemType type = static_cast<ItemType>(item.type);
infoButtonItem.iconTintColor = [self shouldItemTypeHaveCheckmark:type]
? [UIColor colorNamed:kBlueColor]
: [UIColor clearColor];
}
if (notifyConsumer) {
[self.consumer reloadCellsForItems];
[self selectItem];
}
}
// Check if selected row should display enterprise popover.
- (BOOL)shouldEnterprisePopOverDisplay:(TableViewItem*)item {
ItemType type = static_cast<ItemType>(item.type);
return self.enterpriseEnabled && (![self shouldItemTypeHaveCheckmark:type] ||
type == ItemTypeSafeBrowsingNoProtection);
}
#pragma mark - SafeBrowsingViewControllerDelegate
- (void)didSelectItem:(TableViewItem*)item {
ItemType type = static_cast<ItemType>(item.type);
if (type == ItemTypeSafeBrowsingEnhancedProtection) {
if ([self shouldItemTypeHaveCheckmark:type]) {
base::RecordAction(base::UserMetricsAction(
"SafeBrowsing.Settings.EnhancedProtectionExpandArrowClicked"));
[self.handler showSafeBrowsingEnhancedProtection];
} else {
base::RecordAction(base::UserMetricsAction(
"SafeBrowsing.Settings.EnhancedProtectionClicked"));
[self selectSettingItem:item];
}
}
if (type == ItemTypeSafeBrowsingStandardProtection) {
if ([self shouldItemTypeHaveCheckmark:type]) {
base::RecordAction(base::UserMetricsAction(
"SafeBrowsing.Settings.StandardProtectionExpandArrowClicked"));
[self.handler showSafeBrowsingStandardProtection];
} else {
base::RecordAction(base::UserMetricsAction(
"SafeBrowsing.Settings.StandardProtectionClicked"));
[self selectSettingItem:item];
}
}
if (type == ItemTypeSafeBrowsingNoProtection &&
![self shouldItemTypeHaveCheckmark:type]) {
base::RecordAction(base::UserMetricsAction(
"SafeBrowsing.Settings.DisableSafeBrowsingClicked"));
[self.handler showSafeBrowsingNoProtectionPopUp:item];
}
}
- (void)didTapInfoButton:(UIButton*)button onItem:(TableViewItem*)item {
if ([self shouldEnterprisePopOverDisplay:item]) {
[self.consumer showEnterprisePopUp:button];
return;
}
// Info button tap logic when not in enterprise mode.
ItemType type = static_cast<ItemType>(item.type);
switch (type) {
case ItemTypeSafeBrowsingEnhancedProtection:
base::RecordAction(base::UserMetricsAction(
"SafeBrowsing.Settings.EnhancedProtectionExpandArrowClicked"));
[self.handler showSafeBrowsingEnhancedProtection];
break;
case ItemTypeSafeBrowsingStandardProtection:
base::RecordAction(base::UserMetricsAction(
"SafeBrowsing.Settings.StandardProtectionExpandArrowClicked"));
[self.handler showSafeBrowsingStandardProtection];
break;
default:
NOTREACHED();
break;
}
}
- (void)selectItem {
for (TableViewItem* item in self.safeBrowsingItems) {
ItemType type = static_cast<ItemType>(item.type);
if ([self shouldItemTypeHaveCheckmark:type]) {
[self.consumer selectItem:item];
break;
}
}
}
#pragma mark - TableViewInfoButtonItemDelegate
- (void)handleTappedInfoButtonForItem:(TableViewItem*)item {
[self didTapInfoButton:nil onItem:item];
}
#pragma mark - BooleanObserver
- (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean {
[self updatePrivacySafeBrowsingSectionAndNotifyConsumer:YES];
}
@end