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.
5 #include "chrome/browser/ui/android/autofill/autofill_dialog_view_android.h"
6 #include "base/android/jni_android.h"
7 #include "base/android/jni_array.h"
8 #include "base/android/jni_string.h"
9 #include "base/android/scoped_java_ref.h"
10 #include "base/utf_string_conversions.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/ui/android/window_android_helper.h"
13 #include "chrome/browser/ui/autofill/data_model_wrapper.h"
14 #include "components/autofill/browser/autofill_profile.h"
15 #include "components/autofill/browser/autofill_type.h"
16 #include "components/autofill/browser/credit_card.h"
17 #include "content/public/browser/web_contents.h"
18 #include "grit/generated_resources.h"
19 #include "jni/AutofillDialogGlue_jni.h"
20 #include "ui/android/window_android.h"
21 #include "ui/base/l10n/l10n_util.h"
22 #include "ui/base/models/combobox_model.h"
23 #include "ui/base/models/menu_model.h"
24 #include "ui/gfx/android/java_bitmap.h"
28 // AutofillDialogView ----------------------------------------------------------
31 AutofillDialogView
* AutofillDialogView::Create(
32 AutofillDialogController
* controller
) {
33 return new AutofillDialogViewAndroid(controller
);
36 // AutofillDialogView ----------------------------------------------------------
38 AutofillDialogViewAndroid::AutofillDialogViewAndroid(
39 AutofillDialogController
* controller
)
40 : controller_(controller
) {}
42 AutofillDialogViewAndroid::~AutofillDialogViewAndroid() {
43 JNIEnv
* env
= base::android::AttachCurrentThread();
44 Java_AutofillDialogGlue_onDestroy(env
, java_object_
.obj());
47 void AutofillDialogViewAndroid::Show() {
48 JNIEnv
* env
= base::android::AttachCurrentThread();
49 java_object_
.Reset(Java_AutofillDialogGlue_create(
51 reinterpret_cast<jint
>(this),
52 WindowAndroidHelper::FromWebContents(controller_
->web_contents())->
53 GetWindowAndroid()->GetJavaObject().obj()));
55 UpdateNotificationArea();
56 UpdateAccountChooser();
59 void AutofillDialogViewAndroid::Hide() {
60 JNIEnv
* env
= base::android::AttachCurrentThread();
61 // This will call DialogDismissed(), and that could cause |this| to be
62 // deleted by the |controller|.
63 Java_AutofillDialogGlue_dismissDialog(env
, java_object_
.obj());
66 void AutofillDialogViewAndroid::UpdateNotificationArea() {
67 JNIEnv
* env
= base::android::AttachCurrentThread();
68 std::vector
<DialogNotification
> notifications
=
69 controller_
->CurrentNotifications();
70 const size_t count
= notifications
.size();
71 ScopedJavaLocalRef
<jobjectArray
> notification_array
=
72 Java_AutofillDialogGlue_createAutofillDialogNotificationArray(
74 for (size_t i
= 0; i
< count
; ++i
) {
75 ScopedJavaLocalRef
<jstring
> text
=
76 base::android::ConvertUTF16ToJavaString(
77 env
, notifications
[i
].display_text());
79 Java_AutofillDialogGlue_addToAutofillDialogNotificationArray(
81 notification_array
.obj(),
83 static_cast<int>(notifications
[i
].GetBackgroundColor()),
84 static_cast<int>(notifications
[i
].GetTextColor()),
85 notifications
[i
].HasArrow(),
86 notifications
[i
].HasCheckbox(),
90 Java_AutofillDialogGlue_updateNotificationArea(env
,
92 notification_array
.obj());
95 void AutofillDialogViewAndroid::UpdateAccountChooser() {
96 JNIEnv
* env
= base::android::AttachCurrentThread();
97 std::vector
<string16
> account_names
;
98 int selected_account_index
= -1;
100 ui::MenuModel
* model
= controller_
->MenuModelForAccountChooser();
101 if (!model
|| controller_
->ShouldShowSpinner()) {
102 account_names
.push_back(controller_
->AccountChooserText());
103 selected_account_index
= 0;
105 for (int i
= 0; i
< model
->GetItemCount(); ++i
) {
106 if (model
->IsItemCheckedAt(i
))
107 selected_account_index
= i
;
108 account_names
.push_back(model
->GetLabelAt(i
));
112 ScopedJavaLocalRef
<jobjectArray
> jaccount_names
=
113 base::android::ToJavaArrayOfStrings(env
, account_names
);
114 Java_AutofillDialogGlue_updateAccountChooser(
115 env
, java_object_
.obj(), jaccount_names
.obj(), selected_account_index
);
118 void AutofillDialogViewAndroid::UpdateButtonStrip() {
122 void AutofillDialogViewAndroid::UpdateSection(DialogSection section
) {
123 UpdateOrFillSectionToJava(section
, true, UNKNOWN_TYPE
);
126 void AutofillDialogViewAndroid::FillSection(
127 DialogSection section
,
128 const DetailInput
& originating_input
) {
129 UpdateOrFillSectionToJava(section
, false, originating_input
.type
);
132 void AutofillDialogViewAndroid::GetUserInput(DialogSection section
,
133 DetailOutputMap
* output
) {
134 JNIEnv
* env
= base::android::AttachCurrentThread();
135 ScopedJavaLocalRef
<jobjectArray
> fields
=
136 Java_AutofillDialogGlue_getSection(env
, java_object_
.obj(), section
);
137 if (fields
.is_null())
140 const int arrayLength
= env
->GetArrayLength(fields
.obj());
141 for (int i
= 0; i
< arrayLength
; ++i
) {
142 ScopedJavaLocalRef
<jobject
> field(
143 env
, env
->GetObjectArrayElement(fields
.obj(), i
));
144 DetailInput
* input
= reinterpret_cast<DetailInput
*>(
145 Java_AutofillDialogGlue_getFieldNativePointer(env
, field
.obj()));
146 string16 value
= base::android::ConvertJavaStringToUTF16(
147 env
, Java_AutofillDialogGlue_getFieldValue(env
, field
.obj()).obj());
148 output
->insert(std::make_pair(input
, value
));
152 string16
AutofillDialogViewAndroid::GetCvc() {
153 JNIEnv
* env
= base::android::AttachCurrentThread();
154 ScopedJavaLocalRef
<jstring
> cvc
=
155 Java_AutofillDialogGlue_getCvc(env
, java_object_
.obj());
156 return base::android::ConvertJavaStringToUTF16(env
, cvc
.obj());
159 bool AutofillDialogViewAndroid::SaveDetailsLocally() {
160 JNIEnv
* env
= base::android::AttachCurrentThread();
161 return Java_AutofillDialogGlue_shouldSaveDetailsLocally(env
,
165 const content::NavigationController
* AutofillDialogViewAndroid::ShowSignIn() {
170 void AutofillDialogViewAndroid::HideSignIn() {
174 // TODO(aruslan): bind to the automatic sign-in.
175 bool AutofillDialogViewAndroid::StartAutomaticSignIn(
176 const std::string
& username
) {
177 if (username
.empty())
179 JNIEnv
* env
= base::android::AttachCurrentThread();
180 ScopedJavaLocalRef
<jstring
> jusername
=
181 base::android::ConvertUTF8ToJavaString(env
, username
);
182 Java_AutofillDialogGlue_startAutomaticSignIn(env
, java_object_
.obj(),
187 void AutofillDialogViewAndroid::UpdateProgressBar(double value
) {
188 JNIEnv
* env
= base::android::AttachCurrentThread();
189 Java_AutofillDialogGlue_updateProgressBar(env
, java_object_
.obj(), value
);
192 void AutofillDialogViewAndroid::ModelChanged() {
193 JNIEnv
* env
= base::android::AttachCurrentThread();
194 Java_AutofillDialogGlue_modelChanged(
195 env
, java_object_
.obj(),
196 controller_
->ShouldShowSpinner());
197 UpdateSaveLocallyCheckBox();
198 UpdateSection(SECTION_EMAIL
);
199 UpdateSection(SECTION_CC
);
200 UpdateSection(SECTION_BILLING
);
201 UpdateSection(SECTION_CC_BILLING
);
202 UpdateSection(SECTION_SHIPPING
);
205 // TODO(aruslan): bind to the list of accounts population.
206 std::vector
<std::string
> AutofillDialogViewAndroid::GetAvailableUserAccounts() {
207 std::vector
<std::string
> account_names
;
208 JNIEnv
* env
= base::android::AttachCurrentThread();
209 ScopedJavaLocalRef
<jobjectArray
> jaccount_names
=
210 Java_AutofillDialogGlue_getUserAccountNames(env
, java_object_
.obj());
211 base::android::AppendJavaStringArrayToStringVector(
212 env
, jaccount_names
.obj(), &account_names
);
213 return account_names
;
216 // Calls from Java to C++
218 void AutofillDialogViewAndroid::ItemSelected(JNIEnv
* env
, jobject obj
,
219 jint section
, jint index
) {
220 ui::MenuModel
* menuModel
=
221 controller_
->MenuModelForSection(static_cast<DialogSection
>(section
));
222 menuModel
->ActivatedAt(index
);
225 ScopedJavaLocalRef
<jobject
> AutofillDialogViewAndroid::GetIconForField(
230 string16 input
= base::android::ConvertJavaStringToUTF16(env
, jinput
);
231 gfx::Image icon
= controller_
->
232 IconForField(static_cast<AutofillFieldType
>(field_id
), input
);
233 const SkBitmap
& sk_icon
= icon
.AsBitmap();
234 return gfx::ConvertToJavaBitmap(&sk_icon
);
237 ScopedJavaLocalRef
<jstring
> AutofillDialogViewAndroid::GetPlaceholderForField(
242 if (static_cast<int>(field_id
) == CREDIT_CARD_VERIFICATION_CODE
) {
243 return base::android::ConvertUTF16ToJavaString(
245 l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_CVC
));
247 return ScopedJavaLocalRef
<jstring
>();
250 ScopedJavaLocalRef
<jstring
> AutofillDialogViewAndroid::GetDialogButtonText(
253 jint dialog_button_id
) {
254 switch (static_cast<ui::DialogButton
>(dialog_button_id
)) {
255 case ui::DIALOG_BUTTON_OK
:
256 return base::android::ConvertUTF16ToJavaString(
258 controller_
->ConfirmButtonText());
260 case ui::DIALOG_BUTTON_CANCEL
:
261 return base::android::ConvertUTF16ToJavaString(
263 controller_
->CancelButtonText());
265 case ui::DIALOG_BUTTON_NONE
:
270 return ScopedJavaLocalRef
<jstring
>();
273 jboolean
AutofillDialogViewAndroid::IsDialogButtonEnabled(
276 jint dialog_button_id
) {
277 return static_cast<jboolean
>(
278 controller_
->IsDialogButtonEnabled(
279 static_cast<ui::DialogButton
>(dialog_button_id
)));
282 ScopedJavaLocalRef
<jstring
> AutofillDialogViewAndroid::GetSaveLocallyText(
285 return base::android::ConvertUTF16ToJavaString(
287 controller_
->SaveLocallyText());
290 ScopedJavaLocalRef
<jstring
> AutofillDialogViewAndroid::GetProgressBarText(
293 return base::android::ConvertUTF16ToJavaString(
295 controller_
->ProgressBarText());
298 void AutofillDialogViewAndroid::AccountSelected(JNIEnv
* env
, jobject obj
,
300 ui::MenuModel
* model
= controller_
->MenuModelForAccountChooser();
304 model
->ActivatedAt(index
);
307 void AutofillDialogViewAndroid::EditingStart(JNIEnv
* env
, jobject obj
,
309 const DialogSection section
= static_cast<DialogSection
>(jsection
);
310 // TODO(estade): respect |suggestion_state.text_style|.
311 const SuggestionState
& suggestion_state
=
312 controller_
->SuggestionStateForSection(section
);
313 if (suggestion_state
.text
.empty()) {
314 // The section is already in the editing mode, or it's the "Add...".
318 controller_
->EditClickedForSection(section
);
321 jboolean
AutofillDialogViewAndroid::EditingComplete(JNIEnv
* env
,
324 // Unfortunately, edits are not sent to the models, http://crbug.com/223919.
325 const DialogSection section
= static_cast<DialogSection
>(jsection
);
326 if (ValidateSection(section
, AutofillDialogController::VALIDATE_FINAL
)) {
327 UpdateOrFillSectionToJava(section
, false, UNKNOWN_TYPE
);
334 void AutofillDialogViewAndroid::EditingCancel(JNIEnv
* env
,
337 const DialogSection section
= static_cast<DialogSection
>(jsection
);
338 controller_
->EditCancelledForSection(section
);
339 UpdateSection(section
);
342 ScopedJavaLocalRef
<jstring
> AutofillDialogViewAndroid::ValidateField(
347 string16 field_value
= base::android::ConvertJavaStringToUTF16(env
, value
);
348 AutofillFieldType field_type
= static_cast<AutofillFieldType
>(type
);
349 if (controller_
->InputIsValid(field_type
, field_value
)) {
350 return ScopedJavaLocalRef
<jstring
>();
352 // TODO(aurimas) Start using real error strings.
353 string16 error
= ASCIIToUTF16("Error");
354 ScopedJavaLocalRef
<jstring
> error_text
=
355 base::android::ConvertUTF16ToJavaString(env
, error
);
360 void AutofillDialogViewAndroid::ValidateSection(JNIEnv
* env
,
363 ValidateSection(static_cast<DialogSection
>(section
),
364 AutofillDialogController::VALIDATE_EDIT
);
367 void AutofillDialogViewAndroid::DialogSubmit(JNIEnv
* env
, jobject obj
) {
368 // TODO(aurimas): add validation step.
369 controller_
->OnAccept();
372 void AutofillDialogViewAndroid::DialogCancel(JNIEnv
* env
, jobject obj
) {
373 controller_
->OnCancel();
377 void AutofillDialogViewAndroid::DialogDismissed(JNIEnv
* env
, jobject obj
) {
378 // This might delete |this|, as |this| is owned by the |controller_|.
379 controller_
->ViewClosed();
382 ScopedJavaLocalRef
<jstring
> AutofillDialogViewAndroid::GetLabelForSection(
386 string16
label(controller_
->LabelForSection(
387 static_cast<DialogSection
>(section
)));
388 return base::android::ConvertUTF16ToJavaString(env
, label
);
391 ScopedJavaLocalRef
<jobjectArray
> AutofillDialogViewAndroid::GetListForField(
395 ui::ComboboxModel
* model
= controller_
->ComboboxModelForAutofillType(
396 static_cast<AutofillFieldType
>(field
));
398 return ScopedJavaLocalRef
<jobjectArray
>();
400 std::vector
<string16
> list(model
->GetItemCount());
401 for (int i
= 0; i
< model
->GetItemCount(); ++i
) {
402 list
[i
] = model
->GetItemAt(i
);
404 return base::android::ToJavaArrayOfStrings(env
, list
);
407 void AutofillDialogViewAndroid::ContinueAutomaticSignin(
408 JNIEnv
* env
, jobject obj
,
409 jstring jaccount_name
, jstring jsid
, jstring jlsid
) {
410 const std::string account_name
=
411 base::android::ConvertJavaStringToUTF8(env
, jaccount_name
);
412 const std::string sid
=
413 base::android::ConvertJavaStringToUTF8(env
, jsid
);
414 const std::string lsid
=
415 base::android::ConvertJavaStringToUTF8(env
, jlsid
);
416 // TODO(aruslan): bind to the automatic sign-in.
417 // controller_->ContinueAutomaticSignIn(account_name, sid, lsid);
421 bool AutofillDialogViewAndroid::RegisterAutofillDialogViewAndroid(JNIEnv
* env
) {
422 return RegisterNativesImpl(env
);
425 bool AutofillDialogViewAndroid::ValidateSection(
426 DialogSection section
, AutofillDialogController::ValidationType type
) {
427 DetailOutputMap detail_outputs
;
428 GetUserInput(section
, &detail_outputs
);
429 std::vector
<AutofillFieldType
> invalid_inputs
= controller_
->InputsAreValid(
430 detail_outputs
, type
);
432 const size_t item_count
= invalid_inputs
.size();
433 if (item_count
== 0) return true;
435 JNIEnv
* env
= base::android::AttachCurrentThread();
436 ScopedJavaLocalRef
<jobjectArray
> error_array
=
437 Java_AutofillDialogGlue_createAutofillDialogFieldError(env
, item_count
);
438 for (size_t i
= 0; i
< item_count
; ++i
) {
439 // TODO(aurimas) Start using real error strings.
440 string16 error
= ASCIIToUTF16("Error");
441 ScopedJavaLocalRef
<jstring
> error_text
=
442 base::android::ConvertUTF16ToJavaString(env
, error
);
443 Java_AutofillDialogGlue_addToAutofillDialogFieldErrorArray(
444 env
, error_array
.obj(), i
, invalid_inputs
[i
], error_text
.obj());
446 Java_AutofillDialogGlue_updateSectionErrors(env
,
453 void AutofillDialogViewAndroid::UpdateSaveLocallyCheckBox() {
454 // TODO(aruslan) : Call this when at least one section is being edited.
455 JNIEnv
* env
= base::android::AttachCurrentThread();
456 Java_AutofillDialogGlue_updateSaveLocallyCheckBox(
457 env
, java_object_
.obj(), controller_
->ShouldOfferToSaveInChrome());
460 void AutofillDialogViewAndroid::UpdateOrFillSectionToJava(
461 DialogSection section
,
463 int field_type_to_always_clobber
) {
464 JNIEnv
* env
= base::android::AttachCurrentThread();
465 const DetailInputs
& updated_inputs
=
466 controller_
->RequestedFieldsForSection(section
);
468 const size_t inputCount
= updated_inputs
.size();
469 ScopedJavaLocalRef
<jobjectArray
> field_array
=
470 Java_AutofillDialogGlue_createAutofillDialogFieldArray(
473 for (size_t i
= 0; i
< inputCount
; ++i
) {
474 const DetailInput
& input
= updated_inputs
[i
];
476 ScopedJavaLocalRef
<jstring
> autofilled
=
477 base::android::ConvertUTF16ToJavaString(env
, input
.initial_value
);
479 string16 placeholder16
;
480 if (input
.placeholder_text_rid
> 0)
481 placeholder16
= l10n_util::GetStringUTF16(input
.placeholder_text_rid
);
482 ScopedJavaLocalRef
<jstring
> placeholder
=
483 base::android::ConvertUTF16ToJavaString(env
, placeholder16
);
485 Java_AutofillDialogGlue_addToAutofillDialogFieldArray(
489 reinterpret_cast<jint
>(&input
),
495 ui::MenuModel
* menuModel
= controller_
->MenuModelForSection(section
);
496 const int itemCount
= menuModel
->GetItemCount();
497 ScopedJavaLocalRef
<jobjectArray
> menu_array
=
498 Java_AutofillDialogGlue_createAutofillDialogMenuItemArray(env
,
501 int checkedItem
= -1;
503 for (int i
= 0; i
< itemCount
; ++i
) {
504 const bool editable
= IsMenuItemEditable(section
, i
);
506 string16 line1_value
= menuModel
->GetLabelAt(i
);
507 string16 line2_value
= menuModel
->GetSublabelAt(i
);
508 gfx::Image icon_value
;
509 menuModel
->GetIconAt(i
, &icon_value
);
511 if (menuModel
->IsItemCheckedAt(i
)) {
513 CollapseUserDataIntoMenuItem(section
,
514 &line1_value
, &line2_value
,
518 ScopedJavaLocalRef
<jstring
> line1
=
519 base::android::ConvertUTF16ToJavaString(env
, line1_value
);
520 ScopedJavaLocalRef
<jstring
> line2
=
521 base::android::ConvertUTF16ToJavaString(env
, line2_value
);
522 ScopedJavaLocalRef
<jobject
> bitmap
;
523 const SkBitmap
& sk_icon
= icon_value
.AsBitmap();
524 if (!sk_icon
.isNull() && sk_icon
.bytesPerPixel() != 0)
525 bitmap
= gfx::ConvertToJavaBitmap(&sk_icon
);
527 Java_AutofillDialogGlue_addToAutofillDialogMenuItemArray(
528 env
, menu_array
.obj(), i
,
529 line1
.obj(), line2
.obj(), bitmap
.obj(), editable
);
532 Java_AutofillDialogGlue_updateSection(env
,
535 controller_
->SectionIsActive(section
),
540 field_type_to_always_clobber
);
543 // Whether the item at the |index| in the |section| menu model is editable.
544 // TODO(aruslan): Remove/fix this once http://crbug.com/224162 is closed.
545 bool AutofillDialogViewAndroid::IsMenuItemEditable(DialogSection section
,
547 // "Use billing for shipping" is not editable and it's always first.
548 if (section
== SECTION_SHIPPING
&& index
== 0)
551 // Any other items except the last ("Manage...") are editable.
552 ui::MenuModel
* menuModel
= controller_
->MenuModelForSection(section
);
553 return index
< menuModel
->GetItemCount() - 1;
556 // TODO(aruslan): Remove/fix this once http://crbug.com/230685 is closed.
559 bool IsCreditCardType(AutofillFieldType type
) {
560 return AutofillType(type
).group() == AutofillType::CREDIT_CARD
;
563 class CollapsedAutofillProfileWrapper
: public AutofillProfileWrapper
{
565 explicit CollapsedAutofillProfileWrapper(const AutofillProfile
* profile
)
566 : AutofillProfileWrapper(profile
, 0) {
568 virtual ~CollapsedAutofillProfileWrapper() {
571 virtual string16
GetDisplayText() OVERRIDE
{
572 const string16 name_full
= GetInfo(NAME_FULL
);
573 const string16 comma
= ASCIIToUTF16(", ");
574 const string16 address2
= GetInfo(ADDRESS_HOME_LINE2
);
577 if (!name_full
.empty())
578 label
= name_full
+ comma
;
579 label
+= GetInfo(ADDRESS_HOME_LINE1
);
580 if (!address2
.empty())
581 label
+= comma
+ address2
;
585 string16
GetSublabel() {
586 const string16 comma
= ASCIIToUTF16(", ");
588 GetInfo(ADDRESS_HOME_CITY
) + comma
+
589 GetInfo(ADDRESS_HOME_STATE
) + ASCIIToUTF16(" ") +
590 GetInfo(ADDRESS_HOME_ZIP
);
594 DISALLOW_COPY_AND_ASSIGN(CollapsedAutofillProfileWrapper
);
598 // Get billing info from |output| and put it into |card|, |cvc|, and |profile|.
599 // These outparams are required because |card|/|profile| accept different types
601 void GetBillingInfoFromOutputs(const DetailOutputMap
& output
,
603 AutofillProfile
* profile
) {
604 for (DetailOutputMap::const_iterator it
= output
.begin();
605 it
!= output
.end(); ++it
) {
607 TrimWhitespace(it
->second
, TRIM_ALL
, &trimmed
);
609 if (it
->first
->type
== ADDRESS_HOME_COUNTRY
||
610 it
->first
->type
== ADDRESS_BILLING_COUNTRY
) {
611 profile
->SetInfo(it
->first
->type
,
613 g_browser_process
->GetApplicationLocale());
615 // Copy the credit card name to |profile| in addition to |card| as
616 // wallet::Instrument requires a recipient name for its billing address.
617 if (profile
&& it
->first
->type
== CREDIT_CARD_NAME
)
618 profile
->SetRawInfo(NAME_FULL
, trimmed
);
620 if (IsCreditCardType(it
->first
->type
)) {
622 card
->SetRawInfo(it
->first
->type
, trimmed
);
623 } else if (profile
) {
624 profile
->SetRawInfo(it
->first
->type
, trimmed
);
632 // Returns true and fills in the |label|, |sublabel| and |icon if
633 // a given |section| has the user input.
634 // TODO(aruslan): Remove/fix this once http://crbug.com/230685 is closed.
635 bool AutofillDialogViewAndroid::CollapseUserDataIntoMenuItem(
636 DialogSection section
,
637 string16
* label_to_set
,
638 string16
* sublabel_to_set
,
639 gfx::Image
* icon_to_set
) {
641 const SuggestionState
& suggestion_state
=
642 controller_
->SuggestionStateForSection(section
);
643 if (!suggestion_state
.text
.empty())
646 DetailOutputMap inputs
;
647 GetUserInput(section
, &inputs
);
656 GetBillingInfoFromOutputs(inputs
, &card
, NULL
);
657 AutofillCreditCardWrapper
ccw(&card
);
658 label
= ccw
.GetDisplayText();
659 icon
= ccw
.GetIcon();
663 case SECTION_BILLING
: {
664 AutofillProfile profile
;
665 GetBillingInfoFromOutputs(inputs
, NULL
, &profile
);
666 CollapsedAutofillProfileWrapper
pw(&profile
);
667 label
= pw
.GetDisplayText();
668 sublabel
= pw
.GetSublabel();
672 case SECTION_CC_BILLING
: {
674 AutofillProfile profile
;
675 GetBillingInfoFromOutputs(inputs
, &card
, &profile
);
676 AutofillCreditCardWrapper
ccw(&card
);
677 CollapsedAutofillProfileWrapper
pw(&profile
);
678 label
= ccw
.GetDisplayText();
679 sublabel
= pw
.GetDisplayText();
680 icon
= ccw
.GetIcon();
684 case SECTION_SHIPPING
: {
685 AutofillProfile profile
;
686 GetBillingInfoFromOutputs(inputs
, NULL
, &profile
);
687 CollapsedAutofillProfileWrapper
pw(&profile
);
688 label
= pw
.GetDisplayText();
689 sublabel
= pw
.GetSublabel();
693 case SECTION_EMAIL
: {
694 for (DetailOutputMap::const_iterator iter
= inputs
.begin();
695 iter
!= inputs
.end(); ++iter
) {
696 if (iter
->first
->type
== EMAIL_ADDRESS
)
697 label
= iter
->second
;
706 *label_to_set
= label
;
707 *sublabel_to_set
= sublabel
;
712 } // namespace autofill