1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /** 18 * Part of the test suite for the WebView's Java Bridge. This test checks that 19 * we correctly convert Java values to JavaScript values when returning them 20 * from the methods of injected Java objects. 21 * 22 * The conversions should follow 23 * http://jdk6.java.net/plugin2/liveconnect/#JS_JAVA_CONVERSIONS. Places in 24 * which the implementation differs from the spec are marked with 25 * LIVECONNECT_COMPLIANCE. 26 * FIXME: Consider making our implementation more compliant, if it will not 27 * break backwards-compatibility. See b/4408210. 28 * 29 * To run this test ... 30 * adb shell am instrument -w -e class com.android.webviewtests.JavaBridgeReturnValuesTest \ 31 * com.android.webviewtests/android.test.InstrumentationTestRunner 32 */ 33 34 package com.android.webviewtests; 35 36 public class JavaBridgeReturnValuesTest extends JavaBridgeTestBase { 37 // An instance of this class is injected into the page to test returning 38 // Java values to JavaScript. 39 private class TestObject extends Controller { 40 private String mStringValue; 41 private boolean mBooleanValue; 42 43 // These four methods are used to control the test. 44 public synchronized void setStringValue(String x) { 45 mStringValue = x; 46 notifyResultIsReady(); 47 } 48 public synchronized String waitForStringValue() { 49 waitForResult(); 50 return mStringValue; 51 } 52 public synchronized void setBooleanValue(boolean x) { 53 mBooleanValue = x; 54 notifyResultIsReady(); 55 } 56 public synchronized boolean waitForBooleanValue() { 57 waitForResult(); 58 return mBooleanValue; 59 } 60 61 public boolean getBooleanValue() { 62 return true; 63 } 64 public byte getByteValue() { 65 return 42; 66 } 67 public char getCharValue() { 68 return '\u002A'; 69 } 70 public short getShortValue() { 71 return 42; 72 } 73 public int getIntValue() { 74 return 42; 75 } 76 public long getLongValue() { 77 return 42L; 78 } 79 public float getFloatValue() { 80 return 42.1f; 81 } 82 public float getFloatValueNoDecimal() { 83 return 42.0f; 84 } 85 public double getDoubleValue() { 86 return 42.1; 87 } 88 public double getDoubleValueNoDecimal() { 89 return 42.0; 90 } 91 public String getStringValue() { 92 return "foo"; 93 } 94 public String getEmptyStringValue() { 95 return ""; 96 } 97 public String getNullStringValue() { 98 return null; 99 } 100 public Object getObjectValue() { 101 return new Object(); 102 } 103 public Object getNullObjectValue() { 104 return null; 105 } 106 public CustomType getCustomTypeValue() { 107 return new CustomType(); 108 } 109 public void getVoidValue() { 110 } 111 } 112 113 // A custom type used when testing passing objects. 114 private class CustomType { 115 } 116 117 TestObject mTestObject; 118 119 @Override 120 protected void setUp() throws Exception { 121 super.setUp(); 122 mTestObject = new TestObject(); 123 setUpWebView(mTestObject, "testObject"); 124 } 125 126 // Note that this requires that we can pass a JavaScript string to Java. 127 protected String executeJavaScriptAndGetStringResult(String script) throws Throwable { 128 executeJavaScript("testObject.setStringValue(" + script + ");"); 129 return mTestObject.waitForStringValue(); 130 } 131 132 // Note that this requires that we can pass a JavaScript boolean to Java. 133 private boolean executeJavaScriptAndGetBooleanResult(String script) throws Throwable { 134 executeJavaScript("testObject.setBooleanValue(" + script + ");"); 135 return mTestObject.waitForBooleanValue(); 136 } 137 138 public void testMethodReturnTypes() throws Throwable { 139 assertEquals("boolean", 140 executeJavaScriptAndGetStringResult("typeof testObject.getBooleanValue()")); 141 assertEquals("number", 142 executeJavaScriptAndGetStringResult("typeof testObject.getByteValue()")); 143 // char values are returned to JavaScript as numbers. 144 assertEquals("number", 145 executeJavaScriptAndGetStringResult("typeof testObject.getCharValue()")); 146 assertEquals("number", 147 executeJavaScriptAndGetStringResult("typeof testObject.getShortValue()")); 148 assertEquals("number", 149 executeJavaScriptAndGetStringResult("typeof testObject.getIntValue()")); 150 assertEquals("number", 151 executeJavaScriptAndGetStringResult("typeof testObject.getLongValue()")); 152 assertEquals("number", 153 executeJavaScriptAndGetStringResult("typeof testObject.getFloatValue()")); 154 assertEquals("number", 155 executeJavaScriptAndGetStringResult("typeof testObject.getFloatValueNoDecimal()")); 156 assertEquals("number", 157 executeJavaScriptAndGetStringResult("typeof testObject.getDoubleValue()")); 158 assertEquals("number", 159 executeJavaScriptAndGetStringResult("typeof testObject.getDoubleValueNoDecimal()")); 160 assertEquals("string", 161 executeJavaScriptAndGetStringResult("typeof testObject.getStringValue()")); 162 assertEquals("string", 163 executeJavaScriptAndGetStringResult("typeof testObject.getEmptyStringValue()")); 164 // LIVECONNECT_COMPLIANCE: This should have type object. 165 assertEquals("undefined", 166 executeJavaScriptAndGetStringResult("typeof testObject.getNullStringValue()")); 167 assertEquals("object", 168 executeJavaScriptAndGetStringResult("typeof testObject.getObjectValue()")); 169 assertEquals("object", 170 executeJavaScriptAndGetStringResult("typeof testObject.getNullObjectValue()")); 171 assertEquals("object", 172 executeJavaScriptAndGetStringResult("typeof testObject.getCustomTypeValue()")); 173 assertEquals("undefined", 174 executeJavaScriptAndGetStringResult("typeof testObject.getVoidValue()")); 175 } 176 177 public void testMethodReturnValues() throws Throwable { 178 // We do the string comparison in JavaScript, to avoid relying on the 179 // coercion algorithm from JavaScript to Java. 180 assertTrue(executeJavaScriptAndGetBooleanResult("testObject.getBooleanValue()")); 181 assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getByteValue()")); 182 // char values are returned to JavaScript as numbers. 183 assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getCharValue()")); 184 assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getShortValue()")); 185 assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getIntValue()")); 186 assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getLongValue()")); 187 assertTrue(executeJavaScriptAndGetBooleanResult( 188 "Math.abs(42.1 - testObject.getFloatValue()) < 0.001")); 189 assertTrue(executeJavaScriptAndGetBooleanResult( 190 "42.0 === testObject.getFloatValueNoDecimal()")); 191 assertTrue(executeJavaScriptAndGetBooleanResult( 192 "Math.abs(42.1 - testObject.getDoubleValue()) < 0.001")); 193 assertTrue(executeJavaScriptAndGetBooleanResult( 194 "42.0 === testObject.getDoubleValueNoDecimal()")); 195 assertEquals("foo", executeJavaScriptAndGetStringResult("testObject.getStringValue()")); 196 assertEquals("", executeJavaScriptAndGetStringResult("testObject.getEmptyStringValue()")); 197 assertTrue(executeJavaScriptAndGetBooleanResult("undefined === testObject.getVoidValue()")); 198 } 199 } 200