• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.content.browser;
6 
7 import android.test.suitebuilder.annotation.SmallTest;
8 
9 import org.chromium.base.test.util.Feature;
10 
11 /**
12  * Part of the test suite for the Java Bridge. This class tests that
13  * we correctly convert JavaScript values to Java values when passing them to
14  * the methods of injected Java objects.
15  *
16  * The conversions should follow
17  * http://jdk6.java.net/plugin2/liveconnect/#JS_JAVA_CONVERSIONS. Places in
18  * which the implementation differs from the spec are marked with
19  * LIVECONNECT_COMPLIANCE.
20  * FIXME: Consider making our implementation more compliant, if it will not
21  * break backwards-compatibility. See b/4408210.
22  */
23 public class JavaBridgeCoercionTest extends JavaBridgeTestBase {
24     private class TestObject extends Controller {
25         private Object objectInstance;
26         private CustomType customTypeInstance;
27         private CustomType2 customType2Instance;
28 
29         private boolean mBooleanValue;
30         private byte mByteValue;
31         private char mCharValue;
32         private short mShortValue;
33         private int mIntValue;
34         private long mLongValue;
35         private float mFloatValue;
36         private double mDoubleValue;
37         private String mStringValue;
38         private Object mObjectValue;
39         private CustomType mCustomTypeValue;
40 
TestObject()41         public TestObject() {
42             objectInstance = new Object();
43             customTypeInstance = new CustomType();
44             customType2Instance = new CustomType2();
45         }
46 
getObjectInstance()47         public Object getObjectInstance() {
48             return objectInstance;
49         }
getCustomTypeInstance()50         public CustomType getCustomTypeInstance() {
51             return customTypeInstance;
52         }
getCustomType2Instance()53         public CustomType2 getCustomType2Instance() {
54             return customType2Instance;
55         }
56 
setBooleanValue(boolean x)57         public synchronized void setBooleanValue(boolean x) {
58             mBooleanValue = x;
59             notifyResultIsReady();
60         }
setByteValue(byte x)61         public synchronized void setByteValue(byte x) {
62             mByteValue = x;
63             notifyResultIsReady();
64         }
setCharValue(char x)65         public synchronized void setCharValue(char x) {
66             mCharValue = x;
67             notifyResultIsReady();
68         }
setShortValue(short x)69         public synchronized void setShortValue(short x) {
70             mShortValue = x;
71             notifyResultIsReady();
72         }
setIntValue(int x)73         public synchronized void setIntValue(int x) {
74             mIntValue = x;
75             notifyResultIsReady();
76         }
setLongValue(long x)77         public synchronized void setLongValue(long x) {
78             mLongValue = x;
79             notifyResultIsReady();
80         }
setFloatValue(float x)81         public synchronized void setFloatValue(float x) {
82             mFloatValue = x;
83             notifyResultIsReady();
84         }
setDoubleValue(double x)85         public synchronized void setDoubleValue(double x) {
86             mDoubleValue = x;
87             notifyResultIsReady();
88         }
setStringValue(String x)89         public synchronized void setStringValue(String x) {
90             mStringValue = x;
91             notifyResultIsReady();
92         }
setObjectValue(Object x)93         public synchronized void setObjectValue(Object x) {
94             mObjectValue = x;
95             notifyResultIsReady();
96         }
setCustomTypeValue(CustomType x)97         public synchronized void setCustomTypeValue(CustomType x) {
98             mCustomTypeValue = x;
99             notifyResultIsReady();
100         }
101 
waitForBooleanValue()102         public synchronized boolean waitForBooleanValue() {
103             waitForResult();
104             return mBooleanValue;
105         }
waitForByteValue()106         public synchronized byte waitForByteValue() {
107             waitForResult();
108             return mByteValue;
109         }
waitForCharValue()110         public synchronized char waitForCharValue() {
111             waitForResult();
112             return mCharValue;
113         }
waitForShortValue()114         public synchronized short waitForShortValue() {
115             waitForResult();
116             return mShortValue;
117         }
waitForIntValue()118         public synchronized int waitForIntValue() {
119             waitForResult();
120             return mIntValue;
121         }
waitForLongValue()122         public synchronized long waitForLongValue() {
123             waitForResult();
124             return mLongValue;
125         }
waitForFloatValue()126         public synchronized float waitForFloatValue() {
127             waitForResult();
128             return mFloatValue;
129         }
waitForDoubleValue()130         public synchronized double waitForDoubleValue() {
131             waitForResult();
132             return mDoubleValue;
133         }
waitForStringValue()134         public synchronized String waitForStringValue() {
135             waitForResult();
136             return mStringValue;
137         }
waitForObjectValue()138         public synchronized Object waitForObjectValue() {
139             waitForResult();
140             return mObjectValue;
141         }
waitForCustomTypeValue()142         public synchronized CustomType waitForCustomTypeValue() {
143             waitForResult();
144             return mCustomTypeValue;
145         }
146     }
147 
148     // Two custom types used when testing passing objects.
149     private static class CustomType {
150     }
151     private static class CustomType2 {
152     }
153 
154     private TestObject mTestObject;
155 
156     @Override
setUp()157     protected void setUp() throws Exception {
158         super.setUp();
159         mTestObject = new TestObject();
160         setUpContentView(mTestObject, "testObject");
161     }
162 
163     // Test passing a 32-bit integer JavaScript number to a method of an
164     // injected object. Note that JavaScript may choose to represent these
165     // values as either 32-bit integers or doubles, though this should not
166     // affect the result.
167     @SmallTest
168     @Feature({"AndroidWebView", "Android-JavaBridge"})
testPassNumberInt32()169     public void testPassNumberInt32() throws Throwable {
170         executeJavaScript("testObject.setByteValue(42);");
171         assertEquals(42, mTestObject.waitForByteValue());
172         executeJavaScript("testObject.setByteValue(" + Byte.MAX_VALUE + " + 42);");
173         assertEquals(Byte.MIN_VALUE + 42 - 1, mTestObject.waitForByteValue());
174 
175         executeJavaScript("testObject.setCharValue(42);");
176         assertEquals(42, mTestObject.waitForCharValue());
177 
178         executeJavaScript("testObject.setShortValue(42);");
179         assertEquals(42, mTestObject.waitForShortValue());
180         executeJavaScript("testObject.setShortValue(" + Short.MAX_VALUE + " + 42);");
181         assertEquals(Short.MIN_VALUE + 42 - 1, mTestObject.waitForShortValue());
182 
183         executeJavaScript("testObject.setIntValue(42);");
184         assertEquals(42, mTestObject.waitForIntValue());
185 
186         executeJavaScript("testObject.setLongValue(42);");
187         assertEquals(42L, mTestObject.waitForLongValue());
188 
189         executeJavaScript("testObject.setFloatValue(42);");
190         assertEquals(42.0f, mTestObject.waitForFloatValue());
191 
192         executeJavaScript("testObject.setDoubleValue(42);");
193         assertEquals(42.0, mTestObject.waitForDoubleValue());
194 
195         // LIVECONNECT_COMPLIANCE: Should create an instance of java.lang.Number.
196         executeJavaScript("testObject.setObjectValue(42);");
197         assertNull(mTestObject.waitForObjectValue());
198 
199         // The spec allows the JS engine flexibility in how to format the number.
200         executeJavaScript("testObject.setStringValue(42);");
201         String str = mTestObject.waitForStringValue();
202         assertTrue("42".equals(str) || "42.0".equals(str));
203 
204         executeJavaScript("testObject.setBooleanValue(0);");
205         assertFalse(mTestObject.waitForBooleanValue());
206         // LIVECONNECT_COMPLIANCE: Should be true;
207         executeJavaScript("testObject.setBooleanValue(42);");
208         assertFalse(mTestObject.waitForBooleanValue());
209 
210         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
211         executeJavaScript("testObject.setCustomTypeValue(42);");
212         assertNull(mTestObject.waitForCustomTypeValue());
213     }
214 
215     // Test passing a floating-point JavaScript number to a method of an
216     // injected object. JavaScript represents these values as doubles.
217     @SmallTest
218     @Feature({"AndroidWebView", "Android-JavaBridge"})
testPassNumberDouble()219     public void testPassNumberDouble() throws Throwable {
220         executeJavaScript("testObject.setByteValue(42.1);");
221         assertEquals(42, mTestObject.waitForByteValue());
222         executeJavaScript("testObject.setByteValue(" + Byte.MAX_VALUE + " + 42.1);");
223         assertEquals(Byte.MIN_VALUE + 42 - 1, mTestObject.waitForByteValue());
224         executeJavaScript("testObject.setByteValue(" + Byte.MIN_VALUE + " - 42.1);");
225         assertEquals(Byte.MAX_VALUE - 42 + 1, mTestObject.waitForByteValue());
226         executeJavaScript("testObject.setByteValue(" + Integer.MAX_VALUE + " + 42.1);");
227         assertEquals(-1, mTestObject.waitForByteValue());
228         executeJavaScript("testObject.setByteValue(" + Integer.MIN_VALUE + " - 42.1);");
229         assertEquals(0, mTestObject.waitForByteValue());
230 
231         // LIVECONNECT_COMPLIANCE: Should convert to numeric char value.
232         executeJavaScript("testObject.setCharValue(42.1);");
233         assertEquals('\u0000', mTestObject.waitForCharValue());
234 
235         executeJavaScript("testObject.setShortValue(42.1);");
236         assertEquals(42, mTestObject.waitForShortValue());
237         executeJavaScript("testObject.setShortValue(" + Short.MAX_VALUE + " + 42.1);");
238         assertEquals(Short.MIN_VALUE + 42 - 1, mTestObject.waitForShortValue());
239         executeJavaScript("testObject.setShortValue(" + Short.MIN_VALUE + " - 42.1);");
240         assertEquals(Short.MAX_VALUE - 42 + 1, mTestObject.waitForShortValue());
241         executeJavaScript("testObject.setShortValue(" + Integer.MAX_VALUE + " + 42.1);");
242         assertEquals(-1, mTestObject.waitForShortValue());
243         executeJavaScript("testObject.setShortValue(" + Integer.MIN_VALUE + " - 42.1);");
244         assertEquals(0, mTestObject.waitForShortValue());
245 
246         executeJavaScript("testObject.setIntValue(42.1);");
247         assertEquals(42, mTestObject.waitForIntValue());
248         executeJavaScript("testObject.setIntValue(" + Integer.MAX_VALUE + " + 42.1);");
249         assertEquals(Integer.MAX_VALUE, mTestObject.waitForIntValue());
250         executeJavaScript("testObject.setIntValue(" + Integer.MIN_VALUE + " - 42.1);");
251         assertEquals(Integer.MIN_VALUE, mTestObject.waitForIntValue());
252 
253         executeJavaScript("testObject.setLongValue(42.1);");
254         assertEquals(42L, mTestObject.waitForLongValue());
255         executeJavaScript("testObject.setLongValue(" + Long.MAX_VALUE + " + 42.1);");
256         assertEquals(Long.MAX_VALUE, mTestObject.waitForLongValue());
257         executeJavaScript("testObject.setLongValue(" + Long.MIN_VALUE + " - 42.1);");
258         assertEquals(Long.MIN_VALUE, mTestObject.waitForLongValue());
259 
260         executeJavaScript("testObject.setFloatValue(42.1);");
261         assertEquals(42.1f, mTestObject.waitForFloatValue());
262 
263         executeJavaScript("testObject.setDoubleValue(42.1);");
264         assertEquals(42.1, mTestObject.waitForDoubleValue());
265 
266         // LIVECONNECT_COMPLIANCE: Should create an instance of java.lang.Number.
267         executeJavaScript("testObject.setObjectValue(42.1);");
268         assertNull(mTestObject.waitForObjectValue());
269 
270         executeJavaScript("testObject.setStringValue(42.1);");
271         assertEquals("42.1", mTestObject.waitForStringValue());
272 
273         executeJavaScript("testObject.setBooleanValue(0.0);");
274         assertFalse(mTestObject.waitForBooleanValue());
275         // LIVECONNECT_COMPLIANCE: Should be true.
276         executeJavaScript("testObject.setBooleanValue(42.1);");
277         assertFalse(mTestObject.waitForBooleanValue());
278 
279         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
280         executeJavaScript("testObject.setCustomTypeValue(42.1);");
281         assertNull(mTestObject.waitForCustomTypeValue());
282     }
283 
284     // Test passing JavaScript NaN to a method of an injected object.
285     @SmallTest
286     @Feature({"AndroidWebView", "Android-JavaBridge"})
testPassNumberNaN()287     public void testPassNumberNaN() throws Throwable {
288         executeJavaScript("testObject.setByteValue(Number.NaN);");
289         assertEquals(0, mTestObject.waitForByteValue());
290 
291         executeJavaScript("testObject.setCharValue(Number.NaN);");
292         assertEquals('\u0000', mTestObject.waitForCharValue());
293 
294         executeJavaScript("testObject.setShortValue(Number.NaN);");
295         assertEquals(0, mTestObject.waitForShortValue());
296 
297         executeJavaScript("testObject.setIntValue(Number.NaN);");
298         assertEquals(0, mTestObject.waitForIntValue());
299 
300         executeJavaScript("testObject.setLongValue(Number.NaN);");
301         assertEquals(0L, mTestObject.waitForLongValue());
302 
303         executeJavaScript("testObject.setFloatValue(Number.NaN);");
304         assertEquals(Float.NaN, mTestObject.waitForFloatValue());
305 
306         executeJavaScript("testObject.setDoubleValue(Number.NaN);");
307         assertEquals(Double.NaN, mTestObject.waitForDoubleValue());
308 
309         // LIVECONNECT_COMPLIANCE: Should create an instance of java.lang.Number.
310         executeJavaScript("testObject.setObjectValue(Number.NaN);");
311         assertNull(mTestObject.waitForObjectValue());
312 
313         executeJavaScript("testObject.setStringValue(Number.NaN);");
314         assertTrue("nan".equalsIgnoreCase(mTestObject.waitForStringValue()));
315 
316         executeJavaScript("testObject.setBooleanValue(Number.NaN);");
317         assertFalse(mTestObject.waitForBooleanValue());
318 
319         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
320         executeJavaScript("testObject.setCustomTypeValue(Number.NaN);");
321         assertNull(mTestObject.waitForCustomTypeValue());
322     }
323 
324     // Test passing JavaScript infinity to a method of an injected object.
325     @SmallTest
326     @Feature({"AndroidWebView", "Android-JavaBridge"})
testPassNumberInfinity()327     public void testPassNumberInfinity() throws Throwable {
328         executeJavaScript("testObject.setByteValue(Infinity);");
329         assertEquals(-1, mTestObject.waitForByteValue());
330 
331         // LIVECONNECT_COMPLIANCE: Should convert to maximum numeric char value.
332         executeJavaScript("testObject.setCharValue(Infinity);");
333         assertEquals('\u0000', mTestObject.waitForCharValue());
334 
335         executeJavaScript("testObject.setShortValue(Infinity);");
336         assertEquals(-1, mTestObject.waitForShortValue());
337 
338         executeJavaScript("testObject.setIntValue(Infinity);");
339         assertEquals(Integer.MAX_VALUE, mTestObject.waitForIntValue());
340 
341         executeJavaScript("testObject.setLongValue(Infinity);");
342         assertEquals(Long.MAX_VALUE, mTestObject.waitForLongValue());
343 
344         executeJavaScript("testObject.setFloatValue(Infinity);");
345         assertEquals(Float.POSITIVE_INFINITY, mTestObject.waitForFloatValue());
346 
347         executeJavaScript("testObject.setDoubleValue(Infinity);");
348         assertEquals(Double.POSITIVE_INFINITY, mTestObject.waitForDoubleValue());
349 
350         // LIVECONNECT_COMPLIANCE: Should create an instance of java.lang.Number.
351         executeJavaScript("testObject.setObjectValue(Infinity);");
352         assertNull(mTestObject.waitForObjectValue());
353 
354         executeJavaScript("testObject.setStringValue(Infinity);");
355         assertTrue("inf".equalsIgnoreCase(mTestObject.waitForStringValue()));
356 
357         executeJavaScript("testObject.setBooleanValue(Infinity);");
358         assertFalse(mTestObject.waitForBooleanValue());
359 
360         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
361         executeJavaScript("testObject.setCustomTypeValue(Infinity);");
362         assertNull(mTestObject.waitForCustomTypeValue());
363     }
364 
365     // Test passing a JavaScript boolean to a method of an injected object.
366     @SmallTest
367     @Feature({"AndroidWebView", "Android-JavaBridge"})
testPassBoolean()368     public void testPassBoolean() throws Throwable {
369         executeJavaScript("testObject.setBooleanValue(true);");
370         assertTrue(mTestObject.waitForBooleanValue());
371         executeJavaScript("testObject.setBooleanValue(false);");
372         assertFalse(mTestObject.waitForBooleanValue());
373 
374         // LIVECONNECT_COMPLIANCE: Should create an instance of java.lang.Boolean.
375         executeJavaScript("testObject.setObjectValue(true);");
376         assertNull(mTestObject.waitForObjectValue());
377 
378         executeJavaScript("testObject.setStringValue(false);");
379         assertEquals("false", mTestObject.waitForStringValue());
380         executeJavaScript("testObject.setStringValue(true);");
381         assertEquals("true", mTestObject.waitForStringValue());
382 
383         // LIVECONNECT_COMPLIANCE: Should be 1.
384         executeJavaScript("testObject.setByteValue(true);");
385         assertEquals(0, mTestObject.waitForByteValue());
386         executeJavaScript("testObject.setByteValue(false);");
387         assertEquals(0, mTestObject.waitForByteValue());
388 
389         // LIVECONNECT_COMPLIANCE: Should convert to numeric char value 1.
390         executeJavaScript("testObject.setCharValue(true);");
391         assertEquals('\u0000', mTestObject.waitForCharValue());
392         executeJavaScript("testObject.setCharValue(false);");
393         assertEquals('\u0000', mTestObject.waitForCharValue());
394 
395         // LIVECONNECT_COMPLIANCE: Should be 1.
396         executeJavaScript("testObject.setShortValue(true);");
397         assertEquals(0, mTestObject.waitForShortValue());
398         executeJavaScript("testObject.setShortValue(false);");
399         assertEquals(0, mTestObject.waitForShortValue());
400 
401         // LIVECONNECT_COMPLIANCE: Should be 1.
402         executeJavaScript("testObject.setIntValue(true);");
403         assertEquals(0, mTestObject.waitForIntValue());
404         executeJavaScript("testObject.setIntValue(false);");
405         assertEquals(0, mTestObject.waitForIntValue());
406 
407         // LIVECONNECT_COMPLIANCE: Should be 1.
408         executeJavaScript("testObject.setLongValue(true);");
409         assertEquals(0L, mTestObject.waitForLongValue());
410         executeJavaScript("testObject.setLongValue(false);");
411         assertEquals(0L, mTestObject.waitForLongValue());
412 
413         // LIVECONNECT_COMPLIANCE: Should be 1.0.
414         executeJavaScript("testObject.setFloatValue(true);");
415         assertEquals(0.0f, mTestObject.waitForFloatValue());
416         executeJavaScript("testObject.setFloatValue(false);");
417         assertEquals(0.0f, mTestObject.waitForFloatValue());
418 
419         // LIVECONNECT_COMPLIANCE: Should be 1.0.
420         executeJavaScript("testObject.setDoubleValue(true);");
421         assertEquals(0.0, mTestObject.waitForDoubleValue());
422         executeJavaScript("testObject.setDoubleValue(false);");
423         assertEquals(0.0, mTestObject.waitForDoubleValue());
424 
425         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
426         executeJavaScript("testObject.setCustomTypeValue(true);");
427         assertNull(mTestObject.waitForCustomTypeValue());
428     }
429 
430     // Test passing a JavaScript string to a method of an injected object.
431     @SmallTest
432     @Feature({"AndroidWebView", "Android-JavaBridge"})
testPassString()433     public void testPassString() throws Throwable {
434         executeJavaScript("testObject.setStringValue(\"+042.10\");");
435         assertEquals("+042.10", mTestObject.waitForStringValue());
436 
437         // Make sure that we distinguish between the empty string and NULL.
438         executeJavaScript("testObject.setStringValue(\"\");");
439         assertEquals("", mTestObject.waitForStringValue());
440 
441         // LIVECONNECT_COMPLIANCE: Should create an instance of java.lang.String.
442         executeJavaScript("testObject.setObjectValue(\"+042.10\");");
443         assertNull(mTestObject.waitForObjectValue());
444 
445         // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
446         executeJavaScript("testObject.setByteValue(\"+042.10\");");
447         assertEquals(0, mTestObject.waitForByteValue());
448 
449         // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
450         executeJavaScript("testObject.setShortValue(\"+042.10\");");
451         assertEquals(0, mTestObject.waitForShortValue());
452 
453         // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
454         executeJavaScript("testObject.setIntValue(\"+042.10\");");
455         assertEquals(0, mTestObject.waitForIntValue());
456 
457         // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
458         executeJavaScript("testObject.setLongValue(\"+042.10\");");
459         assertEquals(0L, mTestObject.waitForLongValue());
460 
461         // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
462         executeJavaScript("testObject.setFloatValue(\"+042.10\");");
463         assertEquals(0.0f, mTestObject.waitForFloatValue());
464 
465         // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
466         executeJavaScript("testObject.setDoubleValue(\"+042.10\");");
467         assertEquals(0.0, mTestObject.waitForDoubleValue());
468 
469         // LIVECONNECT_COMPLIANCE: Should decode and convert to numeric char value.
470         executeJavaScript("testObject.setCharValue(\"+042.10\");");
471         assertEquals('\u0000', mTestObject.waitForCharValue());
472 
473         // LIVECONNECT_COMPLIANCE: Non-empty string should convert to true.
474         executeJavaScript("testObject.setBooleanValue(\"+042.10\");");
475         assertFalse(mTestObject.waitForBooleanValue());
476 
477         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
478         executeJavaScript("testObject.setCustomTypeValue(\"+042.10\");");
479         assertNull(mTestObject.waitForCustomTypeValue());
480     }
481 
482     // Test passing a JavaScript object to a method of an injected object.
483     @SmallTest
484     @Feature({"AndroidWebView", "Android-JavaBridge"})
testPassJavaScriptObject()485     public void testPassJavaScriptObject() throws Throwable {
486         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
487         executeJavaScript("testObject.setObjectValue({foo: 42});");
488         assertNull(mTestObject.waitForObjectValue());
489 
490         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
491         executeJavaScript("testObject.setCustomTypeValue({foo: 42});");
492         assertNull(mTestObject.waitForCustomTypeValue());
493 
494         // LIVECONNECT_COMPLIANCE: Should call toString() on object.
495         executeJavaScript("testObject.setStringValue({foo: 42});");
496         assertEquals("undefined", mTestObject.waitForStringValue());
497 
498         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
499         executeJavaScript("testObject.setByteValue({foo: 42});");
500         assertEquals(0, mTestObject.waitForByteValue());
501 
502         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
503         executeJavaScript("testObject.setCharValue({foo: 42});");
504         assertEquals('\u0000', mTestObject.waitForCharValue());
505 
506         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
507         executeJavaScript("testObject.setShortValue({foo: 42});");
508         assertEquals(0, mTestObject.waitForShortValue());
509 
510         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
511         executeJavaScript("testObject.setIntValue({foo: 42});");
512         assertEquals(0, mTestObject.waitForIntValue());
513 
514         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
515         executeJavaScript("testObject.setLongValue({foo: 42});");
516         assertEquals(0L, mTestObject.waitForLongValue());
517 
518         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
519         executeJavaScript("testObject.setFloatValue({foo: 42});");
520         assertEquals(0.0f, mTestObject.waitForFloatValue());
521 
522         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
523         executeJavaScript("testObject.setDoubleValue({foo: 42});");
524         assertEquals(0.0, mTestObject.waitForDoubleValue());
525 
526         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
527         executeJavaScript("testObject.setBooleanValue({foo: 42});");
528         assertFalse(mTestObject.waitForBooleanValue());
529     }
530 
531     // Test passing a Java object to a method of an injected object. Note that
532     // this test requires being able to return objects from the methods of
533     // injected objects. This is tested elsewhere.
534     @SmallTest
535     @Feature({"AndroidWebView", "Android-JavaBridge"})
testPassJavaObject()536     public void testPassJavaObject() throws Throwable {
537         executeJavaScript("testObject.setObjectValue(testObject.getObjectInstance());");
538         assertTrue(mTestObject.getObjectInstance() == mTestObject.waitForObjectValue());
539         executeJavaScript("testObject.setObjectValue(testObject.getCustomTypeInstance());");
540         assertTrue(mTestObject.getCustomTypeInstance() == mTestObject.waitForObjectValue());
541 
542         executeJavaScript("testObject.setCustomTypeValue(testObject.getObjectInstance());");
543         assertTrue(mTestObject.getObjectInstance() == mTestObject.waitForCustomTypeValue());
544         executeJavaScript("testObject.setCustomTypeValue(testObject.getCustomTypeInstance());");
545         assertTrue(mTestObject.getCustomTypeInstance() == mTestObject.waitForCustomTypeValue());
546         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception, as the types are unrelated.
547         executeJavaScript("testObject.setCustomTypeValue(testObject.getCustomType2Instance());");
548         assertTrue(mTestObject.getCustomType2Instance() ==
549                 (Object)mTestObject.waitForCustomTypeValue());
550 
551         // LIVECONNECT_COMPLIANCE: Should call toString() on object.
552         executeJavaScript("testObject.setStringValue(testObject.getObjectInstance());");
553         assertEquals("undefined", mTestObject.waitForStringValue());
554 
555         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
556         executeJavaScript("testObject.setByteValue(testObject.getObjectInstance());");
557         assertEquals(0, mTestObject.waitForByteValue());
558 
559         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
560         executeJavaScript("testObject.setCharValue(testObject.getObjectInstance());");
561         assertEquals('\u0000', mTestObject.waitForCharValue());
562 
563         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
564         executeJavaScript("testObject.setShortValue(testObject.getObjectInstance());");
565         assertEquals(0, mTestObject.waitForShortValue());
566 
567         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
568         executeJavaScript("testObject.setIntValue(testObject.getObjectInstance());");
569         assertEquals(0, mTestObject.waitForIntValue());
570 
571         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
572         executeJavaScript("testObject.setLongValue(testObject.getObjectInstance());");
573         assertEquals(0L, mTestObject.waitForLongValue());
574 
575         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
576         executeJavaScript("testObject.setFloatValue(testObject.getObjectInstance());");
577         assertEquals(0.0f, mTestObject.waitForFloatValue());
578 
579         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
580         executeJavaScript("testObject.setDoubleValue(testObject.getObjectInstance());");
581         assertEquals(0.0, mTestObject.waitForDoubleValue());
582 
583         // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
584         executeJavaScript("testObject.setBooleanValue(testObject.getObjectInstance());");
585         assertFalse(mTestObject.waitForBooleanValue());
586     }
587 
588     // Test passing JavaScript null to a method of an injected object.
589     @SmallTest
590     @Feature({"AndroidWebView", "Android-JavaBridge"})
testPassNull()591     public void testPassNull() throws Throwable {
592         executeJavaScript("testObject.setObjectValue(null);");
593         assertNull(mTestObject.waitForObjectValue());
594 
595         executeJavaScript("testObject.setCustomTypeValue(null);");
596         assertNull(mTestObject.waitForCustomTypeValue());
597 
598         executeJavaScript("testObject.setStringValue(null);");
599         assertNull(mTestObject.waitForStringValue());
600 
601         executeJavaScript("testObject.setByteValue(null);");
602         assertEquals(0, mTestObject.waitForByteValue());
603 
604         executeJavaScript("testObject.setCharValue(null);");
605         assertEquals('\u0000', mTestObject.waitForCharValue());
606 
607         executeJavaScript("testObject.setShortValue(null);");
608         assertEquals(0, mTestObject.waitForShortValue());
609 
610         executeJavaScript("testObject.setIntValue(null);");
611         assertEquals(0, mTestObject.waitForIntValue());
612 
613         executeJavaScript("testObject.setLongValue(null);");
614         assertEquals(0L, mTestObject.waitForLongValue());
615 
616         executeJavaScript("testObject.setFloatValue(null);");
617         assertEquals(0.0f, mTestObject.waitForFloatValue());
618 
619         executeJavaScript("testObject.setDoubleValue(null);");
620         assertEquals(0.0, mTestObject.waitForDoubleValue());
621 
622         executeJavaScript("testObject.setBooleanValue(null);");
623         assertFalse(mTestObject.waitForBooleanValue());
624     }
625 
626     // Test passing JavaScript undefined to a method of an injected object.
627     @SmallTest
628     @Feature({"AndroidWebView", "Android-JavaBridge"})
testPassUndefined()629     public void testPassUndefined() throws Throwable {
630         executeJavaScript("testObject.setObjectValue(undefined);");
631         assertNull(mTestObject.waitForObjectValue());
632 
633         executeJavaScript("testObject.setCustomTypeValue(undefined);");
634         assertNull(mTestObject.waitForCustomTypeValue());
635 
636         // LIVECONNECT_COMPLIANCE: Should be NULL.
637         executeJavaScript("testObject.setStringValue(undefined);");
638         assertEquals("undefined", mTestObject.waitForStringValue());
639 
640         executeJavaScript("testObject.setByteValue(undefined);");
641         assertEquals(0, mTestObject.waitForByteValue());
642 
643         executeJavaScript("testObject.setCharValue(undefined);");
644         assertEquals('\u0000', mTestObject.waitForCharValue());
645 
646         executeJavaScript("testObject.setShortValue(undefined);");
647         assertEquals(0, mTestObject.waitForShortValue());
648 
649         executeJavaScript("testObject.setIntValue(undefined);");
650         assertEquals(0, mTestObject.waitForIntValue());
651 
652         executeJavaScript("testObject.setLongValue(undefined);");
653         assertEquals(0L, mTestObject.waitForLongValue());
654 
655         executeJavaScript("testObject.setFloatValue(undefined);");
656         assertEquals(0.0f, mTestObject.waitForFloatValue());
657 
658         executeJavaScript("testObject.setDoubleValue(undefined);");
659         assertEquals(0.0, mTestObject.waitForDoubleValue());
660 
661         executeJavaScript("testObject.setBooleanValue(undefined);");
662         assertFalse(mTestObject.waitForBooleanValue());
663     }
664 
665     // Verify that ArrayBuffers are not converted into objects or strings when passed
666     // to Java. Basically, ArrayBuffers are treated as generic JavaScript objects.
667     @SmallTest
668     @Feature({"AndroidWebView", "Android-JavaBridge"})
testPassArrayBuffer()669     public void testPassArrayBuffer() throws Throwable {
670         executeJavaScript("buffer = new ArrayBuffer(16);");
671 
672         executeJavaScript("testObject.setObjectValue(buffer);");
673         assertNull(mTestObject.waitForObjectValue());
674 
675         executeJavaScript("testObject.setStringValue(buffer);");
676         assertEquals("undefined", mTestObject.waitForStringValue());
677     }
678 
679     // Verify that ArrayBufferViewss are not converted into objects or strings when passed
680     // to Java. Basically, ArrayBufferViews are treated as generic JavaScript objects.
681     // Here, a DataView is used as an ArrayBufferView instance (since the latter is
682     // an interface and can't be instantiated directly).
683     @SmallTest
684     @Feature({"AndroidWebView", "Android-JavaBridge"})
testPassDataView()685     public void testPassDataView() throws Throwable {
686         executeJavaScript("buffer = new ArrayBuffer(16);");
687 
688         executeJavaScript("testObject.setObjectValue(new DataView(buffer));");
689         assertNull(mTestObject.waitForObjectValue());
690 
691         executeJavaScript("testObject.setStringValue(new DataView(buffer));");
692         assertEquals("undefined", mTestObject.waitForStringValue());
693     }
694 
695     // Verify that Date objects are not converted into double values, strings or objects.
696     @SmallTest
697     @Feature({"AndroidWebView", "Android-JavaBridge"})
testPassDateObject()698     public void testPassDateObject() throws Throwable {
699         executeJavaScript("testObject.setDoubleValue(new Date(2000, 0, 1));");
700         assertEquals(0.0, mTestObject.waitForDoubleValue());
701 
702         executeJavaScript("testObject.setStringValue(new Date(2000, 0, 1));");
703         assertEquals("undefined", mTestObject.waitForStringValue());
704 
705         executeJavaScript("testObject.setObjectValue(new Date(2000, 0, 1));");
706         assertNull(mTestObject.waitForObjectValue());
707     }
708 
709     // Verify that RegExp objects are not converted into strings or objects.
710     @SmallTest
711     @Feature({"AndroidWebView", "Android-JavaBridge"})
testPassRegExpObject()712     public void testPassRegExpObject() throws Throwable {
713         executeJavaScript("testObject.setStringValue(/abc/);");
714         assertEquals("undefined", mTestObject.waitForStringValue());
715 
716         executeJavaScript("testObject.setObjectValue(/abc/);");
717         assertNull(mTestObject.waitForObjectValue());
718     }
719 
720     // Verify that Function objects are not converted into strings or objects.
721     @SmallTest
722     @Feature({"AndroidWebView", "Android-JavaBridge"})
testPassFunctionObject()723     public void testPassFunctionObject() throws Throwable {
724         executeJavaScript("func = new Function('a', 'b', 'return a + b');");
725 
726         executeJavaScript("testObject.setStringValue(func);");
727         assertEquals("undefined", mTestObject.waitForStringValue());
728 
729         executeJavaScript("testObject.setObjectValue(func);");
730         assertNull(mTestObject.waitForObjectValue());
731     }
732 }
733