Cts tests for webview file origin policy changes
Bug: 6212665
Add cts test cases for testing file origin policy. Also fix a cts
test that can possible cause the test to freeze due to use of an
indefinite timeout.
Change-Id: I66d10747b5e677fd1e96e9399116a5b0dde7a20c
diff --git a/tests/assets/webkit/test_iframeaccess.html b/tests/assets/webkit/test_iframeaccess.html
new file mode 100644
index 0000000..1b5fc5a
--- /dev/null
+++ b/tests/assets/webkit/test_iframeaccess.html
@@ -0,0 +1,28 @@
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<html>
+ <head>
+ <title>DEFAULT TITLE</title>
+ <script type="text/javascript">
+ function load() {
+ document.title = document.getElementById('frame').contentWindow.location.href;
+ }
+ </script>
+ </head>
+ <body onload="load()">
+ <iframe id="frame" src="./test_hello_world.html"></iframe>
+ </body>
+</html>
diff --git a/tests/assets/webkit/test_imageaccess.html b/tests/assets/webkit/test_imageaccess.html
new file mode 100644
index 0000000..ce76c83
--- /dev/null
+++ b/tests/assets/webkit/test_imageaccess.html
@@ -0,0 +1,28 @@
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<html>
+ <head>
+ <title>TEST FAILED</title>
+ </head>
+ <body>
+ <img id='img' src="../images/tomato.png" onload="success()" />
+ <script>
+ function success() {
+ document.title=document.getElementById('img').naturalHeight;
+ }
+ </script>
+ </body>
+</html>
diff --git a/tests/tests/webkit/src/android/webkit/cts/ChromeClient.java b/tests/tests/webkit/src/android/webkit/cts/ChromeClient.java
new file mode 100644
index 0000000..3df78a4
--- /dev/null
+++ b/tests/tests/webkit/src/android/webkit/cts/ChromeClient.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.webkit.cts;
+
+import android.webkit.ConsoleMessage;
+import android.webkit.cts.WebViewOnUiThread.WaitForProgressClient;
+
+// A chrome client for listening webview chrome events.
+class ChromeClient extends WaitForProgressClient {
+ private boolean mIsMessageLevelAvailable;
+ private ConsoleMessage.MessageLevel mMessageLevel;
+
+ public ChromeClient(WebViewOnUiThread onUiThread) {
+ super(onUiThread);
+ }
+
+ @Override
+ public synchronized boolean onConsoleMessage(ConsoleMessage message) {
+ mMessageLevel = message.messageLevel();
+ mIsMessageLevelAvailable = true;
+ notify();
+ return true;
+ }
+
+ public synchronized ConsoleMessage.MessageLevel getMessageLevel(int timeout) {
+ for(; timeout > 0; timeout -= 1000) {
+ if( mIsMessageLevelAvailable ) break;
+ try {
+ wait(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ return mMessageLevel;
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java b/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java
index 18fdcab..63354d4 100644
--- a/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java
+++ b/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java
@@ -60,6 +60,8 @@
public static final String PARAM_ASSET_URL = "webkit/test_queryparam.html";
public static final String ANCHOR_ASSET_URL = "webkit/test_anchor.html";
+ public static final String IMAGE_ACCESS_URL = "webkit/test_imageaccess.html";
+ public static final String IFRAME_ACCESS_URL = "webkit/test_iframeaccess.html";
// Must match the title of the page at
// android/frameworks/base/core/res/res/raw/loaderror.html
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
index 27fa5a0..b969dd9 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
@@ -15,18 +15,19 @@
*/
package android.webkit.cts;
+import android.content.Context;
import android.cts.util.PollingCheck;
import android.os.Build;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
+import android.webkit.ConsoleMessage;
import android.webkit.MimeTypeMap;
-import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebSettings.LayoutAlgorithm;
import android.webkit.WebSettings.RenderPriority;
import android.webkit.WebSettings.TextSize;
-
+import java.io.FileOutputStream;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -54,6 +55,7 @@
private WebSettings mSettings;
private CtsTestServer mWebServer;
private WebViewOnUiThread mOnUiThread;
+ private Context mContext;
public WebSettingsTest() {
super("com.android.cts.stub", WebViewStubActivity.class);
@@ -64,6 +66,7 @@
super.setUp();
mOnUiThread = new WebViewOnUiThread(this, getActivity().getWebView());
mSettings = mOnUiThread.getSettings();
+ mContext = getInstrumentation().getTargetContext();
}
@Override
@@ -676,6 +679,106 @@
assertEquals(NETWORK_IMAGE_HEIGHT, mOnUiThread.getTitle());
}
+ // Verify that an image in local file system can be loaded by an asset
+ public void testLocalImageLoads() throws Throwable {
+
+ mSettings.setJavaScriptEnabled(true);
+ // Check that local images are loaded without issues regardless of domain checkings
+ mSettings.setAllowUniversalAccessFromFileURLs(false);
+ mSettings.setAllowFileAccessFromFileURLs(false);
+ String url = TestHtmlConstants.getFileUrl(TestHtmlConstants.IMAGE_ACCESS_URL);
+ mOnUiThread.loadUrlAndWaitForCompletion(url);
+ waitForNonEmptyImage();
+ assertEquals(NETWORK_IMAGE_HEIGHT, mOnUiThread.getTitle());
+ }
+
+ // Verify that javascript cross-domain request permissions matches file domain settings
+ // for iframes
+ public void testIframesWhenAccessFromFileURLsEnabled() throws Throwable {
+
+ mSettings.setJavaScriptEnabled(true);
+ // disable universal access from files
+ mSettings.setAllowUniversalAccessFromFileURLs(false);
+ mSettings.setAllowFileAccessFromFileURLs(true);
+
+ // when cross file scripting is enabled, make sure cross domain requests succeed
+ String url = TestHtmlConstants.getFileUrl(TestHtmlConstants.IFRAME_ACCESS_URL);
+ mOnUiThread.loadUrlAndWaitForCompletion(url);
+ String iframeUrl = TestHtmlConstants.getFileUrl(TestHtmlConstants.HELLO_WORLD_URL);
+ assertEquals(iframeUrl, mOnUiThread.getTitle());
+ }
+
+ // Verify that javascript cross-domain request permissions matches file domain settings
+ // for iframes
+ public void testIframesWhenAccessFromFileURLsDisabled() throws Throwable {
+
+ mSettings.setJavaScriptEnabled(true);
+ // disable universal access from files
+ mSettings.setAllowUniversalAccessFromFileURLs(false);
+ mSettings.setAllowFileAccessFromFileURLs(false);
+
+ // when cross file scripting is disabled, make sure cross domain requests fail
+ final ChromeClient webChromeClient = new ChromeClient(mOnUiThread);
+ mOnUiThread.setWebChromeClient(webChromeClient);
+ String url = TestHtmlConstants.getFileUrl(TestHtmlConstants.IFRAME_ACCESS_URL);
+ mOnUiThread.loadUrlAndWaitForCompletion(url);
+ String iframeUrl = TestHtmlConstants.getFileUrl(TestHtmlConstants.HELLO_WORLD_URL);
+ assertFalse(iframeUrl.equals(mOnUiThread.getTitle()));
+ assertEquals(ConsoleMessage.MessageLevel.ERROR, webChromeClient.getMessageLevel(10000));
+ }
+
+ // Verify that enabling file access from file URLs enable XmlHttpRequest (XHR) across files
+ public void testXHRWhenAccessFromFileURLsEnabled() throws Throwable {
+ verifyFileXHR(true);
+ }
+
+ // Verify that disabling file access from file URLs disable XmlHttpRequest (XHR) accross files
+ public void testXHRWhenAccessFromFileURLsDisabled() throws Throwable {
+
+ final ChromeClient webChromeClient = new ChromeClient(mOnUiThread);
+ mOnUiThread.setWebChromeClient(webChromeClient);
+ verifyFileXHR(false);
+ assertEquals(ConsoleMessage.MessageLevel.ERROR, webChromeClient.getMessageLevel(10000));
+ }
+
+ // verify XHR across files matches the allowFileAccessFromFileURLs setting
+ private void verifyFileXHR(boolean enableXHR) throws Throwable {
+ // target file content
+ String target ="<html><body>target</body><html>";
+
+ String targetPath = mContext.getFileStreamPath("target.html").getAbsolutePath();
+ // local file content that use XHR to read the target file
+ String local ="" +
+ "<html><body><script>" +
+ "var client = new XMLHttpRequest();" +
+ "client.open('GET', 'file://" + targetPath + "',false);" +
+ "client.send();" +
+ "document.title = client.responseText;" +
+ "</script></body></html>";
+
+ // create files in internal storage
+ writeFile("local.html", local);
+ writeFile("target.html", target);
+
+ mSettings.setJavaScriptEnabled(true);
+ // disable universal access from files
+ mSettings.setAllowUniversalAccessFromFileURLs(false);
+ mSettings.setAllowFileAccessFromFileURLs(enableXHR);
+ String localPath = mContext.getFileStreamPath("local.html").getAbsolutePath();
+ // when cross file scripting is enabled, make sure cross domain requests succeed
+ mOnUiThread.loadUrlAndWaitForCompletion("file://" + localPath);
+ if (enableXHR) assertEquals(target, mOnUiThread.getTitle());
+ else assertFalse(target.equals(mOnUiThread.getTitle()));
+ }
+
+ // Create a private file on internal storage from the given string
+ private void writeFile(String filename, String content) throws Exception {
+
+ FileOutputStream fos = mContext.openFileOutput(filename, Context.MODE_PRIVATE);
+ fos.write(content.getBytes());
+ fos.close();
+ }
+
/**
* Starts the internal web server. The server will be shut down automatically
* during tearDown().
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
index 3477253..87d0dc3 100755
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -745,34 +745,8 @@
"text/html", null);
assertEquals("Hello,World!", mOnUiThread.getTitle());
- // Test that JavaScript can't access cross-origin content.
- class ConsoleMessageWebChromeClient extends WaitForProgressClient {
- private boolean mIsMessageLevelAvailable;
- private ConsoleMessage.MessageLevel mMessageLevel;
-
- public ConsoleMessageWebChromeClient() {
- super(mOnUiThread);
- }
-
- @Override
- public synchronized boolean onConsoleMessage(ConsoleMessage message) {
- mMessageLevel = message.messageLevel();
- mIsMessageLevelAvailable = true;
- notify();
- return true;
- }
- public synchronized ConsoleMessage.MessageLevel getMessageLevel() {
- while (!mIsMessageLevelAvailable) {
- try {
- wait();
- } catch (InterruptedException e) {
- }
- }
- return mMessageLevel;
- }
- }
startWebServer(false);
- final ConsoleMessageWebChromeClient webChromeClient = new ConsoleMessageWebChromeClient();
+ final ChromeClient webChromeClient = new ChromeClient(mOnUiThread);
final String crossOriginUrl = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
runTestOnUiThread(new Runnable() {
@Override
@@ -787,7 +761,7 @@
"text/html", null);
}
});
- assertEquals(ConsoleMessage.MessageLevel.ERROR, webChromeClient.getMessageLevel());
+ assertEquals(ConsoleMessage.MessageLevel.ERROR, webChromeClient.getMessageLevel(10000));
}
@UiThreadTest