Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / android_webview / javatests / src / org / chromium / android_webview / test / LoadDataWithBaseUrlTest.java
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.
4
5 package org.chromium.android_webview.test;
6
7 import android.graphics.Bitmap;
8 import android.test.suitebuilder.annotation.SmallTest;
9
10 import org.chromium.android_webview.AwContents;
11 import org.chromium.android_webview.AwSettings;
12 import org.chromium.android_webview.test.util.CommonResources;
13 import org.chromium.base.test.util.DisabledTest;
14 import org.chromium.base.test.util.Feature;
15 import org.chromium.content.browser.ContentViewCore;
16 import org.chromium.content.browser.test.util.HistoryUtils;
17 import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
18 import org.chromium.net.test.util.TestWebServer;
19
20 import java.io.File;
21 import java.io.FileOutputStream;
22 import java.util.concurrent.Callable;
23
24 /**
25  * Tests for the {@link android.webkit.WebView#loadDataWithBaseURL(String, String, String, String,
26  * String)} method.
27  */
28 public class LoadDataWithBaseUrlTest extends AwTestBase {
29
30     private TestAwContentsClient mContentsClient;
31     private AwContents mAwContents;
32     private ContentViewCore mContentViewCore;
33
34     @Override
35     public void setUp() throws Exception {
36         super.setUp();
37         mContentsClient = new TestAwContentsClient();
38         final AwTestContainerView testContainerView =
39                 createAwTestContainerViewOnMainSync(mContentsClient);
40         mAwContents = testContainerView.getAwContents();
41         mContentViewCore = testContainerView.getContentViewCore();
42     }
43
44     protected void loadDataWithBaseUrlSync(
45         final String data, final String mimeType, final boolean isBase64Encoded,
46         final String baseUrl, final String historyUrl) throws Throwable {
47         loadDataWithBaseUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
48                 data, mimeType, isBase64Encoded, baseUrl, historyUrl);
49     }
50
51     private static final String SCRIPT_FILE = "/script.js";
52     private static final String SCRIPT_LOADED = "Loaded";
53     private static final String SCRIPT_NOT_LOADED = "Not loaded";
54     private static final String SCRIPT_JS = "script_was_loaded = true;";
55
56     private String getScriptFileTestPageHtml(final String scriptUrl) {
57         return "<html>" +
58                 "  <head>" +
59                 "    <title>" + SCRIPT_NOT_LOADED + "</title>" +
60                 "    <script src='" + scriptUrl + "'></script>" +
61                 "  </head>" +
62                 "  <body onload=\"if(script_was_loaded) document.title='" + SCRIPT_LOADED + "'\">" +
63                 "  </body>" +
64                 "</html>";
65     }
66
67     private String getCrossOriginAccessTestPageHtml(final String iframeUrl) {
68         return "<html>" +
69                 "  <head>" +
70                 "    <script>" +
71                 "      function onload() {" +
72                 "        try {" +
73                 "          document.title = " +
74                 "            document.getElementById('frame').contentWindow.location.href;" +
75                 "        } catch (e) {" +
76                 "          document.title = 'Exception';" +
77                 "        }" +
78                 "      }" +
79                 "    </script>" +
80                 "  </head>" +
81                 "  <body onload='onload()'>" +
82                 "    <iframe id='frame' src='" + iframeUrl + "'></iframe>" +
83                 "  </body>" +
84                 "</html>";
85     }
86
87
88     @SmallTest
89     @Feature({"AndroidWebView"})
90     public void testImageLoad() throws Throwable {
91         TestWebServer webServer = null;
92         try {
93             webServer = new TestWebServer(false);
94             webServer.setResponseBase64("/" + CommonResources.FAVICON_FILENAME,
95                     CommonResources.FAVICON_DATA_BASE64, CommonResources.getImagePngHeaders(true));
96
97             AwSettings contentSettings = getAwSettingsOnUiThread(mAwContents);
98             contentSettings.setImagesEnabled(true);
99             contentSettings.setJavaScriptEnabled(true);
100
101             loadDataWithBaseUrlSync(
102                     CommonResources.getOnImageLoadedHtml(CommonResources.FAVICON_FILENAME),
103                     "text/html", false, webServer.getBaseUrl(), null);
104
105             assertEquals("5", getTitleOnUiThread(mAwContents));
106         } finally {
107             if (webServer != null) webServer.shutdown();
108         }
109     }
110
111     @SmallTest
112     @Feature({"AndroidWebView"})
113     public void testScriptLoad() throws Throwable {
114         TestWebServer webServer = null;
115         try {
116             webServer = new TestWebServer(false);
117
118             final String scriptUrl = webServer.setResponse(SCRIPT_FILE, SCRIPT_JS,
119                     CommonResources.getTextJavascriptHeaders(true));
120             final String pageHtml = getScriptFileTestPageHtml(scriptUrl);
121
122             getAwSettingsOnUiThread(mAwContents).setJavaScriptEnabled(true);
123             loadDataWithBaseUrlSync(pageHtml, "text/html", false, webServer.getBaseUrl(), null);
124             assertEquals(SCRIPT_LOADED, getTitleOnUiThread(mAwContents));
125
126         } finally {
127             if (webServer != null) webServer.shutdown();
128         }
129     }
130
131     @SmallTest
132     @Feature({"AndroidWebView"})
133     public void testSameOrigin() throws Throwable {
134         TestWebServer webServer = null;
135         try {
136             webServer = new TestWebServer(false);
137             final String frameUrl = webServer.setResponse("/" + CommonResources.ABOUT_FILENAME,
138                     CommonResources.ABOUT_HTML, CommonResources.getTextHtmlHeaders(true));
139             final String html = getCrossOriginAccessTestPageHtml(frameUrl);
140
141             getAwSettingsOnUiThread(mAwContents).setJavaScriptEnabled(true);
142             loadDataWithBaseUrlSync(html, "text/html", false, webServer.getBaseUrl(), null);
143             assertEquals(frameUrl, getTitleOnUiThread(mAwContents));
144
145         } finally {
146             if (webServer != null) webServer.shutdown();
147         }
148     }
149
150     @SmallTest
151     @Feature({"AndroidWebView"})
152     public void testCrossOrigin() throws Throwable {
153         TestWebServer webServer = null;
154         try {
155             webServer = new TestWebServer(false);
156             final String frameUrl = webServer.setResponse("/" + CommonResources.ABOUT_FILENAME,
157                     CommonResources.ABOUT_HTML, CommonResources.getTextHtmlHeaders(true));
158             final String html = getCrossOriginAccessTestPageHtml(frameUrl);
159             final String baseUrl = webServer.getBaseUrl().replaceFirst("localhost", "127.0.0.1");
160
161             getAwSettingsOnUiThread(mAwContents).setJavaScriptEnabled(true);
162             loadDataWithBaseUrlSync(html, "text/html", false, baseUrl, null);
163
164             assertEquals("Exception", getTitleOnUiThread(mAwContents));
165
166         } finally {
167             if (webServer != null) webServer.shutdown();
168         }
169     }
170
171     @SmallTest
172     @Feature({"AndroidWebView"})
173     public void testNullBaseUrl() throws Throwable {
174         getAwSettingsOnUiThread(mAwContents).setJavaScriptEnabled(true);
175         final String pageHtml = "<html><body onload='document.title=document.location.href'>" +
176                 "</body></html>";
177         loadDataWithBaseUrlSync(pageHtml, "text/html", false, null, null);
178         assertEquals("about:blank", getTitleOnUiThread(mAwContents));
179     }
180
181     @SmallTest
182     @Feature({"AndroidWebView"})
183     public void testloadDataWithBaseUrlCallsOnPageStarted() throws Throwable {
184         final String baseUrl = "http://base.com/";
185         TestCallbackHelperContainer.OnPageStartedHelper onPageStartedHelper =
186                 mContentsClient.getOnPageStartedHelper();
187         final int callCount = onPageStartedHelper.getCallCount();
188         loadDataWithBaseUrlAsync(mAwContents, CommonResources.ABOUT_HTML, "text/html", false,
189                 baseUrl, "about:blank");
190         onPageStartedHelper.waitForCallback(callCount);
191         assertEquals(baseUrl, onPageStartedHelper.getUrl());
192     }
193
194     @SmallTest
195     @Feature({"AndroidWebView"})
196     public void testHistoryUrl() throws Throwable {
197
198         final String pageHtml = "<html><body>Hello, world!</body></html>";
199         final String baseUrl = "http://example.com";
200         // TODO(mnaganov): Use the same string as Android CTS suite uses
201         // once GURL issue is resolved (http://code.google.com/p/google-url/issues/detail?id=29)
202         final String historyUrl = "http://history.com/";
203         loadDataWithBaseUrlSync(pageHtml, "text/html", false, baseUrl, historyUrl);
204         assertEquals(historyUrl, HistoryUtils.getUrlOnUiThread(
205                 getInstrumentation(), mContentViewCore));
206
207         loadDataWithBaseUrlSync(pageHtml, "text/html", false, baseUrl, null);
208         assertEquals("about:blank", HistoryUtils.getUrlOnUiThread(
209                 getInstrumentation(), mContentViewCore));
210     }
211
212     @SmallTest
213     @Feature({"AndroidWebView"})
214     public void testOnPageFinishedUrlIsBaseUrl() throws Throwable {
215         final String pageHtml = "<html><body>Hello, world!</body></html>";
216         final String baseUrl = "http://example.com/";
217         loadDataWithBaseUrlSync(pageHtml, "text/html", false, baseUrl, baseUrl);
218         loadDataWithBaseUrlSync(pageHtml, "text/html", false, baseUrl, baseUrl);
219         TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
220                 mContentsClient.getOnPageFinishedHelper();
221         assertEquals(baseUrl, onPageFinishedHelper.getUrl());
222     }
223
224     @SmallTest
225     @Feature({"AndroidWebView"})
226     public void testHistoryUrlIgnoredWithDataSchemeBaseUrl() throws Throwable {
227         final String pageHtml = "<html><body>bar</body></html>";
228         final String historyUrl = "http://history.com/";
229         loadDataWithBaseUrlSync(pageHtml, "text/html", false, "data:foo", historyUrl);
230         assertEquals("data:text/html," + pageHtml, HistoryUtils.getUrlOnUiThread(
231                 getInstrumentation(), mContentViewCore));
232     }
233
234     /*
235     @SmallTest
236     @Feature({"AndroidWebView"})
237     http://crbug.com/173274
238     */
239     @DisabledTest
240     public void testHistoryUrlNavigation() throws Throwable {
241         TestWebServer webServer = null;
242         try {
243             webServer = new TestWebServer(false);
244             final String historyUrl = webServer.setResponse("/" + CommonResources.ABOUT_FILENAME,
245                     CommonResources.ABOUT_HTML, CommonResources.getTextHtmlHeaders(true));
246
247             final String page1Title = "Page1";
248             final String page1Html = "<html><head><title>" + page1Title + "</title>" +
249                     "<body>" + page1Title + "</body></html>";
250
251             loadDataWithBaseUrlSync(page1Html, "text/html", false, null, historyUrl);
252             assertEquals(page1Title, getTitleOnUiThread(mAwContents));
253
254             final String page2Title = "Page2";
255             final String page2Html = "<html><head><title>" + page2Title + "</title>" +
256                     "<body>" + page2Title + "</body></html>";
257
258             final TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
259                     mContentsClient.getOnPageFinishedHelper();
260             loadDataSync(mAwContents, onPageFinishedHelper, page2Html, "text/html", false);
261             assertEquals(page2Title, getTitleOnUiThread(mAwContents));
262
263             HistoryUtils.goBackSync(getInstrumentation(), mContentViewCore, onPageFinishedHelper);
264             // The title of the 'about.html' specified via historyUrl.
265             assertEquals(CommonResources.ABOUT_TITLE, getTitleOnUiThread(mAwContents));
266
267         } finally {
268             if (webServer != null) webServer.shutdown();
269         }
270     }
271
272     /**
273      * @return true if |fileUrl| was accessible from a data url with |baseUrl| as it's
274      * base URL.
275      */
276     private boolean canAccessFileFromData(String baseUrl, String fileUrl) throws Throwable {
277         final String IMAGE_LOADED = "LOADED";
278         final String IMAGE_NOT_LOADED = "NOT_LOADED";
279         String data = "<html><body>" +
280                 "<img src=\"" + fileUrl + "\" " +
281                 "onload=\"document.title=\'" + IMAGE_LOADED + "\';\" " +
282                 "onerror=\"document.title=\'" + IMAGE_NOT_LOADED + "\';\" />" +
283                 "</body></html>";
284
285         loadDataWithBaseUrlSync(data, "text/html", false, baseUrl, null);
286
287         poll(new Callable<Boolean>() {
288             @Override
289             public Boolean call() throws Exception {
290                 String title = getTitleOnUiThread(mAwContents);
291                 return IMAGE_LOADED.equals(title) || IMAGE_NOT_LOADED.equals(title);
292             }
293         });
294
295         return IMAGE_LOADED.equals(getTitleOnUiThread(mAwContents));
296     }
297
298     @SmallTest
299     @Feature({"AndroidWebView"})
300     public void testLoadDataWithBaseUrlAccessingFile() throws Throwable {
301         // Create a temporary file on the filesystem we can try to read.
302         File cacheDir = getActivity().getCacheDir();
303         File tempImage = File.createTempFile("test_image", ".png", cacheDir);
304         Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565);
305         FileOutputStream fos = new FileOutputStream(tempImage);
306         bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
307         fos.close();
308         String imagePath = tempImage.getAbsolutePath();
309
310         AwSettings contentSettings = getAwSettingsOnUiThread(mAwContents);
311         contentSettings.setImagesEnabled(true);
312         contentSettings.setJavaScriptEnabled(true);
313
314         try {
315             final String DATA_BASE_URL = "data:";
316             final String NON_DATA_BASE_URL = "http://example.com";
317
318             mAwContents.getSettings().setAllowFileAccess(false);
319             String token = "" + System.currentTimeMillis();
320             // All access to file://, including android_asset and android_res is blocked
321             // with a data: base URL, regardless of AwSettings.getAllowFileAccess().
322             assertFalse(canAccessFileFromData(DATA_BASE_URL,
323                   "file:///android_asset/asset_icon.png?" + token));
324             assertFalse(canAccessFileFromData(DATA_BASE_URL,
325                   "file:///android_res/raw/resource_icon.png?" + token));
326             assertFalse(canAccessFileFromData(DATA_BASE_URL, "file://" + imagePath + "?" + token));
327
328             // WebView always has access to android_asset and android_res for non-data
329             // base URLs and can access other file:// URLs based on the value of
330             // AwSettings.getAllowFileAccess().
331             assertTrue(canAccessFileFromData(NON_DATA_BASE_URL,
332                   "file:///android_asset/asset_icon.png?" + token));
333             assertTrue(canAccessFileFromData(NON_DATA_BASE_URL,
334                   "file:///android_res/raw/resource_icon.png?" + token));
335             assertFalse(canAccessFileFromData(NON_DATA_BASE_URL,
336                   "file://" + imagePath + "?" + token));
337
338             token += "a";
339             mAwContents.getSettings().setAllowFileAccess(true);
340             // We should still be unable to access any file:// with when loading with a
341             // data: base URL, but we should now be able to access the wider file system
342             // (still restricted by OS-level permission checks) with a non-data base URL.
343             assertFalse(canAccessFileFromData(DATA_BASE_URL,
344                   "file:///android_asset/asset_icon.png?" + token));
345             assertFalse(canAccessFileFromData(DATA_BASE_URL,
346                   "file:///android_res/raw/resource_icon.png?" + token));
347             assertFalse(canAccessFileFromData(DATA_BASE_URL, "file://" + imagePath + "?" + token));
348
349             assertTrue(canAccessFileFromData(NON_DATA_BASE_URL,
350                   "file:///android_asset/asset_icon.png?" + token));
351             assertTrue(canAccessFileFromData(NON_DATA_BASE_URL,
352                   "file:///android_res/raw/resource_icon.png?" + token));
353             assertTrue(canAccessFileFromData(NON_DATA_BASE_URL,
354                   "file://" + imagePath + "?" + token));
355         } finally {
356             if (!tempImage.delete()) throw new AssertionError();
357         }
358     }
359 }