1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)package org.chromium.content.browser;
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import android.test.suitebuilder.annotation.SmallTest;
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import org.chromium.base.test.util.Feature;
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Part of the test suite for the Java Bridge. This test checks that we correctly convert Java
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * values to JavaScript values when returning them from the methods of injected Java objects.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The conversions should follow
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * http://jdk6.java.net/plugin2/liveconnect/#JS_JAVA_CONVERSIONS. Places in
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * which the implementation differs from the spec are marked with
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * LIVECONNECT_COMPLIANCE.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FIXME: Consider making our implementation more compliant, if it will not
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * break backwards-compatibility. See b/4408210.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public class JavaBridgeReturnValuesTest extends JavaBridgeTestBase {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // An instance of this class is injected into the page to test returning
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Java values to JavaScript.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private class TestObject extends Controller {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        private String mStringValue;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        private boolean mBooleanValue;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // These four methods are used to control the test.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public synchronized void setStringValue(String x) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mStringValue = x;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            notifyResultIsReady();
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public synchronized String waitForStringValue() {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            waitForResult();
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return mStringValue;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public synchronized void setBooleanValue(boolean x) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mBooleanValue = x;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            notifyResultIsReady();
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public synchronized boolean waitForBooleanValue() {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            waitForResult();
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return mBooleanValue;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public boolean getBooleanValue() {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return true;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public byte getByteValue() {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return 42;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public char getCharValue() {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return '\u002A';
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public short getShortValue() {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return 42;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public int getIntValue() {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return 42;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public long getLongValue() {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return 42L;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public float getFloatValue() {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return 42.1f;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public float getFloatValueNoDecimal() {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return 42.0f;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public double getDoubleValue() {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return 42.1;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public double getDoubleValueNoDecimal() {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return 42.0;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public String getStringValue() {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return "foo";
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public String getEmptyStringValue() {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return "";
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public String getNullStringValue() {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return null;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public Object getObjectValue() {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return new Object();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public Object getNullObjectValue() {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return null;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public CustomType getCustomTypeValue() {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return new CustomType();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        public void getVoidValue() {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A custom type used when testing passing objects.
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private static class CustomType {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestObject mTestObject;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Override
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    protected void setUp() throws Exception {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        super.setUp();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mTestObject = new TestObject();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        setUpContentView(mTestObject, "testObject");
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that this requires that we can pass a JavaScript string to Java.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    protected String executeJavaScriptAndGetStringResult(String script) throws Throwable {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        executeJavaScript("testObject.setStringValue(" + script + ");");
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return mTestObject.waitForStringValue();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that this requires that we can pass a JavaScript boolean to Java.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private boolean executeJavaScriptAndGetBooleanResult(String script) throws Throwable {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        executeJavaScript("testObject.setBooleanValue(" + script + ");");
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return mTestObject.waitForBooleanValue();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @SmallTest
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Feature({"AndroidWebView", "Android-JavaBridge"})
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void testMethodReturnTypes() throws Throwable {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("boolean",
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                executeJavaScriptAndGetStringResult("typeof testObject.getBooleanValue()"));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("number",
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                executeJavaScriptAndGetStringResult("typeof testObject.getByteValue()"));
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // char values are returned to JavaScript as numbers.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("number",
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                executeJavaScriptAndGetStringResult("typeof testObject.getCharValue()"));
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("number",
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                executeJavaScriptAndGetStringResult("typeof testObject.getShortValue()"));
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("number",
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                executeJavaScriptAndGetStringResult("typeof testObject.getIntValue()"));
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("number",
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                executeJavaScriptAndGetStringResult("typeof testObject.getLongValue()"));
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("number",
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                executeJavaScriptAndGetStringResult("typeof testObject.getFloatValue()"));
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("number",
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                executeJavaScriptAndGetStringResult("typeof testObject.getFloatValueNoDecimal()"));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("number",
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                executeJavaScriptAndGetStringResult("typeof testObject.getDoubleValue()"));
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("number",
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                executeJavaScriptAndGetStringResult("typeof testObject.getDoubleValueNoDecimal()"));
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("string",
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                executeJavaScriptAndGetStringResult("typeof testObject.getStringValue()"));
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("string",
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                executeJavaScriptAndGetStringResult("typeof testObject.getEmptyStringValue()"));
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // LIVECONNECT_COMPLIANCE: This should have type object.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("undefined",
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                executeJavaScriptAndGetStringResult("typeof testObject.getNullStringValue()"));
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("object",
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                executeJavaScriptAndGetStringResult("typeof testObject.getObjectValue()"));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("object",
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                executeJavaScriptAndGetStringResult("typeof testObject.getNullObjectValue()"));
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("object",
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                executeJavaScriptAndGetStringResult("typeof testObject.getCustomTypeValue()"));
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("undefined",
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                executeJavaScriptAndGetStringResult("typeof testObject.getVoidValue()"));
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @SmallTest
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    @Feature({"AndroidWebView", "Android-JavaBridge"})
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    public void testMethodReturnValues() throws Throwable {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We do the string comparison in JavaScript, to avoid relying on the
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // coercion algorithm from JavaScript to Java.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertTrue(executeJavaScriptAndGetBooleanResult("testObject.getBooleanValue()"));
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getByteValue()"));
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // char values are returned to JavaScript as numbers.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getCharValue()"));
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getShortValue()"));
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getIntValue()"));
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getLongValue()"));
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertTrue(executeJavaScriptAndGetBooleanResult(
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                "Math.abs(42.1 - testObject.getFloatValue()) < 0.001"));
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertTrue(executeJavaScriptAndGetBooleanResult(
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                "42.0 === testObject.getFloatValueNoDecimal()"));
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertTrue(executeJavaScriptAndGetBooleanResult(
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                "Math.abs(42.1 - testObject.getDoubleValue()) < 0.001"));
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertTrue(executeJavaScriptAndGetBooleanResult(
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                "42.0 === testObject.getDoubleValueNoDecimal()"));
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("foo", executeJavaScriptAndGetStringResult("testObject.getStringValue()"));
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertEquals("", executeJavaScriptAndGetStringResult("testObject.getEmptyStringValue()"));
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assertTrue(executeJavaScriptAndGetBooleanResult("undefined === testObject.getVoidValue()"));
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
190