Avoid Crash for State Dropdown on Address Editor

Problem: if the state is not saved as the key (like NY), and is saved
as a complete form (New York), or is invalid (Caoldo), the assert
would fail on debug mode. On release build, the state would not show
up on the editor.

Solution: Look for both the key and the complete form. If can't find
them (invalid value), show the default or the first item.

Tests added.

Bug: 861821
Change-Id: I8eeb3679c0dd503c264014e22d8e2a6cd8ef5405
Reviewed-on: https://chromium-review.googlesource.com/1140366
Commit-Queue: Parastoo Geranmayeh <parastoog@google.com>
Reviewed-by: Theresa <twellington@chromium.org>
Reviewed-by: Ganggui Tang <gogerald@chromium.org>
Cr-Commit-Position: refs/heads/master@{#576226}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/EditorDropdownField.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/EditorDropdownField.java
index bd97cb6..bc09493 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/EditorDropdownField.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/EditorDropdownField.java
@@ -89,14 +89,19 @@
             mAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
         }
 
-        // If no value is selected, we'll  select the hint, which is the first item on the dropdown
-        // adapter.
+        // If no value is selected or the value previously entered is not valid, we'll  select the
+        // hint, which is the first item on the dropdown adapter. We also need to check for both key
+        // and value, because the saved value could take both forms (as in NY or New York).
         mSelectedIndex = TextUtils.isEmpty(mFieldModel.getValue())
                 ? 0
-                : mAdapter.getPosition(
-                          mFieldModel.getDropdownValueByKey((mFieldModel.getValue().toString())));
-
-        assert mSelectedIndex >= 0;
+                : mAdapter.getPosition(mFieldModel.getValue().toString());
+        if (mSelectedIndex < 0) {
+            // Assuming that mFieldModel.getValue() is the value (New York).
+            mSelectedIndex = mAdapter.getPosition(
+                    mFieldModel.getDropdownValueByKey(mFieldModel.getValue().toString()));
+        }
+        // Invalid value in the mFieldModel
+        if (mSelectedIndex < 0) mSelectedIndex = 0;
 
         mDropdown = (Spinner) mLayout.findViewById(R.id.spinner);
         mDropdown.setTag(this);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/autofill/AutofillProfilesFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/autofill/AutofillProfilesFragmentTest.java
index 6aeeb16..8f538b3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/autofill/AutofillProfilesFragmentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/autofill/AutofillProfilesFragmentTest.java
@@ -49,6 +49,14 @@
         helper.setProfile(new AutofillProfile("", "https://example.com", true, "John Doe", "Google",
                 "111 Second St", "CA", "Los Angeles", "", "90291", "", "US", "650-253-0000",
                 "second@gmail.com", "en-US"));
+        // Invalid state should not cause a crash on the state dropdown list.
+        helper.setProfile(new AutofillProfile("", "https://example.com", true, "Bill Doe", "Google",
+                "111 Third St", "XXXYYY", "Los Angeles", "", "90291", "", "US", "650-253-0000",
+                "third@gmail.com", "en-US"));
+        // Full value for state should show up correctly on the dropdown list.
+        helper.setProfile(new AutofillProfile("", "https://example.com", true, "Bob Doe", "Google",
+                "111 Fourth St", "California", "Los Angeles", "", "90291", "", "US", "650-253-0000",
+                "fourth@gmail.com", "en-US"));
     }
 
     @Test
@@ -62,7 +70,7 @@
                 (AutofillProfilesFragment) activity.getFragmentForTest();
 
         // Check the preferences on the initial screen.
-        Assert.assertEquals(3 /* One add button + two profiles. */,
+        Assert.assertEquals(5 /* One add button + four profiles. */,
                 autofillProfileFragment.getPreferenceScreen().getPreferenceCount());
         PreferenceFragment fragment = (PreferenceFragment) activity.getFragmentForTest();
         AutofillProfileEditorPreference addProfile =
@@ -88,7 +96,7 @@
         });
         // Check if the preferences are updated correctly.
         rule.waitForThePreferenceUpdate();
-        Assert.assertEquals(4 /* One add button + three profiles. */,
+        Assert.assertEquals(6 /* One add button + five profiles. */,
                 autofillProfileFragment.getPreferenceScreen().getPreferenceCount());
         AutofillProfileEditorPreference addedProfile =
                 (AutofillProfileEditorPreference) fragment.findPreference("Alice Doe");
@@ -108,7 +116,7 @@
                 (AutofillProfilesFragment) activity.getFragmentForTest();
 
         // Check the preferences on the initial screen.
-        Assert.assertEquals(3 /* One add button + two profiles. */,
+        Assert.assertEquals(5 /* One add button + four profiles. */,
                 autofillProfileFragment.getPreferenceScreen().getPreferenceCount());
         PreferenceFragment fragment = (PreferenceFragment) activity.getFragmentForTest();
         AutofillProfileEditorPreference addProfile =
@@ -129,8 +137,8 @@
                 } catch (TimeoutException ex) {
                     // There should be no timeout, which means that there should be a validation
                     // error.
-                    Assert.assertTrue(false);
                     ex.printStackTrace();
+                    Assert.assertTrue(false);
                 } catch (Exception ex) {
                     ex.printStackTrace();
                 }
@@ -150,7 +158,7 @@
                 (AutofillProfilesFragment) activity.getFragmentForTest();
 
         // Check the preferences on the initial screen.
-        Assert.assertEquals(3 /* One add button + two profiles. */,
+        Assert.assertEquals(5 /* One add button + four profiles. */,
                 autofillProfileFragment.getPreferenceScreen().getPreferenceCount());
         PreferenceFragment fragment = (PreferenceFragment) activity.getFragmentForTest();
         AutofillProfileEditorPreference sebProfile =
@@ -174,7 +182,7 @@
         });
         // Check if the preferences are updated correctly.
         rule.waitForThePreferenceUpdate();
-        Assert.assertEquals(2 /* One add button + one profile. */,
+        Assert.assertEquals(4 /* One add button + three profile. */,
                 autofillProfileFragment.getPreferenceScreen().getPreferenceCount());
         AutofillProfileEditorPreference remainedProfile =
                 (AutofillProfileEditorPreference) fragment.findPreference("John Doe");
@@ -196,7 +204,7 @@
                 (AutofillProfilesFragment) activity.getFragmentForTest();
 
         // Check the preferences on the initial screen.
-        Assert.assertEquals(3 /* One add button + two profiles. */,
+        Assert.assertEquals(5 /* One add button + four profiles. */,
                 autofillProfileFragment.getPreferenceScreen().getPreferenceCount());
         PreferenceFragment fragment = (PreferenceFragment) activity.getFragmentForTest();
         AutofillProfileEditorPreference johnProfile =
@@ -223,7 +231,7 @@
         });
         // Check if the preferences are updated correctly.
         rule.waitForThePreferenceUpdate();
-        Assert.assertEquals(3 /* One add button + two profiles. */,
+        Assert.assertEquals(5 /* One add button + four profiles. */,
                 autofillProfileFragment.getPreferenceScreen().getPreferenceCount());
         AutofillProfileEditorPreference editedProfile =
                 (AutofillProfileEditorPreference) fragment.findPreference("Emily Doe");
@@ -238,6 +246,78 @@
     @Test
     @MediumTest
     @Feature({"Preferences"})
+    public void testOpenProfileWithCompleteState() throws Exception {
+        Preferences activity =
+                PreferencesTest.startPreferences(InstrumentationRegistry.getInstrumentation(),
+                        AutofillProfilesFragment.class.getName());
+        AutofillProfilesFragment autofillProfileFragment =
+                (AutofillProfilesFragment) activity.getFragmentForTest();
+
+        // Check the preferences on the initial screen.
+        Assert.assertEquals(5 /* One add button + four profiles. */,
+                autofillProfileFragment.getPreferenceScreen().getPreferenceCount());
+        PreferenceFragment fragment = (PreferenceFragment) activity.getFragmentForTest();
+        AutofillProfileEditorPreference bobProfile =
+                (AutofillProfileEditorPreference) fragment.findPreference("Bob Doe");
+        Assert.assertTrue(bobProfile != null);
+        Assert.assertEquals("Bob Doe", bobProfile.getTitle());
+
+        // Open the profile.
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            PreferencesTest.clickPreference(autofillProfileFragment, bobProfile);
+            rule.setEditorDialog(((AutofillProfileEditorPreference) bobProfile).getEditorDialog());
+            try {
+                rule.clickInEditorAndWait(R.id.editor_dialog_done_button);
+            } catch (Exception ex) {
+                ex.printStackTrace();
+                Assert.assertTrue(false);
+            }
+        });
+        rule.waitForThePreferenceUpdate();
+        Assert.assertEquals(5 /* One add button + four profiles. */,
+                autofillProfileFragment.getPreferenceScreen().getPreferenceCount());
+        activity.finish();
+    }
+
+    @Test
+    @MediumTest
+    @Feature({"Preferences"})
+    public void testOpenProfileWithInvalidState() throws Exception {
+        Preferences activity =
+                PreferencesTest.startPreferences(InstrumentationRegistry.getInstrumentation(),
+                        AutofillProfilesFragment.class.getName());
+        AutofillProfilesFragment autofillProfileFragment =
+                (AutofillProfilesFragment) activity.getFragmentForTest();
+
+        // Check the preferences on the initial screen.
+        Assert.assertEquals(5 /* One add button + four profiles. */,
+                autofillProfileFragment.getPreferenceScreen().getPreferenceCount());
+        PreferenceFragment fragment = (PreferenceFragment) activity.getFragmentForTest();
+        AutofillProfileEditorPreference billProfile =
+                (AutofillProfileEditorPreference) fragment.findPreference("Bill Doe");
+        Assert.assertTrue(billProfile != null);
+        Assert.assertEquals("Bill Doe", billProfile.getTitle());
+
+        // Open the profile.
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            PreferencesTest.clickPreference(autofillProfileFragment, billProfile);
+            rule.setEditorDialog(((AutofillProfileEditorPreference) billProfile).getEditorDialog());
+            try {
+                rule.clickInEditorAndWait(R.id.editor_dialog_done_button);
+            } catch (Exception ex) {
+                ex.printStackTrace();
+                Assert.assertTrue(false);
+            }
+        });
+        // Check if the preferences are updated correctly.
+        rule.waitForThePreferenceUpdate();
+        Assert.assertEquals(5 /* One add button + four profiles. */,
+                autofillProfileFragment.getPreferenceScreen().getPreferenceCount());
+    }
+
+    @Test
+    @MediumTest
+    @Feature({"Preferences"})
     public void testKeyboardShownOnDpadCenter() {
         Preferences activity =
                 PreferencesTest.startPreferences(InstrumentationRegistry.getInstrumentation(),