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