EMMA Coverage Report (generated Tue Aug 20 10:07:21 PDT 2013)
[all classes][org.chromium.android_webview.test]

COVERAGE SUMMARY FOR SOURCE FILE [LoadDataWithBaseUrlTest.java]

nameclass, %method, %block, %line, %
LoadDataWithBaseUrlTest.java100% (3/3)95%  (20/21)85%  (705/829)86%  (111.3/130)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class LoadDataWithBaseUrlTest100% (1/1)94%  (16/17)84%  (644/764)87%  (107.4/124)
testHistoryUrlNavigation (): void 0%   (0/1)0%   (0/78)0%   (0/16)
testSameOrigin (): void 100% (1/1)86%  (44/51)98%  (8.9/9)
testScriptLoad (): void 100% (1/1)86%  (44/51)98%  (8.9/9)
testImageLoad (): void 100% (1/1)87%  (46/53)99%  (9.9/10)
testCrossOrigin (): void 100% (1/1)88%  (49/56)99%  (9.9/10)
testLoadDataWithBaseUrlAccessingFile (): void 100% (1/1)94%  (238/252)100% (29.9/30)
LoadDataWithBaseUrlTest (): void 100% (1/1)100% (3/3)100% (1/1)
access$000 (LoadDataWithBaseUrlTest): AwContents 100% (1/1)100% (3/3)100% (1/1)
canAccessFileFromData (String, String): boolean 100% (1/1)100% (49/49)100% (6/6)
getCrossOriginAccessTestPageHtml (String): String 100% (1/1)100% (15/15)100% (1/1)
getScriptFileTestPageHtml (String): String 100% (1/1)100% (23/23)100% (1/1)
loadDataWithBaseUrlAsync (String, String, boolean, String, String): void 100% (1/1)100% (12/12)100% (2/2)
loadDataWithBaseUrlSync (String, String, boolean, String, String): void 100% (1/1)100% (21/21)100% (5/5)
setUp (): void 100% (1/1)100% (21/21)100% (6/6)
testHistoryUrl (): void 100% (1/1)100% (35/35)100% (8/8)
testHistoryUrlIgnoredWithDataSchemeBaseUrl (): void 100% (1/1)100% (19/19)100% (5/5)
testNullBaseUrl (): void 100% (1/1)100% (22/22)100% (5/5)
     
class LoadDataWithBaseUrlTest$2100% (1/1)100% (2/2)86%  (24/28)59%  (2.9/5)
isSatisfied (): boolean 100% (1/1)82%  (18/22)48%  (1.9/4)
LoadDataWithBaseUrlTest$2 (LoadDataWithBaseUrlTest): void 100% (1/1)100% (6/6)100% (1/1)
     
class LoadDataWithBaseUrlTest$1100% (1/1)100% (2/2)100% (37/37)100% (3/3)
LoadDataWithBaseUrlTest$1 (LoadDataWithBaseUrlTest, String, String, boolean, ... 100% (1/1)100% (21/21)100% (1/1)
run (): void 100% (1/1)100% (16/16)100% (2/2)

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

[all classes][org.chromium.android_webview.test]
EMMA 2.0.5312 (C) Vladimir Roubtsov