| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/ui/android/autofill/autofill_dialog_controller_android.
h" | |
| 6 | |
| 7 #include <stddef.h> | |
| 8 | |
| 9 #include "base/android/jni_android.h" | |
| 10 #include "base/android/jni_array.h" | |
| 11 #include "base/android/jni_string.h" | |
| 12 #include "base/android/scoped_java_ref.h" | |
| 13 #include "base/bind.h" | |
| 14 #include "base/logging.h" | |
| 15 #include "base/macros.h" | |
| 16 #include "base/strings/utf_string_conversions.h" | |
| 17 #include "chrome/browser/autofill/personal_data_manager_factory.h" | |
| 18 #include "chrome/browser/browser_process.h" | |
| 19 #include "chrome/browser/profiles/profile.h" | |
| 20 #include "chrome/browser/profiles/profile_manager.h" | |
| 21 #include "chrome/browser/ui/android/autofill/autofill_dialog_result.h" | |
| 22 #include "chrome/browser/ui/android/view_android_helper.h" | |
| 23 #include "chrome/browser/ui/autofill/autofill_dialog_common.h" | |
| 24 #include "chrome/common/pref_names.h" | |
| 25 #include "chrome/common/url_constants.h" | |
| 26 #include "components/autofill/content/browser/wallet/full_wallet.h" | |
| 27 #include "components/autofill/core/browser/autofill_metrics.h" | |
| 28 #include "components/autofill/core/browser/autofill_profile.h" | |
| 29 #include "components/autofill/core/browser/autofill_type.h" | |
| 30 #include "components/autofill/core/browser/credit_card.h" | |
| 31 #include "components/autofill/core/browser/detail_input.h" | |
| 32 #include "components/autofill/core/browser/dialog_section.h" | |
| 33 #include "components/autofill/core/browser/field_types.h" | |
| 34 #include "components/autofill/core/browser/personal_data_manager.h" | |
| 35 #include "components/autofill/core/browser/server_field_types_util.h" | |
| 36 #include "components/autofill/core/common/form_data.h" | |
| 37 #include "components/pref_registry/pref_registry_syncable.h" | |
| 38 #include "components/prefs/pref_service.h" | |
| 39 #include "components/prefs/scoped_user_pref_update.h" | |
| 40 #include "content/public/browser/navigation_controller.h" | |
| 41 #include "content/public/browser/navigation_details.h" | |
| 42 #include "content/public/browser/navigation_entry.h" | |
| 43 #include "content/public/browser/web_contents.h" | |
| 44 #include "jni/AutofillDialogControllerAndroid_jni.h" | |
| 45 #include "ui/android/view_android.h" | |
| 46 #include "ui/android/window_android.h" | |
| 47 #include "ui/base/models/combobox_model.h" | |
| 48 #include "ui/base/models/menu_model.h" | |
| 49 #include "ui/gfx/android/java_bitmap.h" | |
| 50 #include "ui/gfx/geometry/rect.h" | |
| 51 #include "url/gurl.h" | |
| 52 | |
| 53 namespace autofill { | |
| 54 | |
| 55 namespace { | |
| 56 | |
| 57 using wallet::FullWallet; | |
| 58 | |
| 59 // Keys in kAutofillDialogDefaults pref dictionary (do not change these values). | |
| 60 const char kLastUsedAccountName[] = "last_used_account_name"; | |
| 61 const char kLastUsedChoiceIsAutofill[] = "last_used_choice_is_autofill"; | |
| 62 const char kLastUsedBillingAddressGuid[] = "last_used_billing"; | |
| 63 const char kLastUsedShippingAddressGuid[] = "last_used_shipping"; | |
| 64 const char kLastUsedCreditCardGuid[] = "last_used_card"; | |
| 65 | |
| 66 // Constructs |inputs| for the SECTION_BILLING section. | |
| 67 void BuildCcBillingInputs(DetailInputs* inputs) { | |
| 68 const DetailInput kCcBillingInputs[] = { | |
| 69 { DetailInput::LONG, NAME_BILLING_FULL }, | |
| 70 { DetailInput::LONG, ADDRESS_BILLING_STREET_ADDRESS }, | |
| 71 { DetailInput::LONG, ADDRESS_BILLING_CITY }, | |
| 72 { DetailInput::LONG, ADDRESS_BILLING_DEPENDENT_LOCALITY }, | |
| 73 { DetailInput::LONG, ADDRESS_BILLING_STATE }, | |
| 74 { DetailInput::LONG, ADDRESS_BILLING_ZIP }, | |
| 75 { DetailInput::LONG, ADDRESS_BILLING_SORTING_CODE }, | |
| 76 { DetailInput::LONG, ADDRESS_BILLING_COUNTRY }, | |
| 77 { DetailInput::LONG, PHONE_BILLING_WHOLE_NUMBER }, | |
| 78 { DetailInput::LONG, CREDIT_CARD_NUMBER }, | |
| 79 { DetailInput::LONG, CREDIT_CARD_EXP_MONTH }, | |
| 80 { DetailInput::LONG, CREDIT_CARD_EXP_4_DIGIT_YEAR }, | |
| 81 { DetailInput::LONG, CREDIT_CARD_VERIFICATION_CODE }, | |
| 82 }; | |
| 83 BuildInputs(kCcBillingInputs, arraysize(kCcBillingInputs), inputs); | |
| 84 } | |
| 85 | |
| 86 // Constructs |inputs| for the SECTION_SHIPPING section. | |
| 87 void BuildShippingInputs(DetailInputs* inputs) { | |
| 88 const DetailInput kShippingInputs[] = { | |
| 89 { DetailInput::LONG, NAME_FULL }, | |
| 90 { DetailInput::LONG, ADDRESS_HOME_STREET_ADDRESS }, | |
| 91 { DetailInput::LONG, ADDRESS_HOME_CITY }, | |
| 92 { DetailInput::LONG, ADDRESS_HOME_DEPENDENT_LOCALITY }, | |
| 93 { DetailInput::LONG, ADDRESS_HOME_STATE }, | |
| 94 { DetailInput::LONG, ADDRESS_HOME_ZIP }, | |
| 95 { DetailInput::LONG, ADDRESS_HOME_SORTING_CODE }, | |
| 96 { DetailInput::LONG, ADDRESS_HOME_COUNTRY }, | |
| 97 { DetailInput::LONG, PHONE_HOME_WHOLE_NUMBER }, | |
| 98 }; | |
| 99 BuildInputs(kShippingInputs, arraysize(kShippingInputs), inputs); | |
| 100 } | |
| 101 | |
| 102 base::string16 NullGetInfo(const AutofillType& type) { | |
| 103 return base::string16(); | |
| 104 } | |
| 105 | |
| 106 void FillOutputForSectionWithComparator( | |
| 107 DialogSection section, | |
| 108 const DetailInputs& inputs, | |
| 109 const FormStructure::InputFieldComparator& compare, | |
| 110 FormStructure& form_structure, | |
| 111 FullWallet* full_wallet, | |
| 112 const base::string16& email_address) { | |
| 113 if ((section == SECTION_BILLING && !full_wallet->billing_address()) || | |
| 114 (section == SECTION_SHIPPING && !full_wallet->shipping_address())) { | |
| 115 return; | |
| 116 } | |
| 117 | |
| 118 base::Callback<base::string16(const AutofillType&)> get_info = | |
| 119 base::Bind(&FullWallet::GetInfo, | |
| 120 base::Unretained(full_wallet), | |
| 121 g_browser_process->GetApplicationLocale()); | |
| 122 | |
| 123 std::vector<ServerFieldType> types = TypesFromInputs(inputs); | |
| 124 form_structure.FillFields( | |
| 125 types, compare, get_info, | |
| 126 section == SECTION_BILLING | |
| 127 ? full_wallet->billing_address()->language_code() | |
| 128 : full_wallet->shipping_address()->language_code(), | |
| 129 g_browser_process->GetApplicationLocale()); | |
| 130 } | |
| 131 | |
| 132 void FillOutputForSection( | |
| 133 DialogSection section, | |
| 134 FormStructure& form_structure, | |
| 135 FullWallet* full_wallet, | |
| 136 const base::string16& email_address) { | |
| 137 DetailInputs inputs; | |
| 138 if (section == SECTION_BILLING) | |
| 139 BuildCcBillingInputs(&inputs); | |
| 140 else | |
| 141 BuildShippingInputs(&inputs); | |
| 142 | |
| 143 FillOutputForSectionWithComparator( | |
| 144 section, inputs, base::Bind(ServerTypeMatchesField, section), | |
| 145 form_structure, full_wallet, email_address); | |
| 146 | |
| 147 if (section == SECTION_BILLING) { | |
| 148 // Email is hidden while using Wallet, special case it. | |
| 149 for (size_t i = 0; i < form_structure.field_count(); ++i) { | |
| 150 AutofillField* field = form_structure.field(i); | |
| 151 if (field->Type().GetStorableType() == EMAIL_ADDRESS) | |
| 152 field->value = email_address; | |
| 153 } | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 // Returns true if |input_type| in |section| is needed for |form_structure|. | |
| 158 bool IsSectionInputUsedInFormStructure(DialogSection section, | |
| 159 ServerFieldType input_type, | |
| 160 const FormStructure& form_structure) { | |
| 161 for (size_t i = 0; i < form_structure.field_count(); ++i) { | |
| 162 const AutofillField* field = form_structure.field(i); | |
| 163 if (field && ServerTypeMatchesField(section, input_type, *field)) | |
| 164 return true; | |
| 165 } | |
| 166 return false; | |
| 167 } | |
| 168 | |
| 169 // Returns true if one of |inputs| in |section| is needed for |form_structure|. | |
| 170 bool IsSectionInputsUsedInFormStructure(DialogSection section, | |
| 171 const ServerFieldType* input_types, | |
| 172 const size_t input_types_size, | |
| 173 const FormStructure& form_structure) { | |
| 174 for (size_t i = 0; i < input_types_size; ++i) { | |
| 175 if (IsSectionInputUsedInFormStructure( | |
| 176 section, input_types[i], form_structure)) { | |
| 177 return true; | |
| 178 } | |
| 179 } | |
| 180 return false; | |
| 181 } | |
| 182 | |
| 183 } // namespace | |
| 184 | |
| 185 | |
| 186 // static | |
| 187 base::WeakPtr<AutofillDialogController> AutofillDialogControllerAndroid::Create( | |
| 188 content::WebContents* contents, | |
| 189 const FormData& form_structure, | |
| 190 const GURL& source_url, | |
| 191 const AutofillClient::ResultCallback& callback) { | |
| 192 // AutofillDialogControllerAndroid owns itself. | |
| 193 AutofillDialogControllerAndroid* autofill_dialog_controller = | |
| 194 new AutofillDialogControllerAndroid(contents, | |
| 195 form_structure, | |
| 196 source_url, | |
| 197 callback); | |
| 198 return autofill_dialog_controller->weak_ptr_factory_.GetWeakPtr(); | |
| 199 } | |
| 200 | |
| 201 #if defined(ENABLE_AUTOFILL_DIALOG) | |
| 202 // static | |
| 203 base::WeakPtr<AutofillDialogController> | |
| 204 AutofillDialogController::Create( | |
| 205 content::WebContents* contents, | |
| 206 const FormData& form_structure, | |
| 207 const GURL& source_url, | |
| 208 const AutofillClient::ResultCallback& callback) { | |
| 209 return AutofillDialogControllerAndroid::Create(contents, | |
| 210 form_structure, | |
| 211 source_url, | |
| 212 callback); | |
| 213 } | |
| 214 | |
| 215 // static | |
| 216 void AutofillDialogController::RegisterPrefs(PrefRegistrySimple* registry) {} | |
| 217 | |
| 218 // static | |
| 219 void AutofillDialogController::RegisterProfilePrefs( | |
| 220 user_prefs::PrefRegistrySyncable* registry) { | |
| 221 registry->RegisterDictionaryPref( | |
| 222 ::prefs::kAutofillDialogDefaults, | |
| 223 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); | |
| 224 } | |
| 225 #endif // defined(ENABLE_AUTOFILL_DIALOG) | |
| 226 | |
| 227 AutofillDialogControllerAndroid::~AutofillDialogControllerAndroid() { | |
| 228 if (java_object_.is_null()) | |
| 229 return; | |
| 230 | |
| 231 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 232 Java_AutofillDialogControllerAndroid_onDestroy(env, java_object_.obj()); | |
| 233 } | |
| 234 | |
| 235 void AutofillDialogControllerAndroid::Show() { | |
| 236 JNIEnv* env = base::android::AttachCurrentThread(); | |
| 237 dialog_shown_timestamp_ = base::Time::Now(); | |
| 238 | |
| 239 // The Autofill dialog is shown in response to a message from the renderer and | |
| 240 // as such, it can only be made in the context of the current document. A call | |
| 241 // to GetActiveEntry would return a pending entry, if there was one, which | |
| 242 // would be a security bug. Therefore, we use the last committed URL for the | |
| 243 // access checks. | |
| 244 const GURL& current_url = contents_->GetLastCommittedURL(); | |
| 245 invoked_from_same_origin_ = | |
| 246 current_url.GetOrigin() == source_url_.GetOrigin(); | |
| 247 | |
| 248 // Fail if the dialog factory (e.g. SDK) doesn't support cross-origin calls. | |
| 249 if (!Java_AutofillDialogControllerAndroid_isDialogAllowed( | |
| 250 env, | |
| 251 invoked_from_same_origin_)) { | |
| 252 callback_.Run( | |
| 253 AutofillClient::AutocompleteResultErrorDisabled, | |
| 254 base::ASCIIToUTF16("Cross-origin form invocations are not supported."), | |
| 255 NULL); | |
| 256 delete this; | |
| 257 return; | |
| 258 } | |
| 259 | |
| 260 // Determine what field types should be included in the dialog. | |
| 261 form_structure_.ParseFieldTypesFromAutocompleteAttributes(); | |
| 262 | |
| 263 // Fail if the author didn't specify autocomplete types, or | |
| 264 // if the dialog shouldn't be shown in a given circumstances. | |
| 265 if (!form_structure_.has_author_specified_types()) { | |
| 266 callback_.Run( | |
| 267 AutofillClient::AutocompleteResultErrorDisabled, | |
| 268 base::ASCIIToUTF16("Form is missing autocomplete attributes."), | |
| 269 NULL); | |
| 270 delete this; | |
| 271 return; | |
| 272 } | |
| 273 | |
| 274 // Fail if the author didn't ask for at least some kind of credit card | |
| 275 // information. | |
| 276 bool has_credit_card_field = false; | |
| 277 for (size_t i = 0; i < form_structure_.field_count(); ++i) { | |
| 278 AutofillType type = form_structure_.field(i)->Type(); | |
| 279 if (type.html_type() != HTML_TYPE_UNSPECIFIED && | |
| 280 type.group() == CREDIT_CARD) { | |
| 281 has_credit_card_field = true; | |
| 282 break; | |
| 283 } | |
| 284 } | |
| 285 | |
| 286 if (!has_credit_card_field) { | |
| 287 callback_.Run( | |
| 288 AutofillClient::AutocompleteResultErrorDisabled, | |
| 289 base::ASCIIToUTF16("Form is not a payment form (must contain " | |
| 290 "some autocomplete=\"cc-*\" fields). "), | |
| 291 NULL); | |
| 292 delete this; | |
| 293 return; | |
| 294 } | |
| 295 | |
| 296 // Log any relevant UI metrics and security exceptions. | |
| 297 AutofillMetrics::LogDialogUiEvent(AutofillMetrics::DIALOG_UI_SHOWN); | |
| 298 | |
| 299 AutofillMetrics::LogDialogSecurityMetric( | |
| 300 AutofillMetrics::SECURITY_METRIC_DIALOG_SHOWN); | |
| 301 | |
| 302 if (!invoked_from_same_origin_) { | |
| 303 AutofillMetrics::LogDialogSecurityMetric( | |
| 304 AutofillMetrics::SECURITY_METRIC_CROSS_ORIGIN_FRAME); | |
| 305 } | |
| 306 | |
| 307 const ServerFieldType full_billing_is_necessary_if[] = { | |
| 308 ADDRESS_BILLING_LINE1, | |
| 309 ADDRESS_BILLING_LINE2, | |
| 310 ADDRESS_BILLING_APT_NUM, | |
| 311 ADDRESS_BILLING_CITY, | |
| 312 ADDRESS_BILLING_STATE, | |
| 313 // ADDRESS_BILLING_ZIP, // Postal code alone is a short form. | |
| 314 ADDRESS_BILLING_COUNTRY, | |
| 315 ADDRESS_BILLING_STREET_ADDRESS, | |
| 316 ADDRESS_BILLING_DEPENDENT_LOCALITY, | |
| 317 ADDRESS_BILLING_SORTING_CODE, | |
| 318 PHONE_BILLING_WHOLE_NUMBER | |
| 319 }; | |
| 320 const ServerFieldType billing_phone_number_is_necessary_if[] = { | |
| 321 PHONE_BILLING_WHOLE_NUMBER | |
| 322 }; | |
| 323 const ServerFieldType shipping_phone_number_is_necessary_if[] = { | |
| 324 PHONE_HOME_WHOLE_NUMBER | |
| 325 }; | |
| 326 const bool request_full_billing_address = | |
| 327 IsSectionInputsUsedInFormStructure( | |
| 328 SECTION_BILLING, | |
| 329 full_billing_is_necessary_if, | |
| 330 arraysize(full_billing_is_necessary_if), | |
| 331 form_structure_); | |
| 332 const bool request_phone_numbers = | |
| 333 IsSectionInputsUsedInFormStructure( | |
| 334 SECTION_BILLING, | |
| 335 billing_phone_number_is_necessary_if, | |
| 336 arraysize(billing_phone_number_is_necessary_if), | |
| 337 form_structure_) || | |
| 338 IsSectionInputsUsedInFormStructure( | |
| 339 SECTION_SHIPPING, | |
| 340 shipping_phone_number_is_necessary_if, | |
| 341 arraysize(shipping_phone_number_is_necessary_if), | |
| 342 form_structure_); | |
| 343 | |
| 344 bool request_shipping_address = false; | |
| 345 { | |
| 346 DetailInputs inputs; | |
| 347 BuildShippingInputs(&inputs); | |
| 348 request_shipping_address = form_structure_.FillFields( | |
| 349 TypesFromInputs(inputs), | |
| 350 base::Bind(ServerTypeMatchesField, SECTION_SHIPPING), | |
| 351 base::Bind(NullGetInfo), std::string(), | |
| 352 g_browser_process->GetApplicationLocale()); | |
| 353 } | |
| 354 | |
| 355 bool last_used_choice_is_autofill = false; | |
| 356 base::string16 last_used_account_name; | |
| 357 std::string last_used_billing; | |
| 358 std::string last_used_shipping; | |
| 359 std::string last_used_credit_card; | |
| 360 { | |
| 361 const base::DictionaryValue* defaults = | |
| 362 profile_->GetPrefs()->GetDictionary(::prefs::kAutofillDialogDefaults); | |
| 363 if (defaults) { | |
| 364 defaults->GetString(kLastUsedAccountName, &last_used_account_name); | |
| 365 defaults->GetBoolean(kLastUsedChoiceIsAutofill, | |
| 366 &last_used_choice_is_autofill); | |
| 367 defaults->GetString(kLastUsedBillingAddressGuid, &last_used_billing); | |
| 368 defaults->GetString(kLastUsedShippingAddressGuid, &last_used_shipping); | |
| 369 defaults->GetString(kLastUsedCreditCardGuid, &last_used_credit_card); | |
| 370 } else { | |
| 371 DLOG(ERROR) << "Failed to read AutofillDialog preferences"; | |
| 372 } | |
| 373 } | |
| 374 | |
| 375 const bool incognito_mode = profile_->IsOffTheRecord(); | |
| 376 if (incognito_mode) | |
| 377 last_used_choice_is_autofill = true; | |
| 378 | |
| 379 ScopedJavaLocalRef<jstring> jlast_used_account_name = | |
| 380 base::android::ConvertUTF16ToJavaString( | |
| 381 env, last_used_account_name); | |
| 382 ScopedJavaLocalRef<jstring> jlast_used_billing = | |
| 383 base::android::ConvertUTF8ToJavaString( | |
| 384 env, last_used_billing); | |
| 385 ScopedJavaLocalRef<jstring> jlast_used_shipping = | |
| 386 base::android::ConvertUTF8ToJavaString( | |
| 387 env, last_used_shipping); | |
| 388 ScopedJavaLocalRef<jstring> jlast_used_card = | |
| 389 base::android::ConvertUTF8ToJavaString( | |
| 390 env, last_used_credit_card); | |
| 391 ScopedJavaLocalRef<jstring> jmerchant_domain = | |
| 392 base::android::ConvertUTF8ToJavaString( | |
| 393 env, source_url_.GetOrigin().spec()); | |
| 394 const std::set<base::string16> available_shipping_countries = | |
| 395 form_structure_.PossibleValues(ADDRESS_HOME_COUNTRY); | |
| 396 ScopedJavaLocalRef<jobjectArray> jshipping_countries = | |
| 397 base::android::ToJavaArrayOfStrings( | |
| 398 env, | |
| 399 std::vector<base::string16>(available_shipping_countries.begin(), | |
| 400 available_shipping_countries.end())); | |
| 401 const std::set<base::string16> available_credit_card_types = | |
| 402 form_structure_.PossibleValues(CREDIT_CARD_TYPE); | |
| 403 ScopedJavaLocalRef<jobjectArray> jcredit_card_types = | |
| 404 base::android::ToJavaArrayOfStrings( | |
| 405 env, | |
| 406 std::vector<base::string16>(available_credit_card_types.begin(), | |
| 407 available_credit_card_types.end())); | |
| 408 | |
| 409 java_object_.Reset(Java_AutofillDialogControllerAndroid_create( | |
| 410 env, | |
| 411 reinterpret_cast<intptr_t>(this), | |
| 412 ViewAndroidHelper::FromWebContents(contents_)-> | |
| 413 GetViewAndroid()->GetWindowAndroid()->GetJavaObject().obj(), | |
| 414 request_full_billing_address, request_shipping_address, | |
| 415 request_phone_numbers, incognito_mode, | |
| 416 last_used_choice_is_autofill, jlast_used_account_name.obj(), | |
| 417 jlast_used_billing.obj(), jlast_used_shipping.obj(), | |
| 418 jlast_used_card.obj(), | |
| 419 jmerchant_domain.obj(), | |
| 420 jshipping_countries.obj(), | |
| 421 jcredit_card_types.obj())); | |
| 422 } | |
| 423 | |
| 424 void AutofillDialogControllerAndroid::Hide() { | |
| 425 delete this; | |
| 426 } | |
| 427 | |
| 428 void AutofillDialogControllerAndroid::TabActivated() {} | |
| 429 | |
| 430 // static | |
| 431 bool AutofillDialogControllerAndroid:: | |
| 432 RegisterAutofillDialogControllerAndroid(JNIEnv* env) { | |
| 433 return RegisterNativesImpl(env); | |
| 434 } | |
| 435 | |
| 436 void AutofillDialogControllerAndroid::DialogCancel( | |
| 437 JNIEnv* env, | |
| 438 const JavaParamRef<jobject>& obj) { | |
| 439 LogOnCancelMetrics(); | |
| 440 callback_.Run(AutofillClient::AutocompleteResultErrorCancel, | |
| 441 base::string16(), | |
| 442 NULL); | |
| 443 } | |
| 444 | |
| 445 void AutofillDialogControllerAndroid::DialogContinue( | |
| 446 JNIEnv* env, | |
| 447 const JavaParamRef<jobject>& obj, | |
| 448 const JavaParamRef<jobject>& wallet, | |
| 449 jboolean jlast_used_choice_is_autofill, | |
| 450 const JavaParamRef<jstring>& jlast_used_account_name, | |
| 451 const JavaParamRef<jstring>& jlast_used_billing, | |
| 452 const JavaParamRef<jstring>& jlast_used_shipping, | |
| 453 const JavaParamRef<jstring>& jlast_used_card) { | |
| 454 const base::string16 email = | |
| 455 AutofillDialogResult::GetWalletEmail(env, wallet); | |
| 456 const std::string google_transaction_id = | |
| 457 AutofillDialogResult::GetWalletGoogleTransactionId(env, wallet); | |
| 458 | |
| 459 const base::string16 last_used_account_name = | |
| 460 base::android::ConvertJavaStringToUTF16(env, jlast_used_account_name); | |
| 461 const std::string last_used_billing = | |
| 462 base::android::ConvertJavaStringToUTF8(env, jlast_used_billing); | |
| 463 const std::string last_used_shipping = | |
| 464 base::android::ConvertJavaStringToUTF8(env, jlast_used_shipping); | |
| 465 const std::string last_used_card = | |
| 466 base::android::ConvertJavaStringToUTF8(env, jlast_used_card); | |
| 467 | |
| 468 std::unique_ptr<FullWallet> full_wallet = | |
| 469 AutofillDialogResult::ConvertFromJava(env, wallet); | |
| 470 FillOutputForSection(SECTION_BILLING, form_structure_, full_wallet.get(), | |
| 471 email); | |
| 472 FillOutputForSection( | |
| 473 SECTION_SHIPPING, form_structure_, full_wallet.get(), email); | |
| 474 | |
| 475 { | |
| 476 DictionaryPrefUpdate updater(profile_->GetPrefs(), | |
| 477 ::prefs::kAutofillDialogDefaults); | |
| 478 base::DictionaryValue* defaults = updater.Get(); | |
| 479 if (defaults) { | |
| 480 const bool last_used_choice_is_autofill = !!jlast_used_choice_is_autofill; | |
| 481 defaults->SetString(kLastUsedAccountName, last_used_account_name); | |
| 482 defaults->SetBoolean(kLastUsedChoiceIsAutofill, | |
| 483 last_used_choice_is_autofill); | |
| 484 if (!last_used_billing.empty()) | |
| 485 defaults->SetString(kLastUsedBillingAddressGuid, last_used_billing); | |
| 486 if (!last_used_shipping.empty()) | |
| 487 defaults->SetString(kLastUsedShippingAddressGuid, last_used_shipping); | |
| 488 if (!last_used_card.empty()) | |
| 489 defaults->SetString(kLastUsedCreditCardGuid, last_used_card); | |
| 490 } else { | |
| 491 DLOG(ERROR) << "Failed to save AutofillDialog preferences"; | |
| 492 } | |
| 493 } | |
| 494 | |
| 495 LogOnFinishSubmitMetrics(); | |
| 496 | |
| 497 // Callback should be called as late as possible. | |
| 498 callback_.Run(AutofillClient::AutocompleteResultSuccess, | |
| 499 base::string16(), | |
| 500 &form_structure_); | |
| 501 | |
| 502 // This might delete us. | |
| 503 Hide(); | |
| 504 } | |
| 505 | |
| 506 AutofillDialogControllerAndroid::AutofillDialogControllerAndroid( | |
| 507 content::WebContents* contents, | |
| 508 const FormData& form_structure, | |
| 509 const GURL& source_url, | |
| 510 const AutofillClient::ResultCallback& callback) | |
| 511 : profile_(Profile::FromBrowserContext(contents->GetBrowserContext())), | |
| 512 contents_(contents), | |
| 513 initial_user_state_(AutofillMetrics::DIALOG_USER_STATE_UNKNOWN), | |
| 514 form_structure_(form_structure), | |
| 515 invoked_from_same_origin_(true), | |
| 516 source_url_(source_url), | |
| 517 callback_(callback), | |
| 518 cares_about_shipping_(true), | |
| 519 was_ui_latency_logged_(false), | |
| 520 weak_ptr_factory_(this) { | |
| 521 DCHECK(!callback_.is_null()); | |
| 522 } | |
| 523 | |
| 524 void AutofillDialogControllerAndroid::LogOnFinishSubmitMetrics() { | |
| 525 AutofillMetrics::LogDialogUiDuration( | |
| 526 base::Time::Now() - dialog_shown_timestamp_, | |
| 527 AutofillMetrics::DIALOG_ACCEPTED); | |
| 528 | |
| 529 AutofillMetrics::LogDialogUiEvent(AutofillMetrics::DIALOG_UI_ACCEPTED); | |
| 530 } | |
| 531 | |
| 532 void AutofillDialogControllerAndroid::LogOnCancelMetrics() { | |
| 533 AutofillMetrics::LogDialogUiDuration( | |
| 534 base::Time::Now() - dialog_shown_timestamp_, | |
| 535 AutofillMetrics::DIALOG_CANCELED); | |
| 536 | |
| 537 AutofillMetrics::LogDialogUiEvent(AutofillMetrics::DIALOG_UI_CANCELED); | |
| 538 } | |
| 539 | |
| 540 } // namespace autofill | |
| OLD | NEW |