Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: chrome/browser/ui/android/autofill/autofill_dialog_tab_manager_delegate_android.cc

Issue 21124012: [WIP] Split AutofillDialogControllerImpl + integrate rAc on Android. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 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_tab_manager_delegat e_android.h"
6
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_array.h"
9 #include "base/android/jni_string.h"
10 #include "base/android/scoped_java_ref.h"
11 #include "base/bind.h"
12 #include "base/logging.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/browser/autofill/personal_data_manager_factory.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/prefs/scoped_user_pref_update.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/profiles/profile_manager.h"
20 #include "chrome/browser/ui/android/autofill/autofill_dialog_result.h"
21 #include "chrome/browser/ui/android/window_android_helper.h"
22 #include "chrome/browser/ui/autofill/autofill_dialog_utils.h"
23 #include "chrome/browser/ui/autofill/data_model_wrapper.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/personal_data_manager.h"
32 #include "components/autofill/core/common/form_data.h"
33 #include "components/user_prefs/pref_registry_syncable.h"
34 #include "content/public/browser/navigation_controller.h"
35 #include "content/public/browser/navigation_details.h"
36 #include "content/public/browser/navigation_entry.h"
37 #include "content/public/browser/web_contents.h"
38 #include "grit/generated_resources.h"
39 #include "jni/AutofillDialogTabManagerDelegateAndroid_jni.h"
40 #include "ui/android/window_android.h"
41 #include "ui/base/l10n/l10n_util.h"
42 #include "ui/base/models/combobox_model.h"
43 #include "ui/base/models/menu_model.h"
44 #include "ui/gfx/android/java_bitmap.h"
45 #include "ui/gfx/rect.h"
46 #include "url/gurl.h"
47
48 namespace autofill {
49
50 namespace {
51
52 // Keys in kAutofillDialogDefaults pref dictionary (do not change these values).
53 const char kLastUsedAccountName[] = "last_used_account_name";
54 const char kLastUsedChoiceIsAutofill[] = "last_used_choice_is_autofill";
55 const char kLastUsedBillingAddressGuid[] = "last_used_billing";
56 const char kLastUsedShippingAddressGuid[] = "last_used_shipping";
57 const char kLastUsedCreditCardGuid[] = "last_used_card";
58
59 scoped_ptr<DataModelWrapper> CreateWrapper(
60 DialogSection section, wallet::FullWallet* full_wallet) {
61 if (section == SECTION_CC_BILLING) {
62 return scoped_ptr<DataModelWrapper>(
63 new FullWalletBillingWrapper(full_wallet));
64 }
65 if (section == SECTION_SHIPPING) {
66 return scoped_ptr<DataModelWrapper>(
67 new FullWalletShippingWrapper(full_wallet));
68 }
69 NOTREACHED();
70 return scoped_ptr<DataModelWrapper>();
71 }
72
73 void FillOutputForSectionWithComparator(
74 DialogSection section, const DetailInputs& inputs,
75 const InputFieldComparator& compare,
76 FormStructure& form_structure, wallet::FullWallet* full_wallet,
77 const base::string16& email_address) {
78
79 // Email is hidden while using Wallet, special case it.
80 if (section == SECTION_EMAIL) {
81 AutofillProfile profile;
82 profile.SetRawInfo(EMAIL_ADDRESS, email_address);
83 AutofillProfileWrapper profile_wrapper(&profile, 0);
84 profile_wrapper.FillFormStructure(inputs, compare, &form_structure);
85 return;
86 }
87
88 scoped_ptr<DataModelWrapper> wrapper = CreateWrapper(section, full_wallet);
89 if (wrapper)
90 wrapper->FillFormStructure(inputs, compare, &form_structure);
91 }
92
93 void FillOutputForSection(
94 DialogSection section,
95 FormStructure& form_structure,
96 wallet::FullWallet* full_wallet,
97 const base::string16& email_address) {
98 DetailInputs inputs;
99 utils::BuildInputsForSection(section, &inputs);
100
101 FillOutputForSectionWithComparator(
102 section, inputs,
103 base::Bind(utils::DetailInputMatchesField, section),
104 form_structure, full_wallet, email_address);
105 }
106
107 } // namespace
108
109 // static
110 base::WeakPtr<AutofillDialogTabManagerDelegate>
111 AutofillDialogTabManagerDelegateAndroid::Create(
112 content::WebContents* contents,
113 const FormData& form_structure,
114 const GURL& source_url,
115 const DialogType dialog_type,
116 const base::Callback<void(const FormStructure*,
117 const std::string&)>& callback) {
118 // AutofillDialogBridgeAndroid owns itself.
119 AutofillDialogTabManagerDelegateAndroid* autofill_dialog_controller =
120 new AutofillDialogTabManagerDelegateAndroid(contents,
121 form_structure,
122 source_url,
123 dialog_type,
124 callback);
125 return autofill_dialog_controller->weak_ptr_factory_.GetWeakPtr();
126 }
127
128 // static
129 void AutofillDialogTabManagerDelegateAndroid::RegisterProfilePrefs(
130 user_prefs::PrefRegistrySyncable* registry) {
131 registry->RegisterDictionaryPref(
132 ::prefs::kAutofillDialogDefaults,
133 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
134 }
135
136 AutofillDialogTabManagerDelegateAndroid::
137 ~AutofillDialogTabManagerDelegateAndroid() {
138 NOTIMPLEMENTED();
139 JNIEnv* env = base::android::AttachCurrentThread();
140 Java_AutofillDialogTabManagerDelegateAndroid_onDestroy(env, java_object_.obj() );
141 }
142
143 void AutofillDialogTabManagerDelegateAndroid::Show() {
144 dialog_shown_timestamp_ = base::Time::Now();
145
146 content::NavigationEntry* entry = contents_->GetController().GetActiveEntry();
147 const GURL& active_url = entry ? entry->GetURL() : contents_->GetURL();
148 invoked_from_same_origin_ = active_url.GetOrigin() == source_url_.GetOrigin();
149
150 // Log any relevant UI metrics and security exceptions.
151 GetMetricLogger().LogDialogUiEvent(
152 GetDialogType(), AutofillMetrics::DIALOG_UI_SHOWN);
153
154 GetMetricLogger().LogDialogSecurityMetric(
155 GetDialogType(), AutofillMetrics::SECURITY_METRIC_DIALOG_SHOWN);
156
157 if (RequestingCreditCardInfo() && !TransmissionWillBeSecure()) {
158 GetMetricLogger().LogDialogSecurityMetric(
159 GetDialogType(),
160 AutofillMetrics::SECURITY_METRIC_CREDIT_CARD_OVER_HTTP);
161 }
162
163 if (!invoked_from_same_origin_) {
164 GetMetricLogger().LogDialogSecurityMetric(
165 GetDialogType(),
166 AutofillMetrics::SECURITY_METRIC_CROSS_ORIGIN_FRAME);
167 }
168
169 // Determine what field types should be included in the dialog.
170 bool has_types = false;
171 bool has_sections = false;
172 form_structure_.ParseFieldTypesFromAutocompleteAttributes(
173 FormStructure::PARSE_FOR_AUTOFILL_DIALOG, &has_types, &has_sections);
174
175 // Fail if the author didn't specify autocomplete types.
176 if (!has_types) {
177 callback_.Run(NULL, std::string());
178 delete this;
179 return;
180 }
181
182 bool request_full_billing_address = false;
183 bool request_shipping_address = false;
184 bool request_phone_numbers = false;
185
186 for (size_t i = 0; i < form_structure_.field_count(); ++i) {
187 const AutofillFieldType type = form_structure_.field(i)->type();
188 if (type == PHONE_HOME_WHOLE_NUMBER || type == PHONE_BILLING_WHOLE_NUMBER) {
189 request_phone_numbers = true;
190 }
191 if (type == NAME_FULL ||
192 type == ADDRESS_HOME_LINE1 || type == ADDRESS_HOME_LINE2 ||
193 type == ADDRESS_HOME_CITY || type == ADDRESS_HOME_STATE ||
194 type == ADDRESS_HOME_ZIP || type == ADDRESS_HOME_COUNTRY ||
195 type == PHONE_HOME_WHOLE_NUMBER) {
196 request_shipping_address = true;
197 }
198 if (type == ADDRESS_BILLING_LINE1 || type == ADDRESS_BILLING_LINE2 ||
199 type == ADDRESS_BILLING_CITY || type == ADDRESS_BILLING_STATE ||
200 type == PHONE_BILLING_WHOLE_NUMBER) {
201 request_full_billing_address = true;
202 }
203 }
204
205 bool last_used_choice_is_autofill = false;
206 base::string16 last_used_account_name;
207 std::string last_used_billing;
208 std::string last_used_shipping;
209 std::string last_used_credit_card;
210 {
211 const base::DictionaryValue* defaults =
212 profile_->GetPrefs()->GetDictionary(::prefs::kAutofillDialogDefaults);
213 if (defaults) {
214 defaults->GetString(kLastUsedAccountName, &last_used_account_name);
215 defaults->GetBoolean(kLastUsedChoiceIsAutofill,
216 &last_used_choice_is_autofill);
217 defaults->GetString(kLastUsedBillingAddressGuid, &last_used_billing);
218 defaults->GetString(kLastUsedShippingAddressGuid, &last_used_shipping);
219 defaults->GetString(kLastUsedCreditCardGuid, &last_used_credit_card);
220 } else {
221 DLOG(ERROR) << "Failed to read AutofillDialog preferences";
222 }
223 }
224
225 if (contents_->GetBrowserContext()->IsOffTheRecord())
226 last_used_choice_is_autofill = true;
227
228 JNIEnv* env = base::android::AttachCurrentThread();
229 ScopedJavaLocalRef<jstring> jlast_used_account_name =
230 base::android::ConvertUTF16ToJavaString(
231 env, last_used_account_name);
232 ScopedJavaLocalRef<jstring> jlast_used_billing =
233 base::android::ConvertUTF8ToJavaString(
234 env, last_used_billing);
235 ScopedJavaLocalRef<jstring> jlast_used_shipping =
236 base::android::ConvertUTF8ToJavaString(
237 env, last_used_shipping);
238 ScopedJavaLocalRef<jstring> jlast_used_card =
239 base::android::ConvertUTF8ToJavaString(
240 env, last_used_credit_card);
241 ScopedJavaLocalRef<jstring> jmerchant_domain =
242 base::android::ConvertUTF8ToJavaString(
243 env, source_url_.GetOrigin().spec());
244 java_object_.Reset(Java_AutofillDialogTabManagerDelegateAndroid_create(
245 env,
246 reinterpret_cast<jint>(this),
247 WindowAndroidHelper::FromWebContents(contents_)->
248 GetWindowAndroid()->GetJavaObject().obj(),
249 request_full_billing_address, request_shipping_address,
250 request_phone_numbers,
251 last_used_choice_is_autofill, jlast_used_account_name.obj(),
252 jlast_used_billing.obj(), jlast_used_shipping.obj(),
253 jlast_used_card.obj(),
254 jmerchant_domain.obj()));
255 }
256
257 void AutofillDialogTabManagerDelegateAndroid::Hide() {
258 NOTIMPLEMENTED();
259 }
260
261 void AutofillDialogTabManagerDelegateAndroid::TabActivated() {
262 NOTIMPLEMENTED();
263 }
264
265 void AutofillDialogTabManagerDelegateAndroid::AddAutocheckoutStep(
266 AutocheckoutStepType step_type) {
267 NOTIMPLEMENTED() << " step_type = " << step_type;
268 }
269
270 void AutofillDialogTabManagerDelegateAndroid::UpdateAutocheckoutStep(
271 AutocheckoutStepType step_type,
272 AutocheckoutStepStatus step_status) {
273 NOTIMPLEMENTED() << " step_type=" << step_type
274 << " step_status=" << step_status;
275 }
276
277 void AutofillDialogTabManagerDelegateAndroid::OnAutocheckoutError() {
278 NOTIMPLEMENTED();
279 DCHECK_EQ(AUTOCHECKOUT_IN_PROGRESS, autocheckout_state_);
280 GetMetricLogger().LogAutocheckoutDuration(
281 base::Time::Now() - autocheckout_started_timestamp_,
282 AutofillMetrics::AUTOCHECKOUT_FAILED);
283 SetAutocheckoutState(AUTOCHECKOUT_ERROR);
284 autocheckout_started_timestamp_ = base::Time();
285 }
286
287 void AutofillDialogTabManagerDelegateAndroid::OnAutocheckoutSuccess() {
288 NOTIMPLEMENTED();
289 DCHECK_EQ(AUTOCHECKOUT_IN_PROGRESS, autocheckout_state_);
290 GetMetricLogger().LogAutocheckoutDuration(
291 base::Time::Now() - autocheckout_started_timestamp_,
292 AutofillMetrics::AUTOCHECKOUT_SUCCEEDED);
293 SetAutocheckoutState(AUTOCHECKOUT_SUCCESS);
294 autocheckout_started_timestamp_ = base::Time();
295 }
296
297 DialogType AutofillDialogTabManagerDelegateAndroid::GetDialogType() const {
298 return dialog_type_;
299 }
300
301 // static
302 bool AutofillDialogTabManagerDelegateAndroid::
303 RegisterAutofillDialogTabManagerDelegateAndroid(JNIEnv* env) {
304 return RegisterNativesImpl(env);
305 }
306
307 void AutofillDialogTabManagerDelegateAndroid::DialogCancel(JNIEnv* env,
308 jobject obj) {
309 // if (autocheckout_state_ == AUTOCHECKOUT_NOT_STARTED && !is_submitting_)
310 // LogOnCancelMetrics();
311 if (autocheckout_state_ == AUTOCHECKOUT_IN_PROGRESS) {
312 GetMetricLogger().LogAutocheckoutDuration(
313 base::Time::Now() - autocheckout_started_timestamp_,
314 AutofillMetrics::AUTOCHECKOUT_CANCELLED);
315 }
316 callback_.Run(NULL, std::string());
317 }
318
319 void AutofillDialogTabManagerDelegateAndroid::DialogContinue(
320 JNIEnv* env,
321 jobject obj,
322 jobject wallet,
323 jboolean jlast_used_choice_is_autofill,
324 jstring jlast_used_account_name,
325 jstring jlast_used_billing,
326 jstring jlast_used_shipping,
327 jstring jlast_used_card) {
328 const string16 email = AutofillDialogResult::GetWalletEmail(env, wallet);
329 const std::string google_transaction_id =
330 AutofillDialogResult::GetWalletGoogleTransactionId(env, wallet);
331
332 const string16 last_used_account_name =
333 base::android::ConvertJavaStringToUTF16(env, jlast_used_account_name);
334 const std::string last_used_billing =
335 base::android::ConvertJavaStringToUTF8(env, jlast_used_billing);
336 const std::string last_used_shipping =
337 base::android::ConvertJavaStringToUTF8(env, jlast_used_shipping);
338 const std::string last_used_card =
339 base::android::ConvertJavaStringToUTF8(env, jlast_used_card);
340
341 scoped_ptr<wallet::FullWallet> full_wallet =
342 AutofillDialogResult::ConvertFromJava(env, wallet);
343 FillOutputForSection(
344 SECTION_EMAIL, form_structure_, full_wallet.get(), email);
345 FillOutputForSection(
346 SECTION_CC_BILLING, form_structure_, full_wallet.get(), email);
347 FillOutputForSection(
348 SECTION_SHIPPING, form_structure_, full_wallet.get(), email);
349
350 {
351 DictionaryPrefUpdate updater(profile_->GetPrefs(),
352 ::prefs::kAutofillDialogDefaults);
353 base::DictionaryValue* defaults = updater.Get();
354 if (defaults) {
355 const bool last_used_choice_is_autofill = !!jlast_used_choice_is_autofill;
356 defaults->SetString(kLastUsedAccountName, last_used_account_name);
357 defaults->SetBoolean(kLastUsedChoiceIsAutofill,
358 last_used_choice_is_autofill);
359 defaults->SetString(kLastUsedBillingAddressGuid, last_used_billing);
360 defaults->SetString(kLastUsedShippingAddressGuid, last_used_shipping);
361 defaults->SetString(kLastUsedCreditCardGuid, last_used_card);
362 } else {
363 LOG(ERROR) << "Failed to save Autofill Dialog preferences";
364 }
365 }
366
367 if (GetDialogType() == DIALOG_TYPE_AUTOCHECKOUT) {
368 autocheckout_started_timestamp_ = base::Time::Now();
369 SetAutocheckoutState(AUTOCHECKOUT_IN_PROGRESS);
370 }
371
372 // LogOnFinishSubmitMetrics();
373
374 // Callback should be called as late as possible.
375 callback_.Run(&form_structure_, google_transaction_id);
376
377 // This might delete us.
378 if (GetDialogType() == DIALOG_TYPE_REQUEST_AUTOCOMPLETE)
379 Hide();
380 }
381
382 AutofillDialogTabManagerDelegateAndroid::
383 AutofillDialogTabManagerDelegateAndroid(
384 content::WebContents* contents,
385 const FormData& form_structure,
386 const GURL& source_url,
387 const DialogType dialog_type,
388 const base::Callback<void(const FormStructure*,
389 const std::string&)>& callback)
390 : profile_(Profile::FromBrowserContext(contents->GetBrowserContext())),
391 contents_(contents),
392 initial_user_state_(AutofillMetrics::DIALOG_USER_STATE_UNKNOWN),
393 dialog_type_(dialog_type),
394 form_structure_(form_structure, std::string()),
395 invoked_from_same_origin_(true),
396 source_url_(source_url),
397 callback_(callback),
398 cares_about_shipping_(true),
399 weak_ptr_factory_(this),
400 autocheckout_state_(AUTOCHECKOUT_NOT_STARTED),
401 was_ui_latency_logged_(false) {
402 DCHECK(!callback_.is_null());
403 }
404
405 bool AutofillDialogTabManagerDelegateAndroid::RequestingCreditCardInfo() const {
406 DCHECK_GT(form_structure_.field_count(), 0U);
407
408 for (size_t i = 0; i < form_structure_.field_count(); ++i) {
409 if (utils::IsCreditCardType(form_structure_.field(i)->type()))
410 return true;
411 }
412
413 return false;
414 }
415
416 bool AutofillDialogTabManagerDelegateAndroid::TransmissionWillBeSecure() const {
417 return source_url_.SchemeIs(chrome::kHttpsScheme);
418 }
419
420 void AutofillDialogTabManagerDelegateAndroid::SetAutocheckoutState(
421 AutocheckoutState autocheckout_state) {
422 if (autocheckout_state_ == autocheckout_state)
423 return;
424
425 autocheckout_state_ = autocheckout_state;
426 // if (view_) {
427 // view_->UpdateDetailArea();
428 // view_->UpdateButtonStrip();
429 // view_->UpdateAutocheckoutStepsArea();
430 // view_->UpdateNotificationArea();
431 // }
432 }
433
434 // static
435 base::WeakPtr<AutofillDialogTabManagerDelegate>
436 AutofillDialogTabManagerDelegate::Create(
437 content::WebContents* contents,
438 const FormData& form_structure,
439 const GURL& source_url,
440 const DialogType dialog_type,
441 const base::Callback<void(const FormStructure*,
442 const std::string&)>& callback) {
443 return AutofillDialogTabManagerDelegateAndroid::Create(
444 contents,
445 form_structure,
446 source_url,
447 dialog_type,
448 callback);
449 }
450
451 // static
452 void AutofillDialogTabManagerDelegate::RegisterProfilePrefs(
453 user_prefs::PrefRegistrySyncable* registry) {
454 AutofillDialogTabManagerDelegateAndroid::RegisterProfilePrefs(registry);
455 }
456
457 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698