Commit e8d3e6d9 authored by Javier Ernesto Flores Robles's avatar Javier Ernesto Flores Robles Committed by Commit Bot

[iOS][MF] Refactors coordinator logic to mediator

This CL only moves the logic from the coordinator to the mediator. It
shouldn't change any behavior. And it only moves logic related to the
manual fill view controller.

Bug: 845472
Change-Id: Id17a14903c50fa63a4a643025ef235256bc2474e
Reviewed-on: https://chromium-review.googlesource.com/c/1352185Reviewed-by: default avatarOlivier Robin <olivierrobin@chromium.org>
Reviewed-by: default avatarVasilii Sukhanov <vasilii@chromium.org>
Commit-Queue: Javier Ernesto Flores Robles <javierrobles@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612130}
parent 58346166
......@@ -262,7 +262,10 @@ void AutofillControllerTest::SetUp() {
accessory_mediator_ =
[[FormInputAccessoryMediator alloc] initWithConsumer:nil
webStateList:NULL];
webStateList:NULL
personalDataManager:NULL
passwordStore:NULL];
[accessory_mediator_ injectWebState:web_state()];
[accessory_mediator_ injectProviders:@[ suggestion_controller_ ]];
auto suggestionManager = base::mac::ObjCCastStrict<JsSuggestionManager>(
......
......@@ -17,6 +17,15 @@
@property(nonatomic, weak) id<FormInputAccessoryViewDelegate>
navigationDelegate;
// Hides or shows the manual fill password button.
@property(nonatomic) BOOL passwordButtonHidden;
// Hides or shows the manual fill credit card button.
@property(nonatomic) BOOL creditCardButtonHidden;
// Hides or shows the manual fill address button.
@property(nonatomic) BOOL addressButtonHidden;
// Enables or disables the next button if any.
@property(nonatomic) BOOL formInputNextButtonEnabled;
......
......@@ -14,6 +14,7 @@ extern CGFloat const kInputAccessoryHeight;
} // namespace autofill
@class ManualFillAccessoryViewController;
@protocol ManualFillAccessoryViewControllerDelegate;
// Creates and manages a custom input accessory view while the user is
// interacting with a form. Also handles hiding and showing the default
......@@ -21,11 +22,6 @@ extern CGFloat const kInputAccessoryHeight;
@interface FormInputAccessoryViewController
: NSObject<FormInputAccessoryConsumer>
// The manual fill accessory view controller to add at the end of the
// suggestions.
@property(nonatomic, weak)
ManualFillAccessoryViewController* manualFillAccessoryViewController;
// Presents a view above the keyboard.
- (void)presentView:(UIView*)view;
......@@ -37,6 +33,22 @@ extern CGFloat const kInputAccessoryHeight;
// and locks them in that position.
- (void)lockManualFallbackView;
// Tells the view to restore the manual fallback icons to a clean state. That
// means no icon selected.
- (void)resetManualFallbackIcons;
// Instances an object with the desired delegate.
//
// @param manualFillAccessoryViewControllerDelegate the delegate for the actions
// in the manual fallback icons.
// @return A fresh object with the passed delegate.
- (instancetype)initWithManualFillAccessoryViewControllerDelegate:
(id<ManualFillAccessoryViewControllerDelegate>)
manualFillAccessoryViewControllerDelegate;
// Unavailable
- (instancetype)init NS_UNAVAILABLE;
@end
#endif // IOS_CHROME_BROWSER_AUTOFILL_FORM_INPUT_ACCESSORY_VIEW_CONTROLLER_H_
......@@ -21,7 +21,8 @@ namespace autofill {
CGFloat const kInputAccessoryHeight = 44.0f;
} // namespace autofill
@interface FormInputAccessoryViewController ()
@interface FormInputAccessoryViewController () <
ManualFillAccessoryViewControllerDelegate>
// Grey view used as the background of the keyboard to fix
// http://crbug.com/847523
......@@ -39,6 +40,16 @@ CGFloat const kInputAccessoryHeight = 44.0f;
// If this view controller is paused it shouldn't add its views to the keyboard.
@property(nonatomic, getter=isPaused) BOOL paused;
// The manual fill accessory view controller to add at the end of the
// suggestions.
@property(nonatomic, strong, readonly)
ManualFillAccessoryViewController* manualFillAccessoryViewController;
// Delegate to handle interactions with the manual fill buttons.
@property(nonatomic, readonly, weak)
id<ManualFillAccessoryViewControllerDelegate>
manualFillAccessoryViewControllerDelegate;
// Called when the keyboard will or did change frame.
- (void)keyboardWillOrDidChangeFrame:(NSNotification*)notification;
......@@ -52,15 +63,27 @@ CGFloat const kInputAccessoryHeight = 44.0f;
BOOL _suggestionsHaveBeenShown;
}
@synthesize navigationDelegate = _navigationDelegate;
@synthesize addressButtonHidden = _addressButtonHidden;
@synthesize creditCardButtonHidden = _creditCardButtonHidden;
@synthesize formInputNextButtonEnabled = _formInputNextButtonEnabled;
@synthesize formInputPreviousButtonEnabled = _formInputPreviousButtonEnabled;
@synthesize navigationDelegate = _navigationDelegate;
@synthesize passwordButtonHidden = _passwordButtonHidden;
#pragma mark - Life Cycle
- (instancetype)init {
- (instancetype)initWithManualFillAccessoryViewControllerDelegate:
(id<ManualFillAccessoryViewControllerDelegate>)
manualFillAccessoryViewControllerDelegate {
self = [super init];
if (self) {
_manualFillAccessoryViewControllerDelegate =
manualFillAccessoryViewControllerDelegate;
if (autofill::features::IsPasswordManualFallbackEnabled()) {
_manualFillAccessoryViewController =
[[ManualFillAccessoryViewController alloc] initWithDelegate:self];
}
_suggestionsHaveBeenShown = NO;
if (IsIPadIdiom()) {
_grayBackgroundView = [[UIView alloc] init];
......@@ -115,6 +138,10 @@ CGFloat const kInputAccessoryHeight = 44.0f;
[self.formSuggestionView lockTrailingView];
}
- (void)resetManualFallbackIcons {
[self.manualFillAccessoryViewController reset];
}
#pragma mark - FormInputAccessoryConsumer
- (void)showAccessorySuggestions:(NSArray<FormSuggestion*>*)suggestions
......@@ -207,6 +234,24 @@ CGFloat const kInputAccessoryHeight = 44.0f;
#pragma mark - Setters
- (void)setPasswordButtonHidden:(BOOL)passwordButtonHidden {
_passwordButtonHidden = passwordButtonHidden;
self.manualFillAccessoryViewController.passwordButtonHidden =
passwordButtonHidden;
}
- (void)setAddressButtonHidden:(BOOL)addressButtonHidden {
_addressButtonHidden = addressButtonHidden;
self.manualFillAccessoryViewController.addressButtonHidden =
addressButtonHidden;
}
- (void)setCreditCardButtonHidden:(BOOL)creditCardButtonHidden {
_creditCardButtonHidden = creditCardButtonHidden;
self.manualFillAccessoryViewController.creditCardButtonHidden =
creditCardButtonHidden;
}
- (void)setFormInputNextButtonEnabled:(BOOL)formInputNextButtonEnabled {
if (formInputNextButtonEnabled == _formInputNextButtonEnabled) {
return;
......@@ -365,4 +410,22 @@ CGFloat const kInputAccessoryHeight = 44.0f;
}
}
#pragma mark - ManualFillAccessoryViewControllerDelegate
- (void)keyboardButtonPressed {
[self.manualFillAccessoryViewControllerDelegate keyboardButtonPressed];
}
- (void)accountButtonPressed:(UIButton*)sender {
[self.manualFillAccessoryViewControllerDelegate accountButtonPressed:sender];
}
- (void)cardButtonPressed:(UIButton*)sender {
[self.manualFillAccessoryViewControllerDelegate cardButtonPressed:sender];
}
- (void)passwordButtonPressed:(UIButton*)sender {
[self.manualFillAccessoryViewControllerDelegate passwordButtonPressed:sender];
}
@end
......@@ -196,7 +196,9 @@ class FormSuggestionControllerTest : public PlatformTest {
accessory_mediator_ =
[[FormInputAccessoryMediator alloc] initWithConsumer:mock_consumer_
webStateList:NULL];
webStateList:NULL
personalDataManager:NULL
passwordStore:NULL];
[accessory_mediator_ injectWebState:&test_web_state_];
[accessory_mediator_ injectProviders:@[ suggestion_controller_ ]];
......
......@@ -217,7 +217,9 @@ class PasswordControllerTest : public ChromeWebTest {
providers:@[ [passwordController_ suggestionProvider] ]];
accessoryMediator_ =
[[FormInputAccessoryMediator alloc] initWithConsumer:nil
webStateList:NULL];
webStateList:NULL
personalDataManager:NULL
passwordStore:NULL];
[accessoryMediator_ injectWebState:web_state()];
[accessoryMediator_ injectProviders:@[ suggestionController_ ]];
}
......
......@@ -10,11 +10,8 @@
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/common/autofill_features.h"
#import "components/autofill/ios/browser/js_suggestion_manager.h"
#import "components/autofill/ios/browser/personal_data_manager_observer_bridge.h"
#include "components/keyed_service/core/service_access_type.h"
#include "components/password_manager/core/browser/password_store.h"
#import "ios/chrome/browser/autofill/form_input_accessory_view_controller.h"
#import "ios/chrome/browser/autofill/manual_fill/passwords_fetcher.h"
#include "ios/chrome/browser/autofill/personal_data_manager_factory.h"
#include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h"
#import "ios/chrome/browser/ui/autofill/form_input_accessory_mediator.h"
......@@ -31,21 +28,12 @@
#error "This file requires ARC support."
#endif
@interface FormInputAccessoryCoordinator ()<
@interface FormInputAccessoryCoordinator () <
AutofillSecurityAlertPresenter,
AddressCoordinatorDelegate,
CardCoordinatorDelegate,
ManualFillAccessoryViewControllerDelegate,
PasswordCoordinatorDelegate,
PasswordFetcherDelegate,
PersonalDataManagerObserver> {
// Personal data manager to be observed.
autofill::PersonalDataManager* _personalDataManager;
// C++ to ObjC bridge for PersonalDataManagerObserver.
std::unique_ptr<autofill::PersonalDataManagerObserverBridge>
_personalDataManagerObserver;
}
PasswordCoordinatorDelegate>
// The Mediator for the input accessory view controller.
@property(nonatomic, strong)
......@@ -55,18 +43,11 @@
@property(nonatomic, strong)
FormInputAccessoryViewController* formInputAccessoryViewController;
// The manual fill accessory to show above the keyboard.
@property(nonatomic, strong)
ManualFillAccessoryViewController* manualFillAccessoryViewController;
// The object in charge of interacting with the web view. Used to fill the data
// in the forms.
@property(nonatomic, strong)
ManualFillInjectionHandler* manualFillInjectionHandler;
// The password fetcher used to inform if passwords are available.
@property(nonatomic, strong) PasswordFetcher* passwordFetcher;
// The WebStateList for this instance. Used to instantiate the child
// coordinators lazily.
@property(nonatomic, assign) WebStateList* webStateList;
......@@ -91,64 +72,25 @@
securityAlertPresenter:self];
_formInputAccessoryViewController =
[[FormInputAccessoryViewController alloc] init];
if (autofill::features::IsPasswordManualFallbackEnabled()) {
_manualFillAccessoryViewController =
[[ManualFillAccessoryViewController alloc] initWithDelegate:self];
_formInputAccessoryViewController.manualFillAccessoryViewController =
_manualFillAccessoryViewController;
}
_formInputAccessoryMediator = [[FormInputAccessoryMediator alloc]
initWithConsumer:self.formInputAccessoryViewController
webStateList:webStateList];
[[FormInputAccessoryViewController alloc]
initWithManualFillAccessoryViewControllerDelegate:self];
auto passwordStore = IOSChromePasswordStoreFactory::GetForBrowserState(
browserState, ServiceAccessType::EXPLICIT_ACCESS);
// In BVC unit tests the password store doesn't exist. Skip creating the
// fetcher.
// TODO:(crbug.com/878388) Remove this workaround.
if (passwordStore) {
_passwordFetcher =
[[PasswordFetcher alloc] initWithPasswordStore:passwordStore
delegate:self];
}
autofill::PersonalDataManager* personalDataManager =
autofill::PersonalDataManagerFactory::GetForBrowserState(browserState);
// There is no personal data manager in OTR (incognito).
// TODO:(crbug.com/905720) Support Incognito.
if (personalDataManager) {
_personalDataManager = personalDataManager;
_personalDataManagerObserver.reset(
new autofill::PersonalDataManagerObserverBridge(self));
personalDataManager->AddObserver(_personalDataManagerObserver.get());
// TODO:(crbug.com/845472) Add earl grey test to verify the credit card
// button is hidden when local cards are saved and then
// kAutofillCreditCardEnabled is changed to disabled.
_manualFillAccessoryViewController.creditCardButtonHidden =
personalDataManager->GetCreditCards().empty();
_manualFillAccessoryViewController.addressButtonHidden =
personalDataManager->GetProfilesToSuggest().empty();
} else {
_manualFillAccessoryViewController.creditCardButtonHidden = YES;
_manualFillAccessoryViewController.addressButtonHidden = YES;
}
}
return self;
}
- (void)dealloc {
if (_personalDataManager) {
_personalDataManager->RemoveObserver(_personalDataManagerObserver.get());
_formInputAccessoryMediator = [[FormInputAccessoryMediator alloc]
initWithConsumer:self.formInputAccessoryViewController
webStateList:webStateList
personalDataManager:personalDataManager
passwordStore:passwordStore];
}
return self;
}
- (void)stop {
[self stopChildren];
[self.manualFillAccessoryViewController reset];
[self.formInputAccessoryViewController restoreOriginalKeyboardView];
}
......@@ -248,7 +190,7 @@
}
- (void)resetAccessoryView {
[self.manualFillAccessoryViewController reset];
[self.formInputAccessoryViewController resetManualFallbackIcons];
}
#pragma mark - CardCoordinatorDelegate
......@@ -263,30 +205,6 @@
[self.delegate openAddressSettings];
}
#pragma mark - PasswordFetcherDelegate
- (void)passwordFetcher:(PasswordFetcher*)passwordFetcher
didFetchPasswords:
(std::vector<std::unique_ptr<autofill::PasswordForm>>&)passwords {
self.manualFillAccessoryViewController.passwordButtonHidden =
passwords.empty();
}
#pragma mark - PersonalDataManagerObserver
- (void)onPersonalDataChanged {
autofill::PersonalDataManager* personalDataManager =
autofill::PersonalDataManagerFactory::GetForBrowserState(
self.browserState);
DCHECK(personalDataManager);
self.manualFillAccessoryViewController.creditCardButtonHidden =
personalDataManager->GetCreditCards().empty();
self.manualFillAccessoryViewController.addressButtonHidden =
personalDataManager->GetProfilesToSuggest().empty();
}
#pragma mark - AutofillSecurityAlertPresenter
- (void)presentSecurityWarningAlertWithText:(NSString*)body {
......
......@@ -7,6 +7,7 @@
#import <Foundation/Foundation.h>
#include "components/password_manager/core/browser/password_store.h"
#import "ios/chrome/browser/autofill/form_input_navigator.h"
#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
#import "ios/web/public/web_state/web_state_observer_bridge.h"
......@@ -15,11 +16,17 @@
@protocol FormInputAccessoryConsumer;
@protocol FormInputSuggestionsProvider;
@class JsSuggestionManager;
class WebStateList;
namespace autofill {
class PersonalDataManager;
}
namespace web {
class WebState;
}
class WebStateList;
// This class contains all the logic to get and provide keyboard input accessory
// views to its consumer. As well as telling the consumer when the default
// accessory view shoeuld be restored to the system default.
......@@ -27,8 +34,12 @@ class WebState;
// Returns a mediator observing the passed `WebStateList` and associated with
// the passed consumer. `webSateList` can be nullptr and `consumer` can be nil.
- (instancetype)initWithConsumer:(id<FormInputAccessoryConsumer>)consumer
webStateList:(WebStateList*)webStateList;
- (instancetype)
initWithConsumer:(id<FormInputAccessoryConsumer>)consumer
webStateList:(WebStateList*)webStateList
personalDataManager:(autofill::PersonalDataManager*)personalDataManager
passwordStore:
(scoped_refptr<password_manager::PasswordStore>)passwordStore;
// Unavailable, use initWithConsumer:webStateList: instead.
- (instancetype)init NS_UNAVAILABLE;
......
......@@ -8,9 +8,11 @@
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_block.h"
#import "base/strings/sys_string_conversions.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/ios/browser/autofill_switches.h"
#import "components/autofill/ios/browser/js_suggestion_manager.h"
#import "components/autofill/ios/browser/personal_data_manager_observer_bridge.h"
#import "components/autofill/ios/form_util/form_activity_observer_bridge.h"
#include "components/autofill/ios/form_util/form_activity_params.h"
#import "ios/chrome/browser/autofill/form_input_accessory_consumer.h"
......@@ -19,6 +21,7 @@
#import "ios/chrome/browser/autofill/form_input_suggestions_provider.h"
#import "ios/chrome/browser/autofill/form_suggestion_tab_helper.h"
#import "ios/chrome/browser/autofill/form_suggestion_view.h"
#import "ios/chrome/browser/autofill/manual_fill/passwords_fetcher.h"
#import "ios/chrome/browser/passwords/password_generation_utils.h"
#import "ios/chrome/browser/ui/autofill/manual_fill/keyboard_observer_helper.h"
#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
......@@ -38,11 +41,10 @@
FormInputAccessoryViewDelegate,
CRWWebStateObserver,
KeyboardObserverHelperConsumer,
PasswordFetcherDelegate,
PersonalDataManagerObserver,
WebStateListObserving>
// The JS manager for interacting with the underlying form.
@property(nonatomic, weak) JsSuggestionManager* JSSuggestionManager;
// The main consumer for this mediator.
@property(nonatomic, weak) id<FormInputAccessoryConsumer> consumer;
......@@ -53,6 +55,13 @@
@property(nonatomic, strong)
FormInputAccessoryViewHandler* formInputAccessoryHandler;
// Track the use of hardware keyboard, when there's a notification of keyboard
// use but no keyboard on the screen.
@property(nonatomic, assign) BOOL hardwareKeyboard;
// The JS manager for interacting with the underlying form.
@property(nonatomic, weak) JsSuggestionManager* JSSuggestionManager;
// The observer to determine when the keyboard dissapears and when it stays.
@property(nonatomic, strong) KeyboardObserverHelper* keyboardObserver;
......@@ -62,20 +71,20 @@
// Last seen suggestions. Used to reenable suggestions.
@property(nonatomic, strong) NSArray<FormSuggestion*>* lastSuggestions;
// Whether suggestions are disabled.
@property(nonatomic, assign) BOOL suggestionsDisabled;
// The objects that can provide a custom input accessory view while filling
// forms.
@property(nonatomic, copy) NSArray<id<FormInputSuggestionsProvider>>* providers;
// The password fetcher used to know if passwords are available and update the
// consumer accordingly.
@property(nonatomic, strong) PasswordFetcher* passwordFetcher;
// Whether suggestions are disabled.
@property(nonatomic, assign) BOOL suggestionsDisabled;
// The WebState this instance is observing. Can be null.
@property(nonatomic, assign) web::WebState* webState;
// Track the use of hardware keyboard, when there's a notification of keyboard
// use but no keyboard on the screen.
@property(nonatomic, assign) BOOL hardwareKeyboard;
@end
@implementation FormInputAccessoryMediator {
......@@ -83,6 +92,13 @@
// active WebState.
WebStateList* _webStateList;
// Personal data manager to be observed.
autofill::PersonalDataManager* _personalDataManager;
// C++ to ObjC bridge for PersonalDataManagerObserver.
std::unique_ptr<autofill::PersonalDataManagerObserverBridge>
_personalDataManagerObserver;
// Bridge to observe the web state list from Objective-C.
std::unique_ptr<WebStateListObserverBridge> _webStateListObserver;
......@@ -97,12 +113,17 @@
BOOL _suggestionsHaveBeenShown;
}
- (instancetype)initWithConsumer:(id<FormInputAccessoryConsumer>)consumer
webStateList:(WebStateList*)webStateList {
- (instancetype)
initWithConsumer:(id<FormInputAccessoryConsumer>)consumer
webStateList:(WebStateList*)webStateList
personalDataManager:(autofill::PersonalDataManager*)personalDataManager
passwordStore:
(scoped_refptr<password_manager::PasswordStore>)passwordStore {
self = [super init];
if (self) {
_consumer = consumer;
_consumer.navigationDelegate = self;
if (webStateList) {
_webStateList = webStateList;
_webStateListObserver =
......@@ -143,6 +164,35 @@
_keyboardObserver = [[KeyboardObserverHelper alloc] init];
_keyboardObserver.consumer = self;
}
// In BVC unit tests the password store doesn't exist. Skip creating the
// fetcher.
// TODO:(crbug.com/878388) Remove this workaround.
if (passwordStore) {
_passwordFetcher =
[[PasswordFetcher alloc] initWithPasswordStore:passwordStore
delegate:self];
}
// There is no personal data manager in OTR (incognito).
// TODO:(crbug.com/905720) Support Incognito.
if (personalDataManager) {
_personalDataManager = personalDataManager;
_personalDataManagerObserver.reset(
new autofill::PersonalDataManagerObserverBridge(self));
personalDataManager->AddObserver(_personalDataManagerObserver.get());
// TODO:(crbug.com/845472) Add earl grey test to verify the credit card
// button is hidden when local cards are saved and then
// kAutofillCreditCardEnabled is changed to disabled.
consumer.creditCardButtonHidden =
personalDataManager->GetCreditCards().empty();
consumer.addressButtonHidden =
personalDataManager->GetProfilesToSuggest().empty();
} else {
consumer.creditCardButtonHidden = YES;
consumer.addressButtonHidden = YES;
}
return self;
}
......@@ -158,6 +208,9 @@
_webStateList = nullptr;
}
_formActivityObserverBridge.reset();
if (_personalDataManager) {
_personalDataManager->RemoveObserver(_personalDataManagerObserver.get());
}
}
- (void)detachFromWebState {
......@@ -467,6 +520,26 @@ queryViewBlockForProvider:(id<FormInputSuggestionsProvider>)provider
[self.consumer continueCustomKeyboardView];
}
#pragma mark - PasswordFetcherDelegate
- (void)passwordFetcher:(PasswordFetcher*)passwordFetcher
didFetchPasswords:
(std::vector<std::unique_ptr<autofill::PasswordForm>>&)passwords {
self.consumer.passwordButtonHidden = passwords.empty();
}
#pragma mark - PersonalDataManagerObserver
- (void)onPersonalDataChanged {
DCHECK(_personalDataManager);
self.consumer.creditCardButtonHidden =
_personalDataManager->GetCreditCards().empty();
self.consumer.addressButtonHidden =
_personalDataManager->GetProfilesToSuggest().empty();
}
#pragma mark - Tests
- (void)injectWebState:(web::WebState*)webState {
......
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