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

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

Issue 21205007: [rAc Android] Remove the old dialog implementation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase. 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_view_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/strings/utf_string_conversions.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/ui/android/window_android_helper.h"
14 #include "chrome/browser/ui/autofill/data_model_wrapper.h"
15 #include "components/autofill/core/browser/autofill_profile.h"
16 #include "components/autofill/core/browser/autofill_type.h"
17 #include "components/autofill/core/browser/credit_card.h"
18 #include "content/public/browser/web_contents.h"
19 #include "grit/generated_resources.h"
20 #include "jni/AutofillDialogGlue_jni.h"
21 #include "ui/android/window_android.h"
22 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/base/models/combobox_model.h"
24 #include "ui/base/models/menu_model.h"
25 #include "ui/gfx/android/java_bitmap.h"
26 #include "ui/gfx/rect.h"
27
28 namespace autofill {
29
30 // AutofillDialogView ----------------------------------------------------------
31
32 // static
33 AutofillDialogView* AutofillDialogView::Create(
34 AutofillDialogController* controller) {
35 return new AutofillDialogViewAndroid(controller);
36 }
37
38 // AutofillDialogView ----------------------------------------------------------
39
40 AutofillDialogViewAndroid::AutofillDialogViewAndroid(
41 AutofillDialogController* controller)
42 : controller_(controller) {}
43
44 AutofillDialogViewAndroid::~AutofillDialogViewAndroid() {
45 JNIEnv* env = base::android::AttachCurrentThread();
46 Java_AutofillDialogGlue_onDestroy(env, java_object_.obj());
47 }
48
49 void AutofillDialogViewAndroid::Show() {
50 JNIEnv* env = base::android::AttachCurrentThread();
51 java_object_.Reset(Java_AutofillDialogGlue_create(
52 env,
53 reinterpret_cast<jint>(this),
54 WindowAndroidHelper::FromWebContents(controller_->web_contents())->
55 GetWindowAndroid()->GetJavaObject().obj()));
56 ModelChanged();
57 UpdateNotificationArea();
58 UpdateAccountChooser();
59 }
60
61 void AutofillDialogViewAndroid::Hide() {
62 JNIEnv* env = base::android::AttachCurrentThread();
63 // This will call DialogDismissed(), and that could cause |this| to be
64 // deleted by the |controller|.
65 Java_AutofillDialogGlue_dismissDialog(env, java_object_.obj());
66 }
67
68 void AutofillDialogViewAndroid::UpdateNotificationArea() {
69 JNIEnv* env = base::android::AttachCurrentThread();
70 std::vector<DialogNotification> notifications =
71 controller_->CurrentNotifications();
72 const size_t count = notifications.size();
73 ScopedJavaLocalRef<jobjectArray> notification_array =
74 Java_AutofillDialogGlue_createAutofillDialogNotificationArray(
75 env, count);
76 for (size_t i = 0; i < count; ++i) {
77 ScopedJavaLocalRef<jstring> text =
78 base::android::ConvertUTF16ToJavaString(
79 env, notifications[i].display_text());
80
81 Java_AutofillDialogGlue_addToAutofillDialogNotificationArray(
82 env,
83 notification_array.obj(),
84 i,
85 static_cast<int>(notifications[i].type()),
86 static_cast<int>(notifications[i].GetBackgroundColor()),
87 static_cast<int>(notifications[i].GetTextColor()),
88 notifications[i].HasArrow(),
89 notifications[i].HasCheckbox(),
90 notifications[i].checked(),
91 notifications[i].interactive(),
92 text.obj());
93 }
94
95 Java_AutofillDialogGlue_updateNotificationArea(env,
96 java_object_.obj(),
97 notification_array.obj());
98 }
99
100 void AutofillDialogViewAndroid::UpdateAccountChooser() {
101 JNIEnv* env = base::android::AttachCurrentThread();
102 std::vector<string16> account_names;
103 int selected_account_index = -1;
104
105 ui::MenuModel* model = controller_->MenuModelForAccountChooser();
106 if (controller_->ShouldShowSpinner()) {
107 // Do not show accounts if not yet known.
108 } else if (!model) {
109 // TODO(aruslan): http://crbug.com/177495 Publish Android accounts.
110 account_names.push_back(controller_->AccountChooserText());
111 selected_account_index = 0;
112 } else {
113 for (int i = 0; i < model->GetItemCount(); ++i) {
114 if (model->IsItemCheckedAt(i))
115 selected_account_index = i;
116 account_names.push_back(model->GetLabelAt(i));
117 }
118 }
119
120 ScopedJavaLocalRef<jobjectArray> jaccount_names =
121 base::android::ToJavaArrayOfStrings(env, account_names);
122 Java_AutofillDialogGlue_updateAccountChooser(
123 env, java_object_.obj(), jaccount_names.obj(), selected_account_index);
124 }
125
126 void AutofillDialogViewAndroid::UpdateButtonStrip() {
127 NOTIMPLEMENTED();
128 }
129
130 void AutofillDialogViewAndroid::UpdateDetailArea() {
131 NOTIMPLEMENTED();
132 }
133
134 void AutofillDialogViewAndroid::UpdateForErrors() {
135 NOTIMPLEMENTED();
136 }
137
138 void AutofillDialogViewAndroid::UpdateAutocheckoutStepsArea() {
139 NOTIMPLEMENTED();
140 }
141
142 void AutofillDialogViewAndroid::UpdateSection(DialogSection section) {
143 UpdateOrFillSectionToJava(section, true, UNKNOWN_TYPE);
144 }
145
146 void AutofillDialogViewAndroid::FillSection(
147 DialogSection section,
148 const DetailInput& originating_input) {
149 UpdateOrFillSectionToJava(section, false, originating_input.type);
150 }
151
152 void AutofillDialogViewAndroid::GetUserInput(DialogSection section,
153 DetailOutputMap* output) {
154 GetUserInputImpl(section, output);
155 }
156
157 string16 AutofillDialogViewAndroid::GetCvc() {
158 JNIEnv* env = base::android::AttachCurrentThread();
159 ScopedJavaLocalRef<jstring> cvc =
160 Java_AutofillDialogGlue_getCvc(env, java_object_.obj());
161 return base::android::ConvertJavaStringToUTF16(env, cvc.obj());
162 }
163
164 bool AutofillDialogViewAndroid::SaveDetailsLocally() {
165 JNIEnv* env = base::android::AttachCurrentThread();
166 return Java_AutofillDialogGlue_shouldSaveDetailsLocally(env,
167 java_object_.obj());
168 }
169
170 const content::NavigationController* AutofillDialogViewAndroid::ShowSignIn() {
171 NOTIMPLEMENTED();
172 return NULL;
173 }
174
175 void AutofillDialogViewAndroid::HideSignIn() {
176 NOTIMPLEMENTED();
177 }
178
179 // TODO(aruslan): bind to the automatic sign-in.
180 bool AutofillDialogViewAndroid::StartAutomaticSignIn(
181 const std::string& username) {
182 if (username.empty())
183 return false;
184 JNIEnv* env = base::android::AttachCurrentThread();
185 ScopedJavaLocalRef<jstring> jusername =
186 base::android::ConvertUTF8ToJavaString(env, username);
187 Java_AutofillDialogGlue_startAutomaticSignIn(env, java_object_.obj(),
188 jusername.obj());
189 return true;
190 }
191
192 void AutofillDialogViewAndroid::UpdateProgressBar(double value) {
193 JNIEnv* env = base::android::AttachCurrentThread();
194 Java_AutofillDialogGlue_updateProgressBar(env, java_object_.obj(), value);
195 }
196
197 void AutofillDialogViewAndroid::ModelChanged() {
198 JNIEnv* env = base::android::AttachCurrentThread();
199 Java_AutofillDialogGlue_modelChanged(
200 env, java_object_.obj(),
201 controller_->ShouldShowSpinner());
202 UpdateSection(SECTION_EMAIL);
203 UpdateSection(SECTION_CC);
204 UpdateSection(SECTION_BILLING);
205 UpdateSection(SECTION_CC_BILLING);
206 UpdateSection(SECTION_SHIPPING);
207 }
208
209 void AutofillDialogViewAndroid::OnSignInResize(const gfx::Size& pref_size) {
210 NOTIMPLEMENTED();
211 }
212
213 TestableAutofillDialogView* AutofillDialogViewAndroid::GetTestableView() {
214 return NULL;
215 }
216
217 // TODO(aruslan): bind to the list of accounts population.
218 std::vector<std::string> AutofillDialogViewAndroid::GetAvailableUserAccounts() {
219 std::vector<std::string> account_names;
220 JNIEnv* env = base::android::AttachCurrentThread();
221 ScopedJavaLocalRef<jobjectArray> jaccount_names =
222 Java_AutofillDialogGlue_getUserAccountNames(env, java_object_.obj());
223 base::android::AppendJavaStringArrayToStringVector(
224 env, jaccount_names.obj(), &account_names);
225 return account_names;
226 }
227
228 // Calls from Java to C++
229
230 void AutofillDialogViewAndroid::ItemSelected(JNIEnv* env, jobject obj,
231 jint section, jint index) {
232 ui::MenuModel* menuModel =
233 GetMenuModelForSection(static_cast<DialogSection>(section));
234 if (menuModel)
235 menuModel->ActivatedAt(index);
236 }
237
238 ScopedJavaLocalRef<jobject> AutofillDialogViewAndroid::GetIconForField(
239 JNIEnv* env,
240 jobject obj,
241 jint field_id,
242 jstring jinput) {
243 string16 input = base::android::ConvertJavaStringToUTF16(env, jinput);
244 return GetJavaBitmap(controller_->IconForField(
245 static_cast<AutofillFieldType>(field_id), input));
246 }
247
248 ScopedJavaLocalRef<jstring> AutofillDialogViewAndroid::GetPlaceholderForField(
249 JNIEnv* env,
250 jobject obj,
251 jint section,
252 jint field_id) {
253 if (static_cast<int>(field_id) == CREDIT_CARD_VERIFICATION_CODE) {
254 return base::android::ConvertUTF16ToJavaString(
255 env,
256 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC));
257 }
258 return ScopedJavaLocalRef<jstring>();
259 }
260
261 ScopedJavaLocalRef<jstring> AutofillDialogViewAndroid::GetDialogButtonText(
262 JNIEnv* env,
263 jobject obj,
264 jint dialog_button_id) {
265 switch (static_cast<ui::DialogButton>(dialog_button_id)) {
266 case ui::DIALOG_BUTTON_OK:
267 return base::android::ConvertUTF16ToJavaString(
268 env,
269 controller_->ConfirmButtonText());
270
271 case ui::DIALOG_BUTTON_CANCEL:
272 return base::android::ConvertUTF16ToJavaString(
273 env,
274 controller_->CancelButtonText());
275
276 case ui::DIALOG_BUTTON_NONE:
277 break;
278 }
279
280 NOTREACHED();
281 return ScopedJavaLocalRef<jstring>();
282 }
283
284 jboolean AutofillDialogViewAndroid::IsDialogButtonEnabled(
285 JNIEnv* env,
286 jobject obj,
287 jint dialog_button_id) {
288 return static_cast<jboolean>(
289 controller_->IsDialogButtonEnabled(
290 static_cast<ui::DialogButton>(dialog_button_id)));
291 }
292
293 ScopedJavaLocalRef<jstring> AutofillDialogViewAndroid::GetSaveLocallyText(
294 JNIEnv* env,
295 jobject obj) {
296 return base::android::ConvertUTF16ToJavaString(
297 env,
298 controller_->SaveLocallyText());
299 }
300
301 ScopedJavaLocalRef<jstring> AutofillDialogViewAndroid::GetLegalDocumentsText(
302 JNIEnv* env,
303 jobject obj) {
304 return base::android::ConvertUTF16ToJavaString(
305 env,
306 controller_->LegalDocumentsText());
307 }
308
309 jboolean AutofillDialogViewAndroid::IsTheAddItem(
310 JNIEnv* env,
311 jobject obj,
312 jint section,
313 jint index) {
314 return IsTheAddMenuItem(static_cast<DialogSection>(section),
315 static_cast<int>(index));
316 }
317
318 void AutofillDialogViewAndroid::AccountSelected(JNIEnv* env, jobject obj,
319 jint index) {
320 ui::MenuModel* model = controller_->MenuModelForAccountChooser();
321 if (!model)
322 return;
323
324 model->ActivatedAt(index);
325 }
326
327 void AutofillDialogViewAndroid::NotificationCheckboxStateChanged(
328 JNIEnv* env,
329 jobject obj,
330 jint type,
331 jboolean checked) {
332 controller_->NotificationCheckboxStateChanged(
333 static_cast<DialogNotification::Type>(type),
334 static_cast<bool>(checked));
335 }
336
337 void AutofillDialogViewAndroid::EditingStart(JNIEnv* env, jobject obj,
338 jint jsection) {
339 const DialogSection section = static_cast<DialogSection>(jsection);
340 // TODO(estade): respect |suggestion_state.text_style|.
341 const SuggestionState& suggestion_state =
342 controller_->SuggestionStateForSection(section);
343 if (suggestion_state.text.empty()) {
344 // The section is already in the editing mode, or it's the "Add...".
345 return;
346 }
347
348 controller_->EditClickedForSection(section);
349 UpdateOrFillSectionToJava(section, false, UNKNOWN_TYPE);
350 }
351
352 jboolean AutofillDialogViewAndroid::EditingComplete(JNIEnv* env,
353 jobject obj,
354 jint jsection) {
355 // Unfortunately, edits are not sent to the models, http://crbug.com/223919.
356 const DialogSection section = static_cast<DialogSection>(jsection);
357 if (ValidateSection(section, VALIDATE_FINAL)) {
358 UpdateOrFillSectionToJava(section, false, UNKNOWN_TYPE);
359 return true;
360 }
361
362 return false;
363 }
364
365 void AutofillDialogViewAndroid::EditingCancel(JNIEnv* env,
366 jobject obj,
367 jint jsection) {
368 const DialogSection section = static_cast<DialogSection>(jsection);
369 controller_->EditCancelledForSection(section);
370 UpdateSection(section);
371 }
372
373 void AutofillDialogViewAndroid::EditedOrActivatedField(JNIEnv* env,
374 jobject obj,
375 jint jsection,
376 jint detail_input,
377 jint view_android,
378 jstring value,
379 jboolean was_edit) {
380 const DialogSection section = static_cast<DialogSection>(jsection);
381 DetailInput* input = reinterpret_cast<DetailInput*>(detail_input);
382 ui::ViewAndroid* view = reinterpret_cast<ui::ViewAndroid*>(view_android);
383 gfx::Rect rect = gfx::Rect(0, 0, 0, 0);
384 string16 value16 = base::android::ConvertJavaStringToUTF16(
385 env, value);
386 controller_->UserEditedOrActivatedInput(
387 section, input, view, rect, value16, was_edit);
388 }
389
390 ScopedJavaLocalRef<jstring> AutofillDialogViewAndroid::ValidateField(
391 JNIEnv* env,
392 jobject obj,
393 jint jsection,
394 jint type,
395 jstring value) {
396 string16 field_value = base::android::ConvertJavaStringToUTF16(env, value);
397 const DialogSection section = static_cast<DialogSection>(jsection);
398 AutofillFieldType field_type = static_cast<AutofillFieldType>(type);
399 string16 error_message =
400 controller_->InputValidityMessage(section, field_type, field_value);
401 ScopedJavaLocalRef<jstring> error_text =
402 base::android::ConvertUTF16ToJavaString(env, error_message);
403 return error_text;
404 }
405
406 void AutofillDialogViewAndroid::ValidateSection(JNIEnv* env,
407 jobject obj,
408 jint section) {
409 ValidateSection(static_cast<DialogSection>(section), VALIDATE_EDIT);
410 }
411
412 void AutofillDialogViewAndroid::DialogSubmit(JNIEnv* env, jobject obj) {
413 // TODO(aurimas): add validation step.
414 controller_->OnAccept();
415 }
416
417 void AutofillDialogViewAndroid::DialogCancel(JNIEnv* env, jobject obj) {
418 controller_->OnCancel();
419 Hide();
420 }
421
422 void AutofillDialogViewAndroid::DialogDismissed(JNIEnv* env, jobject obj) {
423 // This might delete |this|, as |this| is owned by the |controller_|.
424 controller_->ViewClosed();
425 }
426
427 ScopedJavaLocalRef<jstring> AutofillDialogViewAndroid::GetLabelForSection(
428 JNIEnv* env,
429 jobject obj,
430 jint section) {
431 string16 label(controller_->LabelForSection(
432 static_cast<DialogSection>(section)));
433 return base::android::ConvertUTF16ToJavaString(env, label);
434 }
435
436 ScopedJavaLocalRef<jobjectArray> AutofillDialogViewAndroid::GetListForField(
437 JNIEnv* env,
438 jobject obj,
439 jint field) {
440 ui::ComboboxModel* model = controller_->ComboboxModelForAutofillType(
441 static_cast<AutofillFieldType>(field));
442 if (!model)
443 return ScopedJavaLocalRef<jobjectArray>();
444
445 std::vector<string16> list(model->GetItemCount());
446 for (int i = 0; i < model->GetItemCount(); ++i) {
447 list[i] = model->GetItemAt(i);
448 }
449 return base::android::ToJavaArrayOfStrings(env, list);
450 }
451
452 void AutofillDialogViewAndroid::ContinueAutomaticSignin(
453 JNIEnv* env, jobject obj,
454 jstring jaccount_name, jstring jsid, jstring jlsid) {
455 const std::string account_name =
456 base::android::ConvertJavaStringToUTF8(env, jaccount_name);
457 const std::string sid =
458 base::android::ConvertJavaStringToUTF8(env, jsid);
459 const std::string lsid =
460 base::android::ConvertJavaStringToUTF8(env, jlsid);
461 // TODO(aruslan): bind to the automatic sign-in.
462 // controller_->ContinueAutomaticSignIn(account_name, sid, lsid);
463 }
464
465 // static
466 bool AutofillDialogViewAndroid::RegisterAutofillDialogViewAndroid(JNIEnv* env) {
467 return RegisterNativesImpl(env);
468 }
469
470 bool AutofillDialogViewAndroid::ValidateSection(DialogSection section,
471 ValidationType type) {
472 DetailOutputMap detail_outputs;
473 GetUserInput(section, &detail_outputs);
474 ValidityData invalid_inputs =
475 controller_->InputsAreValid(section, detail_outputs, type);
476
477 const size_t item_count = invalid_inputs.size();
478 if (item_count == 0) return true;
479
480 JNIEnv* env = base::android::AttachCurrentThread();
481 ScopedJavaLocalRef<jobjectArray> error_array =
482 Java_AutofillDialogGlue_createAutofillDialogFieldError(env, item_count);
483 size_t i = 0;
484 for (ValidityData::const_iterator iter =
485 invalid_inputs.begin(); iter != invalid_inputs.end(); ++iter, ++i) {
486 ScopedJavaLocalRef<jstring> error_text =
487 base::android::ConvertUTF16ToJavaString(env, iter->second);
488 Java_AutofillDialogGlue_addToAutofillDialogFieldErrorArray(
489 env, error_array.obj(), i, iter->first, error_text.obj());
490 }
491 Java_AutofillDialogGlue_updateSectionErrors(env,
492 java_object_.obj(),
493 section,
494 error_array.obj());
495 return false;
496 }
497
498 void AutofillDialogViewAndroid::UpdateSaveLocallyCheckBox() {
499 JNIEnv* env = base::android::AttachCurrentThread();
500 Java_AutofillDialogGlue_updateSaveLocallyCheckBox(
501 env, java_object_.obj(), controller_->ShouldOfferToSaveInChrome());
502 }
503
504 void AutofillDialogViewAndroid::UpdateOrFillSectionToJava(
505 DialogSection section,
506 bool clobber_inputs,
507 int field_type_to_always_clobber) {
508 JNIEnv* env = base::android::AttachCurrentThread();
509 const DetailInputs& updated_inputs =
510 controller_->RequestedFieldsForSection(section);
511
512 const size_t input_count = updated_inputs.size();
513 ScopedJavaLocalRef<jobjectArray> field_array =
514 Java_AutofillDialogGlue_createAutofillDialogFieldArray(
515 env, input_count);
516
517 for (size_t i = 0; i < input_count; ++i) {
518 const DetailInput& input = updated_inputs[i];
519
520 ScopedJavaLocalRef<jstring> autofilled =
521 base::android::ConvertUTF16ToJavaString(env, input.initial_value);
522
523 string16 placeholder16;
524 if (input.placeholder_text_rid > 0)
525 placeholder16 = l10n_util::GetStringUTF16(input.placeholder_text_rid);
526 ScopedJavaLocalRef<jstring> placeholder =
527 base::android::ConvertUTF16ToJavaString(env, placeholder16);
528
529 Java_AutofillDialogGlue_addToAutofillDialogFieldArray(
530 env,
531 field_array.obj(),
532 i,
533 reinterpret_cast<jint>(&input),
534 input.type,
535 placeholder.obj(),
536 autofilled.obj());
537 }
538
539 ui::MenuModel* menu_model = GetMenuModelForSection(section);
540 const int item_count = menu_model->GetItemCount();
541
542 // Never show the "Manage..." item.
543 // TODO(aruslan): fix this once we have UI design http://crbug.com/235639.
544 const int jitem_count = item_count >= 1 ? item_count - 1 : 0;
545
546 ScopedJavaLocalRef<jobjectArray> menu_array =
547 Java_AutofillDialogGlue_createAutofillDialogMenuItemArray(env,
548 jitem_count);
549 const int selected_item = GetSelectedItemIndexForSection(section);
550
551 for (int i = 0; i < jitem_count; ++i) {
552 const MenuItemButtonType button_type = GetMenuItemButtonType(section, i);
553 string16 line1_value = menu_model->GetLabelAt(i);
554 string16 line2_value = menu_model->GetSublabelAt(i);
555 gfx::Image icon_value;
556 menu_model->GetIconAt(i, &icon_value);
557
558 if (i == selected_item) {
559 CollapseUserDataIntoMenuItem(section,
560 &line1_value, &line2_value,
561 &icon_value);
562 }
563
564 ScopedJavaLocalRef<jstring> line1 =
565 base::android::ConvertUTF16ToJavaString(env, line1_value);
566 ScopedJavaLocalRef<jstring> line2 =
567 base::android::ConvertUTF16ToJavaString(env, line2_value);
568 ScopedJavaLocalRef<jobject> icon = GetJavaBitmap(icon_value);
569
570 Java_AutofillDialogGlue_addToAutofillDialogMenuItemArray(
571 env, menu_array.obj(), i,
572 line1.obj(), line2.obj(), icon.obj(),
573 static_cast<int>(button_type));
574 }
575
576 const SuggestionState& suggestion_state =
577 controller_->SuggestionStateForSection(section);
578 ScopedJavaLocalRef<jstring> suggestion_text =
579 base::android::ConvertUTF16ToJavaString(env, suggestion_state.text);
580 ScopedJavaLocalRef<jstring> suggestion_text_extra =
581 base::android::ConvertUTF16ToJavaString(env, suggestion_state.extra_text);
582 ScopedJavaLocalRef<jobject> suggestion_icon =
583 GetJavaBitmap(suggestion_state.icon);
584 ScopedJavaLocalRef<jobject> suggestion_icon_extra =
585 GetJavaBitmap(suggestion_state.extra_icon);
586
587 Java_AutofillDialogGlue_updateSection(env,
588 java_object_.obj(),
589 section,
590 controller_->SectionIsActive(section),
591 field_array.obj(),
592 suggestion_text.obj(),
593 suggestion_icon.obj(),
594 suggestion_text_extra.obj(),
595 suggestion_icon_extra.obj(),
596 menu_array.obj(),
597 selected_item,
598 clobber_inputs,
599 field_type_to_always_clobber);
600
601 UpdateSaveLocallyCheckBox();
602 }
603
604 void AutofillDialogViewAndroid::GetUserInputImpl(
605 DialogSection section,
606 DetailOutputMap* output) const {
607 JNIEnv* env = base::android::AttachCurrentThread();
608 ScopedJavaLocalRef<jobjectArray> fields =
609 Java_AutofillDialogGlue_getSection(env, java_object_.obj(), section);
610 if (fields.is_null())
611 return;
612
613 const int arrayLength = env->GetArrayLength(fields.obj());
614 for (int i = 0; i < arrayLength; ++i) {
615 ScopedJavaLocalRef<jobject> field(
616 env, env->GetObjectArrayElement(fields.obj(), i));
617 DetailInput* input = reinterpret_cast<DetailInput*>(
618 Java_AutofillDialogGlue_getFieldNativePointer(env, field.obj()));
619 string16 value = base::android::ConvertJavaStringToUTF16(
620 env, Java_AutofillDialogGlue_getFieldValue(env, field.obj()).obj());
621 output->insert(std::make_pair(input, value));
622 }
623 }
624
625 ui::MenuModel* AutofillDialogViewAndroid::GetMenuModelForSection(
626 DialogSection section) const {
627 // TODO(aruslan/estade): This should use MenuModelForSectionHack(), which
628 // never returns NULL. Later the controller should return a proper platform-
629 // specific menu model to match the platform UI flow (or it shouldn't attempt
630 // to control the presentation details).
631 return controller_->MenuModelForSectionHack(section);
632 }
633
634 // Returns the index of the currently selected item in |section|, or -1.
635 int AutofillDialogViewAndroid::GetSelectedItemIndexForSection(
636 DialogSection section) const {
637 ui::MenuModel* menuModel = GetMenuModelForSection(section);
638 if (!menuModel) return -1;
639
640 for (int i = 0; i < menuModel->GetItemCount(); ++i) {
641 if (menuModel->IsItemCheckedAt(i))
642 return i;
643 }
644
645 return -1;
646 }
647
648 // Returns true if the item at |index| in |section| is the "Add...".
649 bool AutofillDialogViewAndroid::IsTheAddMenuItem(
650 DialogSection section, int index) const {
651 ui::MenuModel* menuModel = GetMenuModelForSection(section);
652 return menuModel && index == menuModel->GetItemCount() - 2;
653 }
654
655 // Returns true if the item at |index| in |section| is the "Manage...".
656 bool AutofillDialogViewAndroid::IsTheManageMenuItem(
657 DialogSection section, int index) const {
658 ui::MenuModel* menuModel = GetMenuModelForSection(section);
659 return menuModel && index == menuModel->GetItemCount() - 1;
660 }
661
662 // Returns an |image| converted to a Java image, or null if |image| is empty.
663 ScopedJavaLocalRef<jobject> AutofillDialogViewAndroid::GetJavaBitmap(
664 const gfx::Image& image) const {
665 ScopedJavaLocalRef<jobject> bitmap;
666 const SkBitmap& sk_bitmap = image.AsBitmap();
667 if (!sk_bitmap.isNull() && sk_bitmap.bytesPerPixel() != 0)
668 bitmap = gfx::ConvertToJavaBitmap(&sk_bitmap);
669 return bitmap;
670 }
671
672 // Returns a MenuItemButtonType for a menu item at |index| in |section|.
673 AutofillDialogViewAndroid::MBT AutofillDialogViewAndroid::GetMenuItemButtonType(
674 DialogSection section,
675 int index) const {
676 // TODO(aruslan): Remove/fix this once http://crbug.com/224162 is closed.
677 ui::MenuModel* menu_model = GetMenuModelForSection(section);
678 if (!menu_model)
679 return MENU_ITEM_BUTTON_TYPE_NONE;
680
681 // "Use billing for shipping" is not editable and it's always first.
682 if (section == SECTION_SHIPPING && index == 0)
683 return MENU_ITEM_BUTTON_TYPE_NONE;
684
685 // The last item ("Manage...") is never editable.
686 if (IsTheManageMenuItem(section, index))
687 return MENU_ITEM_BUTTON_TYPE_NONE;
688
689 // The second last item ("Add..."):
690 if (IsTheAddMenuItem(section, index)) {
691 const bool currently_selected =
692 index == GetSelectedItemIndexForSection(section);
693 // - should show "Add..." button if not selected;
694 if (!currently_selected)
695 return MENU_ITEM_BUTTON_TYPE_ADD;
696
697 // - should show "Add..." button if selected and doesn't have user data;
698 string16 label, sublabel;
699 gfx::Image icon;
700 const bool has_user_data =
701 CollapseUserDataIntoMenuItem(section, &label, &sublabel, &icon);
702 if (!has_user_data)
703 return MENU_ITEM_BUTTON_TYPE_ADD;
704
705 // - otherwise, should show the "Edit..." button (as any "normal" items).
706 }
707
708 return MENU_ITEM_BUTTON_TYPE_EDIT;
709 }
710
711 // TODO(aruslan): Remove/fix this once http://crbug.com/230685 is closed.
712 namespace {
713
714 bool IsCreditCardType(AutofillFieldType type) {
715 return AutofillType(type).group() == AutofillType::CREDIT_CARD;
716 }
717
718 class CollapsedAutofillProfileWrapper : public AutofillProfileWrapper {
719 public:
720 explicit CollapsedAutofillProfileWrapper(const AutofillProfile* profile)
721 : AutofillProfileWrapper(profile, 0) {
722 }
723 virtual ~CollapsedAutofillProfileWrapper() {
724 }
725
726 virtual string16 GetDisplayText() OVERRIDE {
727 const string16 name_full = GetInfo(NAME_FULL);
728 const string16 comma = ASCIIToUTF16(", ");
729 const string16 address2 = GetInfo(ADDRESS_HOME_LINE2);
730
731 string16 label;
732 if (!name_full.empty())
733 label = name_full + comma;
734 label += GetInfo(ADDRESS_HOME_LINE1);
735 if (!address2.empty())
736 label += comma + address2;
737 return label;
738 }
739
740 string16 GetSublabel() {
741 const string16 comma = ASCIIToUTF16(", ");
742 return
743 GetInfo(ADDRESS_HOME_CITY) + comma +
744 GetInfo(ADDRESS_HOME_STATE) + ASCIIToUTF16(" ") +
745 GetInfo(ADDRESS_HOME_ZIP);
746 }
747
748 private:
749 DISALLOW_COPY_AND_ASSIGN(CollapsedAutofillProfileWrapper);
750 };
751
752
753 // Get billing info from |output| and put it into |card|, |cvc|, and |profile|.
754 // These outparams are required because |card|/|profile| accept different types
755 // of raw info.
756 void GetBillingInfoFromOutputs(const DetailOutputMap& output,
757 CreditCard* card,
758 AutofillProfile* profile) {
759 for (DetailOutputMap::const_iterator it = output.begin();
760 it != output.end(); ++it) {
761 string16 trimmed;
762 TrimWhitespace(it->second, TRIM_ALL, &trimmed);
763
764 if (it->first->type == ADDRESS_HOME_COUNTRY ||
765 it->first->type == ADDRESS_BILLING_COUNTRY) {
766 profile->SetInfo(it->first->type,
767 trimmed,
768 g_browser_process->GetApplicationLocale());
769 } else {
770 // Copy the credit card name to |profile| in addition to |card| as
771 // wallet::Instrument requires a recipient name for its billing address.
772 if (profile && it->first->type == CREDIT_CARD_NAME)
773 profile->SetRawInfo(NAME_FULL, trimmed);
774
775 if (IsCreditCardType(it->first->type)) {
776 if (card)
777 card->SetRawInfo(it->first->type, trimmed);
778 } else if (profile) {
779 profile->SetRawInfo(it->first->type, trimmed);
780 }
781 }
782 }
783 }
784
785 } // namespace
786
787 // Returns true and fills in the |label|, |sublabel| and |icon if
788 // a given |section| has the user input.
789 // TODO(aruslan): Remove/fix this once http://crbug.com/230685 is closed.
790 bool AutofillDialogViewAndroid::CollapseUserDataIntoMenuItem(
791 DialogSection section,
792 string16* label_to_set,
793 string16* sublabel_to_set,
794 gfx::Image* icon_to_set) const {
795 const SuggestionState& suggestion_state =
796 controller_->SuggestionStateForSection(section);
797 if (!suggestion_state.text.empty())
798 return false;
799
800 DetailOutputMap inputs;
801 GetUserInputImpl(section, &inputs);
802
803 string16 label;
804 string16 sublabel;
805 gfx::Image icon;
806
807 switch (section) {
808 case SECTION_CC: {
809 CreditCard card;
810 GetBillingInfoFromOutputs(inputs, &card, NULL);
811 AutofillCreditCardWrapper ccw(&card);
812 label = card.Label();
813 icon = ccw.GetIcon();
814 break;
815 }
816
817 case SECTION_BILLING: {
818 AutofillProfile profile;
819 GetBillingInfoFromOutputs(inputs, NULL, &profile);
820 CollapsedAutofillProfileWrapper pw(&profile);
821 label = pw.GetDisplayText();
822 sublabel = pw.GetSublabel();
823 break;
824 }
825
826 case SECTION_CC_BILLING: {
827 CreditCard card;
828 AutofillProfile profile;
829 GetBillingInfoFromOutputs(inputs, &card, &profile);
830 AutofillCreditCardWrapper ccw(&card);
831 CollapsedAutofillProfileWrapper pw(&profile);
832 label = ccw.GetDisplayText();
833 sublabel = pw.GetDisplayText();
834 icon = ccw.GetIcon();
835 break;
836 }
837
838 case SECTION_SHIPPING: {
839 AutofillProfile profile;
840 GetBillingInfoFromOutputs(inputs, NULL, &profile);
841 CollapsedAutofillProfileWrapper pw(&profile);
842 label = pw.GetDisplayText();
843 sublabel = pw.GetSublabel();
844 break;
845 }
846
847 case SECTION_EMAIL: {
848 for (DetailOutputMap::const_iterator iter = inputs.begin();
849 iter != inputs.end(); ++iter) {
850 if (iter->first->type == EMAIL_ADDRESS)
851 label = iter->second;
852 }
853 break;
854 }
855 }
856
857 if (label.empty())
858 return false;
859
860 *label_to_set = label;
861 *sublabel_to_set = sublabel;
862 *icon_to_set = icon;
863 return true;
864 }
865 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698