Index: chrome/browser/ui/android/autofill/autofill_dialog_controller_android.cc |
diff --git a/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.cc b/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.cc |
deleted file mode 100644 |
index 896d7283e6e246992b697e0548f4842c32e3cffa..0000000000000000000000000000000000000000 |
--- a/chrome/browser/ui/android/autofill/autofill_dialog_controller_android.cc |
+++ /dev/null |
@@ -1,540 +0,0 @@ |
-// Copyright 2013 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. |
- |
-#include "chrome/browser/ui/android/autofill/autofill_dialog_controller_android.h" |
- |
-#include <stddef.h> |
- |
-#include "base/android/jni_android.h" |
-#include "base/android/jni_array.h" |
-#include "base/android/jni_string.h" |
-#include "base/android/scoped_java_ref.h" |
-#include "base/bind.h" |
-#include "base/logging.h" |
-#include "base/macros.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "chrome/browser/autofill/personal_data_manager_factory.h" |
-#include "chrome/browser/browser_process.h" |
-#include "chrome/browser/profiles/profile.h" |
-#include "chrome/browser/profiles/profile_manager.h" |
-#include "chrome/browser/ui/android/autofill/autofill_dialog_result.h" |
-#include "chrome/browser/ui/android/view_android_helper.h" |
-#include "chrome/browser/ui/autofill/autofill_dialog_common.h" |
-#include "chrome/common/pref_names.h" |
-#include "chrome/common/url_constants.h" |
-#include "components/autofill/content/browser/wallet/full_wallet.h" |
-#include "components/autofill/core/browser/autofill_metrics.h" |
-#include "components/autofill/core/browser/autofill_profile.h" |
-#include "components/autofill/core/browser/autofill_type.h" |
-#include "components/autofill/core/browser/credit_card.h" |
-#include "components/autofill/core/browser/detail_input.h" |
-#include "components/autofill/core/browser/dialog_section.h" |
-#include "components/autofill/core/browser/field_types.h" |
-#include "components/autofill/core/browser/personal_data_manager.h" |
-#include "components/autofill/core/browser/server_field_types_util.h" |
-#include "components/autofill/core/common/form_data.h" |
-#include "components/pref_registry/pref_registry_syncable.h" |
-#include "components/prefs/pref_service.h" |
-#include "components/prefs/scoped_user_pref_update.h" |
-#include "content/public/browser/navigation_controller.h" |
-#include "content/public/browser/navigation_details.h" |
-#include "content/public/browser/navigation_entry.h" |
-#include "content/public/browser/web_contents.h" |
-#include "jni/AutofillDialogControllerAndroid_jni.h" |
-#include "ui/android/view_android.h" |
-#include "ui/android/window_android.h" |
-#include "ui/base/models/combobox_model.h" |
-#include "ui/base/models/menu_model.h" |
-#include "ui/gfx/android/java_bitmap.h" |
-#include "ui/gfx/geometry/rect.h" |
-#include "url/gurl.h" |
- |
-namespace autofill { |
- |
-namespace { |
- |
-using wallet::FullWallet; |
- |
-// Keys in kAutofillDialogDefaults pref dictionary (do not change these values). |
-const char kLastUsedAccountName[] = "last_used_account_name"; |
-const char kLastUsedChoiceIsAutofill[] = "last_used_choice_is_autofill"; |
-const char kLastUsedBillingAddressGuid[] = "last_used_billing"; |
-const char kLastUsedShippingAddressGuid[] = "last_used_shipping"; |
-const char kLastUsedCreditCardGuid[] = "last_used_card"; |
- |
-// Constructs |inputs| for the SECTION_BILLING section. |
-void BuildCcBillingInputs(DetailInputs* inputs) { |
- const DetailInput kCcBillingInputs[] = { |
- { DetailInput::LONG, NAME_BILLING_FULL }, |
- { DetailInput::LONG, ADDRESS_BILLING_STREET_ADDRESS }, |
- { DetailInput::LONG, ADDRESS_BILLING_CITY }, |
- { DetailInput::LONG, ADDRESS_BILLING_DEPENDENT_LOCALITY }, |
- { DetailInput::LONG, ADDRESS_BILLING_STATE }, |
- { DetailInput::LONG, ADDRESS_BILLING_ZIP }, |
- { DetailInput::LONG, ADDRESS_BILLING_SORTING_CODE }, |
- { DetailInput::LONG, ADDRESS_BILLING_COUNTRY }, |
- { DetailInput::LONG, PHONE_BILLING_WHOLE_NUMBER }, |
- { DetailInput::LONG, CREDIT_CARD_NUMBER }, |
- { DetailInput::LONG, CREDIT_CARD_EXP_MONTH }, |
- { DetailInput::LONG, CREDIT_CARD_EXP_4_DIGIT_YEAR }, |
- { DetailInput::LONG, CREDIT_CARD_VERIFICATION_CODE }, |
- }; |
- BuildInputs(kCcBillingInputs, arraysize(kCcBillingInputs), inputs); |
-} |
- |
-// Constructs |inputs| for the SECTION_SHIPPING section. |
-void BuildShippingInputs(DetailInputs* inputs) { |
- const DetailInput kShippingInputs[] = { |
- { DetailInput::LONG, NAME_FULL }, |
- { DetailInput::LONG, ADDRESS_HOME_STREET_ADDRESS }, |
- { DetailInput::LONG, ADDRESS_HOME_CITY }, |
- { DetailInput::LONG, ADDRESS_HOME_DEPENDENT_LOCALITY }, |
- { DetailInput::LONG, ADDRESS_HOME_STATE }, |
- { DetailInput::LONG, ADDRESS_HOME_ZIP }, |
- { DetailInput::LONG, ADDRESS_HOME_SORTING_CODE }, |
- { DetailInput::LONG, ADDRESS_HOME_COUNTRY }, |
- { DetailInput::LONG, PHONE_HOME_WHOLE_NUMBER }, |
- }; |
- BuildInputs(kShippingInputs, arraysize(kShippingInputs), inputs); |
-} |
- |
-base::string16 NullGetInfo(const AutofillType& type) { |
- return base::string16(); |
-} |
- |
-void FillOutputForSectionWithComparator( |
- DialogSection section, |
- const DetailInputs& inputs, |
- const FormStructure::InputFieldComparator& compare, |
- FormStructure& form_structure, |
- FullWallet* full_wallet, |
- const base::string16& email_address) { |
- if ((section == SECTION_BILLING && !full_wallet->billing_address()) || |
- (section == SECTION_SHIPPING && !full_wallet->shipping_address())) { |
- return; |
- } |
- |
- base::Callback<base::string16(const AutofillType&)> get_info = |
- base::Bind(&FullWallet::GetInfo, |
- base::Unretained(full_wallet), |
- g_browser_process->GetApplicationLocale()); |
- |
- std::vector<ServerFieldType> types = TypesFromInputs(inputs); |
- form_structure.FillFields( |
- types, compare, get_info, |
- section == SECTION_BILLING |
- ? full_wallet->billing_address()->language_code() |
- : full_wallet->shipping_address()->language_code(), |
- g_browser_process->GetApplicationLocale()); |
-} |
- |
-void FillOutputForSection( |
- DialogSection section, |
- FormStructure& form_structure, |
- FullWallet* full_wallet, |
- const base::string16& email_address) { |
- DetailInputs inputs; |
- if (section == SECTION_BILLING) |
- BuildCcBillingInputs(&inputs); |
- else |
- BuildShippingInputs(&inputs); |
- |
- FillOutputForSectionWithComparator( |
- section, inputs, base::Bind(ServerTypeMatchesField, section), |
- form_structure, full_wallet, email_address); |
- |
- if (section == SECTION_BILLING) { |
- // Email is hidden while using Wallet, special case it. |
- for (size_t i = 0; i < form_structure.field_count(); ++i) { |
- AutofillField* field = form_structure.field(i); |
- if (field->Type().GetStorableType() == EMAIL_ADDRESS) |
- field->value = email_address; |
- } |
- } |
-} |
- |
-// Returns true if |input_type| in |section| is needed for |form_structure|. |
-bool IsSectionInputUsedInFormStructure(DialogSection section, |
- ServerFieldType input_type, |
- const FormStructure& form_structure) { |
- for (size_t i = 0; i < form_structure.field_count(); ++i) { |
- const AutofillField* field = form_structure.field(i); |
- if (field && ServerTypeMatchesField(section, input_type, *field)) |
- return true; |
- } |
- return false; |
-} |
- |
-// Returns true if one of |inputs| in |section| is needed for |form_structure|. |
-bool IsSectionInputsUsedInFormStructure(DialogSection section, |
- const ServerFieldType* input_types, |
- const size_t input_types_size, |
- const FormStructure& form_structure) { |
- for (size_t i = 0; i < input_types_size; ++i) { |
- if (IsSectionInputUsedInFormStructure( |
- section, input_types[i], form_structure)) { |
- return true; |
- } |
- } |
- return false; |
-} |
- |
-} // namespace |
- |
- |
-// static |
-base::WeakPtr<AutofillDialogController> AutofillDialogControllerAndroid::Create( |
- content::WebContents* contents, |
- const FormData& form_structure, |
- const GURL& source_url, |
- const AutofillClient::ResultCallback& callback) { |
- // AutofillDialogControllerAndroid owns itself. |
- AutofillDialogControllerAndroid* autofill_dialog_controller = |
- new AutofillDialogControllerAndroid(contents, |
- form_structure, |
- source_url, |
- callback); |
- return autofill_dialog_controller->weak_ptr_factory_.GetWeakPtr(); |
-} |
- |
-#if defined(ENABLE_AUTOFILL_DIALOG) |
-// static |
-base::WeakPtr<AutofillDialogController> |
-AutofillDialogController::Create( |
- content::WebContents* contents, |
- const FormData& form_structure, |
- const GURL& source_url, |
- const AutofillClient::ResultCallback& callback) { |
- return AutofillDialogControllerAndroid::Create(contents, |
- form_structure, |
- source_url, |
- callback); |
-} |
- |
-// static |
-void AutofillDialogController::RegisterPrefs(PrefRegistrySimple* registry) {} |
- |
-// static |
-void AutofillDialogController::RegisterProfilePrefs( |
- user_prefs::PrefRegistrySyncable* registry) { |
- registry->RegisterDictionaryPref( |
- ::prefs::kAutofillDialogDefaults, |
- user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); |
-} |
-#endif // defined(ENABLE_AUTOFILL_DIALOG) |
- |
-AutofillDialogControllerAndroid::~AutofillDialogControllerAndroid() { |
- if (java_object_.is_null()) |
- return; |
- |
- JNIEnv* env = base::android::AttachCurrentThread(); |
- Java_AutofillDialogControllerAndroid_onDestroy(env, java_object_.obj()); |
-} |
- |
-void AutofillDialogControllerAndroid::Show() { |
- JNIEnv* env = base::android::AttachCurrentThread(); |
- dialog_shown_timestamp_ = base::Time::Now(); |
- |
- // The Autofill dialog is shown in response to a message from the renderer and |
- // as such, it can only be made in the context of the current document. A call |
- // to GetActiveEntry would return a pending entry, if there was one, which |
- // would be a security bug. Therefore, we use the last committed URL for the |
- // access checks. |
- const GURL& current_url = contents_->GetLastCommittedURL(); |
- invoked_from_same_origin_ = |
- current_url.GetOrigin() == source_url_.GetOrigin(); |
- |
- // Fail if the dialog factory (e.g. SDK) doesn't support cross-origin calls. |
- if (!Java_AutofillDialogControllerAndroid_isDialogAllowed( |
- env, |
- invoked_from_same_origin_)) { |
- callback_.Run( |
- AutofillClient::AutocompleteResultErrorDisabled, |
- base::ASCIIToUTF16("Cross-origin form invocations are not supported."), |
- NULL); |
- delete this; |
- return; |
- } |
- |
- // Determine what field types should be included in the dialog. |
- form_structure_.ParseFieldTypesFromAutocompleteAttributes(); |
- |
- // Fail if the author didn't specify autocomplete types, or |
- // if the dialog shouldn't be shown in a given circumstances. |
- if (!form_structure_.has_author_specified_types()) { |
- callback_.Run( |
- AutofillClient::AutocompleteResultErrorDisabled, |
- base::ASCIIToUTF16("Form is missing autocomplete attributes."), |
- NULL); |
- delete this; |
- return; |
- } |
- |
- // Fail if the author didn't ask for at least some kind of credit card |
- // information. |
- bool has_credit_card_field = false; |
- for (size_t i = 0; i < form_structure_.field_count(); ++i) { |
- AutofillType type = form_structure_.field(i)->Type(); |
- if (type.html_type() != HTML_TYPE_UNSPECIFIED && |
- type.group() == CREDIT_CARD) { |
- has_credit_card_field = true; |
- break; |
- } |
- } |
- |
- if (!has_credit_card_field) { |
- callback_.Run( |
- AutofillClient::AutocompleteResultErrorDisabled, |
- base::ASCIIToUTF16("Form is not a payment form (must contain " |
- "some autocomplete=\"cc-*\" fields). "), |
- NULL); |
- delete this; |
- return; |
- } |
- |
- // Log any relevant UI metrics and security exceptions. |
- AutofillMetrics::LogDialogUiEvent(AutofillMetrics::DIALOG_UI_SHOWN); |
- |
- AutofillMetrics::LogDialogSecurityMetric( |
- AutofillMetrics::SECURITY_METRIC_DIALOG_SHOWN); |
- |
- if (!invoked_from_same_origin_) { |
- AutofillMetrics::LogDialogSecurityMetric( |
- AutofillMetrics::SECURITY_METRIC_CROSS_ORIGIN_FRAME); |
- } |
- |
- const ServerFieldType full_billing_is_necessary_if[] = { |
- ADDRESS_BILLING_LINE1, |
- ADDRESS_BILLING_LINE2, |
- ADDRESS_BILLING_APT_NUM, |
- ADDRESS_BILLING_CITY, |
- ADDRESS_BILLING_STATE, |
- // ADDRESS_BILLING_ZIP, // Postal code alone is a short form. |
- ADDRESS_BILLING_COUNTRY, |
- ADDRESS_BILLING_STREET_ADDRESS, |
- ADDRESS_BILLING_DEPENDENT_LOCALITY, |
- ADDRESS_BILLING_SORTING_CODE, |
- PHONE_BILLING_WHOLE_NUMBER |
- }; |
- const ServerFieldType billing_phone_number_is_necessary_if[] = { |
- PHONE_BILLING_WHOLE_NUMBER |
- }; |
- const ServerFieldType shipping_phone_number_is_necessary_if[] = { |
- PHONE_HOME_WHOLE_NUMBER |
- }; |
- const bool request_full_billing_address = |
- IsSectionInputsUsedInFormStructure( |
- SECTION_BILLING, |
- full_billing_is_necessary_if, |
- arraysize(full_billing_is_necessary_if), |
- form_structure_); |
- const bool request_phone_numbers = |
- IsSectionInputsUsedInFormStructure( |
- SECTION_BILLING, |
- billing_phone_number_is_necessary_if, |
- arraysize(billing_phone_number_is_necessary_if), |
- form_structure_) || |
- IsSectionInputsUsedInFormStructure( |
- SECTION_SHIPPING, |
- shipping_phone_number_is_necessary_if, |
- arraysize(shipping_phone_number_is_necessary_if), |
- form_structure_); |
- |
- bool request_shipping_address = false; |
- { |
- DetailInputs inputs; |
- BuildShippingInputs(&inputs); |
- request_shipping_address = form_structure_.FillFields( |
- TypesFromInputs(inputs), |
- base::Bind(ServerTypeMatchesField, SECTION_SHIPPING), |
- base::Bind(NullGetInfo), std::string(), |
- g_browser_process->GetApplicationLocale()); |
- } |
- |
- bool last_used_choice_is_autofill = false; |
- base::string16 last_used_account_name; |
- std::string last_used_billing; |
- std::string last_used_shipping; |
- std::string last_used_credit_card; |
- { |
- const base::DictionaryValue* defaults = |
- profile_->GetPrefs()->GetDictionary(::prefs::kAutofillDialogDefaults); |
- if (defaults) { |
- defaults->GetString(kLastUsedAccountName, &last_used_account_name); |
- defaults->GetBoolean(kLastUsedChoiceIsAutofill, |
- &last_used_choice_is_autofill); |
- defaults->GetString(kLastUsedBillingAddressGuid, &last_used_billing); |
- defaults->GetString(kLastUsedShippingAddressGuid, &last_used_shipping); |
- defaults->GetString(kLastUsedCreditCardGuid, &last_used_credit_card); |
- } else { |
- DLOG(ERROR) << "Failed to read AutofillDialog preferences"; |
- } |
- } |
- |
- const bool incognito_mode = profile_->IsOffTheRecord(); |
- if (incognito_mode) |
- last_used_choice_is_autofill = true; |
- |
- ScopedJavaLocalRef<jstring> jlast_used_account_name = |
- base::android::ConvertUTF16ToJavaString( |
- env, last_used_account_name); |
- ScopedJavaLocalRef<jstring> jlast_used_billing = |
- base::android::ConvertUTF8ToJavaString( |
- env, last_used_billing); |
- ScopedJavaLocalRef<jstring> jlast_used_shipping = |
- base::android::ConvertUTF8ToJavaString( |
- env, last_used_shipping); |
- ScopedJavaLocalRef<jstring> jlast_used_card = |
- base::android::ConvertUTF8ToJavaString( |
- env, last_used_credit_card); |
- ScopedJavaLocalRef<jstring> jmerchant_domain = |
- base::android::ConvertUTF8ToJavaString( |
- env, source_url_.GetOrigin().spec()); |
- const std::set<base::string16> available_shipping_countries = |
- form_structure_.PossibleValues(ADDRESS_HOME_COUNTRY); |
- ScopedJavaLocalRef<jobjectArray> jshipping_countries = |
- base::android::ToJavaArrayOfStrings( |
- env, |
- std::vector<base::string16>(available_shipping_countries.begin(), |
- available_shipping_countries.end())); |
- const std::set<base::string16> available_credit_card_types = |
- form_structure_.PossibleValues(CREDIT_CARD_TYPE); |
- ScopedJavaLocalRef<jobjectArray> jcredit_card_types = |
- base::android::ToJavaArrayOfStrings( |
- env, |
- std::vector<base::string16>(available_credit_card_types.begin(), |
- available_credit_card_types.end())); |
- |
- java_object_.Reset(Java_AutofillDialogControllerAndroid_create( |
- env, |
- reinterpret_cast<intptr_t>(this), |
- ViewAndroidHelper::FromWebContents(contents_)-> |
- GetViewAndroid()->GetWindowAndroid()->GetJavaObject().obj(), |
- request_full_billing_address, request_shipping_address, |
- request_phone_numbers, incognito_mode, |
- last_used_choice_is_autofill, jlast_used_account_name.obj(), |
- jlast_used_billing.obj(), jlast_used_shipping.obj(), |
- jlast_used_card.obj(), |
- jmerchant_domain.obj(), |
- jshipping_countries.obj(), |
- jcredit_card_types.obj())); |
-} |
- |
-void AutofillDialogControllerAndroid::Hide() { |
- delete this; |
-} |
- |
-void AutofillDialogControllerAndroid::TabActivated() {} |
- |
-// static |
-bool AutofillDialogControllerAndroid:: |
- RegisterAutofillDialogControllerAndroid(JNIEnv* env) { |
- return RegisterNativesImpl(env); |
-} |
- |
-void AutofillDialogControllerAndroid::DialogCancel( |
- JNIEnv* env, |
- const JavaParamRef<jobject>& obj) { |
- LogOnCancelMetrics(); |
- callback_.Run(AutofillClient::AutocompleteResultErrorCancel, |
- base::string16(), |
- NULL); |
-} |
- |
-void AutofillDialogControllerAndroid::DialogContinue( |
- JNIEnv* env, |
- const JavaParamRef<jobject>& obj, |
- const JavaParamRef<jobject>& wallet, |
- jboolean jlast_used_choice_is_autofill, |
- const JavaParamRef<jstring>& jlast_used_account_name, |
- const JavaParamRef<jstring>& jlast_used_billing, |
- const JavaParamRef<jstring>& jlast_used_shipping, |
- const JavaParamRef<jstring>& jlast_used_card) { |
- const base::string16 email = |
- AutofillDialogResult::GetWalletEmail(env, wallet); |
- const std::string google_transaction_id = |
- AutofillDialogResult::GetWalletGoogleTransactionId(env, wallet); |
- |
- const base::string16 last_used_account_name = |
- base::android::ConvertJavaStringToUTF16(env, jlast_used_account_name); |
- const std::string last_used_billing = |
- base::android::ConvertJavaStringToUTF8(env, jlast_used_billing); |
- const std::string last_used_shipping = |
- base::android::ConvertJavaStringToUTF8(env, jlast_used_shipping); |
- const std::string last_used_card = |
- base::android::ConvertJavaStringToUTF8(env, jlast_used_card); |
- |
- std::unique_ptr<FullWallet> full_wallet = |
- AutofillDialogResult::ConvertFromJava(env, wallet); |
- FillOutputForSection(SECTION_BILLING, form_structure_, full_wallet.get(), |
- email); |
- FillOutputForSection( |
- SECTION_SHIPPING, form_structure_, full_wallet.get(), email); |
- |
- { |
- DictionaryPrefUpdate updater(profile_->GetPrefs(), |
- ::prefs::kAutofillDialogDefaults); |
- base::DictionaryValue* defaults = updater.Get(); |
- if (defaults) { |
- const bool last_used_choice_is_autofill = !!jlast_used_choice_is_autofill; |
- defaults->SetString(kLastUsedAccountName, last_used_account_name); |
- defaults->SetBoolean(kLastUsedChoiceIsAutofill, |
- last_used_choice_is_autofill); |
- if (!last_used_billing.empty()) |
- defaults->SetString(kLastUsedBillingAddressGuid, last_used_billing); |
- if (!last_used_shipping.empty()) |
- defaults->SetString(kLastUsedShippingAddressGuid, last_used_shipping); |
- if (!last_used_card.empty()) |
- defaults->SetString(kLastUsedCreditCardGuid, last_used_card); |
- } else { |
- DLOG(ERROR) << "Failed to save AutofillDialog preferences"; |
- } |
- } |
- |
- LogOnFinishSubmitMetrics(); |
- |
- // Callback should be called as late as possible. |
- callback_.Run(AutofillClient::AutocompleteResultSuccess, |
- base::string16(), |
- &form_structure_); |
- |
- // This might delete us. |
- Hide(); |
-} |
- |
-AutofillDialogControllerAndroid::AutofillDialogControllerAndroid( |
- content::WebContents* contents, |
- const FormData& form_structure, |
- const GURL& source_url, |
- const AutofillClient::ResultCallback& callback) |
- : profile_(Profile::FromBrowserContext(contents->GetBrowserContext())), |
- contents_(contents), |
- initial_user_state_(AutofillMetrics::DIALOG_USER_STATE_UNKNOWN), |
- form_structure_(form_structure), |
- invoked_from_same_origin_(true), |
- source_url_(source_url), |
- callback_(callback), |
- cares_about_shipping_(true), |
- was_ui_latency_logged_(false), |
- weak_ptr_factory_(this) { |
- DCHECK(!callback_.is_null()); |
-} |
- |
-void AutofillDialogControllerAndroid::LogOnFinishSubmitMetrics() { |
- AutofillMetrics::LogDialogUiDuration( |
- base::Time::Now() - dialog_shown_timestamp_, |
- AutofillMetrics::DIALOG_ACCEPTED); |
- |
- AutofillMetrics::LogDialogUiEvent(AutofillMetrics::DIALOG_UI_ACCEPTED); |
-} |
- |
-void AutofillDialogControllerAndroid::LogOnCancelMetrics() { |
- AutofillMetrics::LogDialogUiDuration( |
- base::Time::Now() - dialog_shown_timestamp_, |
- AutofillMetrics::DIALOG_CANCELED); |
- |
- AutofillMetrics::LogDialogUiEvent(AutofillMetrics::DIALOG_UI_CANCELED); |
-} |
- |
-} // namespace autofill |