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.browser; |
| 6 |
| 7 import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_TABLET; |
| 8 |
| 9 import android.test.FlakyTest; |
| 10 import android.test.suitebuilder.annotation.MediumTest; |
| 11 |
| 12 import com.google.android.apps.chrome.R; |
| 13 |
| 14 import org.chromium.base.ThreadUtils; |
| 15 import org.chromium.base.test.util.Feature; |
| 16 import org.chromium.base.test.util.Restriction; |
| 17 import org.chromium.base.test.util.UrlUtils; |
| 18 import org.chromium.chrome.browser.tabmodel.TabModel; |
| 19 import org.chromium.chrome.browser.tabmodel.TabModelUtils; |
| 20 import org.chromium.chrome.test.ChromeTabbedActivityTestBase; |
| 21 import org.chromium.chrome.test.util.ChromeTabUtils; |
| 22 import org.chromium.chrome.test.util.TestHttpServerClient; |
| 23 import org.chromium.content.browser.test.util.Criteria; |
| 24 import org.chromium.content.browser.test.util.CriteriaHelper; |
| 25 import org.chromium.content.browser.test.util.DOMUtils; |
| 26 import org.chromium.content.browser.test.util.JavaScriptUtils; |
| 27 import org.chromium.content.browser.test.util.UiUtils; |
| 28 import org.chromium.net.test.util.TestWebServer; |
| 29 |
| 30 import java.net.URLEncoder; |
| 31 import java.util.concurrent.Callable; |
| 32 import java.util.concurrent.ExecutionException; |
| 33 import java.util.concurrent.Semaphore; |
| 34 import java.util.concurrent.TimeUnit; |
| 35 import java.util.concurrent.TimeoutException; |
| 36 |
| 37 /** |
| 38 * Navigate in UrlBar tests. |
| 39 */ |
| 40 public class NavigateTest extends ChromeTabbedActivityTestBase { |
| 41 private static final String HTTP_SCHEME = "http://"; |
| 42 private static final String NEW_TAB_PAGE = "chrome-native://newtab/"; |
| 43 |
| 44 /** |
| 45 * @return the expected contents of the location bar after navigating to url
. |
| 46 */ |
| 47 private String expectedLocation(String url) { |
| 48 assertTrue(url.startsWith(HTTP_SCHEME)); |
| 49 return url.replaceFirst(HTTP_SCHEME, ""); |
| 50 } |
| 51 |
| 52 /** |
| 53 * Verify Selection on the Location Bar |
| 54 * Bug: crbug.com/413277 |
| 55 * @Smoke |
| 56 * @MediumTest |
| 57 * @Feature({"Navigation", "Main"}) |
| 58 */ |
| 59 @FlakyTest |
| 60 public void testNavigate() throws InterruptedException { |
| 61 String url = TestHttpServerClient.getUrl("chrome/test/data/android/navig
ate/simple.html"); |
| 62 String result = typeInOmniboxAndNavigate(url); |
| 63 assertEquals(expectedLocation(url), result.trim()); |
| 64 } |
| 65 |
| 66 @Restriction(RESTRICTION_TYPE_TABLET) |
| 67 @MediumTest |
| 68 @Feature({"Navigation"}) |
| 69 public void testNavigateMany() throws InterruptedException { |
| 70 final String[] urls = { |
| 71 TestHttpServerClient.getUrl("chrome/test/data/android/navigate/o
ne.html"), |
| 72 TestHttpServerClient.getUrl("chrome/test/data/android/navigate/t
wo.html"), |
| 73 TestHttpServerClient.getUrl("chrome/test/data/android/navigate/t
hree.html") |
| 74 }; |
| 75 final int repeats = 3; |
| 76 for (int i = 0; i < repeats; i++) { |
| 77 for (int j = 0; j < urls.length; j++) { |
| 78 String result = typeInOmniboxAndNavigate(urls[j]); |
| 79 assertEquals(expectedLocation(urls[j]), result); |
| 80 } |
| 81 } |
| 82 } |
| 83 |
| 84 /** |
| 85 * Verify Selection on the Location Bar in Landscape Mode |
| 86 */ |
| 87 @MediumTest |
| 88 @Feature({"Navigation"}) |
| 89 public void testNavigateLandscape() throws InterruptedException { |
| 90 // '0' is Landscape Mode. '1' is Portrait. |
| 91 getActivity().setRequestedOrientation(0); |
| 92 String url = TestHttpServerClient.getUrl("chrome/test/data/android/navig
ate/simple.html"); |
| 93 String result = typeInOmniboxAndNavigate(url); |
| 94 assertEquals(expectedLocation(url), result); |
| 95 } |
| 96 |
| 97 /** |
| 98 * Verify New Tab Open and Navigate. |
| 99 */ |
| 100 @MediumTest |
| 101 @Feature({"Navigation"}) |
| 102 public void testOpenAndNavigate() throws InterruptedException { |
| 103 final int tabCount = getActivity().getCurrentTabModel().getCount(); |
| 104 ChromeTabUtils.newTabFromMenu(getInstrumentation(), getActivity()); |
| 105 UiUtils.settleDownUI(getInstrumentation()); |
| 106 |
| 107 assertEquals("Wrong number of tabs", |
| 108 tabCount + 1, getActivity().getCurrentTabModel().getCount()); |
| 109 String url = TestHttpServerClient.getUrl("chrome/test/data/android/navig
ate/simple.html"); |
| 110 String result = typeInOmniboxAndNavigate(url); |
| 111 assertEquals(expectedLocation(url), result); |
| 112 } |
| 113 |
| 114 /** |
| 115 * Test Opening a link and verify that the desired page is loaded. |
| 116 * Bug: crbug.com/171037 |
| 117 * @MediumTest |
| 118 * @Feature({"Navigation"}) |
| 119 */ |
| 120 @FlakyTest |
| 121 public void testOpenLink() throws InterruptedException, TimeoutException { |
| 122 String url = TestHttpServerClient.getUrl("chrome/test/data/android/googl
e.html"); |
| 123 typeInOmniboxAndNavigate(url); |
| 124 assertEquals(url, getActivity().getActivityTab().getUrl()); |
| 125 |
| 126 Tab tab = getActivity().getActivityTab(); |
| 127 DOMUtils.clickNode(this, tab.getContentViewCore(), "aboutLink"); |
| 128 ChromeTabUtils.waitForTabPageLoaded( |
| 129 tab, TestHttpServerClient.getUrl("chrome/test/data/android/about
.html")); |
| 130 |
| 131 String expectedUrl = TestHttpServerClient.getUrl("chrome/test/data/andro
id/about.html"); |
| 132 assertEquals("Desired Link not open", expectedUrl, |
| 133 getActivity().getActivityTab().getUrl()); |
| 134 } |
| 135 |
| 136 /** |
| 137 * Test re-direct functionality for a web-page. |
| 138 * @throws Exception |
| 139 */ |
| 140 @MediumTest |
| 141 @Feature({"Navigation"}) |
| 142 public void testNavigateRedirect() throws Exception { |
| 143 final String initialUrl = |
| 144 TestHttpServerClient.getUrl("chrome/test/data/android/redirect/a
bout.html"); |
| 145 final String redirectedUrl = |
| 146 TestHttpServerClient.getUrl("chrome/test/data/android/redirect/o
ne.html"); |
| 147 typeInOmniboxAndNavigate(initialUrl); |
| 148 |
| 149 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { |
| 150 @Override |
| 151 public boolean isSatisfied() { |
| 152 return getActivity().getActivityTab().getUrl().equals(redirected
Url); |
| 153 } |
| 154 })); |
| 155 } |
| 156 |
| 157 /** |
| 158 * Test fallback works as intended and that we can go back to the original U
RL |
| 159 * even when redirected via Java redirection. |
| 160 */ |
| 161 @MediumTest |
| 162 @Feature({"Navigation"}) |
| 163 public void testIntentFallbackRedirection() throws Exception { |
| 164 getInstrumentation().waitForIdleSync(); |
| 165 assertEquals(NEW_TAB_PAGE, getActivity().getActivityTab().getUrl()); |
| 166 |
| 167 final String redirectionUrl = |
| 168 TestHttpServerClient.getUrl("chrome/test/data/android/redirect/a
bout.html"); |
| 169 final String initialUrl = TestHttpServerClient.getUrl( |
| 170 "chrome/test/data/android/redirect/js_redirect.cgi?location=" |
| 171 + URLEncoder.encode("intent://non_existent/#Intent;scheme=non_ex
istent;" |
| 172 + "S.browser_fallback_url=" + redirectionUrl + ";end", |
| 173 "UTF-8")); |
| 174 final String targetUrl = |
| 175 TestHttpServerClient.getUrl("chrome/test/data/android/redirect/o
ne.html"); |
| 176 typeInOmniboxAndNavigate(initialUrl); |
| 177 |
| 178 // Now intent fallback should be triggered assuming 'non_existent' schem
e cannot be handled. |
| 179 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { |
| 180 @Override |
| 181 public boolean isSatisfied() { |
| 182 return getActivity().getActivityTab().getUrl().equals(targetUrl)
; |
| 183 } |
| 184 })); |
| 185 |
| 186 // Check if Java redirections were removed from the history. |
| 187 // Note that if we try to go back in the test: NavigateToEntry() is call
ed, but |
| 188 // DidNavigate() does not get called. But in real cases we can go back t
o initial page |
| 189 // without any problem. |
| 190 // TODO(changwan): figure out why we cannot go back on this test. |
| 191 int index = getActivity().getActivityTab().getWebContents().getNavigatio
nController() |
| 192 .getLastCommittedEntryIndex(); |
| 193 assertEquals(1, index); |
| 194 String previousNavigationUrl = getActivity().getActivityTab().getWebCont
ents() |
| 195 .getNavigationController().getEntryAtIndex(0).getUrl(); |
| 196 assertEquals(NEW_TAB_PAGE, previousNavigationUrl); |
| 197 } |
| 198 |
| 199 /** |
| 200 * Test back and forward buttons. |
| 201 * |
| 202 * crbug.com/268463 |
| 203 * @Restriction(RESTRICTION_TYPE_TABLET) |
| 204 * @MediumTest |
| 205 * @Feature({"Navigation"}) |
| 206 */ |
| 207 @FlakyTest |
| 208 public void testNavigateBackAndForwardButtons() throws InterruptedException
{ |
| 209 final String[] urls = { |
| 210 TestHttpServerClient.getUrl("chrome/test/data/android/navigate/o
ne.html"), |
| 211 TestHttpServerClient.getUrl("chrome/test/data/android/navigate/t
wo.html"), |
| 212 TestHttpServerClient.getUrl("chrome/test/data/android/navigate/t
hree.html") |
| 213 }; |
| 214 |
| 215 for (String url : urls) { |
| 216 typeInOmniboxAndNavigate(url); |
| 217 } |
| 218 |
| 219 final int repeats = 3; |
| 220 for (int i = 0; i < repeats; i++) { |
| 221 singleClickView(getActivity().findViewById(R.id.back_button)); |
| 222 UiUtils.settleDownUI(getInstrumentation()); |
| 223 assertEquals(String.format( |
| 224 "URL mismatch after pressing back button for the 1st time in
repetition %d.", |
| 225 i), urls[1], getActivity().getActivityTab().getUrl()); |
| 226 |
| 227 singleClickView(getActivity().findViewById(R.id.back_button)); |
| 228 UiUtils.settleDownUI(getInstrumentation()); |
| 229 assertEquals(String.format( |
| 230 "URL mismatch after pressing back button for the 2nd time in
repetition %d.", |
| 231 i), urls[0], getActivity().getActivityTab().getUrl()); |
| 232 |
| 233 singleClickView(getActivity().findViewById(R.id.forward_button)); |
| 234 UiUtils.settleDownUI(getInstrumentation()); |
| 235 assertEquals(String.format( |
| 236 "URL mismatch after pressing fwd button for the 1st time in
repetition %d.", i), |
| 237 urls[1], getActivity().getActivityTab().getUrl()); |
| 238 |
| 239 singleClickView(getActivity().findViewById(R.id.forward_button)); |
| 240 UiUtils.settleDownUI(getInstrumentation()); |
| 241 assertEquals(String.format( |
| 242 "URL mismatch after pressing fwd button for the 2nd time in
repetition %d.", i), |
| 243 urls[2], getActivity().getActivityTab().getUrl()); |
| 244 } |
| 245 } |
| 246 |
| 247 /* |
| 248 * Bug: crbug.com/413186 |
| 249 * @MediumTest |
| 250 * @Feature({"Navigation"}) |
| 251 */ |
| 252 @FlakyTest |
| 253 public void testWindowOpenUrlSpoof() throws Exception { |
| 254 TestWebServer webServer = TestWebServer.start(); |
| 255 try { |
| 256 // Make sure that we start with one tab. |
| 257 final TabModel model = getActivity().getTabModelSelector().getModel(
false); |
| 258 assertEquals("Invalid starting number of tabs", 1, model.getCount())
; |
| 259 |
| 260 final Semaphore urlServedSemaphore = new Semaphore(0); |
| 261 Runnable checkAction = new Runnable() { |
| 262 @Override |
| 263 public void run() { |
| 264 final Tab tab = TabModelUtils.getCurrentTab(model); |
| 265 |
| 266 // Make sure that we are showing the spoofed data and a blan
k URL. |
| 267 String url = getTabUrlOnUIThread(tab); |
| 268 boolean spoofedUrl = "".equals(url) || "about:blank".equals(
url); |
| 269 assertTrue("URL Spoofed", spoofedUrl); |
| 270 assertEquals("Not showing mocked content", "\"Spoofed\"", ge
tTabBodyText(tab)); |
| 271 urlServedSemaphore.release(); |
| 272 } |
| 273 }; |
| 274 |
| 275 // Mock out the test URL |
| 276 final String mockedUrl = webServer.setResponseWithRunnableAction( |
| 277 "/mockme.html", "<html><body>Real</body></html>", null, chec
kAction); |
| 278 |
| 279 // Navigate to the spoofable URL |
| 280 loadUrl(UrlUtils.encodeHtmlDataUri( |
| 281 "<head>" |
| 282 + " <meta name=\"viewport\"" |
| 283 + " content=\"initial-scale=1,maximum-scale=1,user-scal
able=no\">" |
| 284 + "</head>" |
| 285 + "<script>" |
| 286 + " function spoof() {" |
| 287 + " var w = open();" |
| 288 + " w.opener = null;" |
| 289 + " w.document.write('Spoofed');" |
| 290 + " w.location = '" + mockedUrl + "'" |
| 291 + " }" |
| 292 + "</script>" |
| 293 + "<a href='JavaScript:spoof()' id='link'>Go</a>")); |
| 294 |
| 295 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { |
| 296 @Override |
| 297 public boolean isSatisfied() { |
| 298 return getActivity().getCurrentContentViewCore().getScale()
== 1.f; |
| 299 } |
| 300 })); |
| 301 |
| 302 // Click the 'Go' link |
| 303 DOMUtils.clickNode(this, getActivity().getCurrentContentViewCore(),
"link"); |
| 304 |
| 305 // Wait for the proper URL to be served. |
| 306 assertTrue(urlServedSemaphore.tryAcquire(5, TimeUnit.SECONDS)); |
| 307 |
| 308 final Tab tab = TabModelUtils.getCurrentTab(model); |
| 309 |
| 310 // Wait for the url to change. |
| 311 assertTrue("Page url didn't change", |
| 312 CriteriaHelper.pollForCriteria(new Criteria() { |
| 313 @Override |
| 314 public boolean isSatisfied() { |
| 315 return mockedUrl.equals(getTabUrlOnUIThread(tab)); |
| 316 } |
| 317 }, 5000, 50)); |
| 318 |
| 319 // Make sure that we're showing new content now. |
| 320 assertEquals("Still showing spoofed data", "\"Real\"", getTabBodyTex
t(tab)); |
| 321 } finally { |
| 322 webServer.shutdown(); |
| 323 } |
| 324 } |
| 325 |
| 326 private String getTabUrlOnUIThread(final Tab tab) { |
| 327 try { |
| 328 return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() { |
| 329 @Override |
| 330 public String call() throws Exception { |
| 331 return tab.getUrl(); |
| 332 } |
| 333 }); |
| 334 } catch (ExecutionException ex) { |
| 335 assert false : "Unexpected ExecutionException"; |
| 336 } |
| 337 return null; |
| 338 } |
| 339 |
| 340 private String getTabBodyText(Tab tab) { |
| 341 try { |
| 342 return JavaScriptUtils.executeJavaScriptAndWaitForResult( |
| 343 tab.getWebContents(), "document.body.innerText"); |
| 344 } catch (InterruptedException ex) { |
| 345 assert false : "Unexpected InterruptedException"; |
| 346 } catch (TimeoutException ex) { |
| 347 assert false : "Unexpected TimeoutException"; |
| 348 } |
| 349 return null; |
| 350 } |
| 351 |
| 352 @Override |
| 353 public void startMainActivity() throws InterruptedException { |
| 354 startMainActivityFromLauncher(); |
| 355 } |
| 356 } |
OLD | NEW |