Commit 115ebd8b authored by harrisonsean's avatar harrisonsean Committed by Commit Bot

[iOS][Safety Check] Add further password support, ok and issues

Add support for safety check safe state and issues.

Issues support includes deleting/managing in settings and on site.

Add support for password check error popovers.

Tests coming in later cl

Bug: 1078782
Change-Id: I6c2b388fce4d397a1c1e01d161b4e0b35c91e9b3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2339322Reviewed-by: default avatarJavier Ernesto Flores Robles <javierrobles@chromium.org>
Reviewed-by: default avatarGauthier Ambard <gambard@chromium.org>
Commit-Queue: Sean Harrison <harrisonsean@chromium.org>
Cr-Commit-Position: refs/heads/master@{#797251}
parent 945fdda1
......@@ -331,6 +331,9 @@ locale. The strings in this file are specific to iOS.
<message name="IDS_IOS_PASSWORD_CHECK_ERROR" desc="Description of the password check cell, explaining that Password Check failed. [iOS only]" meaning="Password Check failed due to some error.">
Chromium can't check your passwords
</message>
<message name="IDS_IOS_PASSWORD_CHECK_ERROR_NO_PASSWORDS" desc="Description text for when password check cannot be run because the user has no saved passwords">
No saved passwords. Chromium can check your passwords when you save them.
</message>
<message name="IDS_IOS_PASSWORD_CHECK_ERROR_OFFLINE" desc="Text inside popover which is shown when the user wants to see detailed information about the error. [iOS only]" meaning="The user has no internet connection and can't check passwords.">
Chromium couldn't check your passwords. Try checking your internet connection.
</message>
......
79dd83f5a48633878501b3b1cc8eebd4123017b6
\ No newline at end of file
......@@ -331,6 +331,9 @@ locale. The strings in this file are specific to iOS.
<message name="IDS_IOS_PASSWORD_CHECK_ERROR" desc="Description of the password check cell, explaining that Password Check failed. [iOS only]" meaning="Password Check failed due to some error.">
Chrome can't check your passwords
</message>
<message name="IDS_IOS_PASSWORD_CHECK_ERROR_NO_PASSWORDS" desc="Description text for when password check cannot be run because the user has no saved passwords">
No saved passwords. Chrome can check your passwords when you save them.
</message>
<message name="IDS_IOS_PASSWORD_CHECK_ERROR_OFFLINE" desc="Text inside popover which is shown when the user wants to see detailed information about the error. [iOS only]" meaning="The user has no internet connection and can't check passwords.">
Chrome couldn't check your passwords. Try checking your internet connection.
</message>
......
......@@ -6,6 +6,8 @@
#include "base/mac/foundation_util.h"
#import "ios/chrome/browser/main/browser.h"
#import "ios/chrome/browser/ui/commands/application_commands.h"
#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.h"
#import "ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator_delegate.h"
#import "ios/chrome/browser/ui/settings/password/password_issue_with_form.h"
......@@ -52,6 +54,8 @@
if (self) {
_baseNavigationController = navigationController;
_manager = manager;
_dispatcher = HandlerForProtocol(self.browser->GetCommandDispatcher(),
ApplicationCommands);
}
return self;
}
......
......@@ -1317,7 +1317,6 @@ std::vector<std::unique_ptr<autofill::PasswordForm>> CopyOf(
browser:_browser
passwordCheckManager:_passwordCheck.get()];
_passwordIssuesCoordinator.delegate = self;
_passwordIssuesCoordinator.dispatcher = self.dispatcher;
_passwordIssuesCoordinator.reauthModule = _reauthenticationModule;
[_passwordIssuesCoordinator start];
}
......
......@@ -16,6 +16,8 @@ source_set("safety_check_ui") {
"//ios/chrome/app/strings",
"//ios/chrome/browser/ui:feature_flags",
"//ios/chrome/browser/ui/settings:settings_root",
"//ios/chrome/browser/ui/settings/cells",
"//ios/chrome/browser/ui/settings/cells:public",
"//ios/chrome/browser/ui/settings/utils",
"//ios/chrome/browser/ui/table_view",
"//ui/base",
......@@ -43,16 +45,22 @@ source_set("safety_check") {
"//ios/chrome/browser/content_settings",
"//ios/chrome/browser/main:public",
"//ios/chrome/browser/passwords",
"//ios/chrome/browser/signin",
"//ios/chrome/browser/sync",
"//ios/chrome/browser/ui:feature_flags",
"//ios/chrome/browser/ui/commands",
"//ios/chrome/browser/ui/coordinators:chrome_coordinators",
"//ios/chrome/browser/ui/settings:settings_root",
"//ios/chrome/browser/ui/settings/cells",
"//ios/chrome/browser/ui/settings/cells:public",
"//ios/chrome/browser/ui/settings/password",
"//ios/chrome/browser/ui/settings/utils",
"//ios/chrome/browser/ui/table_view",
"//ios/chrome/browser/ui/table_view/cells:cells_constants",
"//ios/chrome/browser/ui/util",
"//ios/chrome/common",
"//ios/chrome/common/ui/colors",
"//ios/chrome/common/ui/elements:popover_label_view_controller",
"//ui/base",
]
frameworks = [ "UIKit.framework" ]
......
......@@ -7,6 +7,7 @@
#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
@protocol ApplicationCommands;
@class SafetyCheckCoordinator;
// Delegate that allows to dereference the SafetyCheckCoordinator.
......@@ -20,6 +21,7 @@
// The coordinator for the Safety Check screen.
@interface SafetyCheckCoordinator : ChromeCoordinator
// Delegate to pass user interactions to the mediator.
@property(nonatomic, weak) id<SafetyCheckCoordinatorDelegate> delegate;
- (instancetype)initWithBaseViewController:(UIViewController*)viewController
......
......@@ -5,20 +5,32 @@
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_coordinator.h"
#include "base/mac/foundation_util.h"
#include "base/memory/scoped_refptr.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#include "ios/chrome/browser/main/browser.h"
#include "ios/chrome/browser/passwords/ios_chrome_password_check_manager.h"
#include "ios/chrome/browser/passwords/ios_chrome_password_check_manager_factory.h"
#include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h"
#import "ios/chrome/browser/signin/authentication_service_factory.h"
#include "ios/chrome/browser/sync/profile_sync_service_factory.h"
#import "ios/chrome/browser/sync/sync_setup_service.h"
#import "ios/chrome/browser/sync/sync_setup_service_factory.h"
#import "ios/chrome/browser/ui/commands/application_commands.h"
#import "ios/chrome/browser/ui/commands/browser_commands.h"
#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/chrome/browser/ui/settings/password/password_issues_coordinator.h"
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.h"
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_navigation_commands.h"
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
#import "ios/chrome/common/ui/elements/popover_label_view_controller.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface SafetyCheckCoordinator () <
PasswordIssuesCoordinatorDelegate,
SafetyCheckNavigationCommands,
SafetyCheckTableViewControllerPresentationDelegate>
......@@ -28,6 +40,13 @@
// The container view controller.
@property(nonatomic, strong) SafetyCheckTableViewController* viewController;
// Coordinator for passwords issues screen.
@property(nonatomic, strong)
PasswordIssuesCoordinator* passwordIssuesCoordinator;
// Dispatcher which can handle changing passwords on sites.
@property(nonatomic, strong) id<ApplicationCommands> handler;
@end
@implementation SafetyCheckCoordinator
......@@ -41,6 +60,8 @@
browser:browser];
if (self) {
_baseNavigationController = navigationController;
_handler = HandlerForProtocol(self.browser->GetCommandDispatcher(),
ApplicationCommands);
}
return self;
}
......@@ -53,12 +74,18 @@
initWithStyle:UITableViewStylePlain];
self.viewController = viewController;
scoped_refptr<IOSChromePasswordCheckManager> passwordCheckManager =
IOSChromePasswordCheckManagerFactory::GetForBrowserState(
self.browser->GetBrowserState());
self.mediator = [[SafetyCheckMediator alloc]
initWithUserPrefService:self.browser->GetBrowserState()->GetPrefs()
passwordCheckManager:IOSChromePasswordCheckManagerFactory::
GetForBrowserState(
self.browser->GetBrowserState())];
passwordCheckManager:passwordCheckManager
authService:AuthenticationServiceFactory::GetForBrowserState(
self.browser->GetBrowserState())
syncService:SyncSetupServiceFactory::GetForBrowserState(
self.browser->GetBrowserState())];
self.mediator.consumer = self.viewController;
self.mediator.handler = self;
self.viewController.serviceDelegate = self.mediator;
self.viewController.presentationDelegate = self;
......@@ -75,4 +102,57 @@
[self.delegate safetyCheckCoordinatorDidRemove:self];
}
#pragma mark - SafetyCheckNavigationCommands
- (void)showPasswordIssuesPage {
IOSChromePasswordCheckManager* passwordCheckManager =
IOSChromePasswordCheckManagerFactory::GetForBrowserState(
self.browser->GetBrowserState())
.get();
self.passwordIssuesCoordinator = [[PasswordIssuesCoordinator alloc]
initWithBaseNavigationController:self.baseNavigationController
browser:self.browser
passwordCheckManager:passwordCheckManager];
self.passwordIssuesCoordinator.delegate = self;
self.passwordIssuesCoordinator.reauthModule = nil;
[self.passwordIssuesCoordinator start];
}
- (void)showErrorInfoFrom:(UIButton*)buttonView
withText:(NSAttributedString*)text {
PopoverLabelViewController* errorInfoPopover =
[[PopoverLabelViewController alloc] initWithPrimaryAttributedString:text
secondaryAttributedString:nil];
errorInfoPopover.popoverPresentationController.sourceView = buttonView;
errorInfoPopover.popoverPresentationController.sourceRect = buttonView.bounds;
errorInfoPopover.popoverPresentationController.permittedArrowDirections =
UIPopoverArrowDirectionAny;
[self.viewController presentViewController:errorInfoPopover
animated:YES
completion:nil];
}
- (void)showUpdateOnAppStorePage {
// TODO(crbug.com/1078782): Add navigation to App Store Chrome page.
}
- (void)showSafeBrowsingPreferencePage {
// TODO(crbug.com/1078782): Add navigation to Safe Browsing preference page.
}
#pragma mark - PasswordIssuesCoordinatorDelegate
- (void)passwordIssuesCoordinatorDidRemove:
(PasswordIssuesCoordinator*)coordinator {
DCHECK_EQ(self.passwordIssuesCoordinator, coordinator);
[self.passwordIssuesCoordinator stop];
self.passwordIssuesCoordinator.delegate = nil;
self.passwordIssuesCoordinator = nil;
}
- (BOOL)willHandlePasswordDeletion:(const autofill::PasswordForm&)password {
return NO;
}
@end
......@@ -11,9 +11,12 @@
#import <UIKit/UIKit.h>
class AuthenticationService;
class IOSChromePasswordCheckManager;
class PrefService;
@protocol SafetyCheckConsumer;
@protocol SafetyCheckNavigationCommands;
class SyncSetupService;
@class SafetyCheckTableViewController;
......@@ -27,13 +30,19 @@ class PrefService;
- (instancetype)initWithUserPrefService:(PrefService*)userPrefService
passwordCheckManager:
(scoped_refptr<IOSChromePasswordCheckManager>)
passwordCheckManager NS_DESIGNATED_INITIALIZER;
passwordCheckManager
authService:(AuthenticationService*)authService
syncService:(SyncSetupService*)syncService
NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
// The consumer for the Safety Check mediator.
@property(nonatomic, weak) id<SafetyCheckConsumer> consumer;
// Handler used to navigate inside the safety check.
@property(nonatomic, weak) id<SafetyCheckNavigationCommands> handler;
@end
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_SAFETY_CHECK_SAFETY_CHECK_MEDIATOR_H_
......@@ -5,6 +5,10 @@
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.h"
#include "base/mac/foundation_util.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/prefs/pref_service.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
......@@ -14,18 +18,26 @@
#include "ios/chrome/browser/passwords/password_check_observer_bridge.h"
#include "ios/chrome/browser/passwords/password_store_observer_bridge.h"
#include "ios/chrome/browser/pref_names.h"
#import "ios/chrome/browser/signin/authentication_service.h"
#include "ios/chrome/browser/sync/sync_setup_service.h"
#import "ios/chrome/browser/ui/settings/cells/settings_check_item.h"
#import "ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item.h"
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_consumer.h"
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_navigation_commands.h"
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_table_view_controller.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/browser/ui/table_view/cells/table_view_cells_constants.h"
#import "ios/chrome/browser/ui/table_view/cells/table_view_text_item.h"
#import "ios/chrome/browser/ui/ui_feature_flags.h"
#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
#import "ios/chrome/common/string_util.h"
#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h"
#import "ios/chrome/common/ui/colors/semantic_color_names.h"
#include "ios/chrome/grit/ios_chromium_strings.h"
#include "ios/chrome/grit/ios_strings.h"
#import "net/base/mac/url_conversions.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
......@@ -132,7 +144,7 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
@property(nonatomic, assign) PasswordCheckRowStates passwordCheckRowState;
// Row button to start the safety check.
@property(nonatomic, strong) SettingsMultilineDetailItem* checkStartItem;
@property(nonatomic, strong) TableViewTextItem* checkStartItem;
// Current state of the start safety check row button.
@property(nonatomic, assign) CheckStartStates checkStartState;
......@@ -151,6 +163,12 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
// How many safety check items are still running (max 3).
@property(nonatomic, assign) int checkRunningRemaining;
// Service used to check if user is signed in.
@property(nonatomic, assign) AuthenticationService* authService;
// Service to check if passwords are synced.
@property(nonatomic, assign) SyncSetupService* syncService;
@end
@implementation SafetyCheckMediator
......@@ -158,11 +176,18 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
- (instancetype)initWithUserPrefService:(PrefService*)userPrefService
passwordCheckManager:
(scoped_refptr<IOSChromePasswordCheckManager>)
passwordCheckManager {
passwordCheckManager
authService:(AuthenticationService*)authService
syncService:(SyncSetupService*)syncService {
self = [super init];
if (self) {
DCHECK(userPrefService);
DCHECK(passwordCheckManager);
DCHECK(authService);
DCHECK(syncService);
_authService = authService;
_syncService = syncService;
_passwordCheckManager = passwordCheckManager;
_currentPasswordCheckState = _passwordCheckManager->GetPasswordCheckState();
......@@ -196,8 +221,9 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
_checkStartState = CheckStartStateDefault;
_checkStartItem =
[[SettingsMultilineDetailItem alloc] initWithType:CheckStartItemType];
[[TableViewTextItem alloc] initWithType:CheckStartItemType];
_checkStartItem.text = GetNSString(IDS_IOS_CHECK_PASSWORDS_NOW_BUTTON);
_checkStartItem.textColor = [UIColor colorNamed:kBlueColor];
}
return self;
}
......@@ -261,13 +287,10 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
case PasswordCheckRowStateSafe: // No tap action.
break;
case PasswordCheckRowStateUnSafe:
// Link to compromised password page.
break;
case PasswordCheckRowStateDisabled:
// Popover for no passwords.
[self.handler showPasswordIssuesPage];
break;
case PasswordCheckRowStateError:
// Various popover states
case PasswordCheckRowStateDisabled: // Popover handled by cellitem.
case PasswordCheckRowStateError: // Popover handled by cellitem.
break;
}
break;
......@@ -295,6 +318,23 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
}
}
- (BOOL)isItemWithErrorInfo:(TableViewItem*)item {
ItemType type = static_cast<ItemType>(item.type);
return (type != CheckStartItemType);
}
- (void)infoButtonWasTapped:(UIButton*)buttonView
usingItemType:(NSInteger)itemType {
NSAttributedString* info = [self getPopoverInfoForType:itemType];
// If |info| is empty there is no popover to display.
if (!info)
return;
// Push popover to coordinator.
[self.handler showErrorInfoFrom:buttonView withText:info];
}
#pragma mark - BooleanObserver
- (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean {
......@@ -305,6 +345,19 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
#pragma mark - Private methods
// Computes the text needed for a popover on |itemType| if available.
- (NSAttributedString*)getPopoverInfoForType:(NSInteger)itemType {
ItemType type = static_cast<ItemType>(itemType);
switch (type) {
case PasswordItemType:
return [self passwordCheckErrorInfo];
case SafeBrowsingItemType:
case UpdateItemType:
case CheckStartItemType:
return nil;
}
}
// Computes the appropriate display state of the password check row based on
// currentPasswordCheckState.
- (PasswordCheckRowStates)computePasswordCheckRowState:
......@@ -317,7 +370,7 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
case PasswordCheckState::kRunning:
return PasswordCheckRowStateRunning;
case PasswordCheckState::kNoPasswords:
return PasswordCheckRowStateDisabled;
return PasswordCheckRowStateDefault;
case PasswordCheckState::kSignedOut:
case PasswordCheckState::kOffline:
case PasswordCheckState::kQuotaLimit:
......@@ -340,6 +393,84 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
}
}
// Computes the appropriate error info to be displayed in the passwords popover.
- (NSAttributedString*)passwordCheckErrorInfo {
if (!self.passwordCheckManager->GetCompromisedCredentials().empty())
return nil;
NSString* message;
GURL linkURL;
switch (self.currentPasswordCheckState) {
case PasswordCheckState::kRunning:
case PasswordCheckState::kNoPasswords:
message =
l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECK_ERROR_NO_PASSWORDS);
break;
case PasswordCheckState::kCanceled:
case PasswordCheckState::kIdle:
return nil;
case PasswordCheckState::kSignedOut:
message = l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECK_ERROR_SIGNED_OUT);
break;
case PasswordCheckState::kOffline:
message = l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECK_ERROR_OFFLINE);
break;
case PasswordCheckState::kQuotaLimit:
if ([self canUseAccountPasswordCheckup]) {
message = l10n_util::GetNSString(
IDS_IOS_PASSWORD_CHECK_ERROR_QUOTA_LIMIT_VISIT_GOOGLE);
linkURL = password_manager::GetPasswordCheckupURL(
password_manager::PasswordCheckupReferrer::kPasswordCheck);
} else {
message =
l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECK_ERROR_QUOTA_LIMIT);
}
break;
case PasswordCheckState::kOther:
message = l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECK_ERROR_OTHER);
break;
}
return [self attributedStringWithText:message link:linkURL];
}
// Computes whether user is capable to run password check in Google Account.
- (BOOL)canUseAccountPasswordCheckup {
return (self.authService->IsAuthenticated() &&
self.authService->GetAuthenticatedIdentity()) &&
(self.syncService->IsSyncEnabled() &&
!self.syncService->IsEncryptEverythingEnabled());
}
// Configures check passwords error info with a link.
- (NSAttributedString*)attributedStringWithText:(NSString*)text
link:(GURL)link {
NSRange range;
NSString* strippedText = ParseStringWithLink(text, &range);
NSRange fullRange = NSMakeRange(0, strippedText.length);
NSMutableAttributedString* attributedText =
[[NSMutableAttributedString alloc] initWithString:strippedText];
[attributedText addAttribute:NSForegroundColorAttributeName
value:[UIColor colorNamed:kTextSecondaryColor]
range:fullRange];
[attributedText
addAttribute:NSFontAttributeName
value:[UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]
range:fullRange];
if (range.location != NSNotFound && range.length != 0) {
NSURL* URL = net::NSURLWithGURL(link);
id linkValue = URL ? URL : @"";
[attributedText addAttribute:NSLinkAttributeName
value:linkValue
range:range];
}
return attributedText;
}
// Upon a tap of checkStartItem either starts or cancels a safety check.
- (void)checkStartOrCancel {
// If a check is already running cancel it.
......@@ -355,6 +486,9 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
// Set remaining check running counter to 0.
self.checkRunningRemaining = 0;
// Stop any running checks.
self.passwordCheckManager->StopPasswordCheck();
} else {
// Otherwise start a check.
......@@ -375,6 +509,27 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
[self reconfigurePasswordCheckItem];
[self reconfigureSafeBrowsingCheckItem];
[self reconfigureCheckStartSection];
// The display should be changed to loading icons before any checks are
// started.
if (self.checkRunningRemaining > 0) {
// This handles a discrepancy between password check and safety check. In
// password check a user cannot start a check if they have no passwords, but
// in safety check they can, but the |passwordCheckManager| won't even start
// a check. This if block below allows safety check to push the disabled
// state after check now is pressed.
if (self.currentPasswordCheckState == PasswordCheckState::kNoPasswords) {
self.passwordCheckRowState = PasswordCheckRowStateDisabled;
// Want to show the loading wheel momentarily.
dispatch_after(
dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
[self reconfigurePasswordCheckItem];
});
} else {
self.passwordCheckManager->StartPasswordCheck();
}
}
}
// Reconfigures the display of the |updateCheckItem| based on current state of
......@@ -386,12 +541,11 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
self.updateCheckItem.infoButtonHidden = YES;
self.updateCheckItem.detailText = nil;
self.updateCheckItem.trailingImage = nil;
self.updateCheckItem.trailingImageTintColor = nil;
switch (self.updateCheckRowState) {
case UpdateCheckRowStateDefault: {
self.updateCheckItem.enabled = NO;
case UpdateCheckRowStateDefault:
break;
}
case UpdateCheckRowStateRunning: {
self.updateCheckItem.indicatorHidden = NO;
break;
......@@ -414,21 +568,49 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
self.passwordCheckItem.infoButtonHidden = YES;
self.passwordCheckItem.detailText = nil;
self.passwordCheckItem.trailingImage = nil;
self.passwordCheckItem.trailingImageTintColor = nil;
self.passwordCheckItem.accessoryType = UITableViewCellAccessoryNone;
switch (self.passwordCheckRowState) {
case PasswordCheckRowStateDefault: {
self.passwordCheckItem.enabled = NO;
case PasswordCheckRowStateDefault:
break;
}
case PasswordCheckRowStateRunning: {
self.passwordCheckItem.indicatorHidden = NO;
break;
}
case PasswordCheckRowStateSafe:
case PasswordCheckRowStateUnSafe:
case PasswordCheckRowStateSafe: {
DCHECK(self.passwordCheckManager->GetCompromisedCredentials().empty());
UIImage* safeIconImage = [[UIImage imageNamed:@"settings_safe_state"]
imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
self.passwordCheckItem.detailText =
base::SysUTF16ToNSString(l10n_util::GetPluralStringFUTF16(
IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT, 0));
self.passwordCheckItem.trailingImage = safeIconImage;
self.passwordCheckItem.trailingImageTintColor =
[UIColor colorNamed:kGreenColor];
break;
}
case PasswordCheckRowStateUnSafe: {
self.passwordCheckItem.detailText =
base::SysUTF16ToNSString(l10n_util::GetPluralStringFUTF16(
IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT,
self.passwordCheckManager->GetCompromisedCredentials().size()));
UIImage* unSafeIconImage = [[UIImage imageNamed:@"settings_unsafe_state"]
imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
self.passwordCheckItem.trailingImage = unSafeIconImage;
self.passwordCheckItem.trailingImageTintColor =
[UIColor colorNamed:kRedColor];
self.passwordCheckItem.accessoryType =
UITableViewCellAccessoryDisclosureIndicator;
break;
}
case PasswordCheckRowStateDisabled:
case PasswordCheckRowStateError:
case PasswordCheckRowStateError: {
self.passwordCheckItem.detailText =
l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECK_ERROR);
self.passwordCheckItem.infoButtonHidden = NO;
break;
}
}
[self.consumer reconfigureCellsForItems:@[ self.passwordCheckItem ]];
......@@ -443,12 +625,11 @@ typedef NS_ENUM(NSInteger, CheckStartStates) {
self.safeBrowsingCheckItem.infoButtonHidden = YES;
self.safeBrowsingCheckItem.detailText = nil;
self.safeBrowsingCheckItem.trailingImage = nil;
self.safeBrowsingCheckItem.trailingImageTintColor = nil;
switch (self.safeBrowsingCheckRowState) {
case SafeBrowsingCheckRowStateDefault: {
self.safeBrowsingCheckItem.enabled = NO;
case SafeBrowsingCheckRowStateDefault:
break;
}
case SafeBrowsingCheckRowStateRunning: {
self.safeBrowsingCheckItem.indicatorHidden = NO;
break;
......
......@@ -9,8 +9,18 @@
// controller.
@protocol SafetyCheckNavigationCommands
// TODO(crbug.com/1078782): Add navigation commands for updates, passwords, and
// safe browsing.
// Shows password issues page.
- (void)showPasswordIssuesPage;
// Opens Chrome page in App Store for updates.
- (void)showUpdateOnAppStorePage;
// Shows page with Safe Browsing preference toggle.
- (void)showSafeBrowsingPreferencePage;
// Shows the error popover with the corresponding |text|.
- (void)showErrorInfoFrom:(UIButton*)buttonView
withText:(NSAttributedString*)text;
@end
......
......@@ -15,6 +15,13 @@
// Called when item is tapped.
- (void)didSelectItem:(TableViewItem*)item;
// Checks if |item| should have an error popover.
- (BOOL)isItemWithErrorInfo:(TableViewItem*)item;
// Notifies the mediator that an info button was tapped for |itemType|.
- (void)infoButtonWasTapped:(UIButton*)buttonView
usingItemType:(NSInteger)itemType;
@end
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_SAFETY_CHECK_SAFETY_CHECK_SERVICE_DELEGATE_H_
......@@ -10,13 +10,10 @@
@protocol SafetyCheckServiceDelegate;
@class SafetyCheckTableViewController;
@protocol SafetyCheckTableViewControllerModelDelegate;
// The accessibility identifier of the privacy settings collection view.
extern NSString* const kSafetyCheckTableViewId;
@protocol SafetyCheckNavigationCommands;
// Delegate for presentation events related to
// SafetyCheckTableViewController.
@protocol SafetyCheckTableViewControllerPresentationDelegate
......@@ -40,9 +37,6 @@ extern NSString* const kSafetyCheckTableViewId;
// Handler for taps on items on the safety check page.
@property(nonatomic, weak) id<SafetyCheckServiceDelegate> serviceDelegate;
// Handler used to navigate inside the safety check.
@property(nonatomic, weak) id<SafetyCheckNavigationCommands> handler;
@end
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_SAFETY_CHECK_SAFETY_CHECK_TABLE_VIEW_CONTROLLER_H_
......@@ -6,6 +6,8 @@
#import "base/mac/foundation_util.h"
#include "components/strings/grit/components_strings.h"
#import "ios/chrome/browser/ui/settings/cells/settings_check_cell.h"
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_navigation_commands.h"
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_service_delegate.h"
#import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
#include "ios/chrome/browser/ui/ui_feature_flags.h"
......@@ -97,4 +99,31 @@ typedef NS_ENUM(NSInteger, SectionIdentifier) {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#pragma mark - UITableViewDataSource
- (UITableViewCell*)tableView:(UITableView*)tableView
cellForRowAtIndexPath:(NSIndexPath*)indexPath {
UITableViewCell* cell = [super tableView:tableView
cellForRowAtIndexPath:indexPath];
TableViewItem* item = [self.tableViewModel itemAtIndexPath:indexPath];
if ([self.serviceDelegate isItemWithErrorInfo:item]) {
SettingsCheckCell* settingsCheckCell =
base::mac::ObjCCastStrict<SettingsCheckCell>(cell);
settingsCheckCell.infoButton.tag = item.type;
[settingsCheckCell.infoButton addTarget:self
action:@selector(didTapErrorInfoButton:)
forControlEvents:UIControlEventTouchUpInside];
}
return cell;
}
#pragma mark - Private
// Called when user tapped on the information button of an
// item. Shows popover with detailed description of an error if needed.
- (void)didTapErrorInfoButton:(UIButton*)buttonView {
[self.serviceDelegate infoButtonWasTapped:buttonView
usingItemType:buttonView.tag];
}
@end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment