1 // Copyright 2012 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 package org.chromium.android_webview.test;
7 import android.test.suitebuilder.annotation.SmallTest;
9 import org.chromium.android_webview.AwContents;
10 import org.chromium.android_webview.test.util.CommonResources;
11 import org.chromium.base.ThreadUtils;
12 import org.chromium.base.test.util.DisabledTest;
13 import org.chromium.content.browser.test.util.HistoryUtils;
14 import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
15 import org.chromium.content_public.browser.NavigationEntry;
16 import org.chromium.content_public.browser.NavigationHistory;
17 import org.chromium.net.test.util.TestWebServer;
19 import java.util.concurrent.Callable;
22 * Navigation history tests.
24 public class NavigationHistoryTest extends AwTestBase {
26 private static final String PAGE_1_PATH = "/page1.html";
27 private static final String PAGE_1_TITLE = "Page 1 Title";
28 private static final String PAGE_2_PATH = "/page2.html";
29 private static final String PAGE_2_TITLE = "Page 2 Title";
30 private static final String PAGE_WITH_HASHTAG_REDIRECT_TITLE = "Page with hashtag";
31 private static final String LOGIN_PAGE_PATH = "/login.html";
32 private static final String LOGIN_PAGE_TITLE = "Login page";
33 private static final String LOGIN_RESPONSE_PAGE_PATH = "/login-response.html";
34 private static final String LOGIN_RESPONSE_PAGE_TITLE = "Login response";
35 private static final String LOGIN_RESPONSE_PAGE_HELP_LINK_ID = "help";
37 private TestWebServer mWebServer;
38 private TestAwContentsClient mContentsClient;
39 private AwContents mAwContents;
42 public void setUp() throws Exception {
44 AwContents.setShouldDownloadFavicons();
45 mContentsClient = new TestAwContentsClient();
46 final AwTestContainerView testContainerView =
47 createAwTestContainerViewOnMainSync(mContentsClient);
48 mAwContents = testContainerView.getAwContents();
49 mWebServer = new TestWebServer(false);
53 public void tearDown() throws Exception {
54 mWebServer.shutdown();
58 private NavigationHistory getNavigationHistory(final AwContents awContents)
60 return ThreadUtils.runOnUiThreadBlocking(new Callable<NavigationHistory>() {
62 public NavigationHistory call() {
63 return awContents.getNavigationController().getNavigationHistory();
68 private void checkHistoryItem(NavigationEntry item, String url, String originalUrl,
69 String title, boolean faviconNull) {
70 assertEquals(url, item.getUrl());
71 assertEquals(originalUrl, item.getOriginalUrl());
72 assertEquals(title, item.getTitle());
74 assertNull(item.getFavicon());
76 assertNotNull(item.getFavicon());
80 private String addPage1ToServer(TestWebServer webServer) {
81 return mWebServer.setResponse(PAGE_1_PATH,
82 CommonResources.makeHtmlPageFrom(
83 "<title>" + PAGE_1_TITLE + "</title>",
84 "<div>This is test page 1.</div>"),
85 CommonResources.getTextHtmlHeaders(false));
88 private String addPage2ToServer(TestWebServer webServer) {
89 return mWebServer.setResponse(PAGE_2_PATH,
90 CommonResources.makeHtmlPageFrom(
91 "<title>" + PAGE_2_TITLE + "</title>",
92 "<div>This is test page 2.</div>"),
93 CommonResources.getTextHtmlHeaders(false));
96 private String addPageWithHashTagRedirectToServer(TestWebServer webServer) {
97 return mWebServer.setResponse(PAGE_2_PATH,
98 CommonResources.makeHtmlPageFrom(
99 "<title>" + PAGE_WITH_HASHTAG_REDIRECT_TITLE + "</title>",
100 "<iframe onLoad=\"location.replace(location.href + '#tag');\" />"),
101 CommonResources.getTextHtmlHeaders(false));
105 public void testNavigateOneUrl() throws Throwable {
106 NavigationHistory history = getNavigationHistory(mAwContents);
107 assertEquals(0, history.getEntryCount());
109 final String pageWithHashTagRedirectUrl = addPageWithHashTagRedirectToServer(mWebServer);
110 enableJavaScriptOnUiThread(mAwContents);
112 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
113 pageWithHashTagRedirectUrl);
115 history = getNavigationHistory(mAwContents);
116 checkHistoryItem(history.getEntryAtIndex(0),
117 pageWithHashTagRedirectUrl + "#tag",
118 pageWithHashTagRedirectUrl,
119 PAGE_WITH_HASHTAG_REDIRECT_TITLE,
122 assertEquals(0, history.getCurrentEntryIndex());
126 public void testNavigateTwoUrls() throws Throwable {
127 NavigationHistory list = getNavigationHistory(mAwContents);
128 assertEquals(0, list.getEntryCount());
130 final TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
131 mContentsClient.getOnPageFinishedHelper();
132 final String page1Url = addPage1ToServer(mWebServer);
133 final String page2Url = addPage2ToServer(mWebServer);
135 loadUrlSync(mAwContents, onPageFinishedHelper, page1Url);
136 loadUrlSync(mAwContents, onPageFinishedHelper, page2Url);
138 list = getNavigationHistory(mAwContents);
140 // Make sure there is a new entry entry the list
141 assertEquals(2, list.getEntryCount());
143 // Make sure the first entry is still okay
144 checkHistoryItem(list.getEntryAtIndex(0),
150 // Make sure the second entry was added properly
151 checkHistoryItem(list.getEntryAtIndex(1),
157 assertEquals(1, list.getCurrentEntryIndex());
162 public void testNavigateTwoUrlsAndBack() throws Throwable {
163 final TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
164 mContentsClient.getOnPageFinishedHelper();
165 NavigationHistory list = getNavigationHistory(mAwContents);
166 assertEquals(0, list.getEntryCount());
168 final String page1Url = addPage1ToServer(mWebServer);
169 final String page2Url = addPage2ToServer(mWebServer);
171 loadUrlSync(mAwContents, onPageFinishedHelper, page1Url);
172 loadUrlSync(mAwContents, onPageFinishedHelper, page2Url);
174 HistoryUtils.goBackSync(getInstrumentation(), mAwContents.getWebContents(),
175 onPageFinishedHelper);
176 list = getNavigationHistory(mAwContents);
178 // Make sure the first entry is still okay
179 checkHistoryItem(list.getEntryAtIndex(0),
185 // Make sure the second entry is still okay
186 checkHistoryItem(list.getEntryAtIndex(1),
192 // Make sure the current index is back to 0
193 assertEquals(0, list.getCurrentEntryIndex());
197 * Disabled until favicons are getting fetched when using ContentView.
203 public void testFavicon() throws Throwable {
204 NavigationHistory list = getNavigationHistory(mAwContents);
206 mWebServer.setResponseBase64("/" + CommonResources.FAVICON_FILENAME,
207 CommonResources.FAVICON_DATA_BASE64, CommonResources.getImagePngHeaders(false));
208 final String url = mWebServer.setResponse("/favicon.html",
209 CommonResources.FAVICON_STATIC_HTML, null);
211 assertEquals(0, list.getEntryCount());
212 getAwSettingsOnUiThread(mAwContents).setImagesEnabled(true);
213 loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), url);
215 list = getNavigationHistory(mAwContents);
217 // Make sure the first entry is still okay.
218 checkHistoryItem(list.getEntryAtIndex(0), url, url, "", false);
221 private String addNoncacheableLoginPageToServer(TestWebServer webServer) {
222 final String submitButtonId = "submit";
223 final String loginPageHtml =
226 " <title>" + LOGIN_PAGE_TITLE + "</title>" +
228 " function startAction() {" +
229 " button = document.getElementById('" + submitButtonId + "');" +
234 " <body onload='setTimeout(startAction, 0)'>" +
235 " <form action='" + LOGIN_RESPONSE_PAGE_PATH.substring(1) + "' method='post'>" +
236 " <input type='text' name='login'>" +
237 " <input id='" + submitButtonId + "' type='submit' value='Submit'>" +
241 return mWebServer.setResponse(LOGIN_PAGE_PATH,
243 CommonResources.getTextHtmlHeaders(true));
246 private String addNoncacheableLoginResponsePageToServer(TestWebServer webServer) {
247 final String loginResponsePageHtml =
250 " <title>" + LOGIN_RESPONSE_PAGE_TITLE + "</title>" +
254 " <div><a id='" + LOGIN_RESPONSE_PAGE_HELP_LINK_ID + "' href='" +
255 PAGE_1_PATH.substring(1) + "'>Help</a></div>'" +
258 return mWebServer.setResponse(LOGIN_RESPONSE_PAGE_PATH,
259 loginResponsePageHtml,
260 CommonResources.getTextHtmlHeaders(true));
263 // This test simulates Google login page behavior. The page is non-cacheable
264 // and uses POST method for submission. It also contains a help link, leading
265 // to another page. We are verifying that it is possible to go back to the
266 // submitted login page after visiting the help page.
268 * Temporarily disabled. It is blocking a patch that fixes chromium's form
269 * resubmission defenses. This test should probably expect a modal dialog
270 * asking permission to re-post rather than expecting to just be able to navigate
271 * back to a page that specified Cache-Control: no-store.
274 * @Feature({"AndroidWebView"})
277 public void testNavigateBackToNoncacheableLoginPage() throws Throwable {
278 final TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
279 mContentsClient.getOnPageFinishedHelper();
281 final String loginPageUrl = addNoncacheableLoginPageToServer(mWebServer);
282 final String loginResponsePageUrl = addNoncacheableLoginResponsePageToServer(mWebServer);
283 final String page1Url = addPage1ToServer(mWebServer);
285 getAwSettingsOnUiThread(mAwContents).setJavaScriptEnabled(true);
286 loadUrlSync(mAwContents, onPageFinishedHelper, loginPageUrl);
287 // Since the page performs an async action, we can't rely on callbacks.
288 pollOnUiThread(new Callable<Boolean>() {
290 public Boolean call() {
291 String title = mAwContents.getTitle();
292 return LOGIN_RESPONSE_PAGE_TITLE.equals(title);
295 executeJavaScriptAndWaitForResult(mAwContents,
297 "link = document.getElementById('" + LOGIN_RESPONSE_PAGE_HELP_LINK_ID + "');" +
299 pollOnUiThread(new Callable<Boolean>() {
301 public Boolean call() {
302 String title = mAwContents.getTitle();
303 return PAGE_1_TITLE.equals(title);
306 // Verify that we can still go back to the login response page despite that
307 // it is non-cacheable.
308 HistoryUtils.goBackSync(getInstrumentation(), mAwContents.getWebContents(),
309 onPageFinishedHelper);
310 pollOnUiThread(new Callable<Boolean>() {
312 public Boolean call() {
313 String title = mAwContents.getTitle();
314 return LOGIN_RESPONSE_PAGE_TITLE.equals(title);