1f7e26448c3591989840efa65f4f3f93a294b991eSteve Block/* 2f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * Copyright (C) 2011 The Android Open Source Project 3f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * 4f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * Licensed under the Apache License, Version 2.0 (the "License"); 5f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * you may not use this file except in compliance with the License. 6f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * You may obtain a copy of the License at 7f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * 8f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * http://www.apache.org/licenses/LICENSE-2.0 9f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * 10f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * Unless required by applicable law or agreed to in writing, software 11f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * distributed under the License is distributed on an "AS IS" BASIS, 12f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * See the License for the specific language governing permissions and 14f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * limitations under the License. 15f7e26448c3591989840efa65f4f3f93a294b991eSteve Block */ 16f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 17f7e26448c3591989840efa65f4f3f93a294b991eSteve Block/** 18f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * Part of the test suite for the WebView's Java Bridge. Tests a number of features including ... 19f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * - The type of injected objects 20f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * - The type of their methods 21f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * - Replacing objects 22f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * - Removing objects 23f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * - Access control 24f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * - Calling methods on returned objects 25f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * - Multiply injected objects 26f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * - Threading 27f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * - Inheritance 28f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * 29f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * To run this test ... 30f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * adb shell am instrument -w -e class com.android.webviewtests.JavaBridgeBasicsTest \ 31f7e26448c3591989840efa65f4f3f93a294b991eSteve Block * com.android.webviewtests/android.test.InstrumentationTestRunner 32f7e26448c3591989840efa65f4f3f93a294b991eSteve Block */ 33f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 34f7e26448c3591989840efa65f4f3f93a294b991eSteve Blockpackage com.android.webviewtests; 35f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 36f7e26448c3591989840efa65f4f3f93a294b991eSteve Blockpublic class JavaBridgeBasicsTest extends JavaBridgeTestBase { 37f7e26448c3591989840efa65f4f3f93a294b991eSteve Block private class TestController extends Controller { 38f7e26448c3591989840efa65f4f3f93a294b991eSteve Block private int mIntValue; 39f7e26448c3591989840efa65f4f3f93a294b991eSteve Block private long mLongValue; 40f7e26448c3591989840efa65f4f3f93a294b991eSteve Block private String mStringValue; 418e33fe944f9e407e1ba0c40736747c707c40acc7Steve Block private boolean mBooleanValue; 42f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 43f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public synchronized void setIntValue(int x) { 44f7e26448c3591989840efa65f4f3f93a294b991eSteve Block mIntValue = x; 45f7e26448c3591989840efa65f4f3f93a294b991eSteve Block notifyResultIsReady(); 46f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 47f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public synchronized void setLongValue(long x) { 48f7e26448c3591989840efa65f4f3f93a294b991eSteve Block mLongValue = x; 49f7e26448c3591989840efa65f4f3f93a294b991eSteve Block notifyResultIsReady(); 50f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 51f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public synchronized void setStringValue(String x) { 52f7e26448c3591989840efa65f4f3f93a294b991eSteve Block mStringValue = x; 53f7e26448c3591989840efa65f4f3f93a294b991eSteve Block notifyResultIsReady(); 54f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 558e33fe944f9e407e1ba0c40736747c707c40acc7Steve Block public synchronized void setBooleanValue(boolean x) { 568e33fe944f9e407e1ba0c40736747c707c40acc7Steve Block mBooleanValue = x; 578e33fe944f9e407e1ba0c40736747c707c40acc7Steve Block notifyResultIsReady(); 588e33fe944f9e407e1ba0c40736747c707c40acc7Steve Block } 59f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 60f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public synchronized int waitForIntValue() { 61f7e26448c3591989840efa65f4f3f93a294b991eSteve Block waitForResult(); 62f7e26448c3591989840efa65f4f3f93a294b991eSteve Block return mIntValue; 63f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 64f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public synchronized long waitForLongValue() { 65f7e26448c3591989840efa65f4f3f93a294b991eSteve Block waitForResult(); 66f7e26448c3591989840efa65f4f3f93a294b991eSteve Block return mLongValue; 67f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 68f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public synchronized String waitForStringValue() { 69f7e26448c3591989840efa65f4f3f93a294b991eSteve Block waitForResult(); 70f7e26448c3591989840efa65f4f3f93a294b991eSteve Block return mStringValue; 71f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 728e33fe944f9e407e1ba0c40736747c707c40acc7Steve Block public synchronized boolean waitForBooleanValue() { 738e33fe944f9e407e1ba0c40736747c707c40acc7Steve Block waitForResult(); 748e33fe944f9e407e1ba0c40736747c707c40acc7Steve Block return mBooleanValue; 758e33fe944f9e407e1ba0c40736747c707c40acc7Steve Block } 76f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 77f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 7813ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block private static class ObjectWithStaticMethod { 7913ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block public static String staticMethod() { 8013ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block return "foo"; 8113ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block } 8213ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block } 8313ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block 84f7e26448c3591989840efa65f4f3f93a294b991eSteve Block TestController mTestController; 85f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 86f7e26448c3591989840efa65f4f3f93a294b991eSteve Block @Override 87f7e26448c3591989840efa65f4f3f93a294b991eSteve Block protected void setUp() throws Exception { 88f7e26448c3591989840efa65f4f3f93a294b991eSteve Block super.setUp(); 89f7e26448c3591989840efa65f4f3f93a294b991eSteve Block mTestController = new TestController(); 90f7e26448c3591989840efa65f4f3f93a294b991eSteve Block setUpWebView(mTestController, "testController"); 91f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 92f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 93f7e26448c3591989840efa65f4f3f93a294b991eSteve Block // Note that this requires that we can pass a JavaScript string to Java. 94f7e26448c3591989840efa65f4f3f93a294b991eSteve Block protected String executeJavaScriptAndGetStringResult(String script) throws Throwable { 95f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScript("testController.setStringValue(" + script + ");"); 96f7e26448c3591989840efa65f4f3f93a294b991eSteve Block return mTestController.waitForStringValue(); 97f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 98f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 99f7e26448c3591989840efa65f4f3f93a294b991eSteve Block protected void injectObjectAndReload(final Object object, final String name) throws Throwable { 100f7e26448c3591989840efa65f4f3f93a294b991eSteve Block runTestOnUiThread(new Runnable() { 101f7e26448c3591989840efa65f4f3f93a294b991eSteve Block @Override 102f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void run() { 103f7e26448c3591989840efa65f4f3f93a294b991eSteve Block getWebView().addJavascriptInterface(object, name); 104f7e26448c3591989840efa65f4f3f93a294b991eSteve Block getWebView().reload(); 105f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 106f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }); 107f7e26448c3591989840efa65f4f3f93a294b991eSteve Block mWebViewClient.waitForOnPageFinished(); 108f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 109f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 11013ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block // Note that this requires that we can pass a JavaScript boolean to Java. 11113ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block private void assertRaisesException(String script) throws Throwable { 11213ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block executeJavaScript("try {" + 11313ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block script + ";" + 11413ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block " testController.setBooleanValue(false);" + 11513ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block "} catch (exception) {" + 11613ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block " testController.setBooleanValue(true);" + 11713ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block "}"); 11813ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block assertTrue(mTestController.waitForBooleanValue()); 11913ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block } 12013ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block 121f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testTypeOfInjectedObject() throws Throwable { 122f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("object", executeJavaScriptAndGetStringResult("typeof testController")); 123f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 124f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 125f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testAdditionNotReflectedUntilReload() throws Throwable { 126f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof testObject")); 127f7e26448c3591989840efa65f4f3f93a294b991eSteve Block runTestOnUiThread(new Runnable() { 128f7e26448c3591989840efa65f4f3f93a294b991eSteve Block @Override 129f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void run() { 130f7e26448c3591989840efa65f4f3f93a294b991eSteve Block getWebView().addJavascriptInterface(new Object(), "testObject"); 131f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 132f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }); 133f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof testObject")); 134f7e26448c3591989840efa65f4f3f93a294b991eSteve Block runTestOnUiThread(new Runnable() { 135f7e26448c3591989840efa65f4f3f93a294b991eSteve Block @Override 136f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void run() { 137f7e26448c3591989840efa65f4f3f93a294b991eSteve Block getWebView().reload(); 138f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 139f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }); 140f7e26448c3591989840efa65f4f3f93a294b991eSteve Block mWebViewClient.waitForOnPageFinished(); 141f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("object", executeJavaScriptAndGetStringResult("typeof testObject")); 142f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 143f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 144f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testRemovalNotReflectedUntilReload() throws Throwable { 145f7e26448c3591989840efa65f4f3f93a294b991eSteve Block injectObjectAndReload(new Object(), "testObject"); 146f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("object", executeJavaScriptAndGetStringResult("typeof testObject")); 147f7e26448c3591989840efa65f4f3f93a294b991eSteve Block runTestOnUiThread(new Runnable() { 148f7e26448c3591989840efa65f4f3f93a294b991eSteve Block @Override 149f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void run() { 150f7e26448c3591989840efa65f4f3f93a294b991eSteve Block getWebView().removeJavascriptInterface("testObject"); 151f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 152f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }); 153f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("object", executeJavaScriptAndGetStringResult("typeof testObject")); 154f7e26448c3591989840efa65f4f3f93a294b991eSteve Block runTestOnUiThread(new Runnable() { 155f7e26448c3591989840efa65f4f3f93a294b991eSteve Block @Override 156f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void run() { 157f7e26448c3591989840efa65f4f3f93a294b991eSteve Block getWebView().reload(); 158f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 159f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }); 160f7e26448c3591989840efa65f4f3f93a294b991eSteve Block mWebViewClient.waitForOnPageFinished(); 161f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof testObject")); 162f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 163f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 164f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testRemoveObjectNotAdded() throws Throwable { 165f7e26448c3591989840efa65f4f3f93a294b991eSteve Block runTestOnUiThread(new Runnable() { 166f7e26448c3591989840efa65f4f3f93a294b991eSteve Block @Override 167f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void run() { 168f7e26448c3591989840efa65f4f3f93a294b991eSteve Block getWebView().removeJavascriptInterface("foo"); 169f7e26448c3591989840efa65f4f3f93a294b991eSteve Block getWebView().reload(); 170f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 171f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }); 172f7e26448c3591989840efa65f4f3f93a294b991eSteve Block mWebViewClient.waitForOnPageFinished(); 173f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof foo")); 174f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 175f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 176f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testTypeOfMethod() throws Throwable { 177f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("function", 178f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScriptAndGetStringResult("typeof testController.setStringValue")); 179f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 180f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 18113ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block public void testTypeOfInvalidMethod() throws Throwable { 18213ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof testController.foo")); 18313ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block } 18413ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block 18513ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block public void testCallingInvalidMethodRaisesException() throws Throwable { 18613ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block assertRaisesException("testController.foo()"); 18713ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block } 18813ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block 189d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block public void testUncaughtJavaExceptionRaisesJavaException() throws Throwable { 190d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block injectObjectAndReload(new Object() { 191d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block public void method() { throw new RuntimeException("foo"); } 192d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block }, "testObject"); 193d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block assertRaisesException("testObject.method()"); 194d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block } 195d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block 19613ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block // Note that this requires that we can pass a JavaScript string to Java. 19713ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block public void testTypeOfStaticMethod() throws Throwable { 19813ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block injectObjectAndReload(new ObjectWithStaticMethod(), "testObject"); 19913ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block executeJavaScript("testController.setStringValue(typeof testObject.staticMethod)"); 20013ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block assertEquals("function", mTestController.waitForStringValue()); 20113ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block } 20213ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block 20313ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block // Note that this requires that we can pass a JavaScript string to Java. 20413ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block public void testCallStaticMethod() throws Throwable { 20513ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block injectObjectAndReload(new ObjectWithStaticMethod(), "testObject"); 20613ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block executeJavaScript("testController.setStringValue(testObject.staticMethod())"); 20713ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block assertEquals("foo", mTestController.waitForStringValue()); 20813ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block } 20913ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block 210f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testPrivateMethodNotExposed() throws Throwable { 211f7e26448c3591989840efa65f4f3f93a294b991eSteve Block injectObjectAndReload(new Object() { 212f7e26448c3591989840efa65f4f3f93a294b991eSteve Block private void method() {} 213f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }, "testObject"); 214f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("undefined", 215f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScriptAndGetStringResult("typeof testObject.method")); 216f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 217f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 218f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testReplaceInjectedObject() throws Throwable { 219f7e26448c3591989840efa65f4f3f93a294b991eSteve Block injectObjectAndReload(new Object() { 220f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void method() { mTestController.setStringValue("object 1"); } 221f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }, "testObject"); 222f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScript("testObject.method()"); 223f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("object 1", mTestController.waitForStringValue()); 224f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 225f7e26448c3591989840efa65f4f3f93a294b991eSteve Block injectObjectAndReload(new Object() { 226f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void method() { mTestController.setStringValue("object 2"); } 227f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }, "testObject"); 228f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScript("testObject.method()"); 229f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("object 2", mTestController.waitForStringValue()); 230f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 231f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 232f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testInjectNullObjectIsIgnored() throws Throwable { 233f7e26448c3591989840efa65f4f3f93a294b991eSteve Block injectObjectAndReload(null, "testObject"); 234f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof testObject")); 235f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 236f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 237f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testReplaceInjectedObjectWithNullObjectIsIgnored() throws Throwable { 238f7e26448c3591989840efa65f4f3f93a294b991eSteve Block injectObjectAndReload(new Object(), "testObject"); 239f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("object", executeJavaScriptAndGetStringResult("typeof testObject")); 240f7e26448c3591989840efa65f4f3f93a294b991eSteve Block injectObjectAndReload(null, "testObject"); 241f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("object", executeJavaScriptAndGetStringResult("typeof testObject")); 242f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 243f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 244f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testCallOverloadedMethodWithDifferentNumberOfArguments() throws Throwable { 245f7e26448c3591989840efa65f4f3f93a294b991eSteve Block injectObjectAndReload(new Object() { 246f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void method() { mTestController.setStringValue("0 args"); } 247f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void method(int x) { mTestController.setStringValue("1 arg"); } 248f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void method(int x, int y) { mTestController.setStringValue("2 args"); } 249f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }, "testObject"); 250f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScript("testObject.method()"); 251f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("0 args", mTestController.waitForStringValue()); 252f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScript("testObject.method(42)"); 253f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("1 arg", mTestController.waitForStringValue()); 254f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScript("testObject.method(null)"); 255f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("1 arg", mTestController.waitForStringValue()); 256f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScript("testObject.method(undefined)"); 257f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("1 arg", mTestController.waitForStringValue()); 258f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScript("testObject.method(42, 42)"); 259f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("2 args", mTestController.waitForStringValue()); 260f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 261f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 2628e33fe944f9e407e1ba0c40736747c707c40acc7Steve Block public void testCallMethodWithWrongNumberOfArgumentsRaisesException() throws Throwable { 26313ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block assertRaisesException("testController.setIntValue()"); 26413ad467a91ac6d86a959b49f0168a0e6893aef2cSteve Block assertRaisesException("testController.setIntValue(42, 42)"); 2658e33fe944f9e407e1ba0c40736747c707c40acc7Steve Block } 2668e33fe944f9e407e1ba0c40736747c707c40acc7Steve Block 267f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testObjectPersistsAcrossPageLoads() throws Throwable { 268f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("object", executeJavaScriptAndGetStringResult("typeof testController")); 269f7e26448c3591989840efa65f4f3f93a294b991eSteve Block runTestOnUiThread(new Runnable() { 270f7e26448c3591989840efa65f4f3f93a294b991eSteve Block @Override 271f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void run() { 272f7e26448c3591989840efa65f4f3f93a294b991eSteve Block getWebView().reload(); 273f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 274f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }); 275f7e26448c3591989840efa65f4f3f93a294b991eSteve Block mWebViewClient.waitForOnPageFinished(); 276f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("object", executeJavaScriptAndGetStringResult("typeof testController")); 277f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 278f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 279f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testSameObjectInjectedMultipleTimes() throws Throwable { 280f7e26448c3591989840efa65f4f3f93a294b991eSteve Block class TestObject { 281f7e26448c3591989840efa65f4f3f93a294b991eSteve Block private int mNumMethodInvocations; 282f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void method() { mTestController.setIntValue(++mNumMethodInvocations); } 283f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 284f7e26448c3591989840efa65f4f3f93a294b991eSteve Block final TestObject testObject = new TestObject(); 285f7e26448c3591989840efa65f4f3f93a294b991eSteve Block runTestOnUiThread(new Runnable() { 286f7e26448c3591989840efa65f4f3f93a294b991eSteve Block @Override 287f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void run() { 288f7e26448c3591989840efa65f4f3f93a294b991eSteve Block getWebView().addJavascriptInterface(testObject, "testObject1"); 289f7e26448c3591989840efa65f4f3f93a294b991eSteve Block getWebView().addJavascriptInterface(testObject, "testObject2"); 290f7e26448c3591989840efa65f4f3f93a294b991eSteve Block getWebView().reload(); 291f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 292f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }); 293f7e26448c3591989840efa65f4f3f93a294b991eSteve Block mWebViewClient.waitForOnPageFinished(); 294f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScript("testObject1.method()"); 295f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals(1, mTestController.waitForIntValue()); 296f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScript("testObject2.method()"); 297f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals(2, mTestController.waitForIntValue()); 298f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 299f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 300f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testCallMethodOnReturnedObject() throws Throwable { 301f7e26448c3591989840efa65f4f3f93a294b991eSteve Block injectObjectAndReload(new Object() { 302f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public Object getInnerObject() { 303f7e26448c3591989840efa65f4f3f93a294b991eSteve Block return new Object() { 304f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void method(int x) { mTestController.setIntValue(x); } 305f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }; 306f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 307f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }, "testObject"); 308f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScript("testObject.getInnerObject().method(42)"); 309f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals(42, mTestController.waitForIntValue()); 310f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 311f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 312f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testReturnedObjectInjectedElsewhere() throws Throwable { 313f7e26448c3591989840efa65f4f3f93a294b991eSteve Block class InnerObject { 314f7e26448c3591989840efa65f4f3f93a294b991eSteve Block private int mNumMethodInvocations; 315f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void method() { mTestController.setIntValue(++mNumMethodInvocations); } 316f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 317f7e26448c3591989840efa65f4f3f93a294b991eSteve Block final InnerObject innerObject = new InnerObject(); 318f7e26448c3591989840efa65f4f3f93a294b991eSteve Block final Object object = new Object() { 319f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public InnerObject getInnerObject() { 320f7e26448c3591989840efa65f4f3f93a294b991eSteve Block return innerObject; 321f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 322f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }; 323f7e26448c3591989840efa65f4f3f93a294b991eSteve Block runTestOnUiThread(new Runnable() { 324f7e26448c3591989840efa65f4f3f93a294b991eSteve Block @Override 325f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void run() { 326f7e26448c3591989840efa65f4f3f93a294b991eSteve Block getWebView().addJavascriptInterface(object, "testObject"); 327f7e26448c3591989840efa65f4f3f93a294b991eSteve Block getWebView().addJavascriptInterface(innerObject, "innerObject"); 328f7e26448c3591989840efa65f4f3f93a294b991eSteve Block getWebView().reload(); 329f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 330f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }); 331f7e26448c3591989840efa65f4f3f93a294b991eSteve Block mWebViewClient.waitForOnPageFinished(); 332f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScript("testObject.getInnerObject().method()"); 333f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals(1, mTestController.waitForIntValue()); 334f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScript("innerObject.method()"); 335f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals(2, mTestController.waitForIntValue()); 336f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 337f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 338f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testMethodInvokedOnBackgroundThread() throws Throwable { 339f7e26448c3591989840efa65f4f3f93a294b991eSteve Block injectObjectAndReload(new Object() { 340f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void captureThreadId() { 341f7e26448c3591989840efa65f4f3f93a294b991eSteve Block mTestController.setLongValue(Thread.currentThread().getId()); 342f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 343f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }, "testObject"); 344f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScript("testObject.captureThreadId()"); 345f7e26448c3591989840efa65f4f3f93a294b991eSteve Block final long threadId = mTestController.waitForLongValue(); 346f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertFalse(threadId == Thread.currentThread().getId()); 347f7e26448c3591989840efa65f4f3f93a294b991eSteve Block runTestOnUiThread(new Runnable() { 348f7e26448c3591989840efa65f4f3f93a294b991eSteve Block @Override 349f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void run() { 350f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertFalse(threadId == Thread.currentThread().getId()); 351f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 352f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }); 353f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 354f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 355f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testPublicInheritedMethod() throws Throwable { 356f7e26448c3591989840efa65f4f3f93a294b991eSteve Block class Base { 357f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void method(int x) { mTestController.setIntValue(x); } 358f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 359f7e26448c3591989840efa65f4f3f93a294b991eSteve Block class Derived extends Base { 360f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 361f7e26448c3591989840efa65f4f3f93a294b991eSteve Block injectObjectAndReload(new Derived(), "testObject"); 362f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("function", executeJavaScriptAndGetStringResult("typeof testObject.method")); 363f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScript("testObject.method(42)"); 364f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals(42, mTestController.waitForIntValue()); 365f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 366f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 367f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testPrivateInheritedMethod() throws Throwable { 368f7e26448c3591989840efa65f4f3f93a294b991eSteve Block class Base { 369f7e26448c3591989840efa65f4f3f93a294b991eSteve Block private void method() {} 370f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 371f7e26448c3591989840efa65f4f3f93a294b991eSteve Block class Derived extends Base { 372f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 373f7e26448c3591989840efa65f4f3f93a294b991eSteve Block injectObjectAndReload(new Derived(), "testObject"); 374f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof testObject.method")); 375f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 376f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 377f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testOverriddenMethod() throws Throwable { 378f7e26448c3591989840efa65f4f3f93a294b991eSteve Block class Base { 379f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void method() { mTestController.setStringValue("base"); } 380f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 381f7e26448c3591989840efa65f4f3f93a294b991eSteve Block class Derived extends Base { 382f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void method() { mTestController.setStringValue("derived"); } 383f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 384f7e26448c3591989840efa65f4f3f93a294b991eSteve Block injectObjectAndReload(new Derived(), "testObject"); 385f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScript("testObject.method()"); 386f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("derived", mTestController.waitForStringValue()); 387f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 388f7e26448c3591989840efa65f4f3f93a294b991eSteve Block 389f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void testEnumerateMembers() throws Throwable { 390f7e26448c3591989840efa65f4f3f93a294b991eSteve Block injectObjectAndReload(new Object() { 391f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public void method() {} 392f7e26448c3591989840efa65f4f3f93a294b991eSteve Block private void privateMethod() {} 393f7e26448c3591989840efa65f4f3f93a294b991eSteve Block public int field; 394f7e26448c3591989840efa65f4f3f93a294b991eSteve Block private int privateField; 395f7e26448c3591989840efa65f4f3f93a294b991eSteve Block }, "testObject"); 396f7e26448c3591989840efa65f4f3f93a294b991eSteve Block executeJavaScript( 397f7e26448c3591989840efa65f4f3f93a294b991eSteve Block "var result = \"\"; " + 398f7e26448c3591989840efa65f4f3f93a294b991eSteve Block "for (x in testObject) { result += \" \" + x } " + 399f7e26448c3591989840efa65f4f3f93a294b991eSteve Block "testController.setStringValue(result);"); 400f7e26448c3591989840efa65f4f3f93a294b991eSteve Block // LIVECONNECT_COMPLIANCE: Should be able to enumerate members. 401f7e26448c3591989840efa65f4f3f93a294b991eSteve Block assertEquals("", mTestController.waitForStringValue()); 402f7e26448c3591989840efa65f4f3f93a294b991eSteve Block } 4033aa800b9f93a99d6f25623ed24ab5f6fec213c15Steve Block 4043aa800b9f93a99d6f25623ed24ab5f6fec213c15Steve Block public void testReflectPublicMethod() throws Throwable { 4053aa800b9f93a99d6f25623ed24ab5f6fec213c15Steve Block injectObjectAndReload(new Object() { 4063aa800b9f93a99d6f25623ed24ab5f6fec213c15Steve Block public String method() { return "foo"; } 4073aa800b9f93a99d6f25623ed24ab5f6fec213c15Steve Block }, "testObject"); 4083aa800b9f93a99d6f25623ed24ab5f6fec213c15Steve Block assertEquals("foo", executeJavaScriptAndGetStringResult( 4093aa800b9f93a99d6f25623ed24ab5f6fec213c15Steve Block "testObject.getClass().getMethod('method', null).invoke(testObject, null)" + 4103aa800b9f93a99d6f25623ed24ab5f6fec213c15Steve Block ".toString()")); 4113aa800b9f93a99d6f25623ed24ab5f6fec213c15Steve Block } 4123aa800b9f93a99d6f25623ed24ab5f6fec213c15Steve Block 4133aa800b9f93a99d6f25623ed24ab5f6fec213c15Steve Block public void testReflectPublicField() throws Throwable { 4143aa800b9f93a99d6f25623ed24ab5f6fec213c15Steve Block injectObjectAndReload(new Object() { 4153aa800b9f93a99d6f25623ed24ab5f6fec213c15Steve Block public String field = "foo"; 4163aa800b9f93a99d6f25623ed24ab5f6fec213c15Steve Block }, "testObject"); 4173aa800b9f93a99d6f25623ed24ab5f6fec213c15Steve Block assertEquals("foo", executeJavaScriptAndGetStringResult( 4183aa800b9f93a99d6f25623ed24ab5f6fec213c15Steve Block "testObject.getClass().getField('field').get(testObject).toString()")); 4193aa800b9f93a99d6f25623ed24ab5f6fec213c15Steve Block } 420d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block 421d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block public void testReflectPrivateMethodRaisesException() throws Throwable { 422d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block injectObjectAndReload(new Object() { 423d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block private void method() {}; 424d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block }, "testObject"); 425d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block assertRaisesException("testObject.getClass().getMethod('method', null)"); 426d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block // getDeclaredMethod() is able to access a private method, but invoke() 427d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block // throws a Java exception. 428d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block assertRaisesException( 429d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block "testObject.getClass().getDeclaredMethod('method', null).invoke(testObject, null)"); 430d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block } 431d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block 432d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block public void testReflectPrivateFieldRaisesException() throws Throwable { 433d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block injectObjectAndReload(new Object() { 434d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block private int field; 435d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block }, "testObject"); 436d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block assertRaisesException("testObject.getClass().getField('field')"); 437d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block // getDeclaredField() is able to access a private field, but getInt() 438d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block // throws a Java exception. 439d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block assertRaisesException( 440d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block "testObject.getClass().getDeclaredField('field').getInt(testObject)"); 441d890b0ddb607bbff5e809653f065b5e0cf480a6fSteve Block } 442f7e26448c3591989840efa65f4f3f93a294b991eSteve Block} 443