123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- // 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 =
- [self anyKeyWindow];
- CGRect bounds = [self anyKeyWindow].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]];
- }
- [[self anyKeyWindow].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 {
- // TODO(crbug.com/1323932): Fetching suggestions has an important side effect
- // of calling PasswordFormManager::UpdateStateOnUserInput. This will ensure
- // that the typed information can be remembered during the save dialogue.
- // Make this method a no-op once the bug is fixed.
- id completionHandler = ^(NSArray<CWVAutofillSuggestion*>* suggestions) {
- NSLog(@"%@ suggestions: %@", NSStringFromSelector(_cmd), suggestions);
- };
- [autofillController fetchSuggestionsForFormWithName:formName
- fieldIdentifier:fieldIdentifier
- fieldType:fieldType
- frameID:frameID
- completionHandler:completionHandler];
- }
- - (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;
- }];
- [[self anyKeyWindow].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];
- [[self anyKeyWindow].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];
- [[self anyKeyWindow].rootViewController presentViewController:alertController
- animated:YES
- completion:nil];
- }
- - (void)autofillController:(CWVAutofillController*)autofillController
- verifyCreditCardWithVerifier:(CWVCreditCardVerifier*)verifier {
- [[self anyKeyWindow] 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;
- }];
- [[self anyKeyWindow].rootViewController presentViewController:alertController
- animated:YES
- completion:nil];
- }
- - (void)autofillController:(CWVAutofillController*)autofillController
- notifyUserOfPasswordLeakOnURL:(NSURL*)URL
- leakType:(CWVPasswordLeakType)leakType
- username:(NSString*)username {
- NSLog(@"Password on %@ is leaked for username %@!", URL, username);
- }
- - (void)autofillController:(CWVAutofillController*)autofillController
- suggestGeneratedPassword:(NSString*)generatedPassword
- decisionHandler:(void (^)(BOOL accept))decisionHandler {
- NSLog(@"Accepting suggested password: %@", generatedPassword);
- decisionHandler(YES);
- }
- - (void)autofillController:(CWVAutofillController*)autofillController
- confirmSaveForNewAutofillProfile:(CWVAutofillProfile*)newProfile
- oldProfile:(nullable CWVAutofillProfile*)oldProfile
- decisionHandler:
- (void (^)(CWVAutofillProfileUserDecision decision))
- decisionHandler {
- NSString* message =
- [NSString stringWithFormat:@"new: %@\nold: %@",
- newProfile.debugDescription, oldProfile];
- UIAlertController* alertController = [UIAlertController
- alertControllerWithTitle:@"Confirm save for new profile?"
- message:message
- preferredStyle:UIAlertControllerStyleAlert];
- UIAlertAction* accept = [UIAlertAction
- actionWithTitle:@"Accept"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- decisionHandler(CWVAutofillProfileUserDecisionAccepted);
- }];
- [alertController addAction:accept];
- UIAlertAction* decline = [UIAlertAction
- actionWithTitle:@"Decline"
- style:UIAlertActionStyleCancel
- handler:^(UIAlertAction* action) {
- decisionHandler(CWVAutofillProfileUserDecisionDeclined);
- }];
- [alertController addAction:decline];
- [[self anyKeyWindow].rootViewController presentViewController:alertController
- animated:YES
- completion:nil];
- }
- #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];
- [[self anyKeyWindow] endEditing:YES];
- }];
- }
- #pragma mark - Private
- - (UIWindow*)anyKeyWindow {
- NSArray<UIWindow*>* windows = [UIApplication sharedApplication].windows;
- for (UIWindow* window in windows) {
- if (window.isKeyWindow)
- return window;
- }
- return nil;
- }
- @end
|