blob: 14a6f58ceb5462891e089fde74205ca41c5605e1 [file] [log] [blame]
// Copyright 2017 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/web_view/shell/shell_autofill_delegate.h"
#import <UIKit/UIKit.h>
#import "ios/web_view/shell/shell_risk_data_loader.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface ShellAutofillDelegate ()
// Autofill controller.
@property(nonatomic, strong) CWVAutofillController* autofillController;
// Risk data loader.
@property(nonatomic, strong) ShellRiskDataLoader* riskDataLoader;
// Returns an action for a suggestion.
- (UIAlertAction*)actionForSuggestion:(CWVAutofillSuggestion*)suggestion;
@end
@implementation ShellAutofillDelegate
@synthesize autofillController = _autofillController;
@synthesize riskDataLoader = _riskDataLoader;
- (instancetype)init {
self = [super init];
if (self) {
_riskDataLoader = [[ShellRiskDataLoader alloc] init];
}
return self;
}
#pragma mark - CWVAutofillControllerDelegate methods
- (void)autofillController:(CWVAutofillController*)autofillController
didFocusOnFieldWithIdentifier:(NSString*)fieldIdentifier
fieldType:(NSString*)fieldType
formName:(NSString*)formName
frameID:(NSString*)frameID
value:(NSString*)value
userInitiated:(BOOL)userInitiated {
_autofillController = autofillController;
__weak ShellAutofillDelegate* weakSelf = self;
id completionHandler = ^(NSArray<CWVAutofillSuggestion*>* suggestions) {
ShellAutofillDelegate* strongSelf = weakSelf;
if (!suggestions.count || !strongSelf) {
return;
}
UIAlertController* alertController = [UIAlertController
alertControllerWithTitle:@"Pick a suggestion"
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
alertController.popoverPresentationController.sourceView =
UIApplication.sharedApplication.keyWindow;
CGRect bounds = UIApplication.sharedApplication.keyWindow.bounds;
alertController.popoverPresentationController.sourceRect =
CGRectMake(CGRectGetWidth(bounds) / 2, 60, 1, 1);
UIAlertAction* cancelAction =
[UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:nil];
[alertController addAction:cancelAction];
for (CWVAutofillSuggestion* suggestion in suggestions) {
[alertController addAction:[self actionForSuggestion:suggestion]];
}
[UIApplication.sharedApplication.keyWindow.rootViewController
presentViewController:alertController
animated:YES
completion:nil];
};
[autofillController fetchSuggestionsForFormWithName:formName
fieldIdentifier:fieldIdentifier
fieldType:fieldType
frameID:frameID
completionHandler:completionHandler];
}
- (void)autofillController:(CWVAutofillController*)autofillController
didInputInFieldWithIdentifier:(NSString*)fieldIdentifier
fieldType:(NSString*)fieldType
formName:(NSString*)formName
frameID:(NSString*)frameID
value:(NSString*)value
userInitiated:(BOOL)userInitiated {
// Not implemented.
}
- (void)autofillController:(CWVAutofillController*)autofillController
didBlurOnFieldWithIdentifier:(NSString*)fieldIdentifier
fieldType:(NSString*)fieldType
formName:(NSString*)formName
frameID:(NSString*)frameID
value:(NSString*)value
userInitiated:(BOOL)userInitiated {
// Not implemented.
}
- (void)autofillController:(CWVAutofillController*)autofillController
didSubmitFormWithName:(NSString*)formName
frameID:(NSString*)frameID
userInitiated:(BOOL)userInitiated {
// Not implemented.
}
- (void)autofillController:(CWVAutofillController*)autofillController
didFindForms:(NSArray<CWVAutofillForm*>*)forms
frameID:(NSString*)frameID {
if (forms.count == 0) {
return;
}
NSArray<NSString*>* debugDescriptions =
[forms valueForKey:NSStringFromSelector(@selector(debugDescription))];
NSLog(@"Found forms in frame %@\n%@", frameID, debugDescriptions);
}
- (void)autofillController:(CWVAutofillController*)autofillController
saveCreditCardWithSaver:(CWVCreditCardSaver*)saver {
CWVCreditCard* creditCard = saver.creditCard;
UIAlertController* alertController =
[UIAlertController alertControllerWithTitle:@"Save card?"
message:creditCard.debugDescription
preferredStyle:UIAlertControllerStyleAlert];
__weak UIAlertController* weakAlertController = alertController;
__weak ShellAutofillDelegate* weakSelf = self;
UIAlertAction* allowAction = [UIAlertAction
actionWithTitle:@"Allow"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction* _Nonnull action) {
NSString* cardHolderFullName =
weakAlertController.textFields[0].text;
NSString* expirationMonth =
weakAlertController.textFields[1].text;
NSString* expirationYear =
weakAlertController.textFields[2].text;
[saver acceptWithCardHolderFullName:cardHolderFullName
expirationMonth:expirationMonth
expirationYear:expirationYear
riskData:weakSelf.riskDataLoader
.riskData
completionHandler:^(BOOL cardSaved) {
if (!cardSaved) {
NSLog(@"Failed to save: %@",
saver.creditCard);
}
}];
}];
UIAlertAction* cancelAction =
[UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction* _Nonnull action) {
[saver decline];
}];
[alertController addAction:allowAction];
[alertController addAction:cancelAction];
[alertController
addTextFieldWithConfigurationHandler:^(UITextField* textField) {
textField.placeholder = @"Card holder full name";
textField.keyboardType = UIKeyboardTypeDefault;
}];
[alertController
addTextFieldWithConfigurationHandler:^(UITextField* textField) {
textField.placeholder = @"Expiration month (MM)";
textField.keyboardType = UIKeyboardTypeNumberPad;
}];
[alertController
addTextFieldWithConfigurationHandler:^(UITextField* textField) {
textField.placeholder = @"Expiration year (YYYY)";
textField.keyboardType = UIKeyboardTypeNumberPad;
}];
[UIApplication.sharedApplication.keyWindow.rootViewController
presentViewController:alertController
animated:YES
completion:nil];
}
- (void)autofillController:(CWVAutofillController*)autofillController
decideSavePolicyForPassword:(CWVPassword*)password
decisionHandler:(void (^)(CWVPasswordUserDecision decision))
decisionHandler {
UIAlertController* alertController =
[UIAlertController alertControllerWithTitle:@"Save password?"
message:password.debugDescription
preferredStyle:UIAlertControllerStyleAlert];
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];
[UIApplication.sharedApplication.keyWindow.rootViewController
presentViewController:alertController
animated:YES
completion:nil];
}
- (void)autofillController:(CWVAutofillController*)autofillController
decideUpdatePolicyForPassword:(CWVPassword*)password
decisionHandler:(void (^)(CWVPasswordUserDecision decision))
decisionHandler {
UIAlertController* alertController =
[UIAlertController alertControllerWithTitle:@"Update password?"
message:password.debugDescription
preferredStyle:UIAlertControllerStyleAlert];
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];
[UIApplication.sharedApplication.keyWindow.rootViewController
presentViewController:alertController
animated:YES
completion:nil];
}
- (void)autofillController:(CWVAutofillController*)autofillController
verifyCreditCardWithVerifier:(CWVCreditCardVerifier*)verifier {
[UIApplication.sharedApplication.keyWindow endEditing:YES];
UIAlertController* alertController =
[UIAlertController alertControllerWithTitle:@"Verify Card"
message:@"Enter CVC"
preferredStyle:UIAlertControllerStyleAlert];
__weak UIAlertController* weakAlertController = alertController;
__weak ShellAutofillDelegate* weakSelf = self;
UIAlertAction* submit = [UIAlertAction
actionWithTitle:@"Confirm"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction* action) {
UITextField* textField =
weakAlertController.textFields.firstObject;
NSString* CVC = textField.text;
[verifier verifyWithCVC:CVC
expirationMonth:nil
expirationYear:nil
riskData:weakSelf.riskDataLoader.riskData
completionHandler:^(NSError* error) {
if (error) {
NSLog(@"Card %@ failed to verify error: %@",
verifier.creditCard, error);
}
}];
}];
[alertController addAction:submit];
UIAlertAction* cancel =
[UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:nil];
[alertController addAction:cancel];
[alertController
addTextFieldWithConfigurationHandler:^(UITextField* textField) {
textField.placeholder = @"CVC";
textField.keyboardType = UIKeyboardTypeNumberPad;
}];
[UIApplication.sharedApplication.keyWindow.rootViewController
presentViewController:alertController
animated:YES
completion:nil];
}
- (void)autofillController:(CWVAutofillController*)autofillController
notifyUserOfPasswordLeakOnURL:(NSURL*)URL
leakType:(CWVPasswordLeakType)leakType {
NSLog(@"Password on %@ is leaked!", URL);
}
- (void)autofillController:(CWVAutofillController*)autofillController
suggestGeneratedPassword:(NSString*)generatedPassword
decisionHandler:(void (^)(BOOL accept))decisionHandler {
NSLog(@"Accepting suggested password: %@", generatedPassword);
decisionHandler(YES);
}
#pragma mark - Private Methods
- (UIAlertAction*)actionForSuggestion:(CWVAutofillSuggestion*)suggestion {
NSString* title =
[NSString stringWithFormat:@"%@ %@", suggestion.value,
suggestion.displayDescription ?: @""];
__weak ShellAutofillDelegate* weakSelf = self;
return [UIAlertAction
actionWithTitle:title
style:UIAlertActionStyleDefault
handler:^(UIAlertAction* action) {
ShellAutofillDelegate* strongSelf = weakSelf;
if (!strongSelf) {
return;
}
[strongSelf.autofillController acceptSuggestion:suggestion
completionHandler:nil];
[UIApplication.sharedApplication.keyWindow endEditing:YES];
}];
}
@end