Commit 758a2704 authored by John Z Wu's avatar John Z Wu Committed by Commit Bot

Implement new api for saving credit cards in ChromeWebView

Introduce CWVCreditCardSaver for clients to interface with saving api.
This also adds support for saving cards to gpay if needed.

Bug: 993130
Change-Id: I7bc0acfe6553428f03f0e3f8c22a0824508f015b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1752560
Commit-Queue: John Wu <jzw@chromium.org>
Reviewed-by: default avatarHiroshi Ichikawa <ichikawa@chromium.org>
Cr-Commit-Position: refs/heads/master@{#688630}
parent 688cb8a3
...@@ -87,6 +87,7 @@ if (ios_web_view_enable_autofill) { ...@@ -87,6 +87,7 @@ if (ios_web_view_enable_autofill) {
"public/cwv_autofill_profile.h", "public/cwv_autofill_profile.h",
"public/cwv_autofill_suggestion.h", "public/cwv_autofill_suggestion.h",
"public/cwv_credit_card.h", "public/cwv_credit_card.h",
"public/cwv_credit_card_saver.h",
"public/cwv_credit_card_verifier.h", "public/cwv_credit_card_verifier.h",
"public/cwv_preferences_autofill.h", "public/cwv_preferences_autofill.h",
"public/cwv_web_view_autofill.h", "public/cwv_web_view_autofill.h",
...@@ -241,6 +242,8 @@ if (ios_web_view_enable_autofill) { ...@@ -241,6 +242,8 @@ if (ios_web_view_enable_autofill) {
"internal/autofill/cwv_autofill_suggestion_internal.h", "internal/autofill/cwv_autofill_suggestion_internal.h",
"internal/autofill/cwv_credit_card.mm", "internal/autofill/cwv_credit_card.mm",
"internal/autofill/cwv_credit_card_internal.h", "internal/autofill/cwv_credit_card_internal.h",
"internal/autofill/cwv_credit_card_saver.mm",
"internal/autofill/cwv_credit_card_saver_internal.h",
"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.h", "internal/passwords/cwv_password_controller.h",
...@@ -399,6 +402,7 @@ test("ios_web_view_unittests") { ...@@ -399,6 +402,7 @@ test("ios_web_view_unittests") {
"internal/autofill/cwv_autofill_form_unittest.mm", "internal/autofill/cwv_autofill_form_unittest.mm",
"internal/autofill/cwv_autofill_profile_unittest.mm", "internal/autofill/cwv_autofill_profile_unittest.mm",
"internal/autofill/cwv_autofill_suggestion_unittest.mm", "internal/autofill/cwv_autofill_suggestion_unittest.mm",
"internal/autofill/cwv_credit_card_saver_unittest.mm",
"internal/autofill/cwv_credit_card_unittest.mm", "internal/autofill/cwv_credit_card_unittest.mm",
"internal/autofill/cwv_credit_card_verifier_unittest.mm", "internal/autofill/cwv_credit_card_verifier_unittest.mm",
"internal/cwv_download_task_unittest.mm", "internal/cwv_download_task_unittest.mm",
......
...@@ -7,8 +7,11 @@ ...@@ -7,8 +7,11 @@
#import "components/autofill/ios/browser/autofill_client_ios_bridge.h" #import "components/autofill/ios/browser/autofill_client_ios_bridge.h"
#include <memory>
#include "base/callback.h" #include "base/callback.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/values.h"
#include "components/autofill/core/browser/autofill_client.h" #include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/payments/card_unmask_delegate.h" #include "components/autofill/core/browser/payments/card_unmask_delegate.h"
...@@ -22,9 +25,25 @@ class FormStructure; ...@@ -22,9 +25,25 @@ class FormStructure;
// Bridge for AutofillClient's method |ConfirmSaveCreditCardLocally|. // Bridge for AutofillClient's method |ConfirmSaveCreditCardLocally|.
- (void)confirmSaveCreditCardLocally:(const autofill::CreditCard&)creditCard - (void)confirmSaveCreditCardLocally:(const autofill::CreditCard&)creditCard
saveCreditCardOptions:
(autofill::AutofillClient::SaveCreditCardOptions)
saveCreditCardOptions
callback:(autofill::AutofillClient:: callback:(autofill::AutofillClient::
LocalSaveCardPromptCallback)callback; LocalSaveCardPromptCallback)callback;
// Bridge for AutofillClient's method |ConfirmSaveCreditCardToCloud|.
- (void)confirmSaveCreditCardToCloud:(const autofill::CreditCard&)creditCard
legalMessage:
(std::unique_ptr<base::DictionaryValue>)legalMessage
saveCreditCardOptions:
(autofill::AutofillClient::SaveCreditCardOptions)
saveCreditCardOptions
callback:(autofill::AutofillClient::
UploadSaveCardPromptCallback)callback;
// Bridge for AutofillClient's method |CreditCardUploadCompleted|.
- (void)handleCreditCardUploadCompleted:(BOOL)cardSaved;
// Bridge for AutofillClient's method |ShowUnmaskPrompt|. // Bridge for AutofillClient's method |ShowUnmaskPrompt|.
- (void) - (void)
showUnmaskPromptForCard:(const autofill::CreditCard&)creditCard showUnmaskPromptForCard:(const autofill::CreditCard&)creditCard
......
...@@ -11,8 +11,10 @@ ...@@ -11,8 +11,10 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/mac/foundation_util.h" #include "base/mac/foundation_util.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "base/values.h"
#include "components/autofill/core/browser/autofill_manager.h" #include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/payments/legal_message_line.h"
#include "components/autofill/core/browser/ui/popup_item_ids.h" #include "components/autofill/core/browser/ui/popup_item_ids.h"
#import "components/autofill/ios/browser/autofill_agent.h" #import "components/autofill/ios/browser/autofill_agent.h"
#include "components/autofill/ios/browser/autofill_driver_ios.h" #include "components/autofill/ios/browser/autofill_driver_ios.h"
...@@ -35,6 +37,7 @@ ...@@ -35,6 +37,7 @@
#import "ios/web_view/internal/autofill/cwv_autofill_form_internal.h" #import "ios/web_view/internal/autofill/cwv_autofill_form_internal.h"
#import "ios/web_view/internal/autofill/cwv_autofill_suggestion_internal.h" #import "ios/web_view/internal/autofill/cwv_autofill_suggestion_internal.h"
#import "ios/web_view/internal/autofill/cwv_credit_card_internal.h" #import "ios/web_view/internal/autofill/cwv_credit_card_internal.h"
#import "ios/web_view/internal/autofill/cwv_credit_card_saver_internal.h"
#import "ios/web_view/internal/autofill/cwv_credit_card_verifier_internal.h" #import "ios/web_view/internal/autofill/cwv_credit_card_verifier_internal.h"
#include "ios/web_view/internal/autofill/web_view_autocomplete_history_manager_factory.h" #include "ios/web_view/internal/autofill/web_view_autocomplete_history_manager_factory.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"
...@@ -95,6 +98,10 @@ fetchNonPasswordSuggestionsForFormWithName:(NSString*)formName ...@@ -95,6 +98,10 @@ fetchNonPasswordSuggestionsForFormWithName:(NSString*)formName
// The |webState| which this autofill controller should observe. // The |webState| which this autofill controller should observe.
web::WebState* _webState; web::WebState* _webState;
// The current credit card saver. Can be nil if no save attempt is pending.
// Held weak because |_delegate| is responsible for maintaing its lifetime.
__weak CWVCreditCardSaver* _saver;
// The current credit card verifier. Can be nil if no verification is pending. // The current credit card verifier. Can be nil if no verification is pending.
// Held weak because |_delegate| is responsible for maintaing its lifetime. // Held weak because |_delegate| is responsible for maintaing its lifetime.
__weak CWVCreditCardVerifier* _verifier; __weak CWVCreditCardVerifier* _verifier;
...@@ -414,25 +421,60 @@ fetchNonPasswordSuggestionsForFormWithName:(NSString*)formName ...@@ -414,25 +421,60 @@ fetchNonPasswordSuggestionsForFormWithName:(NSString*)formName
} }
- (void)confirmSaveCreditCardLocally:(const autofill::CreditCard&)creditCard - (void)confirmSaveCreditCardLocally:(const autofill::CreditCard&)creditCard
saveCreditCardOptions:
(autofill::AutofillClient::SaveCreditCardOptions)
saveCreditCardOptions
callback:(autofill::AutofillClient:: callback:(autofill::AutofillClient::
LocalSaveCardPromptCallback)callback { LocalSaveCardPromptCallback)callback {
if ([_delegate respondsToSelector:@selector if (![_delegate respondsToSelector:@selector(autofillController:
(autofillController:decidePolicyForLocalStorageOfCreditCard saveCreditCardWithSaver:)]) {
:decisionHandler:)]) { return;
CWVCreditCard* card = [[CWVCreditCard alloc] initWithCreditCard:creditCard];
__block autofill::AutofillClient::LocalSaveCardPromptCallback
scopedCallback = std::move(callback);
[_delegate autofillController:self
decidePolicyForLocalStorageOfCreditCard:card
decisionHandler:^(CWVStoragePolicy policy) {
if (policy == CWVStoragePolicyAllow) {
if (scopedCallback)
std::move(scopedCallback)
.Run(autofill::AutofillClient::
ACCEPTED);
}
}];
} }
CWVCreditCardSaver* saver = [[CWVCreditCardSaver alloc]
initWithCreditCard:creditCard
saveOptions:saveCreditCardOptions
willUploadToCloud:NO
legalMessageLines:autofill::LegalMessageLines()
uploadSavePromptCallback:autofill::AutofillClient::
UploadSaveCardPromptCallback()
localSavePromptCallback:std::move(callback)];
[_delegate autofillController:self saveCreditCardWithSaver:saver];
_saver = saver;
}
- (void)confirmSaveCreditCardToCloud:(const autofill::CreditCard&)creditCard
legalMessage:
(std::unique_ptr<base::DictionaryValue>)legalMessage
saveCreditCardOptions:
(autofill::AutofillClient::SaveCreditCardOptions)
saveCreditCardOptions
callback:
(autofill::AutofillClient::
UploadSaveCardPromptCallback)callback {
if (![_delegate respondsToSelector:@selector(autofillController:
saveCreditCardWithSaver:)]) {
return;
}
autofill::LegalMessageLines legalMessageLines;
if (!autofill::LegalMessageLine::Parse(*legalMessage, &legalMessageLines,
/*escape_apostrophes=*/true)) {
return;
}
CWVCreditCardSaver* saver = [[CWVCreditCardSaver alloc]
initWithCreditCard:creditCard
saveOptions:saveCreditCardOptions
willUploadToCloud:YES
legalMessageLines:legalMessageLines
uploadSavePromptCallback:std::move(callback)
localSavePromptCallback:autofill::AutofillClient::
LocalSaveCardPromptCallback()];
[_delegate autofillController:self saveCreditCardWithSaver:saver];
_saver = saver;
}
- (void)handleCreditCardUploadCompleted:(BOOL)cardSaved {
[_saver handleCreditCardUploadCompleted:cardSaved];
} }
- (void) - (void)
...@@ -463,7 +505,11 @@ showUnmaskPromptForCard:(const autofill::CreditCard&)creditCard ...@@ -463,7 +505,11 @@ showUnmaskPromptForCard:(const autofill::CreditCard&)creditCard
} }
- (void)loadRiskData:(base::OnceCallback<void(const std::string&)>)callback { - (void)loadRiskData:(base::OnceCallback<void(const std::string&)>)callback {
[_verifier loadRiskData:std::move(callback)]; if (_verifier) {
[_verifier loadRiskData:std::move(callback)];
} else if (_saver) {
[_saver loadRiskData:std::move(callback)];
}
} }
- (void)propagateAutofillPredictionsForForms: - (void)propagateAutofillPredictionsForForms:
......
// Copyright 2019 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/internal/autofill/cwv_credit_card_saver_internal.h"
#include <memory>
#include "base/bind.h"
#include "base/strings/sys_string_conversions.h"
#include "base/task/post_task.h"
#include "components/autofill/core/browser/payments/legal_message_line.h"
#include "ios/web/public/thread/web_task_traits.h"
#include "ios/web/public/thread/web_thread.h"
#import "ios/web_view/internal/autofill/cwv_credit_card_internal.h"
#import "net/base/mac/url_conversions.h"
#include "ui/gfx/range/range.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
NS_ASSUME_NONNULL_BEGIN
namespace {
// Converts |autofill::LegalMessageLines| into |NSArray<NSAttributedString*>*|.
NSArray<NSAttributedString*>* CWVLegalMessagesFromLegalMessageLines(
const autofill::LegalMessageLines& legalMessageLines) {
NSMutableArray<NSAttributedString*>* legalMessages = [NSMutableArray array];
for (const autofill::LegalMessageLine& legalMessageLine : legalMessageLines) {
NSString* text = base::SysUTF16ToNSString(legalMessageLine.text());
NSMutableAttributedString* legalMessage =
[[NSMutableAttributedString alloc] initWithString:text];
for (const autofill::LegalMessageLine::Link& link :
legalMessageLine.links()) {
NSURL* url = net::NSURLWithGURL(link.url);
NSRange range = link.range.ToNSRange();
[legalMessage addAttribute:NSLinkAttributeName value:url range:range];
}
[legalMessages addObject:[legalMessage copy]];
}
return [legalMessages copy];
}
} // namespace
@implementation CWVCreditCardSaver {
autofill::AutofillClient::SaveCreditCardOptions _saveOptions;
autofill::AutofillClient::UploadSaveCardPromptCallback
_uploadSaveCardCallback;
autofill::AutofillClient::LocalSaveCardPromptCallback _localSaveCardCallback;
// The callback to invoke for save completion results.
void (^_Nullable _saveCompletionHandler)(BOOL);
// The callback to invoke for returning risk data.
base::OnceCallback<void(const std::string&)> _riskDataCallback;
// Whether or not either |acceptCreditCardWithRiskData:completionHandler:| or
// |declineCreditCardSave| has been called.
BOOL _decisionMade;
}
@synthesize creditCard = _creditCard;
@synthesize legalMessages = _legalMessages;
@synthesize willUploadToCloud = _willUploadToCloud;
- (instancetype)
initWithCreditCard:(const autofill::CreditCard&)creditCard
saveOptions:(autofill::AutofillClient::SaveCreditCardOptions)
saveOptions
willUploadToCloud:(BOOL)willUploadToCloud
legalMessageLines:(autofill::LegalMessageLines)legalMessageLines
uploadSavePromptCallback:
(autofill::AutofillClient::UploadSaveCardPromptCallback)
uploadSavePromptCallback
localSavePromptCallback:
(autofill::AutofillClient::LocalSaveCardPromptCallback)
localSavePromptCallback {
self = [super init];
if (self) {
_creditCard = [[CWVCreditCard alloc] initWithCreditCard:creditCard];
_saveOptions = saveOptions;
_willUploadToCloud = willUploadToCloud;
_legalMessages = CWVLegalMessagesFromLegalMessageLines(legalMessageLines);
_uploadSaveCardCallback = std::move(uploadSavePromptCallback);
_localSaveCardCallback = std::move(localSavePromptCallback);
_decisionMade = NO;
}
return self;
}
- (void)dealloc {
// If the user did not choose, the decision should be marked as ignored.
if (_willUploadToCloud && _uploadSaveCardCallback) {
std::move(_uploadSaveCardCallback)
.Run(autofill::AutofillClient::IGNORED,
/*user_provided_card_details=*/{});
} else if (!_willUploadToCloud && _localSaveCardCallback) {
std::move(_localSaveCardCallback).Run(autofill::AutofillClient::IGNORED);
}
}
#pragma mark - Public Methods
- (void)acceptWithRiskData:(nullable NSString*)riskData
completionHandler:(void (^_Nullable)(BOOL))completionHandler {
DCHECK(!_decisionMade)
<< "You may only call -acceptWithRiskData:completionHandler: or "
"-decline: once per instance.";
if (_willUploadToCloud) {
DCHECK(_riskDataCallback && riskData);
std::move(_riskDataCallback).Run(base::SysNSStringToUTF8(riskData));
_saveCompletionHandler = completionHandler;
DCHECK(_uploadSaveCardCallback);
// TODO(crbug.com/993130): Provide additional card details if required.
std::move(_uploadSaveCardCallback)
.Run(autofill::AutofillClient::ACCEPTED,
/*user_provided_card_details=*/{});
} else {
DCHECK(_localSaveCardCallback);
std::move(_localSaveCardCallback).Run(autofill::AutofillClient::ACCEPTED);
base::PostTask(FROM_HERE, {web::WebThread::UI}, base::BindOnce(^{
if (completionHandler) {
completionHandler(YES);
}
}));
}
_decisionMade = YES;
}
- (void)decline {
DCHECK(!_decisionMade)
<< "You may only call -acceptWithRiskData:completionHandler: or "
"-decline: once per instance.";
if (_willUploadToCloud) {
DCHECK(_uploadSaveCardCallback);
std::move(_uploadSaveCardCallback)
.Run(autofill::AutofillClient::DECLINED,
/*user_provided_card_details=*/{});
} else {
DCHECK(_localSaveCardCallback);
std::move(_localSaveCardCallback).Run(autofill::AutofillClient::DECLINED);
}
_decisionMade = YES;
}
#pragma mark - Internal Methods
- (void)handleCreditCardUploadCompleted:(BOOL)cardSaved {
if (_saveCompletionHandler) {
_saveCompletionHandler(cardSaved);
_saveCompletionHandler = nil;
}
}
- (void)loadRiskData:(base::OnceCallback<void(const std::string&)>)callback {
_riskDataCallback = std::move(callback);
}
@end
NS_ASSUME_NONNULL_END
// Copyright 2019 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_AUTOFILL_CWV_CREDIT_CARD_SAVER_INTERNAL_H_
#define IOS_WEB_VIEW_INTERNAL_AUTOFILL_CWV_CREDIT_CARD_SAVER_INTERNAL_H_
#import "ios/web_view/public/cwv_credit_card_saver.h"
#include <memory>
#include "components/autofill/core/browser/autofill_client.h"
#include "components/autofill/core/browser/payments/legal_message_line.h"
namespace autofill {
class CreditCard;
} // namespace autofill
@interface CWVCreditCardSaver ()
// Designated Initializer.
// |creditCard| The card that needs to be saved.
// |saveOptions| Additional options that may apply to this save attempt.
// |willUploadToCloud| Whether or not the card will be saved to the cloud.
// |legalMessage| Contains messaging that must be displayed to the user.
// |uploadSavePromptCallback| A callback to run when saving to the cloud.
// |localSavePromptCallback| A callback to run when saving locally.
- (instancetype)
initWithCreditCard:(const autofill::CreditCard&)creditCard
saveOptions:(autofill::AutofillClient::SaveCreditCardOptions)
saveOptions
willUploadToCloud:(BOOL)willUploadToCloud
legalMessageLines:(autofill::LegalMessageLines)legalMessageLines
uploadSavePromptCallback:
(autofill::AutofillClient::UploadSaveCardPromptCallback)
uploadSavePromptCallback
localSavePromptCallback:
(autofill::AutofillClient::LocalSaveCardPromptCallback)
localSavePromptCallback NS_DESIGNATED_INITIALIZER;
// Called to notify when upload was completed.
- (void)handleCreditCardUploadCompleted:(BOOL)cardSaved;
// Use to notify CWVCreditCardSaver that it needs to obtain risk data for
// credit card upload and to pass it back in |callback|.
- (void)loadRiskData:(base::OnceCallback<void(const std::string&)>)callback;
@end
#endif // IOS_WEB_VIEW_INTERNAL_AUTOFILL_CWV_CREDIT_CARD_SAVER_INTERNAL_H_
...@@ -166,7 +166,9 @@ void WebViewAutofillClientIOS::ConfirmSaveCreditCardLocally( ...@@ -166,7 +166,9 @@ void WebViewAutofillClientIOS::ConfirmSaveCreditCardLocally(
SaveCreditCardOptions options, SaveCreditCardOptions options,
LocalSaveCardPromptCallback callback) { LocalSaveCardPromptCallback callback) {
DCHECK(options.show_prompt); DCHECK(options.show_prompt);
[bridge_ confirmSaveCreditCardLocally:card callback:std::move(callback)]; [bridge_ confirmSaveCreditCardLocally:card
saveCreditCardOptions:options
callback:std::move(callback)];
} }
void WebViewAutofillClientIOS::ConfirmSaveCreditCardToCloud( void WebViewAutofillClientIOS::ConfirmSaveCreditCardToCloud(
...@@ -175,10 +177,14 @@ void WebViewAutofillClientIOS::ConfirmSaveCreditCardToCloud( ...@@ -175,10 +177,14 @@ void WebViewAutofillClientIOS::ConfirmSaveCreditCardToCloud(
SaveCreditCardOptions options, SaveCreditCardOptions options,
UploadSaveCardPromptCallback callback) { UploadSaveCardPromptCallback callback) {
DCHECK(options.show_prompt); DCHECK(options.show_prompt);
[bridge_ confirmSaveCreditCardToCloud:card
legalMessage:std::move(legal_message)
saveCreditCardOptions:options
callback:std::move(callback)];
} }
void WebViewAutofillClientIOS::CreditCardUploadCompleted(bool card_saved) { void WebViewAutofillClientIOS::CreditCardUploadCompleted(bool card_saved) {
NOTIMPLEMENTED(); [bridge_ handleCreditCardUploadCompleted:card_saved];
} }
void WebViewAutofillClientIOS::ConfirmCreditCardFillAssist( void WebViewAutofillClientIOS::ConfirmCreditCardFillAssist(
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/path_service.h" #include "base/path_service.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/sync/driver/sync_driver_switches.h" #include "components/sync/driver/sync_driver_switches.h"
#include "ios/web_view/cwv_web_view_buildflags.h" #include "ios/web_view/cwv_web_view_buildflags.h"
...@@ -52,6 +53,7 @@ void WebViewWebMainParts::PreCreateThreads() { ...@@ -52,6 +53,7 @@ void WebViewWebMainParts::PreCreateThreads() {
std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
std::string enable_features = base::JoinString( std::string enable_features = base::JoinString(
{autofill::features::kAutofillEnableAccountWalletStorage.name, {autofill::features::kAutofillEnableAccountWalletStorage.name,
autofill::features::kAutofillUpstream.name,
switches::kSyncSupportSecondaryAccount.name}, switches::kSyncSupportSecondaryAccount.name},
","); ",");
std::string disabled_features = base::JoinString( std::string disabled_features = base::JoinString(
......
...@@ -12,14 +12,9 @@ NS_ASSUME_NONNULL_BEGIN ...@@ -12,14 +12,9 @@ NS_ASSUME_NONNULL_BEGIN
@class CWVAutofillController; @class CWVAutofillController;
@class CWVAutofillFormSuggestion; @class CWVAutofillFormSuggestion;
@class CWVCreditCard; @class CWVCreditCard;
@class CWVCreditCardSaver;
@class CWVCreditCardVerifier; @class CWVCreditCardVerifier;
// Storage policies for autofill data.
typedef NS_ENUM(NSInteger, CWVStoragePolicy) {
CWVStoragePolicyReject = 0, // Do not store.
CWVStoragePolicyAllow, // Allow storage.
};
// User decision for saving / updating password. // User decision for saving / updating password.
// Note: CWVPasswordUserDecisionNever is only used in saving scenarios. // Note: CWVPasswordUserDecisionNever is only used in saving scenarios.
typedef NS_ENUM(NSInteger, CWVPasswordUserDecision) { typedef NS_ENUM(NSInteger, CWVPasswordUserDecision) {
...@@ -81,14 +76,12 @@ typedef NS_ENUM(NSInteger, CWVPasswordUserDecision) { ...@@ -81,14 +76,12 @@ typedef NS_ENUM(NSInteger, CWVPasswordUserDecision) {
- (void)autofillControllerDidInsertFormElements: - (void)autofillControllerDidInsertFormElements:
(CWVAutofillController*)autofillController; (CWVAutofillController*)autofillController;
// Called when user needs to decide on whether or not to save the card locally. // Called when it is possible to save a new credit card. This is usually called
// This can happen if user is signed out or sync is disabled. // after a new card was entered in a form and submitted.
// Pass final decision to |decisionHandler|. Must only be called once. // |saver| encapsulates information needed to assist with this save attempt.
// If not implemented, assumes CWVStoragePolicyReject. // Life time of |saver| should be managed by the delegate.
- (void)autofillController:(CWVAutofillController*)autofillController - (void)autofillController:(CWVAutofillController*)autofillController
decidePolicyForLocalStorageOfCreditCard:(CWVCreditCard*)creditCard saveCreditCardWithSaver:(CWVCreditCardSaver*)saver;
decisionHandler:(void (^)(CWVStoragePolicy policy))
decisionHandler;
// Called when the user needs to use |verifier| to verify a credit card. // Called when the user needs to use |verifier| to verify a credit card.
// Lifetime of |verifier| should be managed by the delegate. // Lifetime of |verifier| should be managed by the delegate.
......
// Copyright 2019 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_CREDIT_CARD_SAVER_H_
#define IOS_WEB_VIEW_PUBLIC_CWV_CREDIT_CARD_SAVER_H_
#import <Foundation/Foundation.h>
#import "cwv_export.h"
NS_ASSUME_NONNULL_BEGIN
@class CWVCreditCard;
// Helps with saving a credit card locally or uploading to the cloud.
// To make a decision, there are 3 options:
// 1. Call |acceptWithRiskData:completionHandler:| to accept the save.
// 2. Call |decline| to decline the save.
// 3. Do nothing and let this instance be deallocated. This is the same as
// declining, but logs that the user ignored the request.
// Only pick one of these options, and only once.
CWV_EXPORT
@interface CWVCreditCardSaver : NSObject
// The card that can be saved.
@property(nonatomic, readonly) CWVCreditCard* creditCard;
// If not empty, contains legal messaging that must be displayed to the user.
// Contains |NSLinkAttributeName| to indicate links wherever applicable.
@property(nonatomic, readonly) NSArray<NSAttributedString*>* legalMessages;
// Whether or not this card will be saved to Google Pay or local disk. i.e.,
// |YES| means the card is uploaded to Google Pay but NOT stored on local disk.
// |NO| means the card is stored on local disk and NOT uploaded to Google Pay.
// If Chrome Sync is enabled, this value will be |YES|.
@property(nonatomic, readonly) BOOL willUploadToCloud;
- (instancetype)init NS_UNAVAILABLE;
// Saves |creditCard| to device or cloud according to |willUploadToCloud|.
// |riskData| Needed for 1st party integration with the internal payments API.
// Only required if |willUploadToCloud|. See go/risk-eng.g3doc for more details.
// |completionHandler| to be called with BOOL indicating if the card was saved
// or if it wasn't saved due to invalid card or network errors.
// This method should only be called once.
- (void)acceptWithRiskData:(nullable NSString*)riskData
completionHandler:(void (^_Nullable)(BOOL))completionHandler;
// Rejects saving |creditCard|.
// This method should only be called once.
- (void)decline;
@end
NS_ASSUME_NONNULL_END
#endif // IOS_WEB_VIEW_PUBLIC_CWV_CREDIT_CARD_SAVER_H_
...@@ -109,28 +109,36 @@ ...@@ -109,28 +109,36 @@
} }
- (void)autofillController:(CWVAutofillController*)autofillController - (void)autofillController:(CWVAutofillController*)autofillController
decidePolicyForLocalStorageOfCreditCard:(CWVCreditCard*)creditCard saveCreditCardWithSaver:(CWVCreditCardSaver*)saver {
decisionHandler: CWVCreditCard* creditCard = saver.creditCard;
(void (^)(CWVStoragePolicy))decisionHandler {
NSString* cardSummary = [NSString NSString* cardSummary = [NSString
stringWithFormat:@"%@ %@ %@/%@", creditCard.cardHolderFullName, stringWithFormat:@"%@ %@ %@/%@", creditCard.cardHolderFullName,
creditCard.cardNumber, creditCard.expirationMonth, creditCard.cardNumber, creditCard.expirationMonth,
creditCard.expirationYear]; creditCard.expirationYear];
NSArray<NSString*>* legalMessages =
[saver.legalMessages valueForKey:@"string"];
NSString* message = [[legalMessages arrayByAddingObject:cardSummary]
componentsJoinedByString:@"\n"];
UIAlertController* alertController = [UIAlertController UIAlertController* alertController = [UIAlertController
alertControllerWithTitle:@"Update Password" alertControllerWithTitle:@"Save card?"
message:cardSummary message:message
preferredStyle:UIAlertControllerStyleActionSheet]; preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction* allowAction = UIAlertAction* allowAction = [UIAlertAction
[UIAlertAction actionWithTitle:@"Allow" actionWithTitle:@"Allow"
style:UIAlertActionStyleDefault style:UIAlertActionStyleDefault
handler:^(UIAlertAction* _Nonnull action) { handler:^(UIAlertAction* _Nonnull action) {
decisionHandler(CWVStoragePolicyAllow); [saver acceptWithRiskData:self.riskDataLoader.riskData
}]; completionHandler:^(BOOL cardSaved) {
if (!cardSaved) {
NSLog(@"Failed to save: %@", saver.creditCard);
}
}];
}];
UIAlertAction* cancelAction = UIAlertAction* cancelAction =
[UIAlertAction actionWithTitle:@"Cancel" [UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel style:UIAlertActionStyleCancel
handler:^(UIAlertAction* _Nonnull action) { handler:^(UIAlertAction* _Nonnull action) {
decisionHandler(CWVStoragePolicyReject); [saver decline];
}]; }];
[alertController addAction:allowAction]; [alertController addAction:allowAction];
[alertController addAction:cancelAction]; [alertController addAction:cancelAction];
......
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