diff options
author | Phil Dubach <phillipd@google.com> | 2009-10-30 14:27:21 -0700 |
---|---|---|
committer | Phil Dubach <phillipd@google.com> | 2009-11-13 15:01:08 -0800 |
commit | 66a3677e838e6ed1f63f89918ce8cf4e6372ccae (patch) | |
tree | c1684c10e9b2685c6fa6af9e5e8a9abb195829fd | |
parent | b8abc38d471e8e83d81899c70e65d34cb9e92944 (diff) | |
download | cts-66a3677e838e6ed1f63f89918ce8cf4e6372ccae.tar.gz |
Integrate unsubmitted cupcake change 149424:
CTS: add test cases for android.webkit.WebChromeClient and WebViewClient
Change-Id: Ibcb44e264cb25272874f9aff1083e15abc123ff4
-rw-r--r-- | tests/assets/webkit/jsalert.html | 29 | ||||
-rw-r--r-- | tests/assets/webkit/jsconfirm.html | 34 | ||||
-rw-r--r-- | tests/assets/webkit/jsform.html | 34 | ||||
-rw-r--r-- | tests/assets/webkit/jsprompt.html | 31 | ||||
-rw-r--r-- | tests/assets/webkit/jsunload.html | 30 | ||||
-rw-r--r-- | tests/assets/webkit/jswindow.html | 33 | ||||
-rw-r--r-- | tests/src/android/webkit/cts/CtsTestServer.java | 226 | ||||
-rw-r--r-- | tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java | 7 | ||||
-rw-r--r-- | tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java | 470 | ||||
-rw-r--r-- | tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java | 408 |
10 files changed, 1194 insertions, 108 deletions
diff --git a/tests/assets/webkit/jsalert.html b/tests/assets/webkit/jsalert.html new file mode 100644 index 00000000000..c4b35fafbae --- /dev/null +++ b/tests/assets/webkit/jsalert.html @@ -0,0 +1,29 @@ +<!-- 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>javascript alert</title> + </head> + <script type="text/javascript"> + function fireAlert() { + alert("testOnJsAlert"); + } + </script> + <body onload="fireAlert()"> + javascript alert test + </body> +</html> + diff --git a/tests/assets/webkit/jsconfirm.html b/tests/assets/webkit/jsconfirm.html new file mode 100644 index 00000000000..720c5de1e13 --- /dev/null +++ b/tests/assets/webkit/jsconfirm.html @@ -0,0 +1,34 @@ +<!-- 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>javascript confirm</title> + </head> + <script type="text/javascript"> + function fireConfirm() { + var res = confirm("testOnJsConfirm"); + if (res == true) { + document.title = "OK"; + } else { + document.title = "Cancel"; + } + } + </script> + <body onload="fireConfirm()"> + javascript confirm test + </body> +</html> + diff --git a/tests/assets/webkit/jsform.html b/tests/assets/webkit/jsform.html new file mode 100644 index 00000000000..ddf01f8ade1 --- /dev/null +++ b/tests/assets/webkit/jsform.html @@ -0,0 +1,34 @@ +<!-- 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>javascript form</title> + </head> + <script type="text/javascript"> + function fireSubmit() { + if (location.hash == "") { + document.getElementById("formId").submit(); + } + } + </script> + <body onload="fireSubmit()"> + javascript form test + <form id="formId" action="test.html#result" method="post"> + <input type="hidden" name="foo" value="bar" /> + </form> + </body> +</html> + diff --git a/tests/assets/webkit/jsprompt.html b/tests/assets/webkit/jsprompt.html new file mode 100644 index 00000000000..a6b7d57e97d --- /dev/null +++ b/tests/assets/webkit/jsprompt.html @@ -0,0 +1,31 @@ + +<!-- 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>javascript prompt</title> + </head> + <script type="text/javascript"> + function firePrompt() { + var res = prompt("testOnJsPrompt"); + document.title = res; + } + </script> + <body onload="firePrompt()"> + javascript prompt test + </body> +</html> + diff --git a/tests/assets/webkit/jsunload.html b/tests/assets/webkit/jsunload.html new file mode 100644 index 00000000000..fb0673e0acb --- /dev/null +++ b/tests/assets/webkit/jsunload.html @@ -0,0 +1,30 @@ +<!-- 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>javascript unload</title> + </head> + <script type="text/javascript"> + function fireUnload() { + return "testOnJsBeforeUnload"; + } + window.onbeforeunload = fireUnload; + </script> + <body> + javascript unload test + </body> +</html> + diff --git a/tests/assets/webkit/jswindow.html b/tests/assets/webkit/jswindow.html new file mode 100644 index 00000000000..bc723f745c1 --- /dev/null +++ b/tests/assets/webkit/jswindow.html @@ -0,0 +1,33 @@ +<!-- 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>javascript window</title> + </head> + <script type="text/javascript"> + function fireOpen() { + childWindow = window.open(); + childWindow.document.title = "javascript child window"; + childWindow.document.write("javascript child window"); + childWindow.focus(); + setTimeout("childWindow.close()", 2000); + } + </script> + <body onload="fireOpen()"> + javascript window test + </body> +</html> + diff --git a/tests/src/android/webkit/cts/CtsTestServer.java b/tests/src/android/webkit/cts/CtsTestServer.java index a45589dc067..9ec7ee68a36 100644 --- a/tests/src/android/webkit/cts/CtsTestServer.java +++ b/tests/src/android/webkit/cts/CtsTestServer.java @@ -25,7 +25,6 @@ import org.apache.http.HttpVersion; import org.apache.http.NameValuePair; import org.apache.http.RequestLine; import org.apache.http.StatusLine; -import org.apache.http.client.methods.HttpGet; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.entity.InputStreamEntity; @@ -207,8 +206,21 @@ public class CtsTestServer { * @param path The path of the asset. See {@link AssetManager#open(String)} */ public String getRedirectingAssetUrl(String path) { + return getRedirectingAssetUrl(path, 1); + } + + /** + * Return an absolute URL that indirectly refers to the given asset. + * When a client fetches this URL, the server will respond with a temporary redirect (302) + * referring to the absolute URL of the given asset. + * @param path The path of the asset. See {@link AssetManager#open(String)} + * @param numRedirects The number of redirects required to reach the given asset. + */ + public String getRedirectingAssetUrl(String path, int numRedirects) { StringBuilder sb = new StringBuilder(getBaseUri()); - sb.append(REDIRECT_PREFIX); + for (int i = 0; i < numRedirects; i++) { + sb.append(REDIRECT_PREFIX); + } sb.append(ASSET_PREFIX); sb.append(path); return sb.toString(); @@ -271,126 +283,124 @@ public class CtsTestServer { RequestLine requestLine = request.getRequestLine(); HttpResponse response = null; mRequestCount += 1; - if (requestLine.getMethod().equals(HttpGet.METHOD_NAME)) { - Log.i(TAG, "GET: " + requestLine.getUri()); - String uriString = requestLine.getUri(); - mLastQuery = uriString; - URI uri = URI.create(uriString); - String path = uri.getPath(); - if (path.equals(FAVICON_PATH)) { - path = FAVICON_ASSET_PATH; - } - if (path.startsWith(DELAY_PREFIX)) { - try { - Thread.sleep(DELAY_MILLIS); - } catch (InterruptedException ignored) { - // ignore - } - path = path.substring(DELAY_PREFIX.length()); + Log.i(TAG, requestLine.getMethod() + ": " + requestLine.getUri()); + String uriString = requestLine.getUri(); + mLastQuery = uriString; + URI uri = URI.create(uriString); + String path = uri.getPath(); + if (path.equals(FAVICON_PATH)) { + path = FAVICON_ASSET_PATH; + } + if (path.startsWith(DELAY_PREFIX)) { + try { + Thread.sleep(DELAY_MILLIS); + } catch (InterruptedException ignored) { + // ignore } - if (path.startsWith(AUTH_PREFIX)) { - // authentication required - Header[] auth = request.getHeaders("Authorization"); - if (auth.length > 0) { - if (auth[0].getValue().equals(AUTH_CREDENTIALS)) { - // fall through and serve content - path = path.substring(AUTH_PREFIX.length()); - } else { - // incorrect password - response = createResponse(HttpStatus.SC_FORBIDDEN); - } + path = path.substring(DELAY_PREFIX.length()); + } + if (path.startsWith(AUTH_PREFIX)) { + // authentication required + Header[] auth = request.getHeaders("Authorization"); + if (auth.length > 0) { + if (auth[0].getValue().equals(AUTH_CREDENTIALS)) { + // fall through and serve content + path = path.substring(AUTH_PREFIX.length()); } else { - // request authorization - response = createResponse(HttpStatus.SC_UNAUTHORIZED); - response.addHeader("WWW-Authenticate", "Basic realm=\"" + AUTH_REALM + "\""); + // incorrect password + response = createResponse(HttpStatus.SC_FORBIDDEN); } + } else { + // request authorization + response = createResponse(HttpStatus.SC_UNAUTHORIZED); + response.addHeader("WWW-Authenticate", "Basic realm=\"" + AUTH_REALM + "\""); } - if (path.startsWith(BINARY_PREFIX)) { - List <NameValuePair> args = URLEncodedUtils.parse(uri, "UTF-8"); - int length = 0; - String mimeType = null; - try { - for (NameValuePair pair : args) { - String name = pair.getName(); - if (name.equals("type")) { - mimeType = pair.getValue(); - } else if (name.equals("length")) { - length = Integer.parseInt(pair.getValue()); - } - } - if (length > 0 && mimeType != null) { - ByteArrayEntity entity = new ByteArrayEntity(new byte[length]); - entity.setContentType(mimeType); - response = createResponse(HttpStatus.SC_OK); - response.setEntity(entity); - response.addHeader("Content-Disposition", "attachment; filename=test.bin"); - } else { - // fall through, return 404 at the end + } + if (path.startsWith(BINARY_PREFIX)) { + List <NameValuePair> args = URLEncodedUtils.parse(uri, "UTF-8"); + int length = 0; + String mimeType = null; + try { + for (NameValuePair pair : args) { + String name = pair.getName(); + if (name.equals("type")) { + mimeType = pair.getValue(); + } else if (name.equals("length")) { + length = Integer.parseInt(pair.getValue()); } - } catch (Exception e) { - // fall through, return 404 at the end - Log.w(TAG, e); } - } else if (path.startsWith(ASSET_PREFIX)) { - path = path.substring(ASSET_PREFIX.length()); - // request for an asset file - try { - InputStream in = mAssets.open(path); - response = createResponse(HttpStatus.SC_OK); - InputStreamEntity entity = new InputStreamEntity(in, in.available()); - String mimeType = - mMap.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(path)); - if (mimeType == null) { - mimeType = "text/html"; - } + if (length > 0 && mimeType != null) { + ByteArrayEntity entity = new ByteArrayEntity(new byte[length]); entity.setContentType(mimeType); + response = createResponse(HttpStatus.SC_OK); response.setEntity(entity); - } catch (IOException e) { - response = null; + response.addHeader("Content-Disposition", "attachment; filename=test.bin"); + } else { // fall through, return 404 at the end } - } else if (path.startsWith(REDIRECT_PREFIX)) { - response = createResponse(HttpStatus.SC_MOVED_TEMPORARILY); - String location = getBaseUri() + path.substring(REDIRECT_PREFIX.length()); - Log.i(TAG, "Redirecting to: " + location); - response.addHeader("Location", location); - } else if (path.startsWith(COOKIE_PREFIX)) { - /* - * Return a page with a title containing a list of all incoming cookies, - * separated by '|' characters. If a numeric 'count' value is passed in a cookie, - * return a cookie with the value incremented by 1. Otherwise, return a cookie - * setting 'count' to 0. - */ + } catch (Exception e) { + // fall through, return 404 at the end + Log.w(TAG, e); + } + } else if (path.startsWith(ASSET_PREFIX)) { + path = path.substring(ASSET_PREFIX.length()); + // request for an asset file + try { + InputStream in = mAssets.open(path); response = createResponse(HttpStatus.SC_OK); - Header[] cookies = request.getHeaders("Cookie"); - Pattern p = Pattern.compile("count=(\\d+)"); - StringBuilder cookieString = new StringBuilder(100); - int count = 0; - for (Header cookie : cookies) { - String value = cookie.getValue(); - if (cookieString.length() > 0) { - cookieString.append("|"); - } - cookieString.append(value); - Matcher m = p.matcher(value); - if (m.find()) { - count = Integer.parseInt(m.group(1)) + 1; - } + InputStreamEntity entity = new InputStreamEntity(in, in.available()); + String mimeType = + mMap.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(path)); + if (mimeType == null) { + mimeType = "text/html"; } - - response.addHeader("Set-Cookie", "count=" + count + "; path=" + COOKIE_PREFIX); - response.setEntity(createEntity("<html><head><title>" + cookieString + - "</title></head><body>" + cookieString + "</body></html>")); - } else if (path.equals(USERAGENT_PATH)) { - response = createResponse(HttpStatus.SC_OK); - Header agentHeader = request.getFirstHeader("User-Agent"); - String agent = ""; - if (agentHeader != null) { - agent = agentHeader.getValue(); + entity.setContentType(mimeType); + response.setEntity(entity); + } catch (IOException e) { + response = null; + // fall through, return 404 at the end + } + } else if (path.startsWith(REDIRECT_PREFIX)) { + response = createResponse(HttpStatus.SC_MOVED_TEMPORARILY); + String location = getBaseUri() + path.substring(REDIRECT_PREFIX.length()); + Log.i(TAG, "Redirecting to: " + location); + response.addHeader("Location", location); + } else if (path.startsWith(COOKIE_PREFIX)) { + /* + * Return a page with a title containing a list of all incoming cookies, + * separated by '|' characters. If a numeric 'count' value is passed in a cookie, + * return a cookie with the value incremented by 1. Otherwise, return a cookie + * setting 'count' to 0. + */ + response = createResponse(HttpStatus.SC_OK); + Header[] cookies = request.getHeaders("Cookie"); + Pattern p = Pattern.compile("count=(\\d+)"); + StringBuilder cookieString = new StringBuilder(100); + int count = 0; + for (Header cookie : cookies) { + String value = cookie.getValue(); + if (cookieString.length() > 0) { + cookieString.append("|"); + } + cookieString.append(value); + Matcher m = p.matcher(value); + if (m.find()) { + count = Integer.parseInt(m.group(1)) + 1; } - response.setEntity(createEntity("<html><head><title>" + agent + "</title></head>" + - "<body>" + agent + "</body></html>")); } + + response.addHeader("Set-Cookie", "count=" + count + "; path=" + COOKIE_PREFIX); + response.setEntity(createEntity("<html><head><title>" + cookieString + + "</title></head><body>" + cookieString + "</body></html>")); + } else if (path.equals(USERAGENT_PATH)) { + response = createResponse(HttpStatus.SC_OK); + Header agentHeader = request.getFirstHeader("User-Agent"); + String agent = ""; + if (agentHeader != null) { + agent = agentHeader.getValue(); + } + response.setEntity(createEntity("<html><head><title>" + agent + "</title></head>" + + "<body>" + agent + "</body></html>")); } if (response == null) { response = createResponse(HttpStatus.SC_NOT_FOUND); diff --git a/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java b/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java index cc2939bdca6..b2bdfc85f14 100644 --- a/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java +++ b/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java @@ -34,6 +34,13 @@ public class TestHtmlConstants { public static final String EMBEDDED_IMG_URL = "webkit/embedded_image.html"; public static final String POPUP_URL = "webkit/popup_base.html"; public static final String JAVASCRIPT_URL = "webkit/javascript.html"; + public static final String JS_ALERT_URL = "webkit/jsalert.html"; + public static final String JS_CONFIRM_URL = "webkit/jsconfirm.html"; + public static final String JS_PROMPT_URL = "webkit/jsprompt.html"; + public static final String JS_UNLOAD_URL = "webkit/jsunload.html"; + public static final String JS_WINDOW_URL = "webkit/jswindow.html"; + public static final String JS_TIMEOUT_URL = "webkit/jstimeout.html"; + public static final String JS_FORM_URL = "webkit/jsform.html"; public static final String FONT_URL = "webkit/fonts.html"; diff --git a/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java new file mode 100644 index 00000000000..7c1f8508e75 --- /dev/null +++ b/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java @@ -0,0 +1,470 @@ +/* + * 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 dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargets; + +import android.graphics.Bitmap; +import android.os.Message; +import android.test.ActivityInstrumentationTestCase2; +import android.view.animation.cts.DelayedCheck; +import android.webkit.JsPromptResult; +import android.webkit.JsResult; +import android.webkit.WebChromeClient; +import android.webkit.WebIconDatabase; +import android.webkit.WebSettings; +import android.webkit.WebView; + +@TestTargetClass(android.webkit.WebChromeClient.class) +public class WebChromeClientTest extends ActivityInstrumentationTestCase2<WebViewStubActivity> { + private static final long TEST_TIMEOUT = 5000L; + + private WebView mWebView; + private CtsTestServer mWebServer; + private WebIconDatabase mIconDb; + + public WebChromeClientTest() { + super("com.android.cts.stub", WebViewStubActivity.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + mWebView = getActivity().getWebView(); + mWebServer = new CtsTestServer(getActivity()); + } + + @Override + protected void tearDown() throws Exception { + mWebView.clearHistory(); + mWebView.clearCache(true); + if (mWebServer != null) { + mWebServer.shutdown(); + } + if (mIconDb != null) { + mIconDb.removeAllIcons(); + mIconDb.close(); + } + super.tearDown(); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onProgressChanged", + args = {WebView.class, int.class} + ) + }) + public void testOnProgressChanged() throws InterruptedException { + final MockWebChromeClient webChromeClient = new MockWebChromeClient(); + mWebView.setWebChromeClient(webChromeClient); + + assertFalse(webChromeClient.hadOnProgressChanged()); + mWebView.loadUrl(TestHtmlConstants.HELLO_WORLD_URL); + + new DelayedCheck(TEST_TIMEOUT) { + @Override + protected boolean check() { + return webChromeClient.hadOnProgressChanged(); + } + }.run(); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onReceivedTitle", + args = {WebView.class, String.class} + ) + }) + public void testOnReceivedTitle() throws Exception { + final MockWebChromeClient webChromeClient = new MockWebChromeClient(); + mWebView.setWebChromeClient(webChromeClient); + + assertFalse(webChromeClient.hadOnReceivedTitle()); + String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); + mWebView.loadUrl(url); + + new DelayedCheck(TEST_TIMEOUT) { + @Override + protected boolean check() { + return webChromeClient.hadOnReceivedTitle(); + } + }.run(); + assertTrue(webChromeClient.hadOnReceivedTitle()); + assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, webChromeClient.getPageTitle()); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onReceivedIcon", + args = {WebView.class, Bitmap.class} + ) + }) + public void testOnReceivedIcon() { + final MockWebChromeClient webChromeClient = new MockWebChromeClient(); + mWebView.setWebChromeClient(webChromeClient); + + WebIconDatabase mIconDb = WebIconDatabase.getInstance(); + String dbPath = getActivity().getFilesDir().toString() + "/icons"; + mIconDb.open(dbPath); + mIconDb.removeAllIcons(); + + assertFalse(webChromeClient.hadOnReceivedIcon()); + + String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); + mWebView.loadUrl(url); + + new DelayedCheck(TEST_TIMEOUT) { + @Override + protected boolean check() { + return webChromeClient.hadOnReceivedIcon(); + } + }.run(); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onCreateWindow", + args = {WebView.class, boolean.class, boolean.class, Message.class} + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onRequestFocus", + args = {WebView.class} + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onCloseWindow", + args = {WebView.class} + ) + }) + public void testWindows() throws Exception { + final MockWebChromeClient webChromeClient = new MockWebChromeClient(); + mWebView.setWebChromeClient(webChromeClient); + + final WebSettings settings = mWebView.getSettings(); + settings.setJavaScriptEnabled(true); + settings.setJavaScriptCanOpenWindowsAutomatically(true); + settings.setSupportMultipleWindows(true); + + assertFalse(webChromeClient.hadOnCreateWindow()); + + // load a page that opens a child window, requests focus for the child and sets a timeout + // after which the child will be closed + loadUrl(mWebServer.getAssetUrl(TestHtmlConstants.JS_WINDOW_URL)); + + new DelayedCheck(TEST_TIMEOUT) { + @Override + protected boolean check() { + return webChromeClient.hadOnCreateWindow(); + } + }.run(); + assertTrue(webChromeClient.hadOnRequestFocus()); + new DelayedCheck(TEST_TIMEOUT) { + @Override + protected boolean check() { + return webChromeClient.hadOnCloseWindow(); + } + }.run(); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onJsBeforeUnload", + args = {WebView.class, String.class, String.class, JsResult.class} + ) + }) + public void testOnJsBeforeUnload() throws Exception { + final MockWebChromeClient webChromeClient = new MockWebChromeClient(); + mWebView.setWebChromeClient(webChromeClient); + + final WebSettings settings = mWebView.getSettings(); + settings.setJavaScriptEnabled(true); + settings.setJavaScriptCanOpenWindowsAutomatically(true); + + assertFalse(webChromeClient.hadOnJsBeforeUnload()); + + loadUrl(mWebServer.getAssetUrl(TestHtmlConstants.JS_UNLOAD_URL)); + // unload should trigger when we try to navigate away + loadUrl(mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL)); + + new DelayedCheck(TEST_TIMEOUT) { + @Override + protected boolean check() { + return webChromeClient.hadOnJsBeforeUnload(); + } + }.run(); + assertEquals(webChromeClient.getMessage(), "testOnJsBeforeUnload"); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onJsAlert", + args = {WebView.class, String.class, String.class, JsResult.class} + ) + }) + public void testOnJsAlert() throws Exception { + final MockWebChromeClient webChromeClient = new MockWebChromeClient(); + mWebView.setWebChromeClient(webChromeClient); + + final WebSettings settings = mWebView.getSettings(); + settings.setJavaScriptEnabled(true); + settings.setJavaScriptCanOpenWindowsAutomatically(true); + + assertFalse(webChromeClient.hadOnJsAlert()); + + String url = mWebServer.getAssetUrl(TestHtmlConstants.JS_ALERT_URL); + mWebView.loadUrl(url); + + new DelayedCheck(TEST_TIMEOUT) { + @Override + protected boolean check() { + return webChromeClient.hadOnJsAlert(); + } + }.run(); + assertEquals(webChromeClient.getMessage(), "testOnJsAlert"); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onJsConfirm", + args = {WebView.class, String.class, String.class, JsResult.class} + ) + }) + public void testOnJsConfirm() throws Exception { + final MockWebChromeClient webChromeClient = new MockWebChromeClient(); + mWebView.setWebChromeClient(webChromeClient); + + final WebSettings settings = mWebView.getSettings(); + settings.setJavaScriptEnabled(true); + settings.setJavaScriptCanOpenWindowsAutomatically(true); + + assertFalse(webChromeClient.hadOnJsConfirm()); + + String url = mWebServer.getAssetUrl(TestHtmlConstants.JS_CONFIRM_URL); + mWebView.loadUrl(url); + + new DelayedCheck(TEST_TIMEOUT) { + @Override + protected boolean check() { + return webChromeClient.hadOnJsConfirm(); + } + }.run(); + assertEquals(webChromeClient.getMessage(), "testOnJsConfirm"); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onJsPrompt", + args = {WebView.class, String.class, String.class, String.class, JsPromptResult.class} + ) + }) + public void testOnJsPrompt() throws Exception { + final MockWebChromeClient webChromeClient = new MockWebChromeClient(); + mWebView.setWebChromeClient(webChromeClient); + + final WebSettings settings = mWebView.getSettings(); + settings.setJavaScriptEnabled(true); + settings.setJavaScriptCanOpenWindowsAutomatically(true); + + assertFalse(webChromeClient.hadOnJsPrompt()); + + final String promptResult = "CTS"; + webChromeClient.setPromptResult(promptResult); + String url = mWebServer.getAssetUrl(TestHtmlConstants.JS_PROMPT_URL); + mWebView.loadUrl(url); + + new DelayedCheck(TEST_TIMEOUT) { + @Override + protected boolean check() { + return webChromeClient.hadOnJsPrompt(); + } + }.run(); + // the result returned by the client gets set as the page title + new DelayedCheck(TEST_TIMEOUT) { + protected boolean check() { + return mWebView.getTitle().equals(promptResult); + } + }.run(); + assertEquals(webChromeClient.getMessage(), "testOnJsPrompt"); + } + + private void loadUrl(String url) { + mWebView.loadUrl(url); + new DelayedCheck(TEST_TIMEOUT) { + protected boolean check() { + return mWebView.getProgress() == 100; + } + }.run(); + } + + private class MockWebChromeClient extends WebChromeClient { + private boolean mHadOnProgressChanged; + private boolean mHadOnReceivedTitle; + private String mPageTitle; + private boolean mHadOnJsAlert; + private boolean mHadOnJsConfirm; + private boolean mHadOnJsPrompt; + private boolean mHadOnJsBeforeUnload; + private String mMessage; + private String mPromptResult; + private boolean mHadOnCloseWindow; + private boolean mHadOnCreateWindow; + private boolean mHadOnRequestFocus; + private boolean mHadOnReceivedIcon; + + public void setPromptResult(String promptResult) { + mPromptResult = promptResult; + } + + public boolean hadOnProgressChanged() { + return mHadOnProgressChanged; + } + + public boolean hadOnReceivedTitle() { + return mHadOnReceivedTitle; + } + + public String getPageTitle() { + return mPageTitle; + } + + public boolean hadOnJsAlert() { + return mHadOnJsAlert; + } + + public boolean hadOnJsConfirm() { + return mHadOnJsConfirm; + } + + public boolean hadOnJsPrompt() { + return mHadOnJsPrompt; + } + + public boolean hadOnJsBeforeUnload() { + return mHadOnJsBeforeUnload; + } + + public boolean hadOnCreateWindow() { + return mHadOnCreateWindow; + } + + public boolean hadOnCloseWindow() { + return mHadOnCloseWindow; + } + + public boolean hadOnRequestFocus() { + return mHadOnRequestFocus; + } + + public boolean hadOnReceivedIcon() { + return mHadOnReceivedIcon; + } + + public String getMessage() { + return mMessage; + } + + @Override + public void onProgressChanged(WebView view, int newProgress) { + super.onProgressChanged(view, newProgress); + mHadOnProgressChanged = true; + } + + @Override + public void onReceivedTitle(WebView view, String title) { + super.onReceivedTitle(view, title); + mPageTitle = title; + mHadOnReceivedTitle = true; + } + + @Override + public boolean onJsAlert(WebView view, String url, String message, JsResult result) { + super.onJsAlert(view, url, message, result); + mHadOnJsAlert = true; + mMessage = message; + result.confirm(); + return true; + } + + @Override + public boolean onJsConfirm(WebView view, String url, String message, JsResult result) { + super.onJsConfirm(view, url, message, result); + mHadOnJsConfirm = true; + mMessage = message; + result.confirm(); + return true; + } + + @Override + public boolean onJsPrompt(WebView view, String url, String message, + String defaultValue, JsPromptResult result) { + super.onJsPrompt(view, url, message, defaultValue, result); + mHadOnJsPrompt = true; + mMessage = message; + result.confirm(mPromptResult); + return true; + } + + @Override + public boolean onJsBeforeUnload(WebView view, String url, String message, JsResult result) { + super.onJsBeforeUnload(view, url, message, result); + mHadOnJsBeforeUnload = true; + mMessage = message; + result.confirm(); + return true; + } + + @Override + public void onCloseWindow(WebView window) { + super.onCloseWindow(window); + mHadOnCloseWindow = true; + } + + @Override + public boolean onCreateWindow(WebView view, boolean dialog, boolean userGesture, + Message resultMsg) { + WebView childView = new WebView(getActivity()); + childView.setWebChromeClient(this); + WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj; + transport.setWebView(childView); + resultMsg.sendToTarget(); + mHadOnCreateWindow = true; + return true; + } + + @Override + public void onRequestFocus(WebView view) { + mHadOnRequestFocus = true; + } + + @Override + public void onReceivedIcon(WebView view, Bitmap icon) { + mHadOnReceivedIcon = true; + } + } +} diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java new file mode 100644 index 00000000000..dffec7e7e4b --- /dev/null +++ b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java @@ -0,0 +1,408 @@ +/* + * 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 dalvik.annotation.TestLevel; +import dalvik.annotation.TestTargetClass; +import dalvik.annotation.TestTargetNew; +import dalvik.annotation.TestTargets; +import dalvik.annotation.ToBeFixed; + +import android.graphics.Bitmap; +import android.os.Message; +import android.test.ActivityInstrumentationTestCase2; +import android.view.KeyEvent; +import android.view.animation.cts.DelayedCheck; +import android.webkit.HttpAuthHandler; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; + +@TestTargetClass(android.webkit.WebViewClient.class) +public class WebViewClientTest extends ActivityInstrumentationTestCase2<WebViewStubActivity> { + private static final long TEST_TIMEOUT = 5000; + + private WebView mWebView; + private CtsTestServer mWebServer; + + public WebViewClientTest() { + super("com.android.cts.stub", WebViewStubActivity.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + mWebView = getActivity().getWebView(); + } + + @Override + protected void tearDown() throws Exception { + mWebView.clearHistory(); + mWebView.clearCache(true); + if (mWebServer != null) { + mWebServer.shutdown(); + } + super.tearDown(); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "shouldOverrideUrlLoading", + args = {WebView.class, String.class} + ) + public void testShouldOverrideUrlLoading() { + final MockWebViewClient webViewClient = new MockWebViewClient(); + assertFalse(webViewClient.shouldOverrideUrlLoading(mWebView, null)); + } + + @TestTargets({ + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onPageStarted", + args = {WebView.class, String.class, Bitmap.class} + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onPageFinished", + args = {WebView.class, String.class} + ), + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onLoadResource", + args = {WebView.class, String.class} + ) + }) + public void testLoadPage() throws Exception { + final MockWebViewClient webViewClient = new MockWebViewClient(); + mWebView.setWebViewClient(webViewClient); + mWebServer = new CtsTestServer(getActivity()); + String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); + + assertFalse(webViewClient.hasOnPageStartedCalled()); + assertFalse(webViewClient.hasOnLoadResourceCalled()); + assertFalse(webViewClient.hasOnPageFinishedCalled()); + mWebView.loadUrl(url); + + new DelayedCheck(TEST_TIMEOUT) { + protected boolean check() { + return webViewClient.hasOnPageStartedCalled(); + } + }.run(); + + new DelayedCheck(TEST_TIMEOUT) { + protected boolean check() { + return webViewClient.hasOnLoadResourceCalled(); + } + }.run(); + + new DelayedCheck(TEST_TIMEOUT) { + protected boolean check() { + return webViewClient.hasOnPageFinishedCalled(); + } + }.run(); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onTooManyRedirects", + args = {WebView.class, Message.class, Message.class} + ) + @ToBeFixed(explanation="onTooManyRedirects() is never called") + public void testOnTooManyRedirects() throws Exception { + final MockWebViewClient webViewClient = new MockWebViewClient(); + mWebView.setWebViewClient(webViewClient); + mWebServer = new CtsTestServer(getActivity()); + + assertFalse(webViewClient.hasOnTooManyRedirectsCalled()); + assertEquals(0, webViewClient.hasOnReceivedErrorCode()); + String url = mWebServer.getRedirectingAssetUrl(TestHtmlConstants.HELLO_WORLD_URL, 100); + assertLoadUrlSuccessfully(mWebView, url); + // ToBeFixed: onTooManyRedirects() is meant to give the application the choice of continuing + // to follow the redirects, but never gets called. onReceivedError() shadows the callback + // and aborts unconditionally. + assertEquals(WebViewClient.ERROR_REDIRECT_LOOP, webViewClient.hasOnReceivedErrorCode()); + assertFalse(webViewClient.hasOnTooManyRedirectsCalled()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onReceivedError", + args = {WebView.class, int.class, String.class, String.class} + ) + public void testOnReceivedError() throws Exception { + final MockWebViewClient webViewClient = new MockWebViewClient(); + mWebView.setWebViewClient(webViewClient); + + String wrongUri = "invalidscheme://some/resource"; + assertEquals(0, webViewClient.hasOnReceivedErrorCode()); + assertLoadUrlSuccessfully(mWebView, wrongUri); + assertEquals(WebViewClient.ERROR_UNSUPPORTED_SCHEME, + webViewClient.hasOnReceivedErrorCode()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onFormResubmission", + args = {WebView.class, Message.class, Message.class} + ) + public void testOnFormResubmission() throws Exception { + final MockWebViewClient webViewClient = new MockWebViewClient(); + mWebView.setWebViewClient(webViewClient); + final WebSettings settings = mWebView.getSettings(); + settings.setJavaScriptEnabled(true); + mWebServer = new CtsTestServer(getActivity()); + + assertFalse(webViewClient.hasOnFormResubmissionCalled()); + String url = mWebServer.getAssetUrl(TestHtmlConstants.JS_FORM_URL); + // this loads a form, which automatically posts itself + assertLoadUrlSuccessfully(mWebView, url); + Thread.sleep(1000); // allow for javascript to post the form + // the URL should have changed when the form was posted + assertFalse(url.equals(mWebView.getUrl())); + // reloading the current URL should trigger the callback + mWebView.reload(); + new DelayedCheck(TEST_TIMEOUT) { + protected boolean check() { + return webViewClient.hasOnFormResubmissionCalled(); + } + }.run(); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "doUpdateVisitedHistory", + args = {WebView.class, String.class, boolean.class} + ) + public void testDoUpdateVisitedHistory() throws Exception { + final MockWebViewClient webViewClient = new MockWebViewClient(); + mWebView.setWebViewClient(webViewClient); + mWebServer = new CtsTestServer(getActivity()); + + assertFalse(webViewClient.hasDoUpdateVisitedHistoryCalled()); + String url1 = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); + String url2 = mWebServer.getAssetUrl(TestHtmlConstants.BR_TAG_URL); + assertLoadUrlSuccessfully(mWebView, url1); + assertLoadUrlSuccessfully(mWebView, url2); + new DelayedCheck(TEST_TIMEOUT) { + protected boolean check() { + return webViewClient.hasDoUpdateVisitedHistoryCalled(); + } + }.run(); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onReceivedHttpAuthRequest", + args = {WebView.class, HttpAuthHandler.class, String.class, String.class} + ) + public void testOnReceivedHttpAuthRequest() throws Exception { + final MockWebViewClient webViewClient = new MockWebViewClient(); + mWebView.setWebViewClient(webViewClient); + mWebServer = new CtsTestServer(getActivity()); + + assertFalse(webViewClient.hasOnReceivedHttpAuthRequestCalled()); + String url = mWebServer.getAuthAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); + assertLoadUrlSuccessfully(mWebView, url); + assertTrue(webViewClient.hasOnReceivedHttpAuthRequestCalled()); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "shouldOverrideKeyEvent", + args = {WebView.class, KeyEvent.class} + ) + public void testShouldOverrideKeyEvent() { + final MockWebViewClient webViewClient = new MockWebViewClient(); + mWebView.setWebViewClient(webViewClient); + + assertFalse(webViewClient.shouldOverrideKeyEvent(mWebView, null)); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onUnhandledKeyEvent", + args = {WebView.class, KeyEvent.class} + ) + public void testOnUnhandledKeyEvent() throws Throwable { + final MockWebViewClient webViewClient = new MockWebViewClient(); + mWebView.setWebViewClient(webViewClient); + + runTestOnUiThread(new Runnable() { + public void run() { + mWebView.requestFocus(); + } + }); + getInstrumentation().waitForIdleSync(); + + assertFalse(webViewClient.hasOnUnhandledKeyEventCalled()); + sendKeys(KeyEvent.KEYCODE_1); + + new DelayedCheck(TEST_TIMEOUT) { + protected boolean check() { + return webViewClient.hasOnUnhandledKeyEventCalled(); + } + }.run(); + } + + @TestTargetNew( + level = TestLevel.COMPLETE, + method = "onScaleChanged", + args = {WebView.class, float.class, float.class} + ) + public void testOnScaleChanged() throws Throwable { + final MockWebViewClient webViewClient = new MockWebViewClient(); + mWebView.setWebViewClient(webViewClient); + + assertFalse(webViewClient.hasOnScaleChangedCalled()); + runTestOnUiThread(new Runnable() { + public void run() { + mWebView.zoomIn(); + } + }); + getInstrumentation().waitForIdleSync(); + assertTrue(webViewClient.hasOnScaleChangedCalled()); + } + + private void assertLoadUrlSuccessfully(final WebView view, String url) { + view.loadUrl(url); + // wait until load is complete + new DelayedCheck(TEST_TIMEOUT) { + @Override + protected boolean check() { + return view.getProgress() == 100; + } + }.run(); + } + + private class MockWebViewClient extends WebViewClient { + private boolean mOnPageStartedCalled; + private boolean mOnPageFinishedCalled; + private boolean mOnLoadResourceCalled; + private boolean mOnTooManyRedirectsCalled; + private int mOnReceivedErrorCode; + private boolean mOnFormResubmissionCalled; + private boolean mDoUpdateVisitedHistoryCalled; + private boolean mOnReceivedHttpAuthRequestCalled; + private boolean mOnUnhandledKeyEventCalled; + private boolean mOnScaleChangedCalled; + + public boolean hasOnPageStartedCalled() { + return mOnPageStartedCalled; + } + + public boolean hasOnPageFinishedCalled() { + return mOnPageFinishedCalled; + } + + public boolean hasOnLoadResourceCalled() { + return mOnLoadResourceCalled; + } + + public boolean hasOnTooManyRedirectsCalled() { + return mOnTooManyRedirectsCalled; + } + + public int hasOnReceivedErrorCode() { + return mOnReceivedErrorCode; + } + + public boolean hasOnFormResubmissionCalled() { + return mOnFormResubmissionCalled; + } + + public boolean hasDoUpdateVisitedHistoryCalled() { + return mDoUpdateVisitedHistoryCalled; + } + + public boolean hasOnReceivedHttpAuthRequestCalled() { + return mOnReceivedHttpAuthRequestCalled; + } + + public boolean hasOnUnhandledKeyEventCalled() { + return mOnUnhandledKeyEventCalled; + } + + public boolean hasOnScaleChangedCalled() { + return mOnScaleChangedCalled; + } + + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + super.onPageStarted(view, url, favicon); + mOnPageStartedCalled = true; + } + + @Override + public void onPageFinished(WebView view, String url) { + super.onPageFinished(view, url); + assertTrue(mOnPageStartedCalled); + assertTrue(mOnLoadResourceCalled); + mOnPageFinishedCalled = true; + } + + @Override + public void onLoadResource(WebView view, String url) { + super.onLoadResource(view, url); + assertTrue(mOnPageStartedCalled); + mOnLoadResourceCalled = true; + } + + @Override + public void onTooManyRedirects(WebView view, Message cancelMsg, Message continueMsg) { + mOnTooManyRedirectsCalled = true; + continueMsg.sendToTarget(); + } + + @Override + public void onReceivedError(WebView view, int errorCode, + String description, String failingUrl) { + super.onReceivedError(view, errorCode, description, failingUrl); + mOnReceivedErrorCode = errorCode; + } + + @Override + public void onFormResubmission(WebView view, Message dontResend, Message resend) { + mOnFormResubmissionCalled = true; + dontResend.sendToTarget(); + } + + @Override + public void doUpdateVisitedHistory(WebView view, String url, boolean isReload) { + super.doUpdateVisitedHistory(view, url, isReload); + mDoUpdateVisitedHistoryCalled = true; + } + + @Override + public void onReceivedHttpAuthRequest(WebView view, + HttpAuthHandler handler, String host, String realm) { + super.onReceivedHttpAuthRequest(view, handler, host, realm); + mOnReceivedHttpAuthRequestCalled = true; + } + + @Override + public void onUnhandledKeyEvent(WebView view, KeyEvent event) { + super.onUnhandledKeyEvent(view, event); + mOnUnhandledKeyEventCalled = true; + } + + @Override + public void onScaleChanged(WebView view, float oldScale, float newScale) { + super.onScaleChanged(view, oldScale, newScale); + mOnScaleChangedCalled = true; + } + } +} |