Commit 6c1c2a56 authored by Viktor Semeniuk's avatar Viktor Semeniuk Committed by Commit Bot

[iOS] Passwords Coordinator

This change refactors PasswordsTableViewController, by adding
PasswordsCoordinator. All code related to the presenting/dismissing of
the controllers was moved to the coordinator. Mediator moved to the
coordinator as well. Cleaned includes and deps.

Bug: 1128025

Change-Id: I240cc3ff658c26ff6d9f44fada7313885dff98bb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2398686
Commit-Queue: Viktor Semeniuk <vsemeniuk@google.com>
Reviewed-by: default avatarGauthier Ambard <gambard@chromium.org>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Cr-Commit-Position: refs/heads/master@{#806732}
parent b0398ace
......@@ -5,38 +5,24 @@
source_set("password") {
configs += [ "//build/config/compiler:enable_arc" ]
sources = [
"legacy_password_details_table_view_controller.h",
"legacy_password_details_table_view_controller.mm",
"legacy_password_details_table_view_controller_delegate.h",
"password_exporter.h",
"password_exporter.mm",
"password_issue_with_form.h",
"password_issue_with_form.mm",
"password_issues_coordinator.h",
"password_issues_coordinator.mm",
"password_issues_mediator.h",
"password_issues_mediator.mm",
"passwords_consumer.h",
"passwords_coordinator.h",
"passwords_coordinator.mm",
"passwords_mediator.h",
"passwords_mediator.mm",
"passwords_table_view_controller.h",
"passwords_table_view_controller.mm",
]
deps = [
":password_constants",
":password_ui",
"//base",
"//components/autofill/core/common",
"//components/google/core/common",
"//components/keyed_service/core",
"//components/password_manager/core/browser",
"//components/password_manager/core/common",
"//components/prefs",
"//components/strings",
"//components/url_formatter",
"//ios/chrome/app/strings",
"//ios/chrome/browser",
"//ios/chrome/browser",
"//ios/chrome/browser/browser_state",
"//ios/chrome/browser/main:public",
"//ios/chrome/browser/passwords",
......@@ -45,26 +31,11 @@ source_set("password") {
"//ios/chrome/browser/ui:feature_flags",
"//ios/chrome/browser/ui/commands",
"//ios/chrome/browser/ui/coordinators:chrome_coordinators",
"//ios/chrome/browser/ui/elements",
"//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/elements:enterprise_info_popover_view_controller",
"//ios/chrome/browser/ui/settings/password/password_details",
"//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:constants",
"//ios/chrome/common/ui/colors",
"//ios/chrome/common/ui/elements:popover_label_view_controller",
"//ios/chrome/common/ui/reauthentication",
"//ios/chrome/common/ui/util",
"//ios/third_party/material_components_ios",
"//ui/base",
"//ui/base",
"//ui/base/clipboard:clipboard_types",
"//url",
]
frameworks = [ "MobileCoreServices.framework" ]
......@@ -73,6 +44,11 @@ source_set("password") {
source_set("password_ui") {
configs += [ "//build/config/compiler:enable_arc" ]
sources = [
"legacy_password_details_table_view_controller.h",
"legacy_password_details_table_view_controller.mm",
"legacy_password_details_table_view_controller_delegate.h",
"password_exporter.h",
"password_exporter.mm",
"password_issue.h",
"password_issue_content_item.h",
"password_issue_content_item.mm",
......@@ -80,23 +56,51 @@ source_set("password_ui") {
"password_issues_presenter.h",
"password_issues_table_view_controller.h",
"password_issues_table_view_controller.mm",
"passwords_consumer.h",
"passwords_settings_commands.h",
"passwords_table_view_controller.h",
"passwords_table_view_controller.mm",
"passwords_table_view_controller_delegate.h",
"passwords_table_view_controller_presentation_delegate.h",
]
deps = [
":password_constants",
"//base",
"//components/autofill/core/common",
"//components/google/core/common",
"//components/password_manager/core/browser",
"//components/password_manager/core/common",
"//components/prefs",
"//components/strings",
"//components/url_formatter",
"//ios/chrome/app/strings:ios_strings_grit",
"//ios/chrome/app/strings",
"//ios/chrome/browser",
"//ios/chrome/browser/browser_state",
"//ios/chrome/browser/main:public",
"//ios/chrome/browser/passwords",
"//ios/chrome/browser/signin",
"//ios/chrome/browser/ui:feature_flags",
"//ios/chrome/browser/ui/commands",
"//ios/chrome/browser/ui/elements",
"//ios/chrome/browser/ui/settings:settings_root",
"//ios/chrome/browser/ui/settings/autofill",
"//ios/chrome/browser/ui/settings/cells",
"//ios/chrome/browser/ui/settings/cells:public",
"//ios/chrome/browser/ui/settings/elements:enterprise_info_popover_view_controller",
"//ios/chrome/browser/ui/settings/password/password_details",
"//ios/chrome/browser/ui/settings/utils",
"//ios/chrome/browser/ui/table_view",
"//ios/chrome/browser/ui/table_view/cells",
"//ios/chrome/browser/ui/table_view/cells:cells_constants",
"//ios/chrome/browser/ui/util",
"//ios/chrome/common",
"//ios/chrome/common:constants",
"//ios/chrome/common/ui/colors",
"//ios/chrome/common/ui/elements:popover_label_view_controller",
"//ios/chrome/common/ui/reauthentication",
"//ios/chrome/common/ui/util",
"//ios/third_party/material_components_ios",
"//ui/base",
"//ui/base/clipboard:clipboard_types",
]
}
......@@ -116,7 +120,7 @@ source_set("test_support") {
"legacy_password_details_table_view_controller+testing.h",
"password_exporter_for_testing.h",
]
deps = [ ":password" ]
deps = [ ":password_ui" ]
}
source_set("unit_tests") {
......
......@@ -7,6 +7,13 @@
#import <Foundation/Foundation.h>
#include <memory>
#include <vector>
namespace autofill {
struct PasswordForm;
}
// Enum with all possible UI states of password check.
typedef NS_ENUM(NSInteger, PasswordCheckUIState) {
// When no compromised passwords were detected.
......@@ -27,7 +34,8 @@ typedef NS_ENUM(NSInteger, PasswordCheckUIState) {
@protocol PasswordsConsumer <NSObject>
// Displays current password check UI state on screen.
- (void)setPasswordCheckUIState:(PasswordCheckUIState)state;
- (void)setPasswordCheckUIState:(PasswordCheckUIState)state
compromisedPasswordsCount:(NSInteger)count;
// Displays password and blocked forms.
- (void)setPasswordsForms:
......
// Copyright 2020 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.
#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_COORDINATOR_H_
#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_COORDINATOR_H_
#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
class Browser;
@class PasswordsCoordinator;
// Delegate for PasswordsCoordinator.
@protocol PasswordsCoordinatorDelegate
// Called when the view controller is removed from navigation controller.
- (void)passwordsCoordinatorDidRemove:(PasswordsCoordinator*)coordinator;
@end
// This coordinator presents a list of saved passwords and some passwords
// related features.
@interface PasswordsCoordinator : ChromeCoordinator
- (instancetype)initWithBaseNavigationController:
(UINavigationController*)navigationController
browser:(Browser*)browser
NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithBaseViewController:(UIViewController*)viewController
browser:(Browser*)browser NS_UNAVAILABLE;
// Starts password check. For example, used by PasswordBreachDialog to
// automatically start the check.
- (void)checkSavedPasswords;
@property(nonatomic, weak) id<PasswordsCoordinatorDelegate> delegate;
@property(nonatomic, strong, readonly) UIViewController* viewController;
@end
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_COORDINATOR_H_
// Copyright 2020 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/password/passwords_coordinator.h"
#include "base/metrics/histogram_functions.h"
#include "components/keyed_service/core/service_access_type.h"
#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/password_store.h"
#include "components/password_manager/core/common/password_manager_features.h"
#import "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"
#include "ios/chrome/browser/signin/authentication_service_factory.h"
#include "ios/chrome/browser/sync/sync_setup_service_factory.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/legacy_password_details_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_delegate.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_issues_coordinator.h"
#import "ios/chrome/browser/ui/settings/password/passwords_consumer.h"
#import "ios/chrome/browser/ui/settings/password/passwords_mediator.h"
#import "ios/chrome/browser/ui/settings/password/passwords_settings_commands.h"
#import "ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/password/passwords_table_view_controller_presentation_delegate.h"
#include "ios/chrome/browser/ui/ui_feature_flags.h"
#import "ios/chrome/common/ui/reauthentication/reauthentication_module.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface PasswordsCoordinator () <
LegacyPasswordDetailsTableViewControllerDelegate,
PasswordDetailsCoordinatorDelegate,
PasswordIssuesCoordinatorDelegate,
PasswordsSettingsCommands,
PasswordsTableViewControllerPresentationDelegate>
// Main view controller for this coordinator.
@property(nonatomic, strong)
PasswordsTableViewController* passwordsViewController;
// Main mediator for this coordinator.
@property(nonatomic, strong) PasswordsMediator* mediator;
// Reauthentication module used by passwords export and password details.
@property(nonatomic, strong) ReauthenticationModule* reauthModule;
// The dispatcher used by |viewController|.
@property(nonatomic, weak)
id<ApplicationCommands, BrowserCommands, BrowsingDataCommands>
dispatcher;
// Coordinator for password details.
@property(nonatomic, strong)
PasswordIssuesCoordinator* passwordIssuesCoordinator;
// Coordinator for password details.
@property(nonatomic, strong)
PasswordDetailsCoordinator* passwordDetailsCoordinator;
@end
@implementation PasswordsCoordinator
@synthesize baseNavigationController = _baseNavigationController;
- (instancetype)initWithBaseNavigationController:
(UINavigationController*)navigationController
browser:(Browser*)browser {
self = [super initWithBaseViewController:navigationController
browser:browser];
if (self) {
_baseNavigationController = navigationController;
_dispatcher = static_cast<
id<BrowserCommands, ApplicationCommands, BrowsingDataCommands>>(
browser->GetCommandDispatcher());
}
return self;
}
- (void)checkSavedPasswords {
[self.mediator startPasswordCheck];
base::UmaHistogramEnumeration(
"PasswordManager.BulkCheck.UserAction",
password_manager::metrics_util::PasswordCheckInteraction::
kAutomaticPasswordCheck);
}
- (UIViewController*)viewController {
return self.passwordsViewController;
}
#pragma mark - ChromeCoordinator
- (void)start {
self.mediator = [[PasswordsMediator alloc]
initWithPasswordStore:IOSChromePasswordStoreFactory::GetForBrowserState(
self.browser->GetBrowserState(),
ServiceAccessType::EXPLICIT_ACCESS)
passwordCheckManager:[self passwordCheckManager]
authService:AuthenticationServiceFactory::GetForBrowserState(
self.browser->GetBrowserState())
syncService:SyncSetupServiceFactory::GetForBrowserState(
self.browser->GetBrowserState())];
self.reauthModule = [[ReauthenticationModule alloc]
initWithSuccessfulReauthTimeAccessor:self.mediator];
self.passwordsViewController =
[[PasswordsTableViewController alloc] initWithBrowser:self.browser];
self.passwordsViewController.handler = self;
self.passwordsViewController.delegate = self.mediator;
self.passwordsViewController.dispatcher = self.dispatcher;
self.passwordsViewController.presentationDelegate = self;
self.passwordsViewController.reauthenticationModule = self.reauthModule;
self.mediator.consumer = self.passwordsViewController;
[self.baseNavigationController pushViewController:self.passwordsViewController
animated:YES];
}
- (void)stop {
self.passwordsViewController = nil;
[self.passwordIssuesCoordinator stop];
self.passwordIssuesCoordinator.delegate = nil;
self.passwordIssuesCoordinator = nil;
[self.passwordDetailsCoordinator stop];
self.passwordDetailsCoordinator.delegate = nil;
self.passwordDetailsCoordinator = nil;
}
#pragma mark - PasswordsSettingsCommands
- (void)showCompromisedPasswords {
DCHECK(!self.passwordIssuesCoordinator);
self.passwordIssuesCoordinator = [[PasswordIssuesCoordinator alloc]
initWithBaseNavigationController:self.baseNavigationController
browser:self.browser
passwordCheckManager:[self passwordCheckManager].get()];
self.passwordIssuesCoordinator.delegate = self;
self.passwordIssuesCoordinator.reauthModule = self.reauthModule;
[self.passwordIssuesCoordinator start];
}
- (void)showDetailedViewForForm:(const autofill::PasswordForm&)form {
if (base::FeatureList::IsEnabled(
password_manager::features::kPasswordCheck)) {
DCHECK(!self.passwordDetailsCoordinator);
self.passwordDetailsCoordinator = [[PasswordDetailsCoordinator alloc]
initWithBaseNavigationController:self.baseNavigationController
browser:self.browser
password:form
reauthModule:self.reauthModule
passwordCheckManager:[self passwordCheckManager].get()];
self.passwordDetailsCoordinator.delegate = self;
[self.passwordDetailsCoordinator start];
} else {
LegacyPasswordDetailsTableViewController* controller =
[[LegacyPasswordDetailsTableViewController alloc]
initWithPasswordForm:form
delegate:self
reauthenticationModule:self.reauthModule];
controller.dispatcher = self.dispatcher;
[self.baseNavigationController pushViewController:controller animated:YES];
}
}
#pragma mark - PasswordsTableViewControllerPresentationDelegate
- (void)passwordsTableViewControllerDismissed {
[self.delegate passwordsCoordinatorDidRemove:self];
}
#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 {
[self.passwordsViewController deletePasswordForm:password];
return YES;
}
#pragma mark PasswordDetailsCoordinatorDelegate
- (void)passwordDetailsCoordinatorDidRemove:
(PasswordDetailsCoordinator*)coordinator {
DCHECK_EQ(self.passwordDetailsCoordinator, coordinator);
[self.passwordDetailsCoordinator stop];
self.passwordDetailsCoordinator.delegate = nil;
self.passwordDetailsCoordinator = nil;
}
- (void)passwordDetailsCoordinator:(PasswordDetailsCoordinator*)coordinator
deletePassword:(const autofill::PasswordForm&)password {
DCHECK_EQ(self.passwordDetailsCoordinator, coordinator);
[self.passwordsViewController deletePasswordForm:password];
}
#pragma mark LegacyPasswordDetailsTableViewControllerDelegate
- (void)passwordDetailsTableViewController:
(LegacyPasswordDetailsTableViewController*)controller
deletePassword:(const autofill::PasswordForm&)form {
[self.passwordsViewController deletePasswordForm:form];
}
#pragma mark Private
- (scoped_refptr<IOSChromePasswordCheckManager>)passwordCheckManager {
return IOSChromePasswordCheckManagerFactory::GetForBrowserState(
self.browser->GetBrowserState());
}
@end
......@@ -8,6 +8,8 @@
#import <Foundation/Foundation.h>
#include "base/memory/scoped_refptr.h"
#import "ios/chrome/browser/ui/settings/password/passwords_table_view_controller_delegate.h"
#import "ios/chrome/common/ui/reauthentication/reauthentication_module.h"
class AuthenticationService;
class IOSChromePasswordCheckManager;
......@@ -19,7 +21,8 @@ class PasswordStore;
}
// This mediator fetches and organises the passwords for its consumer.
@interface PasswordsMediator : NSObject
@interface PasswordsMediator : NSObject <PasswordsTableViewControllerDelegate,
SuccessfulReauthTimeAccessor>
- (instancetype)
initWithPasswordStore:
......@@ -34,15 +37,6 @@ class PasswordStore;
@property(nonatomic, weak) id<PasswordsConsumer> consumer;
// Returns detailed information about error if applicable.
- (NSAttributedString*)passwordCheckErrorInfo;
// Returns string containing the timestamp of the last password check. If the
// check finished less than 1 minute ago string will look "Last check just
// now.", otherwise "Last check X minutes/hours... ago.". If check never run
// string will be "Check never run.".
- (NSString*)formatElapsedTimeSinceLastCheck;
@end
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_MEDIATOR_H_
......@@ -16,9 +16,7 @@
#import "ios/chrome/browser/signin/authentication_service.h"
#include "ios/chrome/browser/sync/sync_setup_service.h"
#import "ios/chrome/browser/ui/settings/password/passwords_consumer.h"
#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
#include "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/semantic_color_names.h"
#include "ios/chrome/grit/ios_chromium_strings.h"
......@@ -68,6 +66,12 @@ constexpr base::TimeDelta kJustCheckedTimeThresholdInMinutes =
PasswordCheckState _currentState;
}
// Object storing the time of the previous successful re-authentication.
// This is meant to be used by the |ReauthenticationModule| for keeping
// re-authentications valid for a certain time interval within the scope
// of the Passwords Screen.
@property(nonatomic, strong, readonly) NSDate* successfulReauthTime;
@end
@implementation PasswordsMediator
......@@ -116,10 +120,44 @@ constexpr base::TimeDelta kJustCheckedTimeThresholdInMinutes =
password_manager::features::kPasswordCheck)) {
_currentState = _passwordCheckManager->GetPasswordCheckState();
[self.consumer setPasswordCheckUIState:
[self computePasswordCheckUIStateWith:_currentState]];
[self computePasswordCheckUIStateWith:_currentState]
compromisedPasswordsCount:_passwordCheckManager
->GetCompromisedCredentials()
.size()];
}
}
#pragma mark - PasswordsTableViewControllerDelegate
- (void)startPasswordCheck {
_passwordCheckManager->StartPasswordCheck();
}
- (NSString*)formatElapsedTimeSinceLastCheck {
base::Time lastCompletedCheck =
_passwordCheckManager->GetLastPasswordCheckTime();
// lastCompletedCheck is 0.0 in case the check never completely ran before.
if (lastCompletedCheck == base::Time())
return l10n_util::GetNSString(IDS_IOS_CHECK_NEVER_RUN);
base::TimeDelta elapsedTime = base::Time::Now() - lastCompletedCheck;
NSString* timestamp;
// If check finished in less than |kJustCheckedTimeThresholdInMinutes| show
// "just now" instead of timestamp.
if (elapsedTime < kJustCheckedTimeThresholdInMinutes)
timestamp = l10n_util::GetNSString(IDS_IOS_CHECK_FINISHED_JUST_NOW);
else
timestamp = base::SysUTF8ToNSString(
base::UTF16ToUTF8(ui::TimeFormat::SimpleWithMonthAndYear(
ui::TimeFormat::FORMAT_ELAPSED, ui::TimeFormat::LENGTH_LONG,
elapsedTime, true)));
return l10n_util::GetNSStringF(IDS_IOS_LAST_COMPLETED_CHECK,
base::SysNSStringToUTF16(timestamp));
}
- (NSAttributedString*)passwordCheckErrorInfo {
if (!_passwordCheckManager->GetCompromisedCredentials().empty())
return nil;
......@@ -165,7 +203,10 @@ constexpr base::TimeDelta kJustCheckedTimeThresholdInMinutes =
DCHECK(self.consumer);
[self.consumer
setPasswordCheckUIState:[self computePasswordCheckUIStateWith:state]];
setPasswordCheckUIState:[self computePasswordCheckUIStateWith:state]
compromisedPasswordsCount:_passwordCheckManager
->GetCompromisedCredentials()
.size()];
}
- (void)compromisedCredentialsDidChange:
......@@ -176,8 +217,10 @@ constexpr base::TimeDelta kJustCheckedTimeThresholdInMinutes =
return;
DCHECK(self.consumer);
[self.consumer setPasswordCheckUIState:
[self computePasswordCheckUIStateWith:_currentState]];
[self computePasswordCheckUIStateWith:_currentState]
compromisedPasswordsCount:credentials.size()];
}
#pragma mark - Private Methods
......@@ -265,29 +308,14 @@ constexpr base::TimeDelta kJustCheckedTimeThresholdInMinutes =
[self.consumer setPasswordsForms:std::move(results)];
}
- (NSString*)formatElapsedTimeSinceLastCheck {
base::Time lastCompletedCheck =
_passwordCheckManager->GetLastPasswordCheckTime();
// lastCompletedCheck is 0.0 in case the check never completely ran before.
if (lastCompletedCheck == base::Time())
return l10n_util::GetNSString(IDS_IOS_CHECK_NEVER_RUN);
base::TimeDelta elapsedTime = base::Time::Now() - lastCompletedCheck;
#pragma mark SuccessfulReauthTimeAccessor
NSString* timestamp;
// If check finished in less than |kJustCheckedTimeThresholdInMinutes| show
// "just now" instead of timestamp.
if (elapsedTime < kJustCheckedTimeThresholdInMinutes)
timestamp = l10n_util::GetNSString(IDS_IOS_CHECK_FINISHED_JUST_NOW);
else
timestamp = base::SysUTF8ToNSString(
base::UTF16ToUTF8(ui::TimeFormat::SimpleWithMonthAndYear(
ui::TimeFormat::FORMAT_ELAPSED, ui::TimeFormat::LENGTH_LONG,
elapsedTime, true)));
- (void)updateSuccessfulReauthTime {
_successfulReauthTime = [[NSDate alloc] init];
}
return l10n_util::GetNSStringF(IDS_IOS_LAST_COMPLETED_CHECK,
base::SysNSStringToUTF16(timestamp));
- (NSDate*)lastSuccessfulReauthTime {
return [self successfulReauthTime];
}
@end
......@@ -72,7 +72,8 @@ std::unique_ptr<KeyedService> BuildMockSyncSetupService(
@implementation FakePasswordsConsumer
- (void)setPasswordCheckUIState:(PasswordCheckUIState)state {
- (void)setPasswordCheckUIState:(PasswordCheckUIState)state
compromisedPasswordsCount:(NSInteger)count {
}
- (void)setPasswordsForms:
......
// Copyright 2020 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.
#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_SETTINGS_COMMANDS_H_
#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_SETTINGS_COMMANDS_H_
#import <Foundation/Foundation.h>
// Commands relative to the passwords in the Settings.
@protocol PasswordsSettingsCommands <NSObject>
// Shows the screen with password issues.
- (void)showCompromisedPasswords;
// Shows passwords details.
- (void)showDetailedViewForForm:(const autofill::PasswordForm&)form;
@end
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_SETTINGS_COMMANDS_H_
......@@ -5,34 +5,45 @@
#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_H_
#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_H_
#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller_delegate.h"
#import "ios/chrome/browser/ui/settings/password/passwords_consumer.h"
#import "ios/chrome/browser/ui/settings/settings_controller_protocol.h"
#import "ios/chrome/browser/ui/settings/settings_navigation_controller.h"
#import "ios/chrome/browser/ui/settings/settings_root_table_view_controller.h"
#import "ios/chrome/common/ui/reauthentication/reauthentication_module.h"
class Browser;
@protocol ReauthenticationProtocol;
@class PasswordExporter;
@protocol PasswordsSettingsCommands;
@protocol PasswordsTableViewControllerDelegate;
@protocol PasswordsTableViewControllerPresentationDelegate;
@interface PasswordsTableViewController
: SettingsRootTableViewController <SettingsControllerProtocol>
: SettingsRootTableViewController <PasswordsConsumer,
SettingsControllerProtocol>
// The designated initializer. |browser| must not be nil.
- (instancetype)initWithBrowser:(Browser*)browser NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithStyle:(UITableViewStyle)style NS_UNAVAILABLE;
// Starts password check.
- (void)startPasswordCheck;
// Deletes passed password form and updates list accordingly.
- (void)deletePasswordForm:(const autofill::PasswordForm&)form;
@end
@property(nonatomic, weak) id<PasswordsSettingsCommands> handler;
// Delegate.
@property(nonatomic, weak) id<PasswordsTableViewControllerDelegate> delegate;
@property(nonatomic, weak) id<PasswordsTableViewControllerPresentationDelegate>
presentationDelegate;
@interface PasswordsTableViewController (Testing) <
LegacyPasswordDetailsTableViewControllerDelegate>
// Reauthentication module.
@property(nonatomic, strong) id<ReauthenticationProtocol>
reauthenticationModule;
@end
// Initializes the password exporter with a (fake) |reauthenticationModule|.
- (void)setReauthenticationModuleForExporter:
(id<ReauthenticationProtocol>)reauthenticationModule;
@interface PasswordsTableViewController (Testing)
// Returns the password exporter to allow setting fake testing objects on it.
- (PasswordExporter*)getPasswordExporter;
......
// Copyright 2015 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.
#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_DELEGATE_H_
#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_DELEGATE_H_
#import <Foundation/Foundation.h>
// Delegate for |PasswordsTableViewController|.
@protocol PasswordsTableViewControllerDelegate
// Starts password check.
- (void)startPasswordCheck;
// Returns string containing the timestamp of the last password check. If the
// check finished less than 1 minute ago string will look "Last check just
// now.", otherwise "Last check X minutes/hours... ago.". If check never run
// string will be "Check never run.".
- (NSString*)formatElapsedTimeSinceLastCheck;
// Returns detailed information about Password Check error if applicable.
- (NSAttributedString*)passwordCheckErrorInfo;
@end
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_DELEGATE_H_
// Copyright 2015 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.
#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_PRESENTATION_DELEGATE_H_
#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_PRESENTATION_DELEGATE_H_
#import <Foundation/Foundation.h>
// Presentation delegate for |PasswordsTableViewController|.
@protocol PasswordsTableViewControllerPresentationDelegate
// Called when |PasswordsTableViewController| is dismissed.
- (void)passwordsTableViewControllerDismissed;
@end
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_TABLE_VIEW_CONTROLLER_PRESENTATION_DELEGATE_H_
......@@ -21,13 +21,14 @@
#include "ios/chrome/browser/main/test_browser.h"
#include "ios/chrome/browser/passwords/ios_chrome_bulk_leak_check_service_factory.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"
#include "ios/chrome/browser/passwords/password_check_observer_bridge.h"
#include "ios/chrome/browser/passwords/save_passwords_consumer.h"
#import "ios/chrome/browser/ui/settings/cells/settings_check_item.h"
#import "ios/chrome/browser/ui/settings/password/legacy_password_details_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/password/password_issues_coordinator.h"
#import "ios/chrome/browser/ui/settings/password/passwords_consumer.h"
#import "ios/chrome/browser/ui/settings/password/passwords_mediator.h"
#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
#import "ios/chrome/browser/ui/table_view/cells/table_view_detail_text_item.h"
#include "ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.h"
......@@ -57,7 +58,6 @@ using ::testing::Return;
// this file working.
@interface PasswordsTableViewController (Test) <
UISearchBarDelegate,
PasswordIssuesCoordinatorDelegate,
PasswordsConsumer>
- (void)updateExportPasswordsButton;
@end
......@@ -111,9 +111,21 @@ class PasswordsTableViewControllerTest
CreateController();
mediator_ = [[PasswordsMediator alloc]
initWithPasswordStore:IOSChromePasswordStoreFactory::GetForBrowserState(
browser_->GetBrowserState(),
ServiceAccessType::EXPLICIT_ACCESS)
passwordCheckManager:IOSChromePasswordCheckManagerFactory::
GetForBrowserState(
browser_->GetBrowserState())
authService:nil
syncService:nil];
// Inject some fake passwords to pass the loading state.
PasswordsTableViewController* passwords_controller =
static_cast<PasswordsTableViewController*>(controller());
passwords_controller.delegate = mediator_;
mediator_.consumer = passwords_controller;
[passwords_controller setPasswordsForms:{}];
}
......@@ -154,7 +166,9 @@ class PasswordsTableViewControllerTest
void ChangePasswordCheckState(PasswordCheckUIState state) {
PasswordsTableViewController* passwords_controller =
static_cast<PasswordsTableViewController*>(controller());
[passwords_controller setPasswordCheckUIState:state];
NSInteger count = GetTestStore().compromised_credentials().size();
[passwords_controller setPasswordCheckUIState:state
compromisedPasswordsCount:count];
}
// Adds a form to PasswordsTableViewController.
......@@ -284,6 +298,7 @@ class PasswordsTableViewControllerTest
web::WebTaskEnvironment task_environment_;
std::unique_ptr<TestBrowser> browser_;
base::test::ScopedFeatureList scoped_feature_list_;
PasswordsMediator* mediator_;
};
// Tests default case has no saved sites and no blocked sites.
......@@ -502,35 +517,6 @@ TEST_P(PasswordsTableViewControllerTest,
UIAccessibilityTraitNotEnabled);
}
TEST_P(PasswordsTableViewControllerTest, PropagateDeletionToStore) {
PasswordsTableViewController* passwords_controller =
static_cast<PasswordsTableViewController*>(controller());
autofill::PasswordForm form;
form.url = GURL("http://www.example.com/accounts/LoginAuth");
form.action = GURL("http://www.example.com/accounts/Login");
form.username_element = base::ASCIIToUTF16("Email");
form.username_value = base::ASCIIToUTF16("test@egmail.com");
form.password_element = base::ASCIIToUTF16("Passwd");
form.password_value = base::ASCIIToUTF16("test");
form.submit_element = base::ASCIIToUTF16("signIn");
form.signon_realm = "http://www.example.com/";
form.scheme = autofill::PasswordForm::Scheme::kHtml;
form.blocked_by_user = false;
AddPasswordForm(std::make_unique<autofill::PasswordForm>(form));
if (GetParam().password_check_enabled) {
autofill::PasswordForm formFromStore =
GetTestStore().stored_passwords().at("http://www.example.com/")[0];
[passwords_controller passwordDetailsTableViewController:nil
deletePassword:formFromStore];
RunUntilIdle();
} else {
[passwords_controller passwordDetailsTableViewController:nil
deletePassword:form];
}
}
// Tests filtering of items.
TEST_P(PasswordsTableViewControllerTest, FilterItems) {
AddSavedForm1();
......@@ -760,7 +746,7 @@ TEST_P(PasswordsTableViewControllerTest, PasswordIssuesDeletion) {
auto password =
GetTestStore().stored_passwords().at("http://www.example.com/").at(0);
EXPECT_TRUE([passwords_controller willHandlePasswordDeletion:password]);
[passwords_controller deletePasswordForm:password];
EXPECT_EQ(1, NumberOfItemsInSection(GetSectionIndex(SavedPasswords)));
}
......
......@@ -18,7 +18,7 @@
#import "ios/chrome/browser/ui/settings/google_services/google_services_settings_coordinator.h"
#import "ios/chrome/browser/ui/settings/google_services/google_services_settings_view_controller.h"
#import "ios/chrome/browser/ui/settings/import_data_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/password/passwords_coordinator.h"
#import "ios/chrome/browser/ui/settings/settings_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/sync/sync_encryption_passphrase_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/utils/settings_utils.h"
......@@ -39,6 +39,7 @@ NSString* const kSettingsDoneButtonId = @"kSettingsDoneButtonId";
@interface SettingsNavigationController () <
GoogleServicesSettingsCoordinatorDelegate,
PasswordsCoordinatorDelegate,
UIAdaptivePresentationControllerDelegate,
UINavigationControllerDelegate>
......@@ -46,6 +47,9 @@ NSString* const kSettingsDoneButtonId = @"kSettingsDoneButtonId";
@property(nonatomic, strong)
GoogleServicesSettingsCoordinator* googleServicesSettingsCoordinator;
// Saved passwords settings coordinator.
@property(nonatomic, strong) PasswordsCoordinator* savedPasswordsCoordinator;
// Current UIViewController being presented by this Navigation Controller.
// If nil it means the Navigation Controller is not presenting anything, or the
// VC being presented doesn't conform to
......@@ -143,22 +147,17 @@ NSString* const kSettingsDoneButtonId = @"kSettingsDoneButtonId";
delegate
startPasswordCheckAutomatically:(BOOL)startCheck {
DCHECK(browser);
PasswordsTableViewController* controller =
[[PasswordsTableViewController alloc] initWithBrowser:browser];
controller.dispatcher = [delegate handlerForSettings];
if (startCheck) {
[controller startPasswordCheck];
}
SettingsNavigationController* nc = [[SettingsNavigationController alloc]
initWithRootViewController:controller
initWithRootViewController:nil
browser:browser
delegate:delegate];
[controller navigationItem].rightBarButtonItem = [nc doneButton];
[nc showSavedPasswordsAndStartPasswordCheck:startCheck];
// Make sure the cancel button is always present, as the Save Passwords screen
// isn't just shown from Settings.
[controller navigationItem].leftBarButtonItem = [nc cancelButton];
[nc.savedPasswordsCoordinator.viewController navigationItem]
.leftBarButtonItem = [nc cancelButton];
return nc;
}
......@@ -315,9 +314,10 @@ NSString* const kSettingsDoneButtonId = @"kSettingsDoneButtonId";
}
}
// GoogleServicesSettingsCoordinator must be stopped before dismissing the
// sync settings view.
// GoogleServicesSettingsCoordinator and PasswordsCoordinator must be stopped
// before dismissing the sync settings view.
[self stopGoogleServicesSettingsCoordinator];
[self stopPasswordsCoordinator];
// Reset the delegate to prevent any queued transitions from attempting to
// close the settings.
......@@ -384,6 +384,26 @@ NSString* const kSettingsDoneButtonId = @"kSettingsDoneButtonId";
self.googleServicesSettingsCoordinator = nil;
}
// Shows the saved passwords and starts the password check is
// |startPasswordCheck| is true.
- (void)showSavedPasswordsAndStartPasswordCheck:(BOOL)startPasswordCheck {
self.savedPasswordsCoordinator = [[PasswordsCoordinator alloc]
initWithBaseNavigationController:self
browser:self.browser];
self.savedPasswordsCoordinator.delegate = self;
[self.savedPasswordsCoordinator start];
if (startPasswordCheck) {
[self.savedPasswordsCoordinator checkSavedPasswords];
}
}
// Stops the underlying passwords coordinator if it exists.
- (void)stopPasswordsCoordinator {
[self.savedPasswordsCoordinator stop];
self.savedPasswordsCoordinator.delegate = nil;
self.savedPasswordsCoordinator = nil;
}
#pragma mark - GoogleServicesSettingsCoordinatorDelegate
- (void)googleServicesSettingsCoordinatorDidRemove:
......@@ -392,6 +412,13 @@ NSString* const kSettingsDoneButtonId = @"kSettingsDoneButtonId";
[self stopGoogleServicesSettingsCoordinator];
}
#pragma mark - PasswordsCoordinatorDelegate
- (void)passwordsCoordinatorDidRemove:(PasswordsCoordinator*)coordinator {
DCHECK_EQ(self.savedPasswordsCoordinator, coordinator);
[self stopPasswordsCoordinator];
}
#pragma mark - UIAdaptivePresentationControllerDelegate
- (BOOL)presentationControllerShouldDismiss:
......@@ -526,19 +553,12 @@ NSString* const kSettingsDoneButtonId = @"kSettingsDoneButtonId";
// TODO(crbug.com/779791) : Do not pass |baseViewController| through dispatcher.
- (void)showSavedPasswordsSettingsFromViewController:
(UIViewController*)baseViewController {
PasswordsTableViewController* controller =
[[PasswordsTableViewController alloc] initWithBrowser:self.browser];
controller.dispatcher = [self.settingsNavigationDelegate handlerForSettings];
[self pushViewController:controller animated:YES];
[self showSavedPasswordsAndStartPasswordCheck:NO];
}
- (void)showSavedPasswordsSettingsAndStartPasswordCheckFromViewController:
(UIViewController*)baseViewController {
PasswordsTableViewController* controller =
[[PasswordsTableViewController alloc] initWithBrowser:self.browser];
controller.dispatcher = [self.settingsNavigationDelegate handlerForSettings];
[controller startPasswordCheck];
[self pushViewController:controller animated:YES];
[self showSavedPasswordsAndStartPasswordCheck:YES];
}
// TODO(crbug.com/779791) : Do not pass |baseViewController| through dispatcher.
......
......@@ -63,7 +63,7 @@
#import "ios/chrome/browser/ui/settings/google_services/google_services_settings_coordinator.h"
#import "ios/chrome/browser/ui/settings/language/language_settings_mediator.h"
#import "ios/chrome/browser/ui/settings/language/language_settings_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/password/passwords_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/password/passwords_coordinator.h"
#import "ios/chrome/browser/ui/settings/privacy/privacy_coordinator.h"
#import "ios/chrome/browser/ui/settings/safety_check/safety_check_coordinator.h"
#import "ios/chrome/browser/ui/settings/search_engine_table_view_controller.h"
......@@ -178,6 +178,7 @@ NSString* kDevViewSourceKey = @"DevViewSource";
GoogleServicesSettingsCoordinatorDelegate,
IdentityManagerObserverBridgeDelegate,
PasswordCheckObserver,
PasswordsCoordinatorDelegate,
PopoverLabelViewControllerDelegate,
PrefObserverDelegate,
PrivacyCoordinatorDelegate,
......@@ -225,6 +226,9 @@ NSString* kDevViewSourceKey = @"DevViewSource";
// Safety Check coordinator.
SafetyCheckCoordinator* _safetyCheckCoordinator;
// Passwords coordinator.
PasswordsCoordinator* _passwordsCoordinator;
// Cached resized profile image.
UIImage* _resizedImage;
__weak UIImage* _oldImage;
......@@ -955,8 +959,7 @@ NSString* kDevViewSourceKey = @"DevViewSource";
case ItemTypePasswords:
base::RecordAction(
base::UserMetricsAction("Options_ShowPasswordManager"));
controller =
[[PasswordsTableViewController alloc] initWithBrowser:_browser];
[self showPasswords];
break;
case ItemTypeAutofillCreditCard:
base::RecordAction(base::UserMetricsAction("AutofillCreditCardsViewed"));
......@@ -1112,6 +1115,15 @@ NSString* kDevViewSourceKey = @"DevViewSource";
[_googleServicesSettingsCoordinator start];
}
- (void)showPasswords {
DCHECK(!_passwordsCoordinator);
_passwordsCoordinator = [[PasswordsCoordinator alloc]
initWithBaseNavigationController:self.navigationController
browser:_browser];
_passwordsCoordinator.delegate = self;
[_passwordsCoordinator start];
}
// Shows Safety Check Screen.
- (void)showSafetyCheck {
DCHECK(!_safetyCheckCoordinator);
......@@ -1337,6 +1349,10 @@ NSString* kDevViewSourceKey = @"DevViewSource";
[_safetyCheckCoordinator stop];
_safetyCheckCoordinator = nil;
[_passwordsCoordinator stop];
_passwordsCoordinator.delegate = nil;
_passwordsCoordinator = nil;
[_privacyCoordinator stop];
_privacyCoordinator = nil;
......@@ -1539,6 +1555,15 @@ NSString* kDevViewSourceKey = @"DevViewSource";
_safetyCheckCoordinator = nil;
}
#pragma mark - SafetyCheckCoordinatorDelegate
- (void)passwordsCoordinatorDidRemove:(PasswordsCoordinator*)coordinator {
DCHECK_EQ(_passwordsCoordinator, coordinator);
[_passwordsCoordinator stop];
_passwordsCoordinator.delegate = nil;
_passwordsCoordinator = nil;
}
#pragma mark - PrivacyCoordinatorDelegate
- (void)privacyCoordinatorViewControllerWasRemoved:
......
......@@ -79,6 +79,7 @@ source_set("test_support") {
"//ios/chrome/browser/ui/settings",
"//ios/chrome/browser/ui/settings:settings_root",
"//ios/chrome/browser/ui/settings/password",
"//ios/chrome/browser/ui/settings/password:password_ui",
"//ios/chrome/browser/ui/settings/password:test_support",
"//ios/chrome/browser/ui/tab_grid",
"//ios/chrome/browser/ui/tabs",
......
......@@ -76,8 +76,8 @@ SetUpAndReturnMockReauthenticationModuleForExport() {
PasswordsTableViewController* passwords_table_view_controller =
base::mac::ObjCCastStrict<PasswordsTableViewController>(
settings_navigation_controller.topViewController);
[passwords_table_view_controller
setReauthenticationModuleForExporter:mock_reauthentication_module];
passwords_table_view_controller.reauthenticationModule =
mock_reauthentication_module;
return mock_reauthentication_module;
}
......
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