Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 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 package org.chromium.chrome.browser.autofill; | |
| 6 | |
| 7 import android.test.suitebuilder.annotation.MediumTest; | |
| 8 import android.view.View; | |
| 9 import android.view.ViewGroup; | |
| 10 | |
| 11 import org.chromium.base.ThreadUtils; | |
| 12 import org.chromium.base.test.util.Feature; | |
| 13 import org.chromium.base.test.util.UrlUtils; | |
| 14 import org.chromium.chrome.R; | |
| 15 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; | |
| 16 import org.chromium.chrome.shell.ChromeShellActivity; | |
| 17 import org.chromium.chrome.shell.ChromeShellTestBase; | |
| 18 import org.chromium.content.browser.ContentViewCore; | |
| 19 import org.chromium.content.browser.test.util.Criteria; | |
| 20 import org.chromium.content.browser.test.util.CriteriaHelper; | |
| 21 import org.chromium.content.browser.test.util.DOMUtils; | |
| 22 import org.chromium.content_public.browser.WebContents; | |
| 23 import org.chromium.ui.UiUtils; | |
| 24 import org.chromium.ui.autofill.AutofillPopup; | |
| 25 | |
| 26 import java.util.concurrent.Callable; | |
| 27 import java.util.concurrent.ExecutionException; | |
| 28 import java.util.concurrent.TimeoutException; | |
| 29 | |
| 30 /** | |
| 31 * Integration tests for interaction of the AutofillPopup and a keyboard. | |
| 32 */ | |
| 33 public class AutofillPopupWithKeyboardTest extends ChromeShellTestBase { | |
| 34 /** | |
| 35 * Test that showing autofill popup and keyboard will not hide the autofill popup. | |
| 36 */ | |
| 37 @MediumTest | |
| 38 @Feature({"autofill-keyboard"}) | |
| 39 public void testShowAutofillPopupAndKeyboardimultaneously() | |
| 40 throws InterruptedException, ExecutionException, TimeoutException { | |
| 41 launchChromeShellWithUrl(UrlUtils.encodeHtmlDataUri("<html><head>" | |
| 42 + "<meta name=\"viewport\"" | |
| 43 + "content=\"width=device-width, initial-scale=1.0, maximum-scal e=1.0\" /></head>" | |
| 44 + "<body><form method=\"POST\">" | |
| 45 + "<input type=\"text\" id=\"fn\" autocomplete=\"given-name\" /> <br>" | |
| 46 + "<input type=\"text\" id=\"ln\" autocomplete=\"family-name\" / ><br>" | |
| 47 + "<textarea id=\"sa\" autocomplete=\"street-address\"></textare a><br>" | |
| 48 + "<input type=\"text\" id=\"a1\" autocomplete=\"address-line1\" /><br>" | |
| 49 + "<input type=\"text\" id=\"a2\" autocomplete=\"address-line2\" /><br>" | |
| 50 + "<input type=\"text\" id=\"ct\" autocomplete=\"locality\" /><b r>" | |
| 51 + "<input type=\"text\" id=\"zc\" autocomplete=\"postal-code\" / ><br>" | |
| 52 + "<input type=\"text\" id=\"em\" autocomplete=\"email\" /><br>" | |
| 53 + "<input type=\"text\" id=\"ph\" autocomplete=\"tel\" /><br>" | |
| 54 + "<input type=\"text\" id=\"fx\" autocomplete=\"fax\" /><br>" | |
| 55 + "<select id=\"co\" autocomplete=\"country\"><br>" | |
| 56 + "<option value=\"BR\">Brazil</option>" | |
| 57 + "<option value=\"US\">United States</option>" | |
| 58 + "</select>" | |
| 59 + "<input type=\"submit\" />" | |
| 60 + "</form></body></html>")); | |
| 61 assertTrue(waitForActiveShellToBeDoneLoading()); | |
| 62 new AutofillTestHelper().setProfile(new AutofillProfile("", "https://www .example.com", | |
| 63 "John Smith", "Acme Inc", "1 Main\nApt A", "CA", "San Francisco" , "", "94102", "", | |
| 64 "US", "(415) 888-9999", "john@acme.inc", "en")); | |
| 65 class Info { | |
|
newt (away)
2015/01/20 21:28:09
Another option would be to use AtomicReferences in
please use gerrit instead
2015/01/21 01:31:44
Done, that saves 2 lines :-).
| |
| 66 public final ContentViewCore viewCore; | |
| 67 public final WebContents webContents; | |
| 68 public final ViewGroup view; | |
| 69 public Info(ChromeShellActivity activity) { | |
| 70 viewCore = activity.getActiveContentViewCore(); | |
| 71 webContents = viewCore.getWebContents(); | |
| 72 view = viewCore.getContainerView(); | |
| 73 } | |
| 74 } | |
| 75 final Info info = ThreadUtils.runOnUiThreadBlocking(new Callable<Info>() { | |
| 76 @Override | |
| 77 public Info call() { | |
| 78 return new Info(getActivity()); | |
| 79 } | |
| 80 }); | |
| 81 assertTrue(DOMUtils.waitForNonZeroNodeBounds(info.webContents, "fn")); | |
| 82 | |
| 83 // Click on the unfocused input element the first time to focus on it. T his brings up the | |
| 84 // keyboard, but does not show the autofill popup. | |
| 85 DOMUtils.clickNode(this, info.viewCore, "fn"); | |
| 86 waitForKeyboardShownOnUiThreadBlocking(); | |
| 87 notifyViewHeightReducedOnUiThreadBlocking(); | |
| 88 | |
| 89 // Hide the keyboard while still keeping the focus on the input field. | |
| 90 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | |
| 91 @Override | |
| 92 public void run() { | |
| 93 UiUtils.hideKeyboard(info.view); | |
| 94 } | |
| 95 }); | |
| 96 assertTrue("Keyboard was never hidden", CriteriaHelper.pollForCriteria(n ew Criteria() { | |
| 97 @Override | |
| 98 public boolean isSatisfied() { | |
| 99 try { | |
| 100 return !isKeyboardShowingOnUiThreadBlocking(); | |
| 101 } catch (InterruptedException e1) { | |
| 102 return false; | |
| 103 } catch (ExecutionException e2) { | |
| 104 return false; | |
| 105 } | |
| 106 } | |
| 107 })); | |
| 108 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | |
| 109 @Override | |
| 110 public void run() { | |
| 111 info.viewCore.onSizeChanged(info.viewCore.getViewportWidthPix(), | |
| 112 info.viewCore.getViewportHeightPix() + 100, | |
| 113 info.viewCore.getViewportWidthPix(), info.viewCore.getVi ewportHeightPix()); | |
| 114 } | |
| 115 }); | |
| 116 | |
| 117 // Click on the focused input element the second time. This brings up th e autofill popup and | |
| 118 // shows the keyboard at the same time. Showing the keyboard should not hide the autofill | |
| 119 // popup. | |
| 120 DOMUtils.clickNode(this, info.viewCore, "fn"); | |
| 121 waitForKeyboardShownOnUiThreadBlocking(); | |
| 122 notifyViewHeightReducedOnUiThreadBlocking(); | |
| 123 | |
| 124 // Verify that the autofill popup is showing. | |
| 125 assertTrue("Autofill Popup anchor view was never added.", | |
| 126 CriteriaHelper.pollForCriteria(new Criteria() { | |
| 127 @Override | |
| 128 public boolean isSatisfied() { | |
| 129 try { | |
| 130 return findAchorViewOnUiThreadBlocking(info.view) != null; | |
| 131 } catch (InterruptedException e1) { | |
| 132 return false; | |
| 133 } catch (ExecutionException e2) { | |
| 134 return false; | |
| 135 } | |
| 136 } | |
| 137 })); | |
| 138 final View anchorView = findAchorViewOnUiThreadBlocking(info.view); | |
| 139 Object popupObject = ThreadUtils.runOnUiThreadBlocking(new Callable<Obje ct>() { | |
| 140 @Override | |
| 141 public Object call() { | |
| 142 return anchorView.getTag(); | |
| 143 } | |
| 144 }); | |
| 145 assertTrue(popupObject instanceof AutofillPopup); | |
| 146 final AutofillPopup popup = (AutofillPopup) popupObject; | |
| 147 assertTrue( | |
| 148 "Autofill Popup was never shown.", CriteriaHelper.pollForCriteri a(new Criteria() { | |
| 149 @Override | |
| 150 public boolean isSatisfied() { | |
| 151 try { | |
| 152 return isPopupShowingOnUiThreadBlocking(popup); | |
| 153 } catch (InterruptedException e1) { | |
| 154 return false; | |
| 155 } catch (ExecutionException e2) { | |
| 156 return false; | |
| 157 } | |
| 158 } | |
| 159 })); | |
| 160 } | |
| 161 | |
| 162 // Wait until the keyboard is showing on the UI thread. | |
| 163 private void waitForKeyboardShownOnUiThreadBlocking() throws InterruptedExce ption { | |
|
newt (away)
2015/01/20 21:28:10
you could add a "visible" parameter to this method
please use gerrit instead
2015/01/21 01:31:44
Done.
| |
| 164 assertTrue("Keyboard was never shown", CriteriaHelper.pollForCriteria(ne w Criteria() { | |
|
newt (away)
2015/01/20 21:28:09
use pollForUIThreadCriteria() here, then you can s
please use gerrit instead
2015/01/21 01:31:44
Done.
| |
| 165 @Override | |
| 166 public boolean isSatisfied() { | |
| 167 try { | |
| 168 return isKeyboardShowingOnUiThreadBlocking(); | |
| 169 } catch (InterruptedException e1) { | |
| 170 return false; | |
| 171 } catch (ExecutionException e2) { | |
| 172 return false; | |
| 173 } | |
| 174 } | |
| 175 })); | |
| 176 } | |
| 177 | |
| 178 // Notify the ContentViewCore that its height was reduced on the UI thread. | |
| 179 private void notifyViewHeightReducedOnUiThreadBlocking() { | |
|
newt (away)
2015/01/20 21:28:09
I'd remove "OnUiThreadBlocking" from these methods
please use gerrit instead
2015/01/21 01:31:44
Done.
| |
| 180 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | |
| 181 @Override | |
| 182 public void run() { | |
| 183 ContentViewCore viewCore = getActivity().getActiveContentViewCor e(); | |
| 184 viewCore.onSizeChanged(viewCore.getViewportWidthPix(), | |
| 185 viewCore.getViewportHeightPix() - 100, viewCore.getViewp ortWidthPix(), | |
| 186 viewCore.getViewportHeightPix()); | |
| 187 } | |
| 188 }); | |
| 189 } | |
| 190 | |
| 191 // Check whether the keyboard is showing on the UI thread. | |
| 192 private Boolean isKeyboardShowingOnUiThreadBlocking() | |
|
newt (away)
2015/01/20 21:28:09
This should return "boolean" (not Boolean). Same b
please use gerrit instead
2015/01/21 01:31:44
No longer relevant, as this method got inlined.
| |
| 193 throws InterruptedException, ExecutionException { | |
| 194 return ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() { | |
| 195 @Override | |
| 196 public Boolean call() { | |
| 197 return UiUtils.isKeyboardShowing( | |
| 198 getActivity(), getActivity().getActiveContentViewCore(). getContainerView()); | |
| 199 } | |
| 200 }); | |
| 201 } | |
| 202 | |
| 203 // Find the autofill popup view on the UI thread. | |
| 204 private View findAchorViewOnUiThreadBlocking(final ViewGroup view) | |
| 205 throws InterruptedException, ExecutionException { | |
| 206 return ThreadUtils.runOnUiThreadBlocking(new Callable<View>() { | |
|
newt (away)
2015/01/20 21:28:09
I'd use runOnUiThreadBlockingNoException(). Then y
please use gerrit instead
2015/01/21 01:31:44
No longer necessary, as this got inlined.
| |
| 207 @Override | |
| 208 public View call() { | |
| 209 return view.findViewById(R.id.dropdown_popup_window); | |
| 210 } | |
| 211 }); | |
| 212 } | |
| 213 | |
| 214 // Check whether the autofill popup is showing on the UI thread. | |
| 215 private Boolean isPopupShowingOnUiThreadBlocking(final AutofillPopup popup) | |
| 216 throws InterruptedException, ExecutionException { | |
| 217 return ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() { | |
| 218 @Override | |
| 219 public Boolean call() { | |
| 220 return popup.isShowing(); | |
| 221 } | |
| 222 }); | |
| 223 } | |
| 224 } | |
| OLD | NEW |