Commit f830da38 authored by Viktor Semeniuk's avatar Viktor Semeniuk Committed by Commit Bot

[iOS][Password Check] Change password on website

This change adds new section to password details screen when password is
compromised. It allows to change the password on affected website.
Taping Change Password button will close the settings and open affected
website.

Bug: 1075494
Change-Id: I96b0e2383597875ddfdcaa54e07e8365a84ebf60
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2299747Reviewed-by: default avatarGauthier Ambard <gambard@chromium.org>
Reviewed-by: default avatarSergio Collazos <sczs@chromium.org>
Commit-Queue: Viktor Semeniuk <vsemeniuk@google.com>
Cr-Commit-Position: refs/heads/master@{#790928}
parent b22e7882
......@@ -331,6 +331,9 @@ locale. The strings in this file are specific to iOS.
<message name="IDS_IOS_PASSWORD_CHECK_ERROR_OTHER" desc="Text inside popover which is shown when the user wants to see detailed information about the error. [iOS only]" meaning="Password check failed due to specific reason (out of memory).">
Chromium couldn't check all passwords. Try again.
</message>
<message name="IDS_IOS_CHANGE_COMPROMISED_PASSWORD_DESCRIPTION" desc="Text inside Password Details screen shown when password was compromised. [iOS only]" meaning="Text which explains the user that current password is compromised and it should be changed.">
Your password was exposed in a data breach. Chromium recommends changing the password now.
</message>
</messages>
</release>
</grit>
......@@ -331,6 +331,9 @@ locale. The strings in this file are specific to iOS.
<message name="IDS_IOS_PASSWORD_CHECK_ERROR_OTHER" desc="Text inside popover which is shown when the user wants to see detailed information about the error. [iOS only]" meaning="Password check failed due to specific reason (out of memory).">
Chrome couldn't check all passwords. Try again.
</message>
<message name="IDS_IOS_CHANGE_COMPROMISED_PASSWORD_DESCRIPTION" desc="Text inside Password Details screen shown when password was compromised. [iOS only]" meaning="Text which explains the user that current password is compromised and it should be changed.">
Your password was exposed in a data breach. Chrome recommends changing the password now.
</message>
</messages>
</release>
</grit>
......@@ -1645,6 +1645,9 @@ While in incognito, sites can't use cookies to see your browsing activity across
<message name="IDS_IOS_PASSWORD_ISSUES_DESCRIPTION" desc="Description for the screen with Compromised passwords [iOS only]" meaning="This label explains what is compromised password and why is it compromised. It suggest user fixing the issues as soon as possible.">
The following accounts use passwords which were exposed in a third-party data breach or entered on a deceptive website. Change these passwords immediately to keep your accounts safe.
</message>
<message name="IDS_IOS_CHANGE_COMPROMISED_PASSWORD" desc="Button which is shown on Password Details Screen when password is compromised. [iOS only]" meaning="Telling user to change password on a website since it is compromised.">
Change password on Website
</message>
<message name="IDS_IOS_SEARCH_COPIED" desc="The message displayed when the search is copied via long press (contextual search) [Length: 10em] [iOS only]">
Copied
</message>
......
324e42d485c2b5ff652e154aa3ccac09e7b3aa09
\ No newline at end of file
......@@ -26,6 +26,7 @@ source_set("password_details") {
"//ios/chrome/browser/ui/table_view",
"//ios/chrome/common/ui/colors",
"//ios/chrome/common/ui/util",
"//ios/web",
"//ui/base",
]
}
......@@ -48,13 +49,18 @@ source_set("password_details_ui") {
"//components/autofill/core/common",
"//components/password_manager/core/browser:browser",
"//components/strings",
"//ios/chrome/app/strings:ios_chromium_strings_grit",
"//ios/chrome/app/strings:ios_strings_grit",
"//ios/chrome/browser",
"//ios/chrome/browser/passwords",
"//ios/chrome/browser/ui/commands",
"//ios/chrome/browser/ui/settings:settings_root",
"//ios/chrome/browser/ui/settings/autofill",
"//ios/chrome/browser/ui/settings/cells",
"//ios/chrome/browser/ui/table_view/cells",
"//ios/chrome/browser/ui/table_view/cells:cells_constants",
"//ios/chrome/browser/ui/util",
"//ios/chrome/common/ui/colors",
"//ios/chrome/common/ui/util",
"//ui/base",
]
......@@ -74,6 +80,8 @@ source_set("unit_tests") {
"//components/password_manager/core/common",
"//components/strings",
"//ios/chrome/app/strings",
"//ios/chrome/app/strings:ios_chromium_strings_grit",
"//ios/chrome/app/strings:ios_strings_grit",
"//ios/chrome/browser/browser_state:test_support",
"//ios/chrome/browser/passwords",
"//ios/chrome/browser/ui/settings/cells",
......
......@@ -27,6 +27,9 @@ struct PasswordForm;
// Associated password.
@property(nonatomic, strong) NSString* password;
// Whether password is compromised or not.
@property(nonatomic, assign, getter=isCompromised) BOOL compromised;
- (instancetype)initWithPasswordForm:(const autofill::PasswordForm&)form
NS_DESIGNATED_INITIALIZER;
......
......@@ -7,6 +7,8 @@
#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
@protocol ApplicationCommands;
class IOSChromePasswordCheckManager;
@protocol PasswordDetailsCoordinatorDelegate;
namespace autofill {
......@@ -16,10 +18,12 @@ struct PasswordForm;
// This coordinator presents a password details for the user.
@interface PasswordDetailsCoordinator : ChromeCoordinator
- (instancetype)initWithBaseNavigationController:
(UINavigationController*)navigationController
password:(const autofill::PasswordForm&)
password
- (instancetype)
initWithBaseNavigationController:
(UINavigationController*)navigationController
password:(const autofill::PasswordForm&)password
passwordCheckManager:(IOSChromePasswordCheckManager*)manager
dispatcher:(id<ApplicationCommands>)dispatcher
NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithBaseViewController:(UIViewController*)viewController
......
......@@ -20,6 +20,9 @@
@interface PasswordDetailsCoordinator () <PasswordDetailsHandler> {
autofill::PasswordForm _password;
// Manager responsible for password check feature.
IOSChromePasswordCheckManager* _manager;
}
// Main view controller for this coordinator.
......@@ -28,20 +31,31 @@
// Main mediator for this coordinator.
@property(nonatomic, strong) PasswordDetailsMediator* mediator;
// Dispatcher.
@property(nonatomic, weak) id<ApplicationCommands> dispatcher;
@end
@implementation PasswordDetailsCoordinator
@synthesize baseNavigationController = _baseNavigationController;
- (instancetype)initWithBaseNavigationController:
(UINavigationController*)navigationController
password:(const autofill::PasswordForm&)
password {
- (instancetype)
initWithBaseNavigationController:
(UINavigationController*)navigationController
password:(const autofill::PasswordForm&)password
passwordCheckManager:(IOSChromePasswordCheckManager*)manager
dispatcher:(id<ApplicationCommands>)dispatcher {
self = [super initWithBaseViewController:navigationController browser:nil];
if (self) {
_password = password;
DCHECK(navigationController);
DCHECK(manager);
DCHECK(dispatcher);
_baseNavigationController = navigationController;
_password = password;
_manager = manager;
_dispatcher = dispatcher;
}
return self;
}
......@@ -54,15 +68,18 @@
self.viewController =
[[PasswordDetailsViewController alloc] initWithStyle:style];
self.mediator = [[PasswordDetailsMediator alloc] initWithPassword:_password];
self.mediator = [[PasswordDetailsMediator alloc] initWithPassword:_password
passwordCheckManager:_manager];
self.mediator.consumer = self.viewController;
self.viewController.handler = self;
self.viewController.commandsDispatcher = self.dispatcher;
[self.baseNavigationController pushViewController:self.viewController
animated:YES];
}
- (void)stop {
[self.mediator disconnect];
self.mediator = nil;
self.viewController = nil;
}
......
......@@ -7,6 +7,9 @@
#import <Foundation/Foundation.h>
#import "ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_delegate.h"
class IOSChromePasswordCheckManager;
@protocol PasswordDetailsConsumer;
namespace autofill {
......@@ -14,10 +17,12 @@ struct PasswordForm;
}
// This mediator fetches and organises the credentials for its consumer.
@interface PasswordDetailsMediator : NSObject
@interface PasswordDetailsMediator
: NSObject <PasswordDetailsViewControllerDelegate>
// PasswordForm is converted to the PasswordDetails and passed to a consumer.
- (instancetype)initWithPassword:(const autofill::PasswordForm&)passwordForm
passwordCheckManager:(IOSChromePasswordCheckManager*)manager
NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
......@@ -25,6 +30,9 @@ struct PasswordForm;
// Consumer of this mediator.
@property(nonatomic, weak) id<PasswordDetailsConsumer> consumer;
// Disconnects the mediator from all observers.
- (void)disconnect;
@end
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_MEDIATOR_H_
......@@ -5,6 +5,7 @@
#import "ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.h"
#include "components/autofill/core/common/password_form.h"
#include "ios/chrome/browser/passwords/password_check_observer_bridge.h"
#import "ios/chrome/browser/ui/settings/password/password_details/password_details.h"
#import "ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h"
#import "ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_delegate.h"
......@@ -13,22 +14,32 @@
#error "This file requires ARC support."
#endif
namespace autofill {
struct PasswordForm;
}
using CompromisedCredentialsView =
password_manager::CompromisedCredentialsManager::CredentialsView;
@interface PasswordDetailsMediator () <PasswordDetailsViewControllerDelegate> {
@interface PasswordDetailsMediator () <PasswordCheckObserver,
PasswordDetailsViewControllerDelegate> {
autofill::PasswordForm _password;
// Password Check manager.
IOSChromePasswordCheckManager* _manager;
// Listens to compromised passwords changes.
std::unique_ptr<PasswordCheckObserverBridge> _passwordCheckObserver;
}
@end
@implementation PasswordDetailsMediator
- (instancetype)initWithPassword:(const autofill::PasswordForm&)passwordForm {
- (instancetype)initWithPassword:(const autofill::PasswordForm&)passwordForm
passwordCheckManager:(IOSChromePasswordCheckManager*)manager {
self = [super init];
if (self) {
_manager = manager;
_password = passwordForm;
_passwordCheckObserver.reset(
new PasswordCheckObserverBridge(self, manager));
}
return self;
}
......@@ -38,10 +49,11 @@ struct PasswordForm;
return;
_consumer = consumer;
PasswordDetails* password =
[[PasswordDetails alloc] initWithPasswordForm:_password];
[self fetchPasswordWith:_manager->GetCompromisedCredentials()];
}
[self.consumer setPassword:password];
- (void)disconnect {
_manager->RemoveObserver(_passwordCheckObserver.get());
}
#pragma mark - PasswordDetailsViewControllerDelegate
......@@ -51,4 +63,35 @@ struct PasswordForm;
// TODO:(crbug.com/1075494) - Edit password accordingly.
}
#pragma mark - PasswordCheckObserver
- (void)passwordCheckStateDidChange:(PasswordCheckState)state {
// No-op. Changing password check state has no effect on compromised
// passwords.
}
- (void)compromisedCredentialsDidChange:
(CompromisedCredentialsView)credentials {
[self fetchPasswordWith:credentials];
}
#pragma mark - Private
// Updates password details and sets it to a consumer.
- (void)fetchPasswordWith:(CompromisedCredentialsView)credentials {
PasswordDetails* password =
[[PasswordDetails alloc] initWithPasswordForm:_password];
password.compromised = NO;
for (const auto& credential : credentials) {
if (std::tie(credential.signon_realm, credential.username,
credential.password) == std::tie(_password.signon_realm,
_password.username_value,
_password.password_value))
password.compromised = YES;
}
[self.consumer setPassword:password];
}
@end
......@@ -8,6 +8,7 @@
#import "ios/chrome/browser/ui/settings/autofill/autofill_edit_table_view_controller.h"
#import "ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h"
@protocol ApplicationCommands;
@protocol PasswordDetailsHandler;
@protocol PasswordDetailsViewControllerDelegate;
......@@ -21,6 +22,9 @@
// Delegate for PasswordDetails related actions e.g. Password editing.
@property(nonatomic, weak) id<PasswordDetailsViewControllerDelegate> delegate;
// Dispatcher for this ViewController.
@property(nonatomic, weak) id<ApplicationCommands> commandsDispatcher;
@end
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_VIEW_CONTROLLER_H_
......@@ -5,6 +5,10 @@
#import "ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.h"
#include "base/mac/foundation_util.h"
#include "base/strings/sys_string_conversions.h"
#import "ios/chrome/browser/ui/commands/application_commands.h"
#import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
#import "ios/chrome/browser/ui/settings/cells/settings_image_detail_text_item.h"
#import "ios/chrome/browser/ui/settings/password/password_details/password_details.h"
#import "ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h"
#import "ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h"
......@@ -12,6 +16,10 @@
#import "ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_delegate.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_edit_item.h"
#import "ios/chrome/browser/ui/table_view/cells/table_view_text_item.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"
#include "ui/base/l10n/l10n_util_mac.h"
......@@ -21,15 +29,20 @@
namespace {
// Padding used between the image and the text labels.
const CGFloat kWarningIconSize = 20;
typedef NS_ENUM(NSInteger, SectionIdentifier) {
SectionIdentifierPassword = kSectionIdentifierEnumZero,
// TODO:(crbug.com/1075494) - Add password compromised section.
SectionIdentifierCompromisedInfo
};
typedef NS_ENUM(NSInteger, ItemType) {
ItemTypeWebsite = kItemTypeEnumZero,
ItemTypeUsername,
ItemTypePassword,
ItemTypeChangePasswordButton,
ItemTypeChangePasswordRecommendation,
};
} // namespace
......@@ -73,6 +86,9 @@ typedef NS_ENUM(NSInteger, ItemType) {
[self reconfigureCellsForItems:
[self.tableViewModel
itemsInSectionWithIdentifier:SectionIdentifierPassword]];
[self reconfigureCellsForItems:
[self.tableViewModel
itemsInSectionWithIdentifier:SectionIdentifierCompromisedInfo]];
}
- (void)loadModel {
......@@ -90,6 +106,16 @@ typedef NS_ENUM(NSInteger, ItemType) {
[model addItem:[self passwordItem]
toSectionWithIdentifier:SectionIdentifierPassword];
if (self.password.isCompromised) {
[model addSectionWithIdentifier:SectionIdentifierCompromisedInfo];
[model addItem:[self changePasswordItem]
toSectionWithIdentifier:SectionIdentifierCompromisedInfo];
[model addItem:[self changePasswordRecommendationItem]
toSectionWithIdentifier:SectionIdentifierCompromisedInfo];
}
}
#pragma mark - Items
......@@ -130,15 +156,56 @@ typedef NS_ENUM(NSInteger, ItemType) {
return item;
}
- (TableViewTextItem*)changePasswordItem {
TableViewTextItem* item =
[[TableViewTextItem alloc] initWithType:ItemTypeChangePasswordButton];
item.text = l10n_util::GetNSString(IDS_IOS_CHANGE_COMPROMISED_PASSWORD);
item.textColor = self.tableView.editing ? UIColor.cr_secondaryLabelColor
: [UIColor colorNamed:kBlueColor];
item.accessibilityTraits = UIAccessibilityTraitButton;
return item;
}
- (SettingsImageDetailTextItem*)changePasswordRecommendationItem {
SettingsImageDetailTextItem* item = [[SettingsImageDetailTextItem alloc]
initWithType:ItemTypeChangePasswordRecommendation];
item.detailText =
l10n_util::GetNSString(IDS_IOS_CHANGE_COMPROMISED_PASSWORD_DESCRIPTION);
item.image = [self getCompromisedIcon];
return item;
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView*)tableView
didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
if (self.tableView.editing) {
UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
TableViewTextEditCell* textFieldCell =
base::mac::ObjCCastStrict<TableViewTextEditCell>(cell);
[textFieldCell.textField becomeFirstResponder];
TableViewModel* model = self.tableViewModel;
NSInteger itemType = [model itemTypeForIndexPath:indexPath];
switch (itemType) {
case ItemTypeWebsite:
case ItemTypeUsername:
case ItemTypeChangePasswordRecommendation:
break;
case ItemTypePassword: {
if (self.tableView.editing) {
UITableViewCell* cell =
[self.tableView cellForRowAtIndexPath:indexPath];
TableViewTextEditCell* textFieldCell =
base::mac::ObjCCastStrict<TableViewTextEditCell>(cell);
[textFieldCell.textField becomeFirstResponder];
}
break;
}
case ItemTypeChangePasswordButton:
if (!self.tableView.editing) {
DCHECK(self.commandsDispatcher);
GURL URL(base::SysNSStringToUTF8(self.password.website));
DCHECK(URL.is_valid());
OpenNewTabCommand* command =
[OpenNewTabCommand commandWithURLFromChrome:URL];
[self.commandsDispatcher closeSettingsUIAndOpenURL:command];
}
break;
}
}
......@@ -163,10 +230,21 @@ typedef NS_ENUM(NSInteger, ItemType) {
// TODO:(crbug.com/1075494) - Add action to Show/Hide password when user tap
// eye icon.
TableViewTextEditCell* textFieldCell =
base::mac::ObjCCastStrict<TableViewTextEditCell>(cell);
textFieldCell.textField.delegate = self;
return textFieldCell;
NSInteger itemType = [self.tableViewModel itemTypeForIndexPath:indexPath];
switch (itemType) {
case ItemTypePassword: {
TableViewTextEditCell* textFieldCell =
base::mac::ObjCCastStrict<TableViewTextEditCell>(cell);
textFieldCell.textField.delegate = self;
return textFieldCell;
}
case ItemTypeWebsite:
case ItemTypeUsername:
case ItemTypeChangePasswordButton:
case ItemTypeChangePasswordRecommendation:
break;
}
return cell;
}
- (BOOL)tableView:(UITableView*)tableView
......@@ -201,4 +279,18 @@ typedef NS_ENUM(NSInteger, ItemType) {
return !self.editing;
}
// Applies tint colour and resizes image.
- (UIImage*)getCompromisedIcon {
UIImage* image = [UIImage imageNamed:@"settings_unsafe_state"];
UIImage* newImage =
[image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIGraphicsBeginImageContextWithOptions(
CGSizeMake(kWarningIconSize, kWarningIconSize), NO, 0.0);
[UIColor.cr_secondaryLabelColor set];
[newImage drawInRect:CGRectMake(0, 0, kWarningIconSize, kWarningIconSize)];
newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
@end
......@@ -9,6 +9,7 @@
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/core/common/password_form.h"
#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
#import "ios/chrome/browser/ui/settings/cells/settings_image_detail_text_item.h"
#import "ios/chrome/browser/ui/settings/password/password_details/password_details.h"
#import "ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h"
#import "ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h"
......@@ -21,6 +22,7 @@
#include "ios/web/public/test/web_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest_mac.h"
#include "ui/base/l10n/l10n_util_mac.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
......@@ -71,7 +73,7 @@ class PasswordDetailsViewControllerTest : public ChromeTableViewControllerTest {
return controller;
}
void ShowPassword() {
void ShowPassword(bool isCompromised = false) {
auto form = autofill::PasswordForm();
form.url = GURL("http://www.example.com/");
form.action = GURL("http://www.example.com/accounts/Login");
......@@ -84,6 +86,7 @@ class PasswordDetailsViewControllerTest : public ChromeTableViewControllerTest {
form.scheme = autofill::PasswordForm::Scheme::kHtml;
PasswordDetails* password =
[[PasswordDetails alloc] initWithPasswordForm:form];
password.compromised = isCompromised;
PasswordDetailsViewController* passwords_controller =
static_cast<PasswordDetailsViewController*>(controller());
......@@ -96,6 +99,16 @@ class PasswordDetailsViewControllerTest : public ChromeTableViewControllerTest {
EXPECT_NSEQ(expected_text, cell.textFieldValue);
}
void CheckDetailItemTextWithId(int expected_detail_text_id,
int section,
int item) {
SettingsImageDetailTextItem* cell =
static_cast<SettingsImageDetailTextItem*>(
GetTableViewItem(section, item));
EXPECT_NSEQ(l10n_util::GetNSString(expected_detail_text_id),
cell.detailText);
}
FakePasswordDetailsHandler* handler() { return handler_; }
FakePasswordDetailsDelegate* delegate() { return delegate_; }
......@@ -125,3 +138,20 @@ TEST_F(PasswordDetailsViewControllerTest, TestPassword) {
CheckEditCellText(@"test@egmail.com", 0, 1);
CheckEditCellText(kMaskedPassword, 0, 2);
}
// Tests that compromised password is displayed properly.
TEST_F(PasswordDetailsViewControllerTest, TestCompromisedPassword) {
ShowPassword(true);
EXPECT_EQ(2, NumberOfSections());
EXPECT_EQ(3, NumberOfItemsInSection(0));
EXPECT_EQ(2, NumberOfItemsInSection(1));
EXPECT_NSEQ(@"example.com", controller().title);
CheckEditCellText(@"http://www.example.com/", 0, 0);
CheckEditCellText(@"test@egmail.com", 0, 1);
CheckEditCellText(kMaskedPassword, 0, 2);
CheckTextCellTextWithId(IDS_IOS_CHANGE_COMPROMISED_PASSWORD, 1, 0);
CheckDetailItemTextWithId(IDS_IOS_CHANGE_COMPROMISED_PASSWORD_DESCRIPTION, 1,
1);
}
......@@ -7,6 +7,7 @@
#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
@protocol ApplicationCommands;
class IOSChromePasswordCheckManager;
@class PasswordIssuesCoordinator;
......@@ -33,6 +34,8 @@ class IOSChromePasswordCheckManager;
@property(nonatomic, weak) id<PasswordIssuesCoordinatorDelegate> delegate;
@property(nonatomic, weak) id<ApplicationCommands> dispatcher;
@end
#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_ISSUES_COORDINATOR_H_
......@@ -6,6 +6,7 @@
#include "base/mac/foundation_util.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"
#import "ios/chrome/browser/ui/settings/password/password_issues_consumer.h"
#import "ios/chrome/browser/ui/settings/password/password_issues_mediator.h"
......@@ -18,7 +19,8 @@
#error "This file requires ARC support."
#endif
@interface PasswordIssuesCoordinator () <PasswordIssuesPresenter> {
@interface PasswordIssuesCoordinator () <PasswordDetailsCoordinatorDelegate,
PasswordIssuesPresenter> {
// Password check manager to power mediator.
IOSChromePasswordCheckManager* _manager;
}
......@@ -29,6 +31,9 @@
// Main mediator for this coordinator.
@property(nonatomic, strong) PasswordIssuesMediator* mediator;
// Coordinator for password details.
@property(nonatomic, strong) PasswordDetailsCoordinator* passwordDetails;
@end
@implementation PasswordIssuesCoordinator
......@@ -71,6 +76,10 @@
- (void)stop {
self.mediator = nil;
self.viewController = nil;
[self.passwordDetails stop];
self.passwordDetails.delegate = nil;
self.passwordDetails = nil;
}
#pragma mark - PasswordIssuesPresenter
......@@ -83,12 +92,29 @@
autofill::PasswordForm form =
base::mac::ObjCCastStrict<PasswordIssueWithForm>(password).form;
PasswordDetailsCoordinator* passwordDetails =
[[PasswordDetailsCoordinator alloc]
initWithBaseNavigationController:self.baseNavigationController
password:form];
// TODO:(crbug.com/1075494) - Add self as delegate for coordinator.
[passwordDetails start];
DCHECK(!self.passwordDetails);
self.passwordDetails = [[PasswordDetailsCoordinator alloc]
initWithBaseNavigationController:self.baseNavigationController
password:form
passwordCheckManager:_manager
dispatcher:self.dispatcher];
self.passwordDetails.delegate = self;
[self.passwordDetails start];
}
#pragma mark - PasswordDetailsCoordinatorDelegate
- (void)passwordDetailsCoordinatorDidRemove:
(PasswordDetailsCoordinator*)coordinator {
DCHECK_EQ(self.passwordDetails, coordinator);
[self.passwordDetails stop];
self.passwordDetails.delegate = nil;
self.passwordDetails = nil;
}
- (void)passwordDetailsCoordinator:(PasswordDetailsCoordinator*)coordinator
deletePassword:(const autofill::PasswordForm&)password {
// TODO:(crbug.com/1075494) - Delete password.
}
@end
......@@ -1199,6 +1199,7 @@ std::vector<std::unique_ptr<autofill::PasswordForm>> CopyOf(
initWithBaseNavigationController:self.navigationController
passwordCheckManager:_passwordCheck.get()];
_passwordIssuesCoordinator.delegate = self;
_passwordIssuesCoordinator.dispatcher = self.dispatcher;
[_passwordIssuesCoordinator start];
}
......
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