This source file includes following definitions.
- setUp
- tearDown
- setServerResponseAndLoad
- fullPageLink
- simulateTouchCenterOfWebViewOnUiThread
- simulateTabDownUpOnUiThread
- simulateInput
- stringEquals
- pollForHitTestDataOnUiThread
- pollForHrefAndImageSrcOnUiThread
- srcAnchorTypeTestBody
- Feature
- testSrcAnchorType
- Feature
- testSrcAnchorTypeByFocus
- blankHrefTestBody
- Feature
- testSrcAnchorTypeBlankHref
- Feature
- testSrcAnchorTypeBlankHrefByFocus
- srcAnchorTypeRelativeUrlTestBody
- Feature
- testSrcAnchorTypeRelativeUrl
- Feature
- testSrcAnchorTypeRelativeUrlByFocus
- srcEmailTypeTestBody
- Feature
- testSrcEmailType
- Feature
- testSrcEmailTypeByFocus
- srcGeoTypeTestBody
- Feature
- testSrcGeoType
- Feature
- testSrcGeoTypeByFocus
- srcPhoneTypeTestBody
- Feature
- testSrcPhoneType
- Feature
- testSrcPhoneTypeByFocus
- srcImgeAnchorTypeTestBody
- Feature
- testSrcImgeAnchorType
- Feature
- testSrcImgeAnchorTypeByFocus
- srcImgeAnchorTypeRelativeUrlTestBody
- Feature
- testSrcImgeAnchorTypeRelativeUrl
- Feature
- testSrcImgeAnchorTypeRelativeUrlByFocus
- Feature
- testImgeType
- editTextTypeTestBody
- Feature
- testEditTextType
- Feature
- testEditTextTypeByFocus
- unknownTypeJavascriptSchemeTestBody
- Feature
- testUnknownTypeJavascriptScheme
- Feature
- testUnknownTypeJavascriptSchemeByFocus
- Feature
- testUnknownTypeUnrecognizedNode
- Feature
- testUnfocusedNodeAndTouchRace
package org.chromium.android_webview.test;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.webkit.WebView.HitTestResult;
import org.chromium.android_webview.AwContents;
import org.chromium.android_webview.test.util.CommonResources;
import org.chromium.base.ThreadUtils;
import org.chromium.base.test.util.Feature;
import org.chromium.net.test.util.TestWebServer;
import java.util.concurrent.Callable;
public class WebKitHitTestTest extends AwTestBase {
private TestAwContentsClient mContentsClient;
private AwTestContainerView mTestView;
private AwContents mAwContents;
private TestWebServer mWebServer;
private static String HREF = "http://foo/";
private static String ANCHOR_TEXT = "anchor text";
@Override
public void setUp() throws Exception {
super.setUp();
mContentsClient = new TestAwContentsClient();
mTestView = createAwTestContainerViewOnMainSync(mContentsClient);
mAwContents = mTestView.getAwContents();
mWebServer = new TestWebServer(false);
}
@Override
public void tearDown() throws Exception {
if (mWebServer != null) {
mWebServer.shutdown();
}
super.tearDown();
}
private void setServerResponseAndLoad(String response) throws Throwable {
String url = mWebServer.setResponse("/hittest.html", response, null);
loadUrlSync(mAwContents,
mContentsClient.getOnPageFinishedHelper(),
url);
}
private static String fullPageLink(String href, String anchorText) {
return CommonResources.makeHtmlPageFrom("", "<a class=\"full_view\" href=\"" +
href + "\" " + "onclick=\"return false;\">" + anchorText + "</a>");
}
private void simulateTouchCenterOfWebViewOnUiThread() throws Throwable {
runTestOnUiThread(new Runnable() {
@Override
public void run() {
long eventTime = SystemClock.uptimeMillis();
float x = (float) (mTestView.getRight() - mTestView.getLeft()) / 2;
float y = (float) (mTestView.getBottom() - mTestView.getTop()) / 2;
mAwContents.onTouchEvent(MotionEvent.obtain(
eventTime, eventTime, MotionEvent.ACTION_DOWN,
x, y, 0));
mAwContents.onTouchEvent(MotionEvent.obtain(
eventTime, eventTime, MotionEvent.ACTION_UP,
x, y, 0));
}
});
}
private void simulateTabDownUpOnUiThread() throws Throwable {
runTestOnUiThread(new Runnable() {
@Override
public void run() {
mAwContents.getContentViewCore().dispatchKeyEvent(
new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_TAB));
mAwContents.getContentViewCore().dispatchKeyEvent(
new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_TAB));
}
});
}
private void simulateInput(boolean byTouch) throws Throwable {
if (byTouch) {
simulateTouchCenterOfWebViewOnUiThread();
} else {
simulateTabDownUpOnUiThread();
}
}
private static boolean stringEquals(String a, String b) {
return a == null ? b == null : a.equals(b);
}
private void pollForHitTestDataOnUiThread(
final int expectedType, final String expectedExtra) throws Throwable {
pollOnUiThread(new Callable<Boolean>() {
@Override
public Boolean call() {
AwContents.HitTestData data = mAwContents.getLastHitTestResult();
return expectedType == data.hitTestResultType &&
stringEquals(expectedExtra, data.hitTestResultExtraData);
}
});
}
private void pollForHrefAndImageSrcOnUiThread(
final String expectedHref,
final String expectedAnchorText,
final String expectedImageSrc) throws Throwable {
pollOnUiThread(new Callable<Boolean>() {
@Override
public Boolean call() {
AwContents.HitTestData data = mAwContents.getLastHitTestResult();
return stringEquals(expectedHref, data.href) &&
stringEquals(expectedAnchorText, data.anchorText) &&
stringEquals(expectedImageSrc, data.imgSrc);
}
});
Handler dummyHandler = new Handler();
final Message focusNodeHrefMsg = dummyHandler.obtainMessage();
final Message imageRefMsg = dummyHandler.obtainMessage();
ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@Override
public void run() {
mAwContents.requestFocusNodeHref(focusNodeHrefMsg);
mAwContents.requestImageRef(imageRefMsg);
}
});
assertEquals(expectedHref, focusNodeHrefMsg.getData().getString("url"));
assertEquals(expectedAnchorText, focusNodeHrefMsg.getData().getString("title"));
assertEquals(expectedImageSrc, focusNodeHrefMsg.getData().getString("src"));
assertEquals(expectedImageSrc, imageRefMsg.getData().getString("url"));
}
private void srcAnchorTypeTestBody(boolean byTouch) throws Throwable {
String page = fullPageLink(HREF, ANCHOR_TEXT);
setServerResponseAndLoad(page);
simulateInput(byTouch);
pollForHitTestDataOnUiThread(HitTestResult.SRC_ANCHOR_TYPE, HREF);
pollForHrefAndImageSrcOnUiThread(HREF, ANCHOR_TEXT, null);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testSrcAnchorType() throws Throwable {
srcAnchorTypeTestBody(true);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testSrcAnchorTypeByFocus() throws Throwable {
srcAnchorTypeTestBody(false);
}
private void blankHrefTestBody(boolean byTouch) throws Throwable {
String fullPath = mWebServer.getResponseUrl("/hittest.html");
String page = fullPageLink("", ANCHOR_TEXT);
setServerResponseAndLoad(page);
simulateInput(byTouch);
pollForHitTestDataOnUiThread(HitTestResult.SRC_ANCHOR_TYPE, fullPath);
pollForHrefAndImageSrcOnUiThread(fullPath, ANCHOR_TEXT, null);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testSrcAnchorTypeBlankHref() throws Throwable {
blankHrefTestBody(true);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testSrcAnchorTypeBlankHrefByFocus() throws Throwable {
blankHrefTestBody(false);
}
private void srcAnchorTypeRelativeUrlTestBody(boolean byTouch) throws Throwable {
String relPath = "/foo.html";
String fullPath = mWebServer.getResponseUrl(relPath);
String page = fullPageLink(relPath, ANCHOR_TEXT);
setServerResponseAndLoad(page);
simulateInput(byTouch);
pollForHitTestDataOnUiThread(HitTestResult.SRC_ANCHOR_TYPE, fullPath);
pollForHrefAndImageSrcOnUiThread(fullPath, ANCHOR_TEXT, null);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testSrcAnchorTypeRelativeUrl() throws Throwable {
srcAnchorTypeRelativeUrlTestBody(true);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testSrcAnchorTypeRelativeUrlByFocus() throws Throwable {
srcAnchorTypeRelativeUrlTestBody(false);
}
private void srcEmailTypeTestBody(boolean byTouch) throws Throwable {
String email = "foo@bar.com";
String prefix = "mailto:";
String page = fullPageLink(prefix + email, ANCHOR_TEXT);
setServerResponseAndLoad(page);
simulateInput(byTouch);
pollForHitTestDataOnUiThread(HitTestResult.EMAIL_TYPE, email);
pollForHrefAndImageSrcOnUiThread(prefix + email, ANCHOR_TEXT, null);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testSrcEmailType() throws Throwable {
srcEmailTypeTestBody(true);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testSrcEmailTypeByFocus() throws Throwable {
srcEmailTypeTestBody(false);
}
private void srcGeoTypeTestBody(boolean byTouch) throws Throwable {
String location = "Jilin";
String prefix = "geo:0,0?q=";
String page = fullPageLink(prefix + location, ANCHOR_TEXT);
setServerResponseAndLoad(page);
simulateInput(byTouch);
pollForHitTestDataOnUiThread(HitTestResult.GEO_TYPE, location);
pollForHrefAndImageSrcOnUiThread(prefix + location, ANCHOR_TEXT, null);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testSrcGeoType() throws Throwable {
srcGeoTypeTestBody(true);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testSrcGeoTypeByFocus() throws Throwable {
srcGeoTypeTestBody(false);
}
private void srcPhoneTypeTestBody(boolean byTouch) throws Throwable {
String phone_num = "%2B1234567890";
String expected_phone_num = "+1234567890";
String prefix = "tel:";
String page = fullPageLink("tel:" + phone_num, ANCHOR_TEXT);
setServerResponseAndLoad(page);
simulateInput(byTouch);
pollForHitTestDataOnUiThread(HitTestResult.PHONE_TYPE, expected_phone_num);
pollForHrefAndImageSrcOnUiThread(prefix + phone_num, ANCHOR_TEXT, null);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testSrcPhoneType() throws Throwable {
srcPhoneTypeTestBody(true);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testSrcPhoneTypeByFocus() throws Throwable {
srcPhoneTypeTestBody(false);
}
private void srcImgeAnchorTypeTestBody(boolean byTouch) throws Throwable {
String fullImageSrc = "http://foo.bar/nonexistent.jpg";
String page = CommonResources.makeHtmlPageFrom("", "<a class=\"full_view\" href=\"" +
HREF + "\"onclick=\"return false;\"><img class=\"full_view\" src=\"" +
fullImageSrc + "\"></a>");
setServerResponseAndLoad(page);
simulateInput(byTouch);
pollForHitTestDataOnUiThread(HitTestResult.SRC_IMAGE_ANCHOR_TYPE, fullImageSrc);
pollForHrefAndImageSrcOnUiThread(HREF, null, fullImageSrc);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testSrcImgeAnchorType() throws Throwable {
srcImgeAnchorTypeTestBody(true);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testSrcImgeAnchorTypeByFocus() throws Throwable {
srcImgeAnchorTypeTestBody(false);
}
private void srcImgeAnchorTypeRelativeUrlTestBody(boolean byTouch) throws Throwable {
String relImageSrc = "/nonexistent.jpg";
String fullImageSrc = mWebServer.getResponseUrl(relImageSrc);
String relPath = "/foo.html";
String fullPath = mWebServer.getResponseUrl(relPath);
String page = CommonResources.makeHtmlPageFrom("", "<a class=\"full_view\" href=\"" +
relPath + "\"onclick=\"return false;\"><img class=\"full_view\" src=\"" +
relImageSrc + "\"></a>");
setServerResponseAndLoad(page);
simulateInput(byTouch);
pollForHitTestDataOnUiThread(HitTestResult.SRC_IMAGE_ANCHOR_TYPE, fullImageSrc);
pollForHrefAndImageSrcOnUiThread(fullPath, null, fullImageSrc);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testSrcImgeAnchorTypeRelativeUrl() throws Throwable {
srcImgeAnchorTypeRelativeUrlTestBody(true);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testSrcImgeAnchorTypeRelativeUrlByFocus() throws Throwable {
srcImgeAnchorTypeRelativeUrlTestBody(false);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testImgeType() throws Throwable {
String relImageSrc = "/nonexistent2.jpg";
String fullImageSrc = mWebServer.getResponseUrl(relImageSrc);
String page = CommonResources.makeHtmlPageFrom("",
"<img class=\"full_view\" src=\"" + relImageSrc + "\">");
setServerResponseAndLoad(page);
simulateTouchCenterOfWebViewOnUiThread();
pollForHitTestDataOnUiThread(HitTestResult.IMAGE_TYPE, fullImageSrc);
pollForHrefAndImageSrcOnUiThread(null, null, fullImageSrc);
}
private void editTextTypeTestBody(boolean byTouch) throws Throwable {
String page = CommonResources.makeHtmlPageFrom("",
"<form><input class=\"full_view\" type=\"text\" name=\"test\"></form>");
setServerResponseAndLoad(page);
simulateInput(byTouch);
pollForHitTestDataOnUiThread(HitTestResult.EDIT_TEXT_TYPE, null);
pollForHrefAndImageSrcOnUiThread(null, null, null);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testEditTextType() throws Throwable {
editTextTypeTestBody(true);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testEditTextTypeByFocus() throws Throwable {
editTextTypeTestBody(false);
}
public void unknownTypeJavascriptSchemeTestBody(boolean byTouch) throws Throwable {
String javascript = "javascript:alert('foo');";
String page = fullPageLink(javascript, ANCHOR_TEXT);
setServerResponseAndLoad(page);
simulateInput(byTouch);
pollForHrefAndImageSrcOnUiThread(javascript, ANCHOR_TEXT, null);
pollForHitTestDataOnUiThread(HitTestResult.UNKNOWN_TYPE, null);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testUnknownTypeJavascriptScheme() throws Throwable {
unknownTypeJavascriptSchemeTestBody(true);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testUnknownTypeJavascriptSchemeByFocus() throws Throwable {
unknownTypeJavascriptSchemeTestBody(false);
}
@SmallTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testUnknownTypeUnrecognizedNode() throws Throwable {
testSrcAnchorType();
final String title = "UNKNOWN_TYPE title";
String page = CommonResources.makeHtmlPageFrom(
"<title>" + title + "</title>",
"<div class=\"full_view\">div text</div>");
setServerResponseAndLoad(page);
pollOnUiThread(new Callable<Boolean>() {
@Override
public Boolean call() {
return mAwContents.getContentViewCore().getTitle().equals(title);
}
});
simulateTouchCenterOfWebViewOnUiThread();
pollForHitTestDataOnUiThread(HitTestResult.UNKNOWN_TYPE, null);
}
@LargeTest
@Feature({"AndroidWebView", "WebKitHitTest"})
public void testUnfocusedNodeAndTouchRace() throws Throwable {
String relImageSrc = "/nonexistent3.jpg";
String fullImageSrc = mWebServer.getResponseUrl(relImageSrc);
String html = CommonResources.makeHtmlPageFrom(
"<meta name=\"viewport\" content=\"width=device-width,height=device-height\" />" +
"<style type=\"text/css\">" +
".full_width { width:100%; position:absolute; }" +
"</style>",
"<form><input class=\"full_width\" style=\"height:25%;\" " +
"type=\"text\" name=\"test\"></form>" +
"<img class=\"full_width\" style=\"height:50%;top:25%;\" " +
"src=\"" + relImageSrc + "\">");
setServerResponseAndLoad(html);
simulateTabDownUpOnUiThread();
pollForHitTestDataOnUiThread(HitTestResult.EDIT_TEXT_TYPE, null);
pollForHrefAndImageSrcOnUiThread(null, null, null);
simulateTouchCenterOfWebViewOnUiThread();
for (int i = 0; i < 2; ++i) {
Thread.sleep(500);
pollForHitTestDataOnUiThread(HitTestResult.IMAGE_TYPE, fullImageSrc);
pollForHrefAndImageSrcOnUiThread(null, null, fullImageSrc);
}
}
}