OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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.test.util; |
| 6 |
| 7 import android.content.Context; |
| 8 import android.view.View; |
| 9 import android.view.inputmethod.InputMethodManager; |
| 10 |
| 11 import junit.framework.Assert; |
| 12 |
| 13 import org.chromium.base.ThreadUtils; |
| 14 import org.chromium.chrome.browser.omnibox.AutocompleteController; |
| 15 import org.chromium.chrome.browser.omnibox.AutocompleteController.OnSuggestionsR
eceivedListener; |
| 16 import org.chromium.chrome.browser.omnibox.LocationBarLayout; |
| 17 import org.chromium.chrome.browser.omnibox.OmniboxSuggestion; |
| 18 import org.chromium.chrome.browser.omnibox.UrlBar; |
| 19 import org.chromium.chrome.browser.profiles.Profile; |
| 20 import org.chromium.content.browser.test.util.Criteria; |
| 21 import org.chromium.content.browser.test.util.CriteriaHelper; |
| 22 import org.chromium.content.browser.test.util.TouchCommon; |
| 23 |
| 24 import java.util.ArrayList; |
| 25 import java.util.HashMap; |
| 26 import java.util.List; |
| 27 import java.util.Map; |
| 28 import java.util.concurrent.Callable; |
| 29 import java.util.concurrent.ExecutionException; |
| 30 |
| 31 /** |
| 32 * Utility methods and classes for testing the Omnibox. |
| 33 */ |
| 34 public class OmniboxTestUtils { |
| 35 private OmniboxTestUtils() {} |
| 36 |
| 37 /** |
| 38 * Builder for the data structure that describes a set of omnibox results fo
r a given |
| 39 * query. |
| 40 */ |
| 41 public static class TestSuggestionResultsBuilder { |
| 42 private final List<SuggestionsResultBuilder> mSuggestionBuilders = |
| 43 new ArrayList<SuggestionsResultBuilder>(); |
| 44 private String mTextShownFor; |
| 45 |
| 46 public TestSuggestionResultsBuilder addSuggestions(SuggestionsResultBuil
der suggestions) { |
| 47 mSuggestionBuilders.add(suggestions); |
| 48 return this; |
| 49 } |
| 50 |
| 51 public TestSuggestionResultsBuilder setTextShownFor(String text) { |
| 52 mTextShownFor = text; |
| 53 return this; |
| 54 } |
| 55 |
| 56 private List<SuggestionsResult> buildSuggestionsList() { |
| 57 ArrayList<SuggestionsResult> suggestions = new ArrayList<Suggestions
Result>(); |
| 58 for (int i = 0; i < mSuggestionBuilders.size(); i++) { |
| 59 suggestions.add(mSuggestionBuilders.get(i).build()); |
| 60 } |
| 61 return suggestions; |
| 62 } |
| 63 } |
| 64 |
| 65 /** |
| 66 * Builder for {@link SuggestionsResult}. |
| 67 */ |
| 68 public static class SuggestionsResultBuilder { |
| 69 private final List<OmniboxSuggestion> mSuggestions = new ArrayList<Omnib
oxSuggestion>(); |
| 70 private String mAutocompleteText; |
| 71 |
| 72 public SuggestionsResultBuilder addGeneratedSuggestion( |
| 73 OmniboxSuggestion.Type type, String text, String url) { |
| 74 mSuggestions.add(new OmniboxSuggestion( |
| 75 type.nativeType(), 0, 0, text, null, null, null, "", url, ur
l, false, false)); |
| 76 return this; |
| 77 } |
| 78 |
| 79 public SuggestionsResultBuilder addSuggestion(OmniboxSuggestion suggesti
on) { |
| 80 mSuggestions.add(suggestion); |
| 81 return this; |
| 82 } |
| 83 |
| 84 public SuggestionsResultBuilder setAutocompleteText(String autocompleteT
ext) { |
| 85 mAutocompleteText = autocompleteText; |
| 86 return this; |
| 87 } |
| 88 |
| 89 private SuggestionsResult build() { |
| 90 return new SuggestionsResult(mSuggestions, mAutocompleteText); |
| 91 } |
| 92 } |
| 93 |
| 94 /** |
| 95 * Data structure that contains the test data to be sent to |
| 96 * {@link OnSuggestionsReceivedListener#onSuggestionsReceived}. |
| 97 */ |
| 98 public static class SuggestionsResult { |
| 99 private final List<OmniboxSuggestion> mSuggestions; |
| 100 private final String mAutocompleteText; |
| 101 |
| 102 public SuggestionsResult(List<OmniboxSuggestion> suggestions, String aut
ocompleteText) { |
| 103 mSuggestions = suggestions; |
| 104 mAutocompleteText = autocompleteText; |
| 105 } |
| 106 } |
| 107 |
| 108 /** |
| 109 * Builds the necessary suggestion input for a TestAutocompleteController. |
| 110 */ |
| 111 public static Map<String, List<SuggestionsResult>> buildSuggestionMap( |
| 112 TestSuggestionResultsBuilder... builders) { |
| 113 Map<String, List<SuggestionsResult>> suggestionMap = |
| 114 new HashMap<String, List<SuggestionsResult>>(); |
| 115 for (TestSuggestionResultsBuilder builder : builders) { |
| 116 suggestionMap.put(builder.mTextShownFor, builder.buildSuggestionsLis
t()); |
| 117 } |
| 118 return suggestionMap; |
| 119 } |
| 120 |
| 121 /** |
| 122 * AutocompleteController instance that allows for easy testing. |
| 123 */ |
| 124 public static class TestAutocompleteController extends AutocompleteControlle
r { |
| 125 private final View mView; |
| 126 private final Map<String, List<SuggestionsResult>> mSuggestions; |
| 127 private Runnable mSuggestionsDispatcher; |
| 128 private int mZeroSuggestCalledCount; |
| 129 |
| 130 public TestAutocompleteController( |
| 131 View view, |
| 132 OnSuggestionsReceivedListener listener, |
| 133 Map<String, List<SuggestionsResult>> suggestions) { |
| 134 super(listener); |
| 135 mView = view; |
| 136 mSuggestions = suggestions; |
| 137 } |
| 138 |
| 139 @Override |
| 140 public void start( |
| 141 Profile profile, String url , |
| 142 final String text, boolean preventInlineAutocomplete) { |
| 143 mSuggestionsDispatcher = new Runnable() { |
| 144 @Override |
| 145 public void run() { |
| 146 List<SuggestionsResult> suggestions = mSuggestions.get(text.
toLowerCase()); |
| 147 if (suggestions == null) return; |
| 148 |
| 149 for (int i = 0; i < suggestions.size(); i++) { |
| 150 onSuggestionsReceived( |
| 151 suggestions.get(i).mSuggestions, |
| 152 suggestions.get(i).mAutocompleteText, |
| 153 0); |
| 154 } |
| 155 } |
| 156 }; |
| 157 mView.post(mSuggestionsDispatcher); |
| 158 } |
| 159 |
| 160 @Override |
| 161 public void startZeroSuggest(Profile profile, String omniboxText, String
url, |
| 162 boolean isQueryInOmnibox, boolean focusedFromFakebox) { |
| 163 mZeroSuggestCalledCount++; |
| 164 } |
| 165 |
| 166 public int numZeroSuggestRequests() { |
| 167 return mZeroSuggestCalledCount; |
| 168 } |
| 169 |
| 170 @Override |
| 171 public void stop(boolean clear) { |
| 172 if (mSuggestionsDispatcher != null) mView.removeCallbacks(mSuggestio
nsDispatcher); |
| 173 mSuggestionsDispatcher = null; |
| 174 } |
| 175 |
| 176 @Override |
| 177 protected long nativeInit(Profile profile) { |
| 178 return 1; |
| 179 } |
| 180 |
| 181 @Override |
| 182 public void setProfile(Profile profile) {} |
| 183 } |
| 184 |
| 185 /** |
| 186 * AutocompleteController instance that will trigger no suggestions. |
| 187 */ |
| 188 public static class StubAutocompleteController extends AutocompleteControlle
r { |
| 189 public StubAutocompleteController() { |
| 190 super(new OnSuggestionsReceivedListener() { |
| 191 @Override |
| 192 public void onSuggestionsReceived(List<OmniboxSuggestion> sugges
tions, |
| 193 String inlineAutocompleteText) { |
| 194 Assert.fail("No autocomplete suggestions should be received"
); |
| 195 } |
| 196 }); |
| 197 } |
| 198 |
| 199 @Override |
| 200 public void start( |
| 201 Profile profile, String url , |
| 202 final String text, boolean preventInlineAutocomplete) {} |
| 203 |
| 204 @Override |
| 205 public void startZeroSuggest(Profile profile, String omniboxText, String
url, |
| 206 boolean isQueryInOmnibox, boolean focusedFromFakebox) { |
| 207 } |
| 208 |
| 209 @Override |
| 210 public void stop(boolean clear) {} |
| 211 |
| 212 @Override |
| 213 protected long nativeInit(Profile profile) { |
| 214 return 1; |
| 215 } |
| 216 |
| 217 @Override |
| 218 public void setProfile(Profile profile) {} |
| 219 } |
| 220 |
| 221 /** |
| 222 * Checks and verifies that the URL bar can request and release focus X time
s without issue. |
| 223 * @param urlBar The view to focus. |
| 224 * @param times The number of times focus should be requested and released. |
| 225 * @throws InterruptedException |
| 226 */ |
| 227 public static void checkUrlBarRefocus(UrlBar urlBar, int times) |
| 228 throws InterruptedException { |
| 229 for (int i = 0; i < times; i++) { |
| 230 toggleUrlBarFocus(urlBar, true); |
| 231 Assert.assertTrue(waitForFocusAndKeyboardActive(urlBar, true)); |
| 232 toggleUrlBarFocus(urlBar, false); |
| 233 Assert.assertTrue(waitForFocusAndKeyboardActive(urlBar, false)); |
| 234 } |
| 235 } |
| 236 |
| 237 /** |
| 238 * Determines whether the UrlBar currently has focus. |
| 239 * @param urlBar The view to check focus on. |
| 240 * @return Whether the UrlBar has focus. |
| 241 */ |
| 242 public static boolean doesUrlBarHaveFocus(final UrlBar urlBar) { |
| 243 return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Boolean
>() { |
| 244 @Override |
| 245 public Boolean call() throws Exception { |
| 246 return urlBar.hasFocus(); |
| 247 } |
| 248 }); |
| 249 } |
| 250 |
| 251 private static boolean isKeyboardActiveForView(final View view) { |
| 252 return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Boolean
>() { |
| 253 @Override |
| 254 public Boolean call() throws Exception { |
| 255 InputMethodManager imm = |
| 256 (InputMethodManager) view.getContext().getSystemService( |
| 257 Context.INPUT_METHOD_SERVICE); |
| 258 return imm.isActive(view); |
| 259 } |
| 260 }); |
| 261 } |
| 262 |
| 263 /** |
| 264 * Toggles the focus state for the passed in UrlBar. |
| 265 * @param urlBar The UrlBar whose focus is being changed. |
| 266 * @param gainFocus Whether focus should be requested or cleared. |
| 267 */ |
| 268 public static void toggleUrlBarFocus(final UrlBar urlBar, boolean gainFocus)
{ |
| 269 if (gainFocus) { |
| 270 TouchCommon.singleClickView(urlBar); |
| 271 } else { |
| 272 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
| 273 @Override |
| 274 public void run() { |
| 275 urlBar.clearFocus(); |
| 276 } |
| 277 }); |
| 278 } |
| 279 } |
| 280 |
| 281 /** |
| 282 * Waits for the UrlBar to have the expected focus state. |
| 283 * |
| 284 * @param urlBar The UrlBar whose focus is being inspected. |
| 285 * @param active Whether the UrlBar is expected to have focus or not. |
| 286 * @return Whether the UrlBar had the requested focus state. |
| 287 */ |
| 288 public static boolean waitForFocusAndKeyboardActive(final UrlBar urlBar, fin
al boolean active) |
| 289 throws InterruptedException { |
| 290 return CriteriaHelper.pollForCriteria(new Criteria() { |
| 291 @Override |
| 292 public boolean isSatisfied() { |
| 293 return (doesUrlBarHaveFocus(urlBar) == active) |
| 294 && (isKeyboardActiveForView(urlBar) == active); |
| 295 } |
| 296 }); |
| 297 } |
| 298 |
| 299 /** |
| 300 * Waits for a non-empty list of omnibox suggestions is shown. |
| 301 * |
| 302 * @param locationBar The LocationBar who owns the suggestions. |
| 303 * @return Whether the suggestions were shown. |
| 304 */ |
| 305 public static boolean waitForOmniboxSuggestions(final LocationBarLayout loca
tionBar) |
| 306 throws InterruptedException { |
| 307 return CriteriaHelper.pollForCriteria(new Criteria() { |
| 308 @Override |
| 309 public boolean isSatisfied() { |
| 310 try { |
| 311 return ThreadUtils.runOnUiThreadBlocking(new Callable<Boolea
n>() { |
| 312 @Override |
| 313 public Boolean call() throws Exception { |
| 314 LocationBarLayout.OmniboxSuggestionsList suggestions
List = |
| 315 locationBar.getSuggestionList(); |
| 316 return suggestionsList != null |
| 317 && suggestionsList.isShown() |
| 318 && suggestionsList.getCount() >= 1; |
| 319 } |
| 320 }); |
| 321 } catch (ExecutionException e) { |
| 322 return false; |
| 323 } |
| 324 } |
| 325 }); |
| 326 } |
| 327 } |
OLD | NEW |