Update To 11.40.268.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.test.util.HistoryUtils;
16 import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
17 import org.chromium.content_public.browser.WebContents;
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 WebContents mWebContents;
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         mWebContents = mAwContents.getWebContents();
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 = TestWebServer.start();
92         try {
93             webServer.setResponseBase64("/" + CommonResources.FAVICON_FILENAME,
94                     CommonResources.FAVICON_DATA_BASE64, CommonResources.getImagePngHeaders(true));
95
96             AwSettings contentSettings = getAwSettingsOnUiThread(mAwContents);
97             contentSettings.setImagesEnabled(true);
98             contentSettings.setJavaScriptEnabled(true);
99
100             loadDataWithBaseUrlSync(
101                     CommonResources.getOnImageLoadedHtml(CommonResources.FAVICON_FILENAME),
102                     "text/html", false, webServer.getBaseUrl(), null);
103
104             assertEquals("5", getTitleOnUiThread(mAwContents));
105         } finally {
106             webServer.shutdown();
107         }
108     }
109
110     @SmallTest
111     @Feature({"AndroidWebView"})
112     public void testScriptLoad() throws Throwable {
113         TestWebServer webServer = TestWebServer.start();
114         try {
115             final String scriptUrl = webServer.setResponse(SCRIPT_FILE, SCRIPT_JS,
116                     CommonResources.getTextJavascriptHeaders(true));
117             final String pageHtml = getScriptFileTestPageHtml(scriptUrl);
118
119             getAwSettingsOnUiThread(mAwContents).setJavaScriptEnabled(true);
120             loadDataWithBaseUrlSync(pageHtml, "text/html", false, webServer.getBaseUrl(), null);
121             assertEquals(SCRIPT_LOADED, getTitleOnUiThread(mAwContents));
122         } finally {
123             webServer.shutdown();
124         }
125     }
126
127     @SmallTest
128     @Feature({"AndroidWebView"})
129     public void testSameOrigin() throws Throwable {
130         TestWebServer webServer = TestWebServer.start();
131         try {
132             final String frameUrl = webServer.setResponse("/" + CommonResources.ABOUT_FILENAME,
133                     CommonResources.ABOUT_HTML, CommonResources.getTextHtmlHeaders(true));
134             final String html = getCrossOriginAccessTestPageHtml(frameUrl);
135
136             getAwSettingsOnUiThread(mAwContents).setJavaScriptEnabled(true);
137             loadDataWithBaseUrlSync(html, "text/html", false, webServer.getBaseUrl(), null);
138             assertEquals(frameUrl, getTitleOnUiThread(mAwContents));
139         } finally {
140             webServer.shutdown();
141         }
142     }
143
144     @SmallTest
145     @Feature({"AndroidWebView"})
146     public void testCrossOrigin() throws Throwable {
147         TestWebServer webServer = TestWebServer.start();
148         try {
149             final String frameUrl = webServer.setResponse("/" + CommonResources.ABOUT_FILENAME,
150                     CommonResources.ABOUT_HTML, CommonResources.getTextHtmlHeaders(true));
151             final String html = getCrossOriginAccessTestPageHtml(frameUrl);
152             final String baseUrl = webServer.getBaseUrl().replaceFirst("localhost", "127.0.0.1");
153
154             getAwSettingsOnUiThread(mAwContents).setJavaScriptEnabled(true);
155             loadDataWithBaseUrlSync(html, "text/html", false, baseUrl, null);
156
157             assertEquals("Exception", getTitleOnUiThread(mAwContents));
158         } finally {
159             webServer.shutdown();
160         }
161     }
162
163     @SmallTest
164     @Feature({"AndroidWebView"})
165     public void testNullBaseUrl() throws Throwable {
166         getAwSettingsOnUiThread(mAwContents).setJavaScriptEnabled(true);
167         final String pageHtml = "<html><body onload='document.title=document.location.href'>" +
168                 "</body></html>";
169         loadDataWithBaseUrlSync(pageHtml, "text/html", false, null, null);
170         assertEquals("about:blank", getTitleOnUiThread(mAwContents));
171     }
172
173     @SmallTest
174     @Feature({"AndroidWebView"})
175     public void testloadDataWithBaseUrlCallsOnPageStarted() throws Throwable {
176         final String baseUrl = "http://base.com/";
177         TestCallbackHelperContainer.OnPageStartedHelper onPageStartedHelper =
178                 mContentsClient.getOnPageStartedHelper();
179         final int callCount = onPageStartedHelper.getCallCount();
180         loadDataWithBaseUrlAsync(mAwContents, CommonResources.ABOUT_HTML, "text/html", false,
181                 baseUrl, "about:blank");
182         onPageStartedHelper.waitForCallback(callCount);
183         assertEquals(baseUrl, onPageStartedHelper.getUrl());
184     }
185
186     @SmallTest
187     @Feature({"AndroidWebView"})
188     public void testHistoryUrl() throws Throwable {
189
190         final String pageHtml = "<html><body>Hello, world!</body></html>";
191         final String baseUrl = "http://example.com";
192         // TODO(mnaganov): Use the same string as Android CTS suite uses
193         // once GURL issue is resolved (http://code.google.com/p/google-url/issues/detail?id=29)
194         final String historyUrl = "http://history.com/";
195         loadDataWithBaseUrlSync(pageHtml, "text/html", false, baseUrl, historyUrl);
196         assertEquals(historyUrl, HistoryUtils.getUrlOnUiThread(
197                 getInstrumentation(), mWebContents));
198
199         loadDataWithBaseUrlSync(pageHtml, "text/html", false, baseUrl, null);
200         assertEquals("about:blank", HistoryUtils.getUrlOnUiThread(
201                 getInstrumentation(), mWebContents));
202     }
203
204     @SmallTest
205     @Feature({"AndroidWebView"})
206     public void testOnPageFinishedUrlIsBaseUrl() throws Throwable {
207         final String pageHtml = "<html><body>Hello, world!</body></html>";
208         final String baseUrl = "http://example.com/";
209         loadDataWithBaseUrlSync(pageHtml, "text/html", false, baseUrl, baseUrl);
210         loadDataWithBaseUrlSync(pageHtml, "text/html", false, baseUrl, baseUrl);
211         TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
212                 mContentsClient.getOnPageFinishedHelper();
213         assertEquals(baseUrl, onPageFinishedHelper.getUrl());
214     }
215
216     @SmallTest
217     @Feature({"AndroidWebView"})
218     public void testHistoryUrlIgnoredWithDataSchemeBaseUrl() throws Throwable {
219         final String pageHtml = "<html><body>bar</body></html>";
220         final String historyUrl = "http://history.com/";
221         loadDataWithBaseUrlSync(pageHtml, "text/html", false, "data:foo", historyUrl);
222         assertEquals("data:text/html," + pageHtml, HistoryUtils.getUrlOnUiThread(
223                 getInstrumentation(), mWebContents));
224     }
225
226     /*
227     @SmallTest
228     @Feature({"AndroidWebView"})
229     http://crbug.com/173274
230     */
231     @DisabledTest
232     public void testHistoryUrlNavigation() throws Throwable {
233         TestWebServer webServer = TestWebServer.start();
234         try {
235             final String historyUrl = webServer.setResponse("/" + CommonResources.ABOUT_FILENAME,
236                     CommonResources.ABOUT_HTML, CommonResources.getTextHtmlHeaders(true));
237
238             final String page1Title = "Page1";
239             final String page1Html = "<html><head><title>" + page1Title + "</title>" +
240                     "<body>" + page1Title + "</body></html>";
241
242             loadDataWithBaseUrlSync(page1Html, "text/html", false, null, historyUrl);
243             assertEquals(page1Title, getTitleOnUiThread(mAwContents));
244
245             final String page2Title = "Page2";
246             final String page2Html = "<html><head><title>" + page2Title + "</title>" +
247                     "<body>" + page2Title + "</body></html>";
248
249             final TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
250                     mContentsClient.getOnPageFinishedHelper();
251             loadDataSync(mAwContents, onPageFinishedHelper, page2Html, "text/html", false);
252             assertEquals(page2Title, getTitleOnUiThread(mAwContents));
253
254             HistoryUtils.goBackSync(getInstrumentation(), mWebContents, onPageFinishedHelper);
255             // The title of the 'about.html' specified via historyUrl.
256             assertEquals(CommonResources.ABOUT_TITLE, getTitleOnUiThread(mAwContents));
257         } finally {
258             webServer.shutdown();
259         }
260     }
261
262     /**
263      * @return true if |fileUrl| was accessible from a data url with |baseUrl| as it's
264      * base URL.
265      */
266     private boolean canAccessFileFromData(String baseUrl, String fileUrl) throws Throwable {
267         final String imageLoaded = "LOADED";
268         final String imageNotLoaded = "NOT_LOADED";
269         String data = "<html><body>" +
270                 "<img src=\"" + fileUrl + "\" " +
271                 "onload=\"document.title=\'" + imageLoaded + "\';\" " +
272                 "onerror=\"document.title=\'" + imageNotLoaded + "\';\" />" +
273                 "</body></html>";
274
275         loadDataWithBaseUrlSync(data, "text/html", false, baseUrl, null);
276
277         poll(new Callable<Boolean>() {
278             @Override
279             public Boolean call() throws Exception {
280                 String title = getTitleOnUiThread(mAwContents);
281                 return imageLoaded.equals(title) || imageNotLoaded.equals(title);
282             }
283         });
284
285         return imageLoaded.equals(getTitleOnUiThread(mAwContents));
286     }
287
288     @SmallTest
289     @Feature({"AndroidWebView"})
290     public void testLoadDataWithBaseUrlAccessingFile() throws Throwable {
291         // Create a temporary file on the filesystem we can try to read.
292         File cacheDir = getActivity().getCacheDir();
293         File tempImage = File.createTempFile("test_image", ".png", cacheDir);
294         Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.RGB_565);
295         FileOutputStream fos = new FileOutputStream(tempImage);
296         bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
297         fos.close();
298         String imagePath = tempImage.getAbsolutePath();
299
300         AwSettings contentSettings = getAwSettingsOnUiThread(mAwContents);
301         contentSettings.setImagesEnabled(true);
302         contentSettings.setJavaScriptEnabled(true);
303
304         try {
305             final String dataBaseUrl = "data:";
306             final String nonDataBaseUrl = "http://example.com";
307
308             mAwContents.getSettings().setAllowFileAccess(false);
309             String token = "" + System.currentTimeMillis();
310             // All access to file://, including android_asset and android_res is blocked
311             // with a data: base URL, regardless of AwSettings.getAllowFileAccess().
312             assertFalse(canAccessFileFromData(dataBaseUrl,
313                     "file:///android_asset/asset_icon.png?" + token));
314             assertFalse(canAccessFileFromData(dataBaseUrl,
315                     "file:///android_res/raw/resource_icon.png?" + token));
316             assertFalse(canAccessFileFromData(dataBaseUrl, "file://" + imagePath + "?" + token));
317
318             // WebView always has access to android_asset and android_res for non-data
319             // base URLs and can access other file:// URLs based on the value of
320             // AwSettings.getAllowFileAccess().
321             assertTrue(canAccessFileFromData(nonDataBaseUrl,
322                     "file:///android_asset/asset_icon.png?" + token));
323             assertTrue(canAccessFileFromData(nonDataBaseUrl,
324                     "file:///android_res/raw/resource_icon.png?" + token));
325             assertFalse(canAccessFileFromData(nonDataBaseUrl,
326                     "file://" + imagePath + "?" + token));
327
328             token += "a";
329             mAwContents.getSettings().setAllowFileAccess(true);
330             // We should still be unable to access any file:// with when loading with a
331             // data: base URL, but we should now be able to access the wider file system
332             // (still restricted by OS-level permission checks) with a non-data base URL.
333             assertFalse(canAccessFileFromData(dataBaseUrl,
334                     "file:///android_asset/asset_icon.png?" + token));
335             assertFalse(canAccessFileFromData(dataBaseUrl,
336                     "file:///android_res/raw/resource_icon.png?" + token));
337             assertFalse(canAccessFileFromData(dataBaseUrl, "file://" + imagePath + "?" + token));
338
339             assertTrue(canAccessFileFromData(nonDataBaseUrl,
340                     "file:///android_asset/asset_icon.png?" + token));
341             assertTrue(canAccessFileFromData(nonDataBaseUrl,
342                     "file:///android_res/raw/resource_icon.png?" + token));
343             assertTrue(canAccessFileFromData(nonDataBaseUrl,
344                     "file://" + imagePath + "?" + token));
345         } finally {
346             if (!tempImage.delete()) throw new AssertionError();
347         }
348     }
349 }