[go: nahoru, domu]

blob: d45cc3df3bc7b051da1c55a76d8b35754b99e6b0 [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/safe_browsing/safe_browsing_standard_protection_mediator.h"
#import "base/apple/foundation_util.h"
#import "base/notreached.h"
#import "components/password_manager/core/common/password_manager_pref_names.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 "components/signin/public/identity_manager/objc/identity_manager_observer_bridge.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_switch_item.h"
#import "ios/chrome/browser/signin/authentication_service.h"
#import "ios/chrome/browser/ui/settings/cells/safe_browsing_header_item.h"
#import "ios/chrome/browser/ui/settings/cells/sync_switch_item.h"
#import "ios/chrome/browser/ui/settings/privacy/safe_browsing/safe_browsing_constants.h"
#import "ios/chrome/browser/ui/settings/privacy/safe_browsing/safe_browsing_standard_protection_consumer.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_google_chrome_strings.h"
#import "ios/chrome/grit/ios_strings.h"
#import "ui/base/l10n/l10n_util.h"
using ItemArray = NSArray<TableViewItem*>*;
namespace {
// List of item types.
typedef NS_ENUM(NSInteger, ItemType) {
ItemTypeShieldIcon = kItemTypeEnumZero,
ItemTypeMetricIcon,
ItemTypePasswordLeakCheckSwitch,
ItemTypeSafeBrowsingExtendedReporting,
ItemTypeSafeBrowsingManagedExtendedReporting,
};
// The size of the symbols.
const CGFloat kSymbolSize = 20;
} // namespace
@interface SafeBrowsingStandardProtectionMediator () <
BooleanObserver,
IdentityManagerObserverBridgeDelegate> {
std::unique_ptr<signin::IdentityManagerObserverBridge>
_identityManagerObserver;
}
// User pref service used to check if a specific pref is managed by enterprise
// policies.
@property(nonatomic, assign, readonly) PrefService* userPrefService;
// Authentication service.
@property(nonatomic, assign, readonly) AuthenticationService* authService;
// Returns YES if the user has selected Standard Protection for the Safe
// Browsing choice.
@property(nonatomic, assign, readonly) BOOL inSafeBrowsingStandardProtection;
// Preference value for the Safe Browsing Enhanced Protection feature.
@property(nonatomic, strong, readonly)
PrefBackedBoolean* safeBrowsingEnhancedProtectionPreference;
// Preference value for the "Safe Browsing" feature.
@property(nonatomic, strong, readonly)
PrefBackedBoolean* safeBrowsingStandardProtectionPreference;
// Preference value for Safe Browsing Extended Reporting.
@property(nonatomic, strong, readonly)
PrefBackedBoolean* safeBrowsingExtendedReportingPreference;
// The observable boolean that binds to the password leak check settings
// state.
@property(nonatomic, strong, readonly)
PrefBackedBoolean* passwordLeakCheckPreference;
// The item related to the switch for the automatic password leak detection
// setting.
@property(nonatomic, strong, null_resettable)
TableViewSwitchItem* passwordLeakCheckItem;
// Header that has shield icon.
@property(nonatomic, strong) SafeBrowsingHeaderItem* shieldIconHeader;
// Second header which has a metric icon.
@property(nonatomic, strong) SafeBrowsingHeaderItem* metricIconHeader;
// All the items for the standard safe browsing section.
@property(nonatomic, strong, readonly)
ItemArray safeBrowsingStandardProtectionItems;
@end
@implementation SafeBrowsingStandardProtectionMediator
@synthesize safeBrowsingStandardProtectionItems =
_safeBrowsingStandardProtectionItems;
- (instancetype)initWithUserPrefService:(PrefService*)userPrefService
authService:(AuthenticationService*)authService
identityManager:
(signin::IdentityManager*)identityManager {
self = [super init];
if (self) {
DCHECK(userPrefService);
_userPrefService = userPrefService;
_authService = authService;
_identityManagerObserver =
std::make_unique<signin::IdentityManagerObserverBridge>(identityManager,
self);
_safeBrowsingEnhancedProtectionPreference = [[PrefBackedBoolean alloc]
initWithPrefService:userPrefService
prefName:prefs::kSafeBrowsingEnhanced];
_safeBrowsingEnhancedProtectionPreference.observer = self;
_safeBrowsingStandardProtectionPreference = [[PrefBackedBoolean alloc]
initWithPrefService:userPrefService
prefName:prefs::kSafeBrowsingEnabled];
_safeBrowsingStandardProtectionPreference.observer = self;
_safeBrowsingExtendedReportingPreference = [[PrefBackedBoolean alloc]
initWithPrefService:userPrefService
prefName:prefs::kSafeBrowsingScoutReportingEnabled];
_safeBrowsingExtendedReportingPreference.observer = self;
_passwordLeakCheckPreference = [[PrefBackedBoolean alloc]
initWithPrefService:userPrefService
prefName:password_manager::prefs::
kPasswordLeakDetectionEnabled];
_passwordLeakCheckPreference.observer = self;
}
return self;
}
- (void)disconnect {
_identityManagerObserver = nil;
}
#pragma mark - Properties
- (ItemArray)safeBrowsingStandardProtectionItems {
if (!_safeBrowsingStandardProtectionItems) {
NSMutableArray* items = [NSMutableArray array];
if (self.userPrefService->IsManagedPreference(
prefs::kSafeBrowsingEnabled)) {
TableViewInfoButtonItem* safeBrowsingManagedExtendedReportingItem = [self
tableViewInfoButtonItemType:
ItemTypeSafeBrowsingManagedExtendedReporting
textStringID:
IDS_IOS_SAFE_BROWSING_STANDARD_PROTECTION_EXTENDED_REPORTING_TITLE
detailStringID:
IDS_IOS_SAFE_BROWSING_STANDARD_PROTECTION_EXTENDED_REPORTING_SUMMARY
status:
self.safeBrowsingStandardProtectionPreference
.value];
[items addObject:safeBrowsingManagedExtendedReportingItem];
} else {
SyncSwitchItem* safeBrowsingExtendedReportingItem = [self
switchItemWithItemType:ItemTypeSafeBrowsingExtendedReporting
textStringID:
IDS_IOS_SAFE_BROWSING_STANDARD_PROTECTION_EXTENDED_REPORTING_TITLE
detailStringID:
IDS_IOS_SAFE_BROWSING_STANDARD_PROTECTION_EXTENDED_REPORTING_SUMMARY
defaultState:safe_browsing::IsExtendedReportingEnabled(
*self.userPrefService)
enabled:self.inSafeBrowsingStandardProtection];
safeBrowsingExtendedReportingItem.accessibilityIdentifier =
kSafeBrowsingExtendedReportingCellId;
[items addObject:safeBrowsingExtendedReportingItem];
}
[items addObject:self.passwordLeakCheckItem];
_safeBrowsingStandardProtectionItems = items;
}
return _safeBrowsingStandardProtectionItems;
}
- (SafeBrowsingHeaderItem*)shieldIconHeader {
if (!_shieldIconHeader) {
UIImage* shieldIcon;
shieldIcon = CustomSymbolWithPointSize(kPrivacySymbol, kSymbolSize);
SafeBrowsingHeaderItem* shieldIconItem = [self
detailItemWithType:ItemTypeShieldIcon
detailText:
IDS_IOS_SAFE_BROWSING_STANDARD_PROTECTION_BULLET_ONE
image:shieldIcon
accessibilityIdentifier:kSafeBrowsingStandardProtectionShieldCellId];
_shieldIconHeader = shieldIconItem;
}
return _shieldIconHeader;
}
- (SafeBrowsingHeaderItem*)metricIconHeader {
if (!_metricIconHeader) {
UIImage* metricIcon =
DefaultSymbolWithPointSize(kCheckmarkCircleSymbol, kSymbolSize);
SafeBrowsingHeaderItem* metricIconItem = [self
detailItemWithType:ItemTypeMetricIcon
detailText:
IDS_IOS_SAFE_BROWSING_STANDARD_PROTECTION_BULLET_TWO
image:metricIcon
accessibilityIdentifier:kSafeBrowsingStandardProtectionMetricCellId];
_metricIconHeader = metricIconItem;
}
return _metricIconHeader;
}
- (TableViewSwitchItem*)passwordLeakCheckItem {
if (!_passwordLeakCheckItem) {
TableViewSwitchItem* passwordLeakCheckItem = [[TableViewSwitchItem alloc]
initWithType:ItemTypePasswordLeakCheckSwitch];
passwordLeakCheckItem.text = l10n_util::GetNSString(
IDS_IOS_SAFE_BROWSING_STANDARD_PROTECTION_LEAK_CHECK_TITLE);
passwordLeakCheckItem.accessibilityIdentifier =
kSafeBrowsingStandardProtectionPasswordLeakCellId;
[self configureLeakCheckItem:passwordLeakCheckItem];
_passwordLeakCheckItem = passwordLeakCheckItem;
}
return _passwordLeakCheckItem;
}
- (void)setConsumer:(id<SafeBrowsingStandardProtectionConsumer>)consumer {
if (_consumer == consumer)
return;
_consumer = consumer;
[_consumer setSafeBrowsingStandardProtectionItems:
self.safeBrowsingStandardProtectionItems];
[_consumer setShieldIconHeader:self.shieldIconHeader];
[_consumer setMetricIconHeader:self.metricIconHeader];
}
- (BOOL)inSafeBrowsingStandardProtection {
return safe_browsing::GetSafeBrowsingState(*self.userPrefService) ==
safe_browsing::SafeBrowsingState::STANDARD_PROTECTION;
}
#pragma mark - Private
// Creates header in Standard Protection view.
- (SafeBrowsingHeaderItem*)detailItemWithType:(NSInteger)type
detailText:(NSInteger)detailText
image:(UIImage*)image
accessibilityIdentifier:
(NSString*)accessibilityIdentifier {
SafeBrowsingHeaderItem* detailItem =
[[SafeBrowsingHeaderItem alloc] initWithType:type];
detailItem.text = l10n_util::GetNSString(detailText);
detailItem.image = image;
detailItem.imageViewTintColor = [UIColor colorNamed:kGrey600Color];
detailItem.accessibilityIdentifier = accessibilityIdentifier;
return detailItem;
}
// Creates a TableViewInfoButtonItem instance used for items that the user is
// not allowed to switch on or off (enterprise reason for example).
- (TableViewInfoButtonItem*)tableViewInfoButtonItemType:(NSInteger)itemType
textStringID:(int)textStringID
detailStringID:(int)detailStringID
status:(BOOL)status {
TableViewInfoButtonItem* managedItem =
[[TableViewInfoButtonItem alloc] initWithType:itemType];
managedItem.text = l10n_util::GetNSString(textStringID);
managedItem.detailText = l10n_util::GetNSString(detailStringID);
managedItem.statusText = status ? l10n_util::GetNSString(IDS_IOS_SETTING_ON)
: l10n_util::GetNSString(IDS_IOS_SETTING_OFF);
if (!status) {
managedItem.iconTintColor = [UIColor colorNamed:kGrey300Color];
// This item is not controllable, then set the color opacity to 40%.
managedItem.textColor =
[[UIColor colorNamed:kTextPrimaryColor] colorWithAlphaComponent:0.4f];
managedItem.detailTextColor =
[[UIColor colorNamed:kTextSecondaryColor] colorWithAlphaComponent:0.4f];
managedItem.accessibilityHint = l10n_util::GetNSString(
IDS_IOS_TOGGLE_SETTING_MANAGED_ACCESSIBILITY_HINT);
}
return managedItem;
}
// Creates an item with a switch toggle.
- (SyncSwitchItem*)switchItemWithItemType:(NSInteger)itemType
textStringID:(int)textStringID
detailStringID:(int)detailStringID
defaultState:(BOOL)defaultState
enabled:(BOOL)enabled {
SyncSwitchItem* switchItem = [[SyncSwitchItem alloc] initWithType:itemType];
switchItem.text = l10n_util::GetNSString(textStringID);
if (detailStringID)
switchItem.detailText = l10n_util::GetNSString(detailStringID);
switchItem.on = defaultState;
switchItem.enabled = enabled;
return switchItem;
}
// Updates switches' on and enabled status.
- (void)updateSafeBrowsingStandardProtectionModel {
for (TableViewItem* item in self.safeBrowsingStandardProtectionItems) {
ItemType type = static_cast<ItemType>(item.type);
switch (type) {
case ItemTypePasswordLeakCheckSwitch:
[self configureLeakCheckItem:item];
break;
case ItemTypeSafeBrowsingExtendedReporting: {
SyncSwitchItem* syncSwitchItem =
base::apple::ObjCCastStrict<SyncSwitchItem>(item);
syncSwitchItem.on =
safe_browsing::IsExtendedReportingEnabled(*self.userPrefService);
syncSwitchItem.enabled = self.inSafeBrowsingStandardProtection;
break;
}
case ItemTypeSafeBrowsingManagedExtendedReporting:
base::apple::ObjCCastStrict<TableViewInfoButtonItem>(item).statusText =
self.safeBrowsingExtendedReportingPreference.value
? l10n_util::GetNSString(IDS_IOS_SETTING_ON)
: l10n_util::GetNSString(IDS_IOS_SETTING_OFF);
break;
default:
break;
}
}
[self.consumer reloadCellsForItems];
}
// Returns a boolean indicating if the switch should appear as "On" or "Off"
// based on the sync preference, the sign in status, and if the user has
// selected Standard Protection as the Safe Browsing option.
- (BOOL)passwordLeakCheckItemOnState {
return self.safeBrowsingEnhancedProtectionPreference.value ||
(self.safeBrowsingStandardProtectionPreference.value &&
self.passwordLeakCheckPreference.value);
}
// Updates the detail text and on state of the leak check item based on the
// state.
- (void)configureLeakCheckItem:(TableViewItem*)item {
TableViewSwitchItem* leakCheckItem =
base::apple::ObjCCastStrict<TableViewSwitchItem>(item);
leakCheckItem.enabled = self.inSafeBrowsingStandardProtection;
leakCheckItem.on = [self passwordLeakCheckItemOnState];
if (base::FeatureList::IsEnabled(
safe_browsing::kFriendlierSafeBrowsingSettingsStandardProtection)) {
leakCheckItem.detailText = l10n_util::GetNSString(
IDS_IOS_SAFE_BROWSING_STANDARD_PROTECTION_LEAK_CHECK_FRIENDLIER_SUMMARY);
} else {
leakCheckItem.detailText = l10n_util::GetNSString(
IDS_IOS_SAFE_BROWSING_STANDARD_PROTECTION_LEAK_CHECK_SUMMARY);
}
}
#pragma mark - SafeBrowsingStandardProtectionViewControllerDelegate
- (void)toggleSwitchItem:(TableViewItem*)item withValue:(BOOL)value {
SyncSwitchItem* syncSwitchItem = base::apple::ObjCCast<SyncSwitchItem>(item);
syncSwitchItem.on = value;
ItemType type = static_cast<ItemType>(item.type);
switch (type) {
case ItemTypeSafeBrowsingExtendedReporting:
self.safeBrowsingExtendedReportingPreference.value = value;
break;
case ItemTypePasswordLeakCheckSwitch:
self.passwordLeakCheckPreference.value = value;
break;
default:
// Not a switch.
NOTREACHED();
break;
}
}
#pragma mark - BooleanObserver
- (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean {
[self updateSafeBrowsingStandardProtectionModel];
}
#pragma mark - IdentityManagerObserverBridgeDelegate
// Used to update model when signing in/out is completed.
- (void)onPrimaryAccountChanged:
(const signin::PrimaryAccountChangeEvent&)event {
[self updateSafeBrowsingStandardProtectionModel];
}
@end