Commit ca71f697 authored by Scott Wu's avatar Scott Wu Committed by Commit Bot

Extend autofill controller delegate for password autofilling logic in //ios/web_view.

Bug: 865114
Cq-Include-Trybots: luci.chromium.try:ios-simulator-cronet;luci.chromium.try:ios-simulator-full-configs
Change-Id: I48e317b989129cf391ece111df72f98eb62504d1
Reviewed-on: https://chromium-review.googlesource.com/c/1226950
Commit-Queue: Scott Wu <scottwu@chromium.org>
Reviewed-by: default avatarHiroshi Ichikawa <ichikawa@chromium.org>
Cr-Commit-Position: refs/heads/master@{#596478}
parent f72b3398
...@@ -84,11 +84,9 @@ if (ios_web_view_enable_autofill) { ...@@ -84,11 +84,9 @@ if (ios_web_view_enable_autofill) {
"public/cwv_autofill_suggestion.h", "public/cwv_autofill_suggestion.h",
"public/cwv_credit_card.h", "public/cwv_credit_card.h",
"public/cwv_credit_card_verifier.h", "public/cwv_credit_card_verifier.h",
"public/cwv_password_controller.h",
"public/cwv_preferences_autofill.h", "public/cwv_preferences_autofill.h",
"public/cwv_web_view_autofill.h", "public/cwv_web_view_autofill.h",
"public/cwv_web_view_configuration_autofill.h", "public/cwv_web_view_configuration_autofill.h",
"public/cwv_web_view_password.h",
] ]
} }
...@@ -235,7 +233,7 @@ if (ios_web_view_enable_autofill) { ...@@ -235,7 +233,7 @@ if (ios_web_view_enable_autofill) {
"internal/autofill/cwv_credit_card_verifier.mm", "internal/autofill/cwv_credit_card_verifier.mm",
"internal/autofill/cwv_credit_card_verifier_internal.h", "internal/autofill/cwv_credit_card_verifier_internal.h",
"internal/passwords/cwv_password_controller.mm", "internal/passwords/cwv_password_controller.mm",
"internal/passwords/cwv_password_controller_internal.h", "internal/passwords/cwv_password_controller.h",
] ]
} }
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#import "ios/web_view/internal/autofill/cwv_credit_card_verifier_internal.h" #import "ios/web_view/internal/autofill/cwv_credit_card_verifier_internal.h"
#import "ios/web_view/internal/autofill/web_view_autofill_client_ios.h" #import "ios/web_view/internal/autofill/web_view_autofill_client_ios.h"
#include "ios/web_view/internal/autofill/web_view_personal_data_manager_factory.h" #include "ios/web_view/internal/autofill/web_view_personal_data_manager_factory.h"
#import "ios/web_view/internal/passwords/cwv_password_controller.h"
#include "ios/web_view/internal/signin/web_view_identity_manager_factory.h" #include "ios/web_view/internal/signin/web_view_identity_manager_factory.h"
#import "ios/web_view/internal/sync/web_view_profile_sync_service_factory.h" #import "ios/web_view/internal/sync/web_view_profile_sync_service_factory.h"
#include "ios/web_view/internal/web_view_browser_state.h" #include "ios/web_view/internal/web_view_browser_state.h"
...@@ -42,7 +43,8 @@ ...@@ -42,7 +43,8 @@
@interface CWVAutofillController ()<AutofillDriverIOSBridge, @interface CWVAutofillController ()<AutofillDriverIOSBridge,
CRWWebStateObserver, CRWWebStateObserver,
CWVAutofillClientIOSBridge, CWVAutofillClientIOSBridge,
FormActivityObserver> FormActivityObserver,
CWVPasswordControllerDelegate>
@end @end
...@@ -71,6 +73,9 @@ ...@@ -71,6 +73,9 @@
std::unique_ptr<autofill::FormActivityObserverBridge> std::unique_ptr<autofill::FormActivityObserverBridge>
_formActivityObserverBridge; _formActivityObserverBridge;
// Handles password autofilling related logic.
CWVPasswordController* _passwordController;
} }
@synthesize delegate = _delegate; @synthesize delegate = _delegate;
...@@ -116,6 +121,10 @@ ...@@ -116,6 +121,10 @@
_JSAutofillManager = JSAutofillManager; _JSAutofillManager = JSAutofillManager;
_JSSuggestionManager = JSSuggestionManager; _JSSuggestionManager = JSSuggestionManager;
_passwordController =
[[CWVPasswordController alloc] initWithWebState:webState
andDelegate:self];
} }
return self; return self;
} }
...@@ -150,6 +159,7 @@ ...@@ -150,6 +159,7 @@
- (void)fetchSuggestionsForFormWithName:(NSString*)formName - (void)fetchSuggestionsForFormWithName:(NSString*)formName
fieldName:(NSString*)fieldName fieldName:(NSString*)fieldName
fieldIdentifier:(NSString*)fieldIdentifier fieldIdentifier:(NSString*)fieldIdentifier
fieldType:(NSString*)fieldType
frameID:(NSString*)frameID frameID:(NSString*)frameID
completionHandler: completionHandler:
(void (^)(NSArray<CWVAutofillSuggestion*>*)) (void (^)(NSArray<CWVAutofillSuggestion*>*))
...@@ -379,14 +389,16 @@ showUnmaskPromptForCard:(const autofill::CreditCard&)creditCard ...@@ -379,14 +389,16 @@ showUnmaskPromptForCard:(const autofill::CreditCard&)creditCard
NSString* nsFieldIdentifier = NSString* nsFieldIdentifier =
base::SysUTF8ToNSString(params.field_identifier); base::SysUTF8ToNSString(params.field_identifier);
NSString* nsFrameID = base::SysUTF8ToNSString(GetWebFrameId(frame)); NSString* nsFrameID = base::SysUTF8ToNSString(GetWebFrameId(frame));
NSString* nsFieldType = base::SysUTF8ToNSString(params.field_type);
NSString* nsValue = base::SysUTF8ToNSString(params.value); NSString* nsValue = base::SysUTF8ToNSString(params.value);
if (params.type == "focus") { if (params.type == "focus") {
if ([_delegate respondsToSelector:@selector if ([_delegate respondsToSelector:@selector
(autofillController:didFocusOnFieldWithName:fieldIdentifier (autofillController:didFocusOnFieldWithName:fieldIdentifier
:formName:frameID:value:)]) { :fieldType:formName:frameID:value:)]) {
[_delegate autofillController:self [_delegate autofillController:self
didFocusOnFieldWithName:nsFieldName didFocusOnFieldWithName:nsFieldName
fieldIdentifier:nsFieldIdentifier fieldIdentifier:nsFieldIdentifier
fieldType:nsFieldType
formName:nsFormName formName:nsFormName
frameID:nsFrameID frameID:nsFrameID
value:nsValue]; value:nsValue];
...@@ -394,10 +406,11 @@ showUnmaskPromptForCard:(const autofill::CreditCard&)creditCard ...@@ -394,10 +406,11 @@ showUnmaskPromptForCard:(const autofill::CreditCard&)creditCard
} else if (params.type == "input") { } else if (params.type == "input") {
if ([_delegate respondsToSelector:@selector if ([_delegate respondsToSelector:@selector
(autofillController:didInputInFieldWithName:fieldIdentifier (autofillController:didInputInFieldWithName:fieldIdentifier
:formName:frameID:value:)]) { :fieldType:formName:frameID:value:)]) {
[_delegate autofillController:self [_delegate autofillController:self
didInputInFieldWithName:nsFieldName didInputInFieldWithName:nsFieldName
fieldIdentifier:nsFieldIdentifier fieldIdentifier:nsFieldIdentifier
fieldType:nsFieldType
formName:nsFormName formName:nsFormName
frameID:nsFrameID frameID:nsFrameID
value:nsValue]; value:nsValue];
...@@ -405,10 +418,11 @@ showUnmaskPromptForCard:(const autofill::CreditCard&)creditCard ...@@ -405,10 +418,11 @@ showUnmaskPromptForCard:(const autofill::CreditCard&)creditCard
} else if (params.type == "blur") { } else if (params.type == "blur") {
if ([_delegate respondsToSelector:@selector if ([_delegate respondsToSelector:@selector
(autofillController:didBlurOnFieldWithName:fieldIdentifier (autofillController:didBlurOnFieldWithName:fieldIdentifier
:formName:frameID:value:)]) { :fieldType:formName:frameID:value:)]) {
[_delegate autofillController:self [_delegate autofillController:self
didBlurOnFieldWithName:nsFieldName didBlurOnFieldWithName:nsFieldName
fieldIdentifier:nsFieldIdentifier fieldIdentifier:nsFieldIdentifier
fieldType:nsFieldType
formName:nsFormName formName:nsFormName
frameID:nsFrameID frameID:nsFrameID
value:nsValue]; value:nsValue];
...@@ -442,4 +456,34 @@ showUnmaskPromptForCard:(const autofill::CreditCard&)creditCard ...@@ -442,4 +456,34 @@ showUnmaskPromptForCard:(const autofill::CreditCard&)creditCard
_webState = nullptr; _webState = nullptr;
} }
#pragma mark - CWVPasswordControllerDelegate
- (void)passwordController:(CWVPasswordController*)passwordController
decidePasswordSavingPolicyForUsername:(NSString*)username
decisionHandler:
(void (^)(CWVPasswordUserDecision decision))
decisionHandler {
if ([self.delegate respondsToSelector:@selector
(autofillController:decidePasswordSavingPolicyForUsername
:decisionHandler:)]) {
[self.delegate autofillController:self
decidePasswordSavingPolicyForUsername:username
decisionHandler:decisionHandler];
}
}
- (void)passwordController:(CWVPasswordController*)passwordController
decidePasswordUpdatingPolicyForUsername:(NSString*)username
decisionHandler:
(void (^)(CWVPasswordUserDecision decision))
decisionHandler {
if ([self.delegate respondsToSelector:@selector
(autofillController:decidePasswordUpdatingPolicyForUsername
:decisionHandler:)]) {
[self.delegate autofillController:self
decidePasswordUpdatingPolicyForUsername:username
decisionHandler:decisionHandler];
}
}
@end @end
...@@ -116,6 +116,7 @@ TEST_F(CWVAutofillControllerTest, FetchSuggestions) { ...@@ -116,6 +116,7 @@ TEST_F(CWVAutofillControllerTest, FetchSuggestions) {
[autofill_controller_ fetchSuggestionsForFormWithName:kTestFormName [autofill_controller_ fetchSuggestionsForFormWithName:kTestFormName
fieldName:kTestFieldName fieldName:kTestFieldName
fieldIdentifier:kTestFieldIdentifier fieldIdentifier:kTestFieldIdentifier
fieldType:@""
frameID:kTestFrameId frameID:kTestFrameId
completionHandler:fetch_completion]; completionHandler:fetch_completion];
...@@ -217,6 +218,7 @@ TEST_F(CWVAutofillControllerTest, FocusCallback) { ...@@ -217,6 +218,7 @@ TEST_F(CWVAutofillControllerTest, FocusCallback) {
[[delegate expect] autofillController:autofill_controller_ [[delegate expect] autofillController:autofill_controller_
didFocusOnFieldWithName:kTestFieldName didFocusOnFieldWithName:kTestFieldName
fieldIdentifier:kTestFieldIdentifier fieldIdentifier:kTestFieldIdentifier
fieldType:@""
formName:kTestFormName formName:kTestFormName
frameID:kTestFrameId frameID:kTestFrameId
value:kTestFieldValue]; value:kTestFieldValue];
...@@ -247,6 +249,7 @@ TEST_F(CWVAutofillControllerTest, InputCallback) { ...@@ -247,6 +249,7 @@ TEST_F(CWVAutofillControllerTest, InputCallback) {
[[delegate expect] autofillController:autofill_controller_ [[delegate expect] autofillController:autofill_controller_
didInputInFieldWithName:kTestFieldName didInputInFieldWithName:kTestFieldName
fieldIdentifier:kTestFieldIdentifier fieldIdentifier:kTestFieldIdentifier
fieldType:@""
formName:kTestFormName formName:kTestFormName
frameID:kTestFrameId frameID:kTestFrameId
value:kTestFieldValue]; value:kTestFieldValue];
...@@ -276,6 +279,7 @@ TEST_F(CWVAutofillControllerTest, BlurCallback) { ...@@ -276,6 +279,7 @@ TEST_F(CWVAutofillControllerTest, BlurCallback) {
[[delegate expect] autofillController:autofill_controller_ [[delegate expect] autofillController:autofill_controller_
didBlurOnFieldWithName:kTestFieldName didBlurOnFieldWithName:kTestFieldName
fieldIdentifier:kTestFieldIdentifier fieldIdentifier:kTestFieldIdentifier
fieldType:@""
formName:kTestFormName formName:kTestFormName
frameID:kTestFrameId frameID:kTestFrameId
value:kTestFieldValue]; value:kTestFieldValue];
...@@ -307,9 +311,10 @@ TEST_F(CWVAutofillControllerTest, SubmitCallback) { ...@@ -307,9 +311,10 @@ TEST_F(CWVAutofillControllerTest, SubmitCallback) {
didSubmitFormWithName:kTestFormName didSubmitFormWithName:kTestFormName
userInitiated:YES userInitiated:YES
isMainFrame:YES]; isMainFrame:YES];
web::FakeWebFrame frame(base::SysNSStringToUTF8(kTestFrameId), true,
GURL::EmptyGURL());
test_form_activity_tab_helper_->DocumentSubmitted( test_form_activity_tab_helper_->DocumentSubmitted(
/*sender_frame*/ nullptr, base::SysNSStringToUTF8(kTestFormName), /*sender_frame*/ &frame, base::SysNSStringToUTF8(kTestFormName),
/*form_data=*/"", /*form_data=*/"",
/*user_initiated=*/true, /*user_initiated=*/true,
/*is_main_frame=*/true); /*is_main_frame=*/true);
...@@ -320,7 +325,7 @@ TEST_F(CWVAutofillControllerTest, SubmitCallback) { ...@@ -320,7 +325,7 @@ TEST_F(CWVAutofillControllerTest, SubmitCallback) {
isMainFrame:YES]; isMainFrame:YES];
test_form_activity_tab_helper_->DocumentSubmitted( test_form_activity_tab_helper_->DocumentSubmitted(
/*sender_frame*/ nullptr, base::SysNSStringToUTF8(kTestFormName), /*sender_frame*/ &frame, base::SysNSStringToUTF8(kTestFormName),
/*form_data=*/"", /*form_data=*/"",
/*user_initiated=*/false, /*user_initiated=*/false,
/*is_main_frame=*/true); /*is_main_frame=*/true);
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#import "ios/web_view/internal/cwv_script_command_internal.h" #import "ios/web_view/internal/cwv_script_command_internal.h"
#import "ios/web_view/internal/cwv_scroll_view_internal.h" #import "ios/web_view/internal/cwv_scroll_view_internal.h"
#import "ios/web_view/internal/cwv_web_view_configuration_internal.h" #import "ios/web_view/internal/cwv_web_view_configuration_internal.h"
#import "ios/web_view/internal/passwords/cwv_password_controller_internal.h"
#import "ios/web_view/internal/translate/cwv_translation_controller_internal.h" #import "ios/web_view/internal/translate/cwv_translation_controller_internal.h"
#import "ios/web_view/internal/translate/web_view_translate_client.h" #import "ios/web_view/internal/translate/web_view_translate_client.h"
#include "ios/web_view/internal/web_view_browser_state.h" #include "ios/web_view/internal/web_view_browser_state.h"
...@@ -104,7 +103,6 @@ NSDictionary* NSDictionaryFromDictionaryValue( ...@@ -104,7 +103,6 @@ NSDictionary* NSDictionaryFromDictionaryValue(
@property(nonatomic, readwrite) NSURL* visibleURL; @property(nonatomic, readwrite) NSURL* visibleURL;
#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) #if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL)
@property(nonatomic, readonly) CWVAutofillController* autofillController; @property(nonatomic, readonly) CWVAutofillController* autofillController;
@property(nonatomic, readonly) CWVPasswordController* passwordController;
#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) #endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL)
// Updates the availability of the back/forward navigation properties exposed // Updates the availability of the back/forward navigation properties exposed
...@@ -117,8 +115,6 @@ NSDictionary* NSDictionaryFromDictionaryValue( ...@@ -117,8 +115,6 @@ NSDictionary* NSDictionaryFromDictionaryValue(
#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) #if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL)
// Returns a new CWVAutofillController created from |_webState|. // Returns a new CWVAutofillController created from |_webState|.
- (CWVAutofillController*)newAutofillController; - (CWVAutofillController*)newAutofillController;
// Returns a new CWVPasswordController created from |_webState|.
- (CWVPasswordController*)newPasswordController;
#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) #endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL)
// Returns a new CWVTranslationController created from |_webState|. // Returns a new CWVTranslationController created from |_webState|.
- (CWVTranslationController*)newTranslationController; - (CWVTranslationController*)newTranslationController;
...@@ -133,7 +129,6 @@ static NSString* gUserAgentProduct = nil; ...@@ -133,7 +129,6 @@ static NSString* gUserAgentProduct = nil;
#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) #if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL)
@synthesize autofillController = _autofillController; @synthesize autofillController = _autofillController;
@synthesize passwordController = _passwordController;
#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) #endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL)
@synthesize canGoBack = _canGoBack; @synthesize canGoBack = _canGoBack;
@synthesize canGoForward = _canGoForward; @synthesize canGoForward = _canGoForward;
...@@ -509,19 +504,6 @@ static NSString* gUserAgentProduct = nil; ...@@ -509,19 +504,6 @@ static NSString* gUserAgentProduct = nil;
JSSuggestionManager:JSSuggestionManager]; JSSuggestionManager:JSSuggestionManager];
} }
#pragma mark - Password
- (CWVPasswordController*)passwordController {
if (!_passwordController) {
_passwordController = [self newPasswordController];
}
return _passwordController;
}
- (CWVPasswordController*)newPasswordController {
return [[CWVPasswordController alloc] initWithWebState:_webState.get()];
}
#endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) #endif // BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL)
#pragma mark - Preserving and Restoring State #pragma mark - Preserving and Restoring State
...@@ -609,7 +591,6 @@ static NSString* gUserAgentProduct = nil; ...@@ -609,7 +591,6 @@ static NSString* gUserAgentProduct = nil;
#if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL) #if BUILDFLAG(IOS_WEB_VIEW_ENABLE_AUTOFILL)
// Recreate and restore the delegate only if previously lazily loaded. // Recreate and restore the delegate only if previously lazily loaded.
// TODO(crbug.com/865114): Add delegate for password controller.
if (_autofillController) { if (_autofillController) {
id<CWVAutofillControllerDelegate> delegate = _autofillController.delegate; id<CWVAutofillControllerDelegate> delegate = _autofillController.delegate;
_autofillController = [self newAutofillController]; _autofillController = [self newAutofillController];
......
// Copyright 2018 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_WEB_VIEW_INTERNAL_PASSWORDS_CWV_PASSWORD_CONTROLLER_H_
#define IOS_WEB_VIEW_INTERNAL_PASSWORDS_CWV_PASSWORD_CONTROLLER_H_
#import "ios/web/public/web_state/web_state.h"
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger, CWVPasswordUserDecision);
@class CWVPasswordController;
// Internal protocol to receive callbacks related to password autofilling.
@protocol CWVPasswordControllerDelegate
// Called when user needs to decide on whether or not to save the
// password for |username|.
// This can happen when user is successfully logging into a web site with a new
// username.
// Pass user decision to |decisionHandler|. This block should be called only
// once if user made the decision, or not get called if user ignores the prompt.
- (void)passwordController:(CWVPasswordController*)passwordController
decidePasswordSavingPolicyForUsername:(NSString*)username
decisionHandler:
(void (^)(CWVPasswordUserDecision decision))
decisionHandler;
// Called when user needs to decide on whether or not to update the
// password for |username|.
// This can happen when user is successfully logging into a web site with a new
// password and an existing username.
// Pass user decision to |decisionHandler|. This block should be called only
// once if user made the decision, or not get called if user ignores the prompt.
- (void)passwordController:(CWVPasswordController*)passwordController
decidePasswordUpdatingPolicyForUsername:(NSString*)username
decisionHandler:
(void (^)(CWVPasswordUserDecision decision))
decisionHandler;
@end
// Implements features that allow saving entered passwords as well as
// autofilling password forms.
@interface CWVPasswordController : NSObject
// Creates a new password controller with the given |webState|.
// |delegate| is used to receive password autofill suggestion callbacks.
- (instancetype)initWithWebState:(web::WebState*)webState
andDelegate:
(nullable id<CWVPasswordControllerDelegate>)delegate
NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END
#endif // IOS_WEB_VIEW_INTERNAL_PASSWORDS_CWV_PASSWORD_CONTROLLER_H_
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#import "ios/web_view/internal/passwords/cwv_password_controller_internal.h" #import "ios/web_view/internal/passwords/cwv_password_controller.h"
#include <memory> #include <memory>
#include "base/strings/sys_string_conversions.h"
#include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/password_form.h" #include "components/autofill/core/common/password_form.h"
#include "components/autofill/ios/browser/autofill_util.h" #include "components/autofill/ios/browser/autofill_util.h"
...@@ -18,6 +19,7 @@ ...@@ -18,6 +19,7 @@
#import "ios/web_view/internal/passwords/web_view_password_manager_client.h" #import "ios/web_view/internal/passwords/web_view_password_manager_client.h"
#import "ios/web_view/internal/passwords/web_view_password_manager_driver.h" #import "ios/web_view/internal/passwords/web_view_password_manager_driver.h"
#include "ios/web_view/internal/web_view_browser_state.h" #include "ios/web_view/internal/web_view_browser_state.h"
#import "ios/web_view/public/cwv_autofill_controller_delegate.h"
#include "url/gurl.h" #include "url/gurl.h"
#if !defined(__has_feature) || !__has_feature(objc_arc) #if !defined(__has_feature) || !__has_feature(objc_arc)
...@@ -29,6 +31,7 @@ using autofill::PasswordForm; ...@@ -29,6 +31,7 @@ using autofill::PasswordForm;
using ios_web_view::WebViewPasswordManagerClient; using ios_web_view::WebViewPasswordManagerClient;
using ios_web_view::WebViewPasswordManagerDriver; using ios_web_view::WebViewPasswordManagerDriver;
using password_manager::GetPageURLAndCheckTrustLevel; using password_manager::GetPageURLAndCheckTrustLevel;
using password_manager::PasswordFormManagerForUI;
@interface CWVPasswordController ()<CRWWebStateObserver, @interface CWVPasswordController ()<CRWWebStateObserver,
CWVPasswordManagerClientDelegate, CWVPasswordManagerClientDelegate,
...@@ -42,6 +45,9 @@ using password_manager::GetPageURLAndCheckTrustLevel; ...@@ -42,6 +45,9 @@ using password_manager::GetPageURLAndCheckTrustLevel;
// Helper contains common password controller logic. // Helper contains common password controller logic.
@property(nonatomic, readonly) PasswordControllerHelper* helper; @property(nonatomic, readonly) PasswordControllerHelper* helper;
// Delegate to receive password autofill suggestion callbacks.
@property(nonatomic, weak, nullable) id<CWVPasswordControllerDelegate> delegate;
// Informs the |_passwordManager| of the password forms (if any were present) // Informs the |_passwordManager| of the password forms (if any were present)
// that have been found on the page. // that have been found on the page.
- (void)didFinishPasswordFormExtraction: - (void)didFinishPasswordFormExtraction:
...@@ -78,6 +84,7 @@ using password_manager::GetPageURLAndCheckTrustLevel; ...@@ -78,6 +84,7 @@ using password_manager::GetPageURLAndCheckTrustLevel;
#pragma mark - Properties #pragma mark - Properties
@synthesize helper = _helper; @synthesize helper = _helper;
@synthesize delegate = _delegate;
- (password_manager::PasswordManagerDriver*)passwordManagerDriver { - (password_manager::PasswordManagerDriver*)passwordManagerDriver {
return _passwordManagerDriver.get(); return _passwordManagerDriver.get();
...@@ -85,7 +92,9 @@ using password_manager::GetPageURLAndCheckTrustLevel; ...@@ -85,7 +92,9 @@ using password_manager::GetPageURLAndCheckTrustLevel;
#pragma mark - Initialization #pragma mark - Initialization
- (instancetype)initWithWebState:(web::WebState*)webState { - (instancetype)initWithWebState:(web::WebState*)webState
andDelegate:
(nullable id<CWVPasswordControllerDelegate>)delegate {
self = [super init]; self = [super init];
if (self) { if (self) {
DCHECK(webState); DCHECK(webState);
...@@ -105,6 +114,8 @@ using password_manager::GetPageURLAndCheckTrustLevel; ...@@ -105,6 +114,8 @@ using password_manager::GetPageURLAndCheckTrustLevel;
_credentialsSentToPasswordManager = NO; _credentialsSentToPasswordManager = NO;
_delegate = delegate;
// TODO(crbug.com/865114): Credential manager related logic // TODO(crbug.com/865114): Credential manager related logic
} }
return self; return self;
...@@ -179,15 +190,64 @@ using password_manager::GetPageURLAndCheckTrustLevel; ...@@ -179,15 +190,64 @@ using password_manager::GetPageURLAndCheckTrustLevel;
} }
- (void)showSavePasswordInfoBar: - (void)showSavePasswordInfoBar:
(std::unique_ptr<password_manager::PasswordFormManagerForUI>)formToSave { (std::unique_ptr<PasswordFormManagerForUI>)formToSave {
// Always save password for Demo. if (!self.delegate) {
// TODO(crbug.com/865114): Implement remaining logic. return;
formToSave.get()->Save(); }
// Use the same logic as iOS Chrome for saving password, see:
// ios/chrome/browser/passwords/ios_chrome_save_password_infobar_delegate.mm
__block std::unique_ptr<PasswordFormManagerForUI> formPtr(
std::move(formToSave));
NSString* userName =
base::SysUTF16ToNSString(formPtr->GetPendingCredentials().username_value);
[self.delegate passwordController:self
decidePasswordSavingPolicyForUsername:userName
decisionHandler:^(
CWVPasswordUserDecision decision) {
switch (decision) {
case CWVPasswordUserDecisionYes:
formPtr->Save();
break;
case CWVPasswordUserDecisionNever:
formPtr->PermanentlyBlacklist();
break;
default:
// Do nothing.
break;
}
}];
} }
- (void)showUpdatePasswordInfoBar: - (void)showUpdatePasswordInfoBar:
(std::unique_ptr<password_manager::PasswordFormManagerForUI>)formToUpdate { (std::unique_ptr<PasswordFormManagerForUI>)formToUpdate {
// TODO(crbug.com/865114): Implement remaining logic. if (!self.delegate) {
return;
}
// Use the same logic as iOS Chrome for updating password, see:
// ios/chrome/browser/passwords/
// ios_chrome_update_password_infobar_delegate.mm
__block std::unique_ptr<PasswordFormManagerForUI> formPtr(
std::move(formToUpdate));
BOOL hasMultipleCredentials =
formPtr->GetBestMatches().size() > 1 && !formPtr->IsPasswordOverridden();
const autofill::PasswordForm& credentials =
hasMultipleCredentials ? *(formPtr->GetPreferredMatch())
: formPtr->GetPendingCredentials();
NSString* userName = base::SysUTF16ToNSString(credentials.username_value);
[self.delegate passwordController:self
decidePasswordUpdatingPolicyForUsername:userName
decisionHandler:^(
CWVPasswordUserDecision decision) {
DCHECK_NE(decision,
CWVPasswordUserDecisionNever);
if (decision == CWVPasswordUserDecisionYes) {
formPtr->Update(credentials);
}
}];
} }
- (void)showAutosigninNotification: - (void)showAutosigninNotification:
......
// Copyright 2018 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_WEB_VIEW_INTERNAL_PASSWORDS_CWV_PASSWORD_CONTROLLER_INTERNAL_H_
#define IOS_WEB_VIEW_INTERNAL_PASSWORDS_CWV_PASSWORD_CONTROLLER_INTERNAL_H_
#import "ios/web/public/web_state/web_state.h"
#import "ios/web_view/public/cwv_password_controller.h"
NS_ASSUME_NONNULL_BEGIN
@interface CWVPasswordController ()
- (instancetype)initWithWebState:(web::WebState*)webState;
@end
NS_ASSUME_NONNULL_END
#endif // IOS_WEB_VIEW_INTERNAL_PASSWORDS_CWV_PASSWORD_CONTROLLER_INTERNAL_H_
...@@ -42,11 +42,13 @@ CWV_EXPORT ...@@ -42,11 +42,13 @@ CWV_EXPORT
// No-op if no such form and field can be found in the current page. // No-op if no such form and field can be found in the current page.
// |fieldIdentifier| identifies the field that had focus. It is passed to // |fieldIdentifier| identifies the field that had focus. It is passed to
// CWVAutofillControllerDelegate and forwarded to this method. // CWVAutofillControllerDelegate and forwarded to this method.
// |fieldType| is the 'type' attribute of the html field.
// |completionHandler| will only be called on success. // |completionHandler| will only be called on success.
// |frameID| is the ID of the web frame containing the form. // |frameID| is the ID of the web frame containing the form.
- (void)fetchSuggestionsForFormWithName:(NSString*)formName - (void)fetchSuggestionsForFormWithName:(NSString*)formName
fieldName:(NSString*)fieldName fieldName:(NSString*)fieldName
fieldIdentifier:(NSString*)fieldIdentifier fieldIdentifier:(NSString*)fieldIdentifier
fieldType:(NSString*)fieldType
frameID:(NSString*)frameID frameID:(NSString*)frameID
completionHandler: completionHandler:
(void (^)(NSArray<CWVAutofillSuggestion*>*)) (void (^)(NSArray<CWVAutofillSuggestion*>*))
......
...@@ -20,13 +20,25 @@ typedef NS_ENUM(NSInteger, CWVStoragePolicy) { ...@@ -20,13 +20,25 @@ typedef NS_ENUM(NSInteger, CWVStoragePolicy) {
CWVStoragePolicyAllow, // Allow storage. CWVStoragePolicyAllow, // Allow storage.
}; };
// User decision for saving / updating password.
// Note: CWVPasswordUserDecisionNever is only used in saving scenarios.
typedef NS_ENUM(NSInteger, CWVPasswordUserDecision) {
CWVPasswordUserDecisionNotThisTime =
0, // Do not save / update password this time.
CWVPasswordUserDecisionNever, // Never save password for this site.
CWVPasswordUserDecisionYes, // Save / update password.
};
// Protocol to receive callbacks related to autofill. // Protocol to receive callbacks related to autofill.
// |fieldName| is the 'name' attribute of a html field. // |fieldName| is the 'name' attribute of a html field.
// |fieldIdentifier| identifies the html field.
// |fieldType| is the 'type' attribute of the html field.
// |formName| is the 'name' attribute of a html <form>. // |formName| is the 'name' attribute of a html <form>.
// |value| is the 'value' attribute of the html field. // |value| is the 'value' attribute of the html field.
// Example: // Example:
// <form name='_formName_'> // <form name='_formName_'>
// <input name='_fieldName_' value='_value_'> // <input id='_fieldIdentifier_' name='_fieldName_' value='_value_'
// type='_fieldType_'>
// </form> // </form>
@protocol CWVAutofillControllerDelegate<NSObject> @protocol CWVAutofillControllerDelegate<NSObject>
...@@ -36,6 +48,7 @@ typedef NS_ENUM(NSInteger, CWVStoragePolicy) { ...@@ -36,6 +48,7 @@ typedef NS_ENUM(NSInteger, CWVStoragePolicy) {
- (void)autofillController:(CWVAutofillController*)autofillController - (void)autofillController:(CWVAutofillController*)autofillController
didFocusOnFieldWithName:(NSString*)fieldName didFocusOnFieldWithName:(NSString*)fieldName
fieldIdentifier:(NSString*)fieldIdentifier fieldIdentifier:(NSString*)fieldIdentifier
fieldType:(NSString*)fieldType
formName:(NSString*)formName formName:(NSString*)formName
frameID:(NSString*)frameID frameID:(NSString*)frameID
value:(NSString*)value; value:(NSString*)value;
...@@ -44,6 +57,7 @@ typedef NS_ENUM(NSInteger, CWVStoragePolicy) { ...@@ -44,6 +57,7 @@ typedef NS_ENUM(NSInteger, CWVStoragePolicy) {
- (void)autofillController:(CWVAutofillController*)autofillController - (void)autofillController:(CWVAutofillController*)autofillController
didInputInFieldWithName:(NSString*)fieldName didInputInFieldWithName:(NSString*)fieldName
fieldIdentifier:(NSString*)fieldIdentifier fieldIdentifier:(NSString*)fieldIdentifier
fieldType:(NSString*)fieldType
formName:(NSString*)formName formName:(NSString*)formName
frameID:(NSString*)frameID frameID:(NSString*)frameID
value:(NSString*)value; value:(NSString*)value;
...@@ -52,6 +66,7 @@ typedef NS_ENUM(NSInteger, CWVStoragePolicy) { ...@@ -52,6 +66,7 @@ typedef NS_ENUM(NSInteger, CWVStoragePolicy) {
- (void)autofillController:(CWVAutofillController*)autofillController - (void)autofillController:(CWVAutofillController*)autofillController
didBlurOnFieldWithName:(NSString*)fieldName didBlurOnFieldWithName:(NSString*)fieldName
fieldIdentifier:(NSString*)fieldIdentifier fieldIdentifier:(NSString*)fieldIdentifier
fieldType:(NSString*)fieldType
formName:(NSString*)formName formName:(NSString*)formName
frameID:(NSString*)frameID frameID:(NSString*)frameID
value:(NSString*)value; value:(NSString*)value;
...@@ -77,6 +92,31 @@ typedef NS_ENUM(NSInteger, CWVStoragePolicy) { ...@@ -77,6 +92,31 @@ typedef NS_ENUM(NSInteger, CWVStoragePolicy) {
- (void)autofillController:(CWVAutofillController*)autofillController - (void)autofillController:(CWVAutofillController*)autofillController
verifyCreditCardWithVerifier:(CWVCreditCardVerifier*)verifier; verifyCreditCardWithVerifier:(CWVCreditCardVerifier*)verifier;
// Called when user needs to decide on whether or not to save the
// password for |username|.
// This can happen when user successfully logs into a web site with a new
// username.
// Pass user decision to |decisionHandler|. This block should be called only
// once if user made the decision, or not get called if user ignores the prompt.
// Not implementing it is equivalent of not calling |decisionHandler|.
- (void)autofillController:(CWVAutofillController*)autofillController
decidePasswordSavingPolicyForUsername:(NSString*)username
decisionHandler:
(void (^)(CWVPasswordUserDecision decision))
decisionHandler;
// Called when user needs to decide on whether or not to update the
// password for |username|.
// This can happen when user successfully logs into a web site with a new
// password and an existing username.
// Pass user decision to |decisionHandler|. This block should be called only
// once if user made the decision, or not get called if user ignores the prompt.
// Not implementing it is equivalent of not calling |decisionHandler|.
- (void)autofillController:(CWVAutofillController*)autofillController
decidePasswordUpdatingPolicyForUsername:(NSString*)username
decisionHandler:
(void (^)(CWVPasswordUserDecision decision))
decisionHandler;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END
......
// Copyright 2018 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_WEB_VIEW_PUBLIC_CWV_PASSWORD_CONTROLLER_H_
#define IOS_WEB_VIEW_PUBLIC_CWV_PASSWORD_CONTROLLER_H_
#import <Foundation/Foundation.h>
#import "cwv_export.h"
NS_ASSUME_NONNULL_BEGIN
CWV_EXPORT
// Exposes features that allow saving entered passwords as well as autofilling
// password forms.
@interface CWVPasswordController : NSObject
- (instancetype)init NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END
#endif // IOS_WEB_VIEW_PUBLIC_CWV_PASSWORD_CONTROLLER_H_
// Copyright 2018 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_WEB_VIEW_PUBLIC_CWV_WEB_VIEW_PASSWORD_H_
#define IOS_WEB_VIEW_PUBLIC_CWV_WEB_VIEW_PASSWORD_H_
#import "cwv_web_view.h"
@class CWVPasswordController;
@interface CWVWebView (Password)
// The web view's password controller.
@property(nonatomic, readonly) CWVPasswordController* passwordController;
@end
#endif // IOS_WEB_VIEW_PUBLIC_CWV_WEB_VIEW_PASSWORD_H_
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
- (void)autofillController:(CWVAutofillController*)autofillController - (void)autofillController:(CWVAutofillController*)autofillController
didFocusOnFieldWithName:(NSString*)fieldName didFocusOnFieldWithName:(NSString*)fieldName
fieldIdentifier:(NSString*)fieldIdentifier fieldIdentifier:(NSString*)fieldIdentifier
fieldType:(NSString*)fieldType
formName:(NSString*)formName formName:(NSString*)formName
frameID:(NSString*)frameID frameID:(NSString*)frameID
value:(NSString*)value { value:(NSString*)value {
...@@ -81,6 +82,7 @@ ...@@ -81,6 +82,7 @@
[autofillController fetchSuggestionsForFormWithName:formName [autofillController fetchSuggestionsForFormWithName:formName
fieldName:fieldName fieldName:fieldName
fieldIdentifier:fieldIdentifier fieldIdentifier:fieldIdentifier
fieldType:fieldType
frameID:frameID frameID:frameID
completionHandler:completionHandler]; completionHandler:completionHandler];
} }
...@@ -88,6 +90,7 @@ ...@@ -88,6 +90,7 @@
- (void)autofillController:(CWVAutofillController*)autofillController - (void)autofillController:(CWVAutofillController*)autofillController
didInputInFieldWithName:(NSString*)fieldName didInputInFieldWithName:(NSString*)fieldName
fieldIdentifier:(NSString*)fieldIdentifier fieldIdentifier:(NSString*)fieldIdentifier
fieldType:(NSString*)fieldType
formName:(NSString*)formName formName:(NSString*)formName
value:(NSString*)value { value:(NSString*)value {
// Not implemented. // Not implemented.
...@@ -96,6 +99,7 @@ ...@@ -96,6 +99,7 @@
- (void)autofillController:(CWVAutofillController*)autofillController - (void)autofillController:(CWVAutofillController*)autofillController
didBlurOnFieldWithName:(NSString*)fieldName didBlurOnFieldWithName:(NSString*)fieldName
fieldIdentifier:(NSString*)fieldIdentifier fieldIdentifier:(NSString*)fieldIdentifier
fieldType:(NSString*)fieldType
formName:(NSString*)formName formName:(NSString*)formName
value:(NSString*)value { value:(NSString*)value {
[_alertController dismissViewControllerAnimated:YES completion:nil]; [_alertController dismissViewControllerAnimated:YES completion:nil];
...@@ -139,6 +143,75 @@ ...@@ -139,6 +143,75 @@
[self presentAlertController:alertController]; [self presentAlertController:alertController];
} }
- (void)autofillController:(CWVAutofillController*)autofillController
decidePasswordSavingPolicyForUsername:(NSString*)userName
decisionHandler:(void (^)(CWVPasswordUserDecision))
decisionHandler {
UIAlertController* alertController =
[self newAlertControllerWithTitle:@"Save Password"
message:
@"Do you want to save your password on "
@"this site?"];
UIAlertAction* noAction = [UIAlertAction
actionWithTitle:@"Not this time"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction* _Nonnull action) {
decisionHandler(CWVPasswordUserDecisionNotThisTime);
}];
[alertController addAction:noAction];
UIAlertAction* neverAction =
[UIAlertAction actionWithTitle:@"Never"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction* _Nonnull action) {
decisionHandler(CWVPasswordUserDecisionNever);
}];
[alertController addAction:neverAction];
UIAlertAction* yesAction =
[UIAlertAction actionWithTitle:@"Save"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction* _Nonnull action) {
decisionHandler(CWVPasswordUserDecisionYes);
}];
[alertController addAction:yesAction];
[self presentAlertController:alertController];
}
- (void)autofillController:(CWVAutofillController*)autofillController
decidePasswordUpdatingPolicyForUsername:(NSString*)userName
decisionHandler:(void (^)(CWVPasswordUserDecision))
decisionHandler {
UIAlertController* alertController = [self
newAlertControllerWithTitle:@"Update Password"
message:
[NSString
stringWithFormat:
@"Do you want to update your password "
@"for %@ on this site?",
userName]];
UIAlertAction* noAction = [UIAlertAction
actionWithTitle:@"Not this time"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction* _Nonnull action) {
decisionHandler(CWVPasswordUserDecisionNotThisTime);
}];
[alertController addAction:noAction];
UIAlertAction* yesAction =
[UIAlertAction actionWithTitle:@"Update"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction* _Nonnull action) {
decisionHandler(CWVPasswordUserDecisionYes);
}];
[alertController addAction:yesAction];
[self presentAlertController:alertController];
}
#pragma mark - Private Methods #pragma mark - Private Methods
- (UIAlertController*)newAlertControllerWithTitle:(NSString*)title - (UIAlertController*)newAlertControllerWithTitle:(NSString*)title
......
...@@ -270,10 +270,6 @@ NSString* const kWebViewShellJavaScriptDialogTextFieldAccessibiltyIdentifier = ...@@ -270,10 +270,6 @@ NSString* const kWebViewShellJavaScriptDialogTextFieldAccessibiltyIdentifier =
_autofillDelegate = [[ShellAutofillDelegate alloc] init]; _autofillDelegate = [[ShellAutofillDelegate alloc] init];
_webView.autofillController.delegate = _autofillDelegate; _webView.autofillController.delegate = _autofillDelegate;
// Triggers password controller initiation.
// TODO(crbug.com/865114): Add delegate for password controller.
[_webView passwordController];
[_webView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | [_webView setAutoresizingMask:UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight]; UIViewAutoresizingFlexibleHeight];
[_containerView addSubview:_webView]; [_containerView addSubview:_webView];
......
...@@ -30,6 +30,7 @@ NSString* const kTestFormName = @"FormName"; ...@@ -30,6 +30,7 @@ NSString* const kTestFormName = @"FormName";
NSString* const kTestFormID = @"FormID"; NSString* const kTestFormID = @"FormID";
NSString* const kTestFieldName = @"FieldName"; NSString* const kTestFieldName = @"FieldName";
NSString* const kTestFieldID = @"FieldID"; NSString* const kTestFieldID = @"FieldID";
NSString* const kTestFieldType = @"text";
NSString* const kTestFieldValue = @"FieldValue"; NSString* const kTestFieldValue = @"FieldValue";
NSString* const kTestSubmitID = @"SubmitID"; NSString* const kTestSubmitID = @"SubmitID";
NSString* const kTestFormHtml = NSString* const kTestFormHtml =
...@@ -83,6 +84,7 @@ class WebViewAutofillTest : public WebViewInttestBase { ...@@ -83,6 +84,7 @@ class WebViewAutofillTest : public WebViewInttestBase {
fetchSuggestionsForFormWithName:kTestFormName fetchSuggestionsForFormWithName:kTestFormName
fieldName:kTestFieldName fieldName:kTestFieldName
fieldIdentifier:kTestFieldID fieldIdentifier:kTestFieldID
fieldType:kTestFieldType
frameID:GetMainFrameId() frameID:GetMainFrameId()
completionHandler:^( completionHandler:^(
NSArray<CWVAutofillSuggestion*>* suggestions) { NSArray<CWVAutofillSuggestion*>* suggestions) {
...@@ -122,6 +124,7 @@ TEST_F(WebViewAutofillTest, TestDelegateCallbacks) { ...@@ -122,6 +124,7 @@ TEST_F(WebViewAutofillTest, TestDelegateCallbacks) {
[[delegate expect] autofillController:autofill_controller_ [[delegate expect] autofillController:autofill_controller_
didFocusOnFieldWithName:kTestFieldName didFocusOnFieldWithName:kTestFieldName
fieldIdentifier:kTestFieldID fieldIdentifier:kTestFieldID
fieldType:kTestFieldType
formName:kTestFormName formName:kTestFormName
frameID:[OCMArg any] frameID:[OCMArg any]
value:kTestFieldValue]; value:kTestFieldValue];
...@@ -135,6 +138,7 @@ TEST_F(WebViewAutofillTest, TestDelegateCallbacks) { ...@@ -135,6 +138,7 @@ TEST_F(WebViewAutofillTest, TestDelegateCallbacks) {
[[delegate expect] autofillController:autofill_controller_ [[delegate expect] autofillController:autofill_controller_
didBlurOnFieldWithName:kTestFieldName didBlurOnFieldWithName:kTestFieldName
fieldIdentifier:kTestFieldID fieldIdentifier:kTestFieldID
fieldType:kTestFieldType
formName:kTestFormName formName:kTestFormName
frameID:[OCMArg any] frameID:[OCMArg any]
value:kTestFieldValue]; value:kTestFieldValue];
...@@ -151,6 +155,7 @@ TEST_F(WebViewAutofillTest, TestDelegateCallbacks) { ...@@ -151,6 +155,7 @@ TEST_F(WebViewAutofillTest, TestDelegateCallbacks) {
[[delegate expect] autofillController:autofill_controller_ [[delegate expect] autofillController:autofill_controller_
didInputInFieldWithName:kTestFieldName didInputInFieldWithName:kTestFieldName
fieldIdentifier:kTestFieldID fieldIdentifier:kTestFieldID
fieldType:kTestFieldType
formName:kTestFormName formName:kTestFormName
frameID:[OCMArg any] frameID:[OCMArg any]
value:kTestFieldValue]; value:kTestFieldValue];
......
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