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 |