Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(35)

Side by Side Diff: content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeBasicsTest.java

Issue 2766393004: Convert most of the rest of instrumentation tests in content (Closed)
Patch Set: rebase Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.content.browser; 5 package org.chromium.content.browser;
6 6
7 import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout; 7 import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
8 8
9 import android.support.test.InstrumentationRegistry;
9 import android.support.test.filters.SmallTest; 10 import android.support.test.filters.SmallTest;
10 11
11 import junit.framework.Assert; 12 import org.junit.Assert;
13 import org.junit.Before;
14 import org.junit.Rule;
15 import org.junit.Test;
16 import org.junit.runner.RunWith;
12 17
13 import org.chromium.base.annotations.SuppressFBWarnings; 18 import org.chromium.base.annotations.SuppressFBWarnings;
14 import org.chromium.base.test.util.CommandLineFlags; 19 import org.chromium.base.test.util.CommandLineFlags;
15 import org.chromium.base.test.util.Feature; 20 import org.chromium.base.test.util.Feature;
16 import org.chromium.content.browser.JavaBridgeTestCommon.Controller; 21 import org.chromium.content.browser.JavaBridgeTestCommon.Controller;
22 import org.chromium.content.browser.test.ContentJUnit4ClassRunner;
17 import org.chromium.content.browser.test.util.TestCallbackHelperContainer; 23 import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
18 import org.chromium.content_public.browser.LoadUrlParams; 24 import org.chromium.content_public.browser.LoadUrlParams;
19 25
20 import java.lang.annotation.ElementType; 26 import java.lang.annotation.ElementType;
21 import java.lang.annotation.Retention; 27 import java.lang.annotation.Retention;
22 import java.lang.annotation.RetentionPolicy; 28 import java.lang.annotation.RetentionPolicy;
23 import java.lang.annotation.Target; 29 import java.lang.annotation.Target;
24 import java.lang.ref.WeakReference; 30 import java.lang.ref.WeakReference;
25 import java.util.concurrent.CountDownLatch; 31 import java.util.concurrent.CountDownLatch;
26 32
27 /** 33 /**
28 * Part of the test suite for the Java Bridge. Tests a number of features includ ing ... 34 * Part of the test suite for the Java Bridge. Tests a number of features includ ing ...
29 * - The type of injected objects 35 * - The type of injected objects
30 * - The type of their methods 36 * - The type of their methods
31 * - Replacing objects 37 * - Replacing objects
32 * - Removing objects 38 * - Removing objects
33 * - Access control 39 * - Access control
34 * - Calling methods on returned objects 40 * - Calling methods on returned objects
35 * - Multiply injected objects 41 * - Multiply injected objects
36 * - Threading 42 * - Threading
37 * - Inheritance 43 * - Inheritance
38 */ 44 */
45 @RunWith(ContentJUnit4ClassRunner.class)
39 @SuppressFBWarnings( 46 @SuppressFBWarnings(
40 {"UMAC_UNCALLABLE_METHOD_OF_ANONYMOUS_CLASS", "URF_UNREAD_PUBLIC_OR_PROT ECTED_FIELD"}) 47 {"UMAC_UNCALLABLE_METHOD_OF_ANONYMOUS_CLASS", "URF_UNREAD_PUBLIC_OR_PROT ECTED_FIELD"})
41 public class JavaBridgeBasicsTest extends JavaBridgeTestBase { 48 public class JavaBridgeBasicsTest {
49 @Rule
50 public JavaBridgeActivityTestRule mActivityTestRule =
51 new JavaBridgeActivityTestRule().shouldSetUp(false);
52
42 @SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD") 53 @SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
43 private static class TestController extends Controller { 54 private static class TestController extends Controller {
44 private int mIntValue; 55 private int mIntValue;
45 private long mLongValue; 56 private long mLongValue;
46 private String mStringValue; 57 private String mStringValue;
47 private boolean mBooleanValue; 58 private boolean mBooleanValue;
48 59
49 public synchronized void setIntValue(int x) { 60 public synchronized void setIntValue(int x) {
50 mIntValue = x; 61 mIntValue = x;
51 notifyResultIsReady(); 62 notifyResultIsReady();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 } 97 }
87 98
88 private static class ObjectWithStaticMethod { 99 private static class ObjectWithStaticMethod {
89 public static String staticMethod() { 100 public static String staticMethod() {
90 return "foo"; 101 return "foo";
91 } 102 }
92 } 103 }
93 104
94 TestController mTestController; 105 TestController mTestController;
95 106
96 @Override 107 @Before
97 protected void setUp() throws Exception { 108 public void setUp() throws Exception {
98 super.setUp(); 109 mActivityTestRule.setUpContentView();
99 mTestController = new TestController(); 110 mTestController = new TestController();
100 injectObjectAndReload(mTestController, "testController"); 111 mActivityTestRule.injectObjectAndReload(mTestController, "testController ");
101 } 112 }
102 113
103 // Note that this requires that we can pass a JavaScript string to Java. 114 // Note that this requires that we can pass a JavaScript string to Java.
104 protected String executeJavaScriptAndGetStringResult(String script) throws T hrowable { 115 protected String executeJavaScriptAndGetStringResult(String script) throws T hrowable {
105 executeJavaScript("testController.setStringValue(" + script + ");"); 116 mActivityTestRule.executeJavaScript("testController.setStringValue(" + s cript + ");");
106 return mTestController.waitForStringValue(); 117 return mTestController.waitForStringValue();
107 } 118 }
108 119
109 // Note that this requires that we can pass a JavaScript boolean to Java. 120 // Note that this requires that we can pass a JavaScript boolean to Java.
110 private void executeAndSetIfException(String script) throws Throwable { 121 private void executeAndSetIfException(String script) throws Throwable {
111 executeJavaScript("try {" 122 mActivityTestRule.executeJavaScript("try {" + script + ";"
112 + script + ";"
113 + " testController.setBooleanValue(false);" 123 + " testController.setBooleanValue(false);"
114 + "} catch (exception) {" 124 + "} catch (exception) {"
115 + " testController.setBooleanValue(true);" 125 + " testController.setBooleanValue(true);"
116 + "}"); 126 + "}");
117 } 127 }
118 128
119 private void assertRaisesException(String script) throws Throwable { 129 private void assertRaisesException(String script) throws Throwable {
120 executeAndSetIfException(script); 130 executeAndSetIfException(script);
121 assertTrue(mTestController.waitForBooleanValue()); 131 Assert.assertTrue(mTestController.waitForBooleanValue());
122 } 132 }
123 133
124 private void assertNoRaisedException(String script) throws Throwable { 134 private void assertNoRaisedException(String script) throws Throwable {
125 executeAndSetIfException(script); 135 executeAndSetIfException(script);
126 assertFalse(mTestController.waitForBooleanValue()); 136 Assert.assertFalse(mTestController.waitForBooleanValue());
127 } 137 }
128 138
139 @Test
129 @SmallTest 140 @SmallTest
130 @Feature({"AndroidWebView", "Android-JavaBridge"}) 141 @Feature({"AndroidWebView", "Android-JavaBridge"})
131 public void testTypeOfInjectedObject() throws Throwable { 142 public void testTypeOfInjectedObject() throws Throwable {
132 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testC ontroller")); 143 Assert.assertEquals("object", executeJavaScriptAndGetStringResult("typeo f testController"));
133 } 144 }
134 145
146 @Test
135 @SmallTest 147 @SmallTest
136 @Feature({"AndroidWebView", "Android-JavaBridge"}) 148 @Feature({"AndroidWebView", "Android-JavaBridge"})
137 public void testAdditionNotReflectedUntilReload() throws Throwable { 149 public void testAdditionNotReflectedUntilReload() throws Throwable {
138 assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof te stObject")); 150 Assert.assertEquals("undefined", executeJavaScriptAndGetStringResult("ty peof testObject"));
139 runTestOnUiThread(new Runnable() { 151 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable( ) {
140 @Override 152 @Override
141 public void run() { 153 public void run() {
142 getContentViewCore().addPossiblyUnsafeJavascriptInterface( 154 mActivityTestRule.getContentViewCore().addPossiblyUnsafeJavascri ptInterface(
143 new Object(), "testObject", null); 155 new Object(), "testObject", null);
144 } 156 }
145 }); 157 });
146 assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof te stObject")); 158 Assert.assertEquals("undefined", executeJavaScriptAndGetStringResult("ty peof testObject"));
147 synchronousPageReload(); 159 mActivityTestRule.synchronousPageReload();
148 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testO bject")); 160 Assert.assertEquals("object", executeJavaScriptAndGetStringResult("typeo f testObject"));
149 } 161 }
150 162
163 @Test
151 @SmallTest 164 @SmallTest
152 @Feature({"AndroidWebView", "Android-JavaBridge"}) 165 @Feature({"AndroidWebView", "Android-JavaBridge"})
153 public void testRemovalNotReflectedUntilReload() throws Throwable { 166 public void testRemovalNotReflectedUntilReload() throws Throwable {
154 injectObjectAndReload(new Object() { 167 mActivityTestRule.injectObjectAndReload(new Object() {
155 public void method() { 168 public void method() {
156 mTestController.setStringValue("I'm here"); 169 mTestController.setStringValue("I'm here");
157 } 170 }
158 }, "testObject"); 171 }, "testObject");
159 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testO bject")); 172 Assert.assertEquals("object", executeJavaScriptAndGetStringResult("typeo f testObject"));
160 executeJavaScript("testObject.method()"); 173 mActivityTestRule.executeJavaScript("testObject.method()");
161 assertEquals("I'm here", mTestController.waitForStringValue()); 174 Assert.assertEquals("I'm here", mTestController.waitForStringValue());
162 runTestOnUiThread(new Runnable() { 175 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable( ) {
163 @Override 176 @Override
164 public void run() { 177 public void run() {
165 getContentViewCore().removeJavascriptInterface("testObject"); 178 mActivityTestRule.getContentViewCore().removeJavascriptInterface ("testObject");
166 } 179 }
167 }); 180 });
168 // Check that the Java object is being held by the Java bridge, thus it' s not 181 // Check that the Java object is being held by the Java bridge, thus it' s not
169 // collected. Note that despite that what JavaDoc says about invoking "g c()", both Dalvik 182 // collected. Note that despite that what JavaDoc says about invoking "g c()", both Dalvik
170 // and ART actually run the collector if called via Runtime. 183 // and ART actually run the collector if called via Runtime.
171 Runtime.getRuntime().gc(); 184 Runtime.getRuntime().gc();
172 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testO bject")); 185 Assert.assertEquals("object", executeJavaScriptAndGetStringResult("typeo f testObject"));
173 executeJavaScript("testObject.method()"); 186 mActivityTestRule.executeJavaScript("testObject.method()");
174 assertEquals("I'm here", mTestController.waitForStringValue()); 187 Assert.assertEquals("I'm here", mTestController.waitForStringValue());
175 synchronousPageReload(); 188 mActivityTestRule.synchronousPageReload();
176 assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof te stObject")); 189 Assert.assertEquals("undefined", executeJavaScriptAndGetStringResult("ty peof testObject"));
177 } 190 }
178 191
192 @Test
179 @SmallTest 193 @SmallTest
180 @Feature({"AndroidWebView", "Android-JavaBridge"}) 194 @Feature({"AndroidWebView", "Android-JavaBridge"})
181 public void testRemoveObjectNotAdded() throws Throwable { 195 public void testRemoveObjectNotAdded() throws Throwable {
182 TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper = 196 TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
183 getTestCallBackHelperContainer().getOnPageFinishedHelper(); 197 mActivityTestRule.getTestCallBackHelperContainer().getOnPageFini shedHelper();
184 int currentCallCount = onPageFinishedHelper.getCallCount(); 198 int currentCallCount = onPageFinishedHelper.getCallCount();
185 runTestOnUiThread(new Runnable() { 199 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable( ) {
186 @Override 200 @Override
187 public void run() { 201 public void run() {
188 getContentViewCore().removeJavascriptInterface("foo"); 202 mActivityTestRule.getContentViewCore().removeJavascriptInterface ("foo");
189 getContentViewCore().getWebContents().getNavigationController(). reload(true); 203 mActivityTestRule.getContentViewCore()
204 .getWebContents()
205 .getNavigationController()
206 .reload(true);
190 } 207 }
191 }); 208 });
192 onPageFinishedHelper.waitForCallback(currentCallCount); 209 onPageFinishedHelper.waitForCallback(currentCallCount);
193 assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof fo o")); 210 Assert.assertEquals("undefined", executeJavaScriptAndGetStringResult("ty peof foo"));
194 } 211 }
195 212
213 @Test
196 @SmallTest 214 @SmallTest
197 @Feature({"AndroidWebView", "Android-JavaBridge"}) 215 @Feature({"AndroidWebView", "Android-JavaBridge"})
198 public void testTypeOfMethod() throws Throwable { 216 public void testTypeOfMethod() throws Throwable {
199 assertEquals("function", 217 Assert.assertEquals("function",
200 executeJavaScriptAndGetStringResult("typeof testController.setSt ringValue")); 218 executeJavaScriptAndGetStringResult("typeof testController.setSt ringValue"));
201 } 219 }
202 220
221 @Test
203 @SmallTest 222 @SmallTest
204 @Feature({"AndroidWebView", "Android-JavaBridge"}) 223 @Feature({"AndroidWebView", "Android-JavaBridge"})
205 public void testTypeOfInvalidMethod() throws Throwable { 224 public void testTypeOfInvalidMethod() throws Throwable {
206 assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof te stController.foo")); 225 Assert.assertEquals(
226 "undefined", executeJavaScriptAndGetStringResult("typeof testCon troller.foo"));
207 } 227 }
208 228
229 @Test
209 @SmallTest 230 @SmallTest
210 @Feature({"AndroidWebView", "Android-JavaBridge"}) 231 @Feature({"AndroidWebView", "Android-JavaBridge"})
211 public void testCallingInvalidMethodRaisesException() throws Throwable { 232 public void testCallingInvalidMethodRaisesException() throws Throwable {
212 assertRaisesException("testController.foo()"); 233 assertRaisesException("testController.foo()");
213 } 234 }
214 235
236 @Test
215 @SmallTest 237 @SmallTest
216 @Feature({"AndroidWebView", "Android-JavaBridge"}) 238 @Feature({"AndroidWebView", "Android-JavaBridge"})
217 public void testUncaughtJavaExceptionRaisesJavaScriptException() throws Thro wable { 239 public void testUncaughtJavaExceptionRaisesJavaScriptException() throws Thro wable {
218 injectObjectAndReload(new Object() { 240 mActivityTestRule.injectObjectAndReload(new Object() {
219 public void method() { 241 public void method() {
220 throw new RuntimeException("foo"); 242 throw new RuntimeException("foo");
221 } 243 }
222 }, "testObject"); 244 }, "testObject");
223 assertRaisesException("testObject.method()"); 245 assertRaisesException("testObject.method()");
224 } 246 }
225 247
248 @Test
226 @SmallTest 249 @SmallTest
227 @Feature({"AndroidWebView", "Android-JavaBridge"}) 250 @Feature({"AndroidWebView", "Android-JavaBridge"})
228 public void testCallingAsConstructorRaisesException() throws Throwable { 251 public void testCallingAsConstructorRaisesException() throws Throwable {
229 assertRaisesException("new testController.setStringValue('foo')"); 252 assertRaisesException("new testController.setStringValue('foo')");
230 } 253 }
231 254
255 @Test
232 @SmallTest 256 @SmallTest
233 @Feature({"AndroidWebView", "Android-JavaBridge"}) 257 @Feature({"AndroidWebView", "Android-JavaBridge"})
234 public void testCallingOnNonInjectedObjectRaisesException() throws Throwable { 258 public void testCallingOnNonInjectedObjectRaisesException() throws Throwable {
235 assertRaisesException("testController.setStringValue.call({}, 'foo')"); 259 assertRaisesException("testController.setStringValue.call({}, 'foo')");
236 } 260 }
237 261
262 @Test
238 @SmallTest 263 @SmallTest
239 @Feature({"AndroidWebView", "Android-JavaBridge"}) 264 @Feature({"AndroidWebView", "Android-JavaBridge"})
240 public void testCallingOnInstanceOfOtherClassRaisesException() throws Throwa ble { 265 public void testCallingOnInstanceOfOtherClassRaisesException() throws Throwa ble {
241 injectObjectAndReload(new Object(), "testObject"); 266 mActivityTestRule.injectObjectAndReload(new Object(), "testObject");
242 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testO bject")); 267 Assert.assertEquals("object", executeJavaScriptAndGetStringResult("typeo f testObject"));
243 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testC ontroller")); 268 Assert.assertEquals("object", executeJavaScriptAndGetStringResult("typeo f testController"));
244 assertEquals("function", 269 Assert.assertEquals("function",
245 executeJavaScriptAndGetStringResult("typeof testController.setSt ringValue")); 270 executeJavaScriptAndGetStringResult("typeof testController.setSt ringValue"));
246 assertRaisesException("testController.setStringValue.call(testObject, 'f oo')"); 271 assertRaisesException("testController.setStringValue.call(testObject, 'f oo')");
247 } 272 }
248 273
249 // Note that this requires that we can pass a JavaScript string to Java. 274 // Note that this requires that we can pass a JavaScript string to Java.
275 @Test
250 @SmallTest 276 @SmallTest
251 @Feature({"AndroidWebView", "Android-JavaBridge"}) 277 @Feature({"AndroidWebView", "Android-JavaBridge"})
252 public void testTypeOfStaticMethod() throws Throwable { 278 public void testTypeOfStaticMethod() throws Throwable {
253 injectObjectAndReload(new ObjectWithStaticMethod(), "testObject"); 279 mActivityTestRule.injectObjectAndReload(new ObjectWithStaticMethod(), "t estObject");
254 executeJavaScript("testController.setStringValue(typeof testObject.stati cMethod)"); 280 mActivityTestRule.executeJavaScript(
255 assertEquals("function", mTestController.waitForStringValue()); 281 "testController.setStringValue(typeof testObject.staticMethod)") ;
282 Assert.assertEquals("function", mTestController.waitForStringValue());
256 } 283 }
257 284
258 // Note that this requires that we can pass a JavaScript string to Java. 285 // Note that this requires that we can pass a JavaScript string to Java.
286 @Test
259 @SmallTest 287 @SmallTest
260 @Feature({"AndroidWebView", "Android-JavaBridge"}) 288 @Feature({"AndroidWebView", "Android-JavaBridge"})
261 public void testCallStaticMethod() throws Throwable { 289 public void testCallStaticMethod() throws Throwable {
262 injectObjectAndReload(new ObjectWithStaticMethod(), "testObject"); 290 mActivityTestRule.injectObjectAndReload(new ObjectWithStaticMethod(), "t estObject");
263 executeJavaScript("testController.setStringValue(testObject.staticMethod ())"); 291 mActivityTestRule.executeJavaScript(
264 assertEquals("foo", mTestController.waitForStringValue()); 292 "testController.setStringValue(testObject.staticMethod())");
293 Assert.assertEquals("foo", mTestController.waitForStringValue());
265 } 294 }
266 295
296 @Test
267 @SmallTest 297 @SmallTest
268 @Feature({"AndroidWebView", "Android-JavaBridge"}) 298 @Feature({"AndroidWebView", "Android-JavaBridge"})
269 public void testPrivateMethodNotExposed() throws Throwable { 299 public void testPrivateMethodNotExposed() throws Throwable {
270 injectObjectAndReload(new Object() { 300 mActivityTestRule.injectObjectAndReload(new Object() {
271 private void method() {} 301 private void method() {}
272 protected void method2() {} 302 protected void method2() {}
273 }, "testObject"); 303 }, "testObject");
274 assertEquals("undefined", 304 Assert.assertEquals(
275 executeJavaScriptAndGetStringResult("typeof testObject.method")) ; 305 "undefined", executeJavaScriptAndGetStringResult("typeof testObj ect.method"));
276 assertEquals("undefined", 306 Assert.assertEquals(
277 executeJavaScriptAndGetStringResult("typeof testObject.method2") ); 307 "undefined", executeJavaScriptAndGetStringResult("typeof testObj ect.method2"));
278 } 308 }
279 309
310 @Test
280 @SmallTest 311 @SmallTest
281 @Feature({"AndroidWebView", "Android-JavaBridge"}) 312 @Feature({"AndroidWebView", "Android-JavaBridge"})
282 public void testReplaceInjectedObject() throws Throwable { 313 public void testReplaceInjectedObject() throws Throwable {
283 injectObjectAndReload(new Object() { 314 mActivityTestRule.injectObjectAndReload(new Object() {
284 public void method() { 315 public void method() {
285 mTestController.setStringValue("object 1"); 316 mTestController.setStringValue("object 1");
286 } 317 }
287 }, "testObject"); 318 }, "testObject");
288 executeJavaScript("testObject.method()"); 319 mActivityTestRule.executeJavaScript("testObject.method()");
289 assertEquals("object 1", mTestController.waitForStringValue()); 320 Assert.assertEquals("object 1", mTestController.waitForStringValue());
290 321
291 injectObjectAndReload(new Object() { 322 mActivityTestRule.injectObjectAndReload(new Object() {
292 public void method() { 323 public void method() {
293 mTestController.setStringValue("object 2"); 324 mTestController.setStringValue("object 2");
294 } 325 }
295 }, "testObject"); 326 }, "testObject");
296 executeJavaScript("testObject.method()"); 327 mActivityTestRule.executeJavaScript("testObject.method()");
297 assertEquals("object 2", mTestController.waitForStringValue()); 328 Assert.assertEquals("object 2", mTestController.waitForStringValue());
298 } 329 }
299 330
331 @Test
300 @SmallTest 332 @SmallTest
301 @Feature({"AndroidWebView", "Android-JavaBridge"}) 333 @Feature({"AndroidWebView", "Android-JavaBridge"})
302 public void testInjectNullObjectIsIgnored() throws Throwable { 334 public void testInjectNullObjectIsIgnored() throws Throwable {
303 injectObjectAndReload(null, "testObject"); 335 mActivityTestRule.injectObjectAndReload(null, "testObject");
304 assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof te stObject")); 336 Assert.assertEquals("undefined", executeJavaScriptAndGetStringResult("ty peof testObject"));
305 } 337 }
306 338
339 @Test
307 @SmallTest 340 @SmallTest
308 @Feature({"AndroidWebView", "Android-JavaBridge"}) 341 @Feature({"AndroidWebView", "Android-JavaBridge"})
309 public void testReplaceInjectedObjectWithNullObjectIsIgnored() throws Throwa ble { 342 public void testReplaceInjectedObjectWithNullObjectIsIgnored() throws Throwa ble {
310 injectObjectAndReload(new Object(), "testObject"); 343 mActivityTestRule.injectObjectAndReload(new Object(), "testObject");
311 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testO bject")); 344 Assert.assertEquals("object", executeJavaScriptAndGetStringResult("typeo f testObject"));
312 injectObjectAndReload(null, "testObject"); 345 mActivityTestRule.injectObjectAndReload(null, "testObject");
313 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testO bject")); 346 Assert.assertEquals("object", executeJavaScriptAndGetStringResult("typeo f testObject"));
314 } 347 }
315 348
349 @Test
316 @SmallTest 350 @SmallTest
317 @Feature({"AndroidWebView", "Android-JavaBridge"}) 351 @Feature({"AndroidWebView", "Android-JavaBridge"})
318 public void testCallOverloadedMethodWithDifferentNumberOfArguments() throws Throwable { 352 public void testCallOverloadedMethodWithDifferentNumberOfArguments() throws Throwable {
319 injectObjectAndReload(new Object() { 353 mActivityTestRule.injectObjectAndReload(new Object() {
320 public void method() { 354 public void method() {
321 mTestController.setStringValue("0 args"); 355 mTestController.setStringValue("0 args");
322 } 356 }
323 357
324 public void method(int x) { 358 public void method(int x) {
325 mTestController.setStringValue("1 arg"); 359 mTestController.setStringValue("1 arg");
326 } 360 }
327 361
328 public void method(int x, int y) { 362 public void method(int x, int y) {
329 mTestController.setStringValue("2 args"); 363 mTestController.setStringValue("2 args");
330 } 364 }
331 }, "testObject"); 365 }, "testObject");
332 executeJavaScript("testObject.method()"); 366 mActivityTestRule.executeJavaScript("testObject.method()");
333 assertEquals("0 args", mTestController.waitForStringValue()); 367 Assert.assertEquals("0 args", mTestController.waitForStringValue());
334 executeJavaScript("testObject.method(42)"); 368 mActivityTestRule.executeJavaScript("testObject.method(42)");
335 assertEquals("1 arg", mTestController.waitForStringValue()); 369 Assert.assertEquals("1 arg", mTestController.waitForStringValue());
336 executeJavaScript("testObject.method(null)"); 370 mActivityTestRule.executeJavaScript("testObject.method(null)");
337 assertEquals("1 arg", mTestController.waitForStringValue()); 371 Assert.assertEquals("1 arg", mTestController.waitForStringValue());
338 executeJavaScript("testObject.method(undefined)"); 372 mActivityTestRule.executeJavaScript("testObject.method(undefined)");
339 assertEquals("1 arg", mTestController.waitForStringValue()); 373 Assert.assertEquals("1 arg", mTestController.waitForStringValue());
340 executeJavaScript("testObject.method(42, 42)"); 374 mActivityTestRule.executeJavaScript("testObject.method(42, 42)");
341 assertEquals("2 args", mTestController.waitForStringValue()); 375 Assert.assertEquals("2 args", mTestController.waitForStringValue());
342 } 376 }
343 377
378 @Test
344 @SmallTest 379 @SmallTest
345 @Feature({"AndroidWebView", "Android-JavaBridge"}) 380 @Feature({"AndroidWebView", "Android-JavaBridge"})
346 public void testCallMethodWithWrongNumberOfArgumentsRaisesException() throws Throwable { 381 public void testCallMethodWithWrongNumberOfArgumentsRaisesException() throws Throwable {
347 assertRaisesException("testController.setIntValue()"); 382 assertRaisesException("testController.setIntValue()");
348 assertRaisesException("testController.setIntValue(42, 42)"); 383 assertRaisesException("testController.setIntValue(42, 42)");
349 } 384 }
350 385
386 @Test
351 @SmallTest 387 @SmallTest
352 @Feature({"AndroidWebView", "Android-JavaBridge"}) 388 @Feature({"AndroidWebView", "Android-JavaBridge"})
353 public void testObjectPersistsAcrossPageLoads() throws Throwable { 389 public void testObjectPersistsAcrossPageLoads() throws Throwable {
354 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testC ontroller")); 390 Assert.assertEquals("object", executeJavaScriptAndGetStringResult("typeo f testController"));
355 synchronousPageReload(); 391 mActivityTestRule.synchronousPageReload();
356 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testC ontroller")); 392 Assert.assertEquals("object", executeJavaScriptAndGetStringResult("typeo f testController"));
357 } 393 }
358 394
395 @Test
359 @SmallTest 396 @SmallTest
360 @Feature({"AndroidWebView", "Android-JavaBridge"}) 397 @Feature({"AndroidWebView", "Android-JavaBridge"})
361 public void testCustomPropertiesCleanedUpOnPageReloads() throws Throwable { 398 public void testCustomPropertiesCleanedUpOnPageReloads() throws Throwable {
362 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testC ontroller")); 399 Assert.assertEquals("object", executeJavaScriptAndGetStringResult("typeo f testController"));
363 executeJavaScript("testController.myProperty = 42;"); 400 mActivityTestRule.executeJavaScript("testController.myProperty = 42;");
364 assertEquals("42", executeJavaScriptAndGetStringResult("testController.m yProperty")); 401 Assert.assertEquals("42", executeJavaScriptAndGetStringResult("testContr oller.myProperty"));
365 synchronousPageReload(); 402 mActivityTestRule.synchronousPageReload();
366 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testC ontroller")); 403 Assert.assertEquals("object", executeJavaScriptAndGetStringResult("typeo f testController"));
367 assertEquals("undefined", executeJavaScriptAndGetStringResult("testContr oller.myProperty")); 404 Assert.assertEquals(
405 "undefined", executeJavaScriptAndGetStringResult("testController .myProperty"));
368 } 406 }
369 407
408 @Test
370 @SmallTest 409 @SmallTest
371 @Feature({"AndroidWebView", "Android-JavaBridge"}) 410 @Feature({"AndroidWebView", "Android-JavaBridge"})
372 public void testSameObjectInjectedMultipleTimes() throws Throwable { 411 public void testSameObjectInjectedMultipleTimes() throws Throwable {
373 class TestObject { 412 class TestObject {
374 private int mNumMethodInvocations; 413 private int mNumMethodInvocations;
375 414
376 public void method() { 415 public void method() {
377 mTestController.setIntValue(++mNumMethodInvocations); 416 mTestController.setIntValue(++mNumMethodInvocations);
378 } 417 }
379 } 418 }
380 final TestObject testObject = new TestObject(); 419 final TestObject testObject = new TestObject();
381 injectObjectsAndReload(testObject, "testObject1", testObject, "testObjec t2", null); 420 mActivityTestRule.injectObjectsAndReload(
382 executeJavaScript("testObject1.method()"); 421 testObject, "testObject1", testObject, "testObject2", null);
383 assertEquals(1, mTestController.waitForIntValue()); 422 mActivityTestRule.executeJavaScript("testObject1.method()");
384 executeJavaScript("testObject2.method()"); 423 Assert.assertEquals(1, mTestController.waitForIntValue());
385 assertEquals(2, mTestController.waitForIntValue()); 424 mActivityTestRule.executeJavaScript("testObject2.method()");
425 Assert.assertEquals(2, mTestController.waitForIntValue());
386 } 426 }
387 427
428 @Test
388 @SmallTest 429 @SmallTest
389 @Feature({"AndroidWebView", "Android-JavaBridge"}) 430 @Feature({"AndroidWebView", "Android-JavaBridge"})
390 public void testCallMethodOnReturnedObject() throws Throwable { 431 public void testCallMethodOnReturnedObject() throws Throwable {
391 injectObjectAndReload(new Object() { 432 mActivityTestRule.injectObjectAndReload(new Object() {
392 public Object getInnerObject() { 433 public Object getInnerObject() {
393 return new Object() { 434 return new Object() {
394 public void method(int x) { 435 public void method(int x) {
395 mTestController.setIntValue(x); 436 mTestController.setIntValue(x);
396 } 437 }
397 }; 438 };
398 } 439 }
399 }, "testObject"); 440 }, "testObject");
400 executeJavaScript("testObject.getInnerObject().method(42)"); 441 mActivityTestRule.executeJavaScript("testObject.getInnerObject().method( 42)");
401 assertEquals(42, mTestController.waitForIntValue()); 442 Assert.assertEquals(42, mTestController.waitForIntValue());
402 } 443 }
403 444
445 @Test
404 @SmallTest 446 @SmallTest
405 @Feature({"AndroidWebView", "Android-JavaBridge"}) 447 @Feature({"AndroidWebView", "Android-JavaBridge"})
406 public void testReturnedObjectInjectedElsewhere() throws Throwable { 448 public void testReturnedObjectInjectedElsewhere() throws Throwable {
407 class InnerObject { 449 class InnerObject {
408 private int mNumMethodInvocations; 450 private int mNumMethodInvocations;
409 451
410 public void method() { 452 public void method() {
411 mTestController.setIntValue(++mNumMethodInvocations); 453 mTestController.setIntValue(++mNumMethodInvocations);
412 } 454 }
413 } 455 }
414 final InnerObject innerObject = new InnerObject(); 456 final InnerObject innerObject = new InnerObject();
415 final Object object = new Object() { 457 final Object object = new Object() {
416 public InnerObject getInnerObject() { 458 public InnerObject getInnerObject() {
417 return innerObject; 459 return innerObject;
418 } 460 }
419 }; 461 };
420 injectObjectsAndReload(object, "testObject", innerObject, "innerObject", null); 462 mActivityTestRule.injectObjectsAndReload(
421 executeJavaScript("testObject.getInnerObject().method()"); 463 object, "testObject", innerObject, "innerObject", null);
422 assertEquals(1, mTestController.waitForIntValue()); 464 mActivityTestRule.executeJavaScript("testObject.getInnerObject().method( )");
423 executeJavaScript("innerObject.method()"); 465 Assert.assertEquals(1, mTestController.waitForIntValue());
424 assertEquals(2, mTestController.waitForIntValue()); 466 mActivityTestRule.executeJavaScript("innerObject.method()");
467 Assert.assertEquals(2, mTestController.waitForIntValue());
425 } 468 }
426 469
427 // Verify that Java objects returned from bridge object methods are derefere nced 470 // Verify that Java objects returned from bridge object methods are derefere nced
428 // on the Java side once they have been fully dereferenced on the JS side. 471 // on the Java side once they have been fully dereferenced on the JS side.
429 // Failing this test would mean that methods returning objects effectively c reate a memory 472 // Failing this test would mean that methods returning objects effectively c reate a memory
430 // leak. 473 // leak.
474 @Test
431 @SmallTest 475 @SmallTest
432 @Feature({"AndroidWebView", "Android-JavaBridge"}) 476 @Feature({"AndroidWebView", "Android-JavaBridge"})
433 @CommandLineFlags.Add("js-flags=--expose-gc") 477 @CommandLineFlags.Add("js-flags=--expose-gc")
434 public void testReturnedObjectIsGarbageCollected() throws Throwable { 478 public void testReturnedObjectIsGarbageCollected() throws Throwable {
435 // Make sure V8 exposes "gc" property on the global object (enabled with --expose-gc flag) 479 Assert.assertEquals("function", executeJavaScriptAndGetStringResult("typ eof gc"));
436 assertEquals("function", executeJavaScriptAndGetStringResult("typeof gc" ));
437 class InnerObject { 480 class InnerObject {
438 } 481 }
439 class TestObject { 482 class TestObject {
440 public InnerObject getInnerObject() { 483 public InnerObject getInnerObject() {
441 InnerObject inner = new InnerObject(); 484 InnerObject inner = new InnerObject();
442 mWeakRefForInner = new WeakReference<InnerObject>(inner); 485 mWeakRefForInner = new WeakReference<InnerObject>(inner);
443 return inner; 486 return inner;
444 } 487 }
445 // A weak reference is used to check InnerObject instance reachabili ty. 488 // A weak reference is used to check InnerObject instance reachabili ty.
446 WeakReference<InnerObject> mWeakRefForInner; 489 WeakReference<InnerObject> mWeakRefForInner;
447 } 490 }
448 TestObject object = new TestObject(); 491 TestObject object = new TestObject();
449 injectObjectAndReload(object, "testObject"); 492 mActivityTestRule.injectObjectAndReload(object, "testObject");
450 // Initially, store a reference to the inner object in JS to make sure i t's not 493 // Initially, store a reference to the inner object in JS to make sure i t's not
451 // garbage-collected prematurely. 494 // garbage-collected prematurely.
452 assertEquals("object", executeJavaScriptAndGetStringResult( 495 Assert.assertEquals("object",
453 "(function() { " 496 executeJavaScriptAndGetStringResult("(function() { "
454 + "globalInner = testObject.getInnerObject(); return typ eof globalInner; " 497 + "globalInner = testObject.getInnerObject(); return typ eof globalInner; "
455 + "})()")); 498 + "})()"));
456 assertTrue(object.mWeakRefForInner.get() != null); 499 Assert.assertTrue(object.mWeakRefForInner.get() != null);
457 // Check that returned Java object is being held by the Java bridge, thu s it's not 500 // Check that returned Java object is being held by the Java bridge, thu s it's not
458 // collected. Note that despite that what JavaDoc says about invoking " gc()", both Dalvik 501 // collected. Note that despite that what JavaDoc says about invoking " gc()", both Dalvik
459 // and ART actually run the collector. 502 // and ART actually run the collector.
460 Runtime.getRuntime().gc(); 503 Runtime.getRuntime().gc();
461 assertTrue(object.mWeakRefForInner.get() != null); 504 Assert.assertTrue(object.mWeakRefForInner.get() != null);
462 // Now dereference the inner object in JS and run GC to collect the inte rface object. 505 // Now dereference the inner object in JS and run GC to collect the inte rface object.
463 assertEquals("true", executeJavaScriptAndGetStringResult( 506 Assert.assertEquals("true",
464 "(function() { " 507 executeJavaScriptAndGetStringResult("(function() { "
465 + "delete globalInner; gc(); return (typeof globalInner == 'undefined'); " 508 + "delete globalInner; gc(); return (typeof globalInner == 'undefined'); "
466 + "})()")); 509 + "})()"));
467 // Force GC on the Java side again. The bridge had to release the inner object, so it must 510 // Force GC on the Java side again. The bridge had to release the inner object, so it must
468 // be collected this time. 511 // be collected this time.
469 Runtime.getRuntime().gc(); 512 Runtime.getRuntime().gc();
470 assertEquals(null, object.mWeakRefForInner.get()); 513 Assert.assertEquals(null, object.mWeakRefForInner.get());
471 } 514 }
472 515
516 @Test
473 @SmallTest 517 @SmallTest
474 @Feature({"AndroidWebView", "Android-JavaBridge"}) 518 @Feature({"AndroidWebView", "Android-JavaBridge"})
475 public void testSameReturnedObjectUsesSameWrapper() throws Throwable { 519 public void testSameReturnedObjectUsesSameWrapper() throws Throwable {
476 class InnerObject { 520 class InnerObject {
477 } 521 }
478 final InnerObject innerObject = new InnerObject(); 522 final InnerObject innerObject = new InnerObject();
479 final Object injectedTestObject = new Object() { 523 final Object injectedTestObject = new Object() {
480 public InnerObject getInnerObject() { 524 public InnerObject getInnerObject() {
481 return innerObject; 525 return innerObject;
482 } 526 }
483 }; 527 };
484 injectObjectAndReload(injectedTestObject, "injectedTestObject"); 528 mActivityTestRule.injectObjectAndReload(injectedTestObject, "injectedTes tObject");
485 executeJavaScript("inner1 = injectedTestObject.getInnerObject()"); 529 mActivityTestRule.executeJavaScript("inner1 = injectedTestObject.getInne rObject()");
486 executeJavaScript("inner2 = injectedTestObject.getInnerObject()"); 530 mActivityTestRule.executeJavaScript("inner2 = injectedTestObject.getInne rObject()");
487 assertEquals("object", executeJavaScriptAndGetStringResult("typeof inner 1")); 531 Assert.assertEquals("object", executeJavaScriptAndGetStringResult("typeo f inner1"));
488 assertEquals("object", executeJavaScriptAndGetStringResult("typeof inner 2")); 532 Assert.assertEquals("object", executeJavaScriptAndGetStringResult("typeo f inner2"));
489 assertEquals("true", executeJavaScriptAndGetStringResult("inner1 === inn er2")); 533 Assert.assertEquals("true", executeJavaScriptAndGetStringResult("inner1 === inner2"));
490 } 534 }
491 535
536 @Test
492 @SmallTest 537 @SmallTest
493 @Feature({"AndroidWebView", "Android-JavaBridge"}) 538 @Feature({"AndroidWebView", "Android-JavaBridge"})
494 public void testMethodInvokedOnBackgroundThread() throws Throwable { 539 public void testMethodInvokedOnBackgroundThread() throws Throwable {
495 injectObjectAndReload(new Object() { 540 mActivityTestRule.injectObjectAndReload(new Object() {
496 public void captureThreadId() { 541 public void captureThreadId() {
497 mTestController.setLongValue(Thread.currentThread().getId()); 542 mTestController.setLongValue(Thread.currentThread().getId());
498 } 543 }
499 }, "testObject"); 544 }, "testObject");
500 executeJavaScript("testObject.captureThreadId()"); 545 mActivityTestRule.executeJavaScript("testObject.captureThreadId()");
501 final long threadId = mTestController.waitForLongValue(); 546 final long threadId = mTestController.waitForLongValue();
502 assertFalse(threadId == Thread.currentThread().getId()); 547 Assert.assertFalse(threadId == Thread.currentThread().getId());
503 runTestOnUiThread(new Runnable() { 548 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable( ) {
504 @Override 549 @Override
505 public void run() { 550 public void run() {
506 assertFalse(threadId == Thread.currentThread().getId()); 551 Assert.assertFalse(threadId == Thread.currentThread().getId());
507 } 552 }
508 }); 553 });
509 } 554 }
510 555
556 @Test
511 @SmallTest 557 @SmallTest
512 @Feature({"AndroidWebView", "Android-JavaBridge"}) 558 @Feature({"AndroidWebView", "Android-JavaBridge"})
513 public void testBlockingUiThreadDoesNotBlockCallsFromJs() throws Throwable { 559 public void testBlockingUiThreadDoesNotBlockCallsFromJs() throws Throwable {
514 class TestObject { 560 class TestObject {
515 private CountDownLatch mLatch; 561 private CountDownLatch mLatch;
516 public TestObject() { 562 public TestObject() {
517 mLatch = new CountDownLatch(1); 563 mLatch = new CountDownLatch(1);
518 } 564 }
519 public boolean waitOnTheLatch() throws Exception { 565 public boolean waitOnTheLatch() throws Exception {
520 return mLatch.await(scaleTimeout(10000), 566 return mLatch.await(scaleTimeout(10000),
521 java.util.concurrent.TimeUnit.MILLISECONDS); 567 java.util.concurrent.TimeUnit.MILLISECONDS);
522 } 568 }
523 public void unlockTheLatch() throws Exception { 569 public void unlockTheLatch() throws Exception {
524 mTestController.setStringValue("unlocked"); 570 mTestController.setStringValue("unlocked");
525 mLatch.countDown(); 571 mLatch.countDown();
526 } 572 }
527 } 573 }
528 final TestObject testObject = new TestObject(); 574 final TestObject testObject = new TestObject();
529 injectObjectAndReload(testObject, "testObject"); 575 mActivityTestRule.injectObjectAndReload(testObject, "testObject");
530 runTestOnUiThread(new Runnable() { 576 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable( ) {
531 @Override 577 @Override
532 public void run() { 578 public void run() {
533 // loadUrl is asynchronous, the JS code will start running on th e renderer 579 // loadUrl is asynchronous, the JS code will start running on th e renderer
534 // thread. As soon as we exit loadUrl, the browser UI thread wil l be stuck waiting 580 // thread. As soon as we exit loadUrl, the browser UI thread wil l be stuck waiting
535 // on the latch. If blocking the browser thread blocks Java Brid ge, then the call 581 // on the latch. If blocking the browser thread blocks Java Brid ge, then the call
536 // to "unlockTheLatch()" will be executed after the waiting time out, thus the 582 // to "unlockTheLatch()" will be executed after the waiting time out, thus the
537 // string value will not yet be updated by the injected object. 583 // string value will not yet be updated by the injected object.
538 mTestController.setStringValue("locked"); 584 mTestController.setStringValue("locked");
539 getWebContents().getNavigationController().loadUrl(new LoadUrlPa rams( 585 mActivityTestRule.getWebContents().getNavigationController().loa dUrl(
540 "javascript:(function() { testObject.unlockTheLatch() }) ()")); 586 new LoadUrlParams(
587 "javascript:(function() { testObject.unlockTheLa tch() })()"));
541 try { 588 try {
542 assertTrue(testObject.waitOnTheLatch()); 589 Assert.assertTrue(testObject.waitOnTheLatch());
543 } catch (Exception e) { 590 } catch (Exception e) {
544 android.util.Log.e("JavaBridgeBasicsTest", "Wait exception", e); 591 android.util.Log.e("JavaBridgeBasicsTest", "Wait exception", e);
545 Assert.fail("Wait exception"); 592 Assert.fail("Wait exception");
546 } 593 }
547 assertEquals("unlocked", mTestController.getStringValue()); 594 Assert.assertEquals("unlocked", mTestController.getStringValue() );
548 } 595 }
549 }); 596 });
550 } 597 }
551 598
599 @Test
552 @SmallTest 600 @SmallTest
553 @Feature({"AndroidWebView", "Android-JavaBridge"}) 601 @Feature({"AndroidWebView", "Android-JavaBridge"})
554 public void testPublicInheritedMethod() throws Throwable { 602 public void testPublicInheritedMethod() throws Throwable {
555 class Base { 603 class Base {
556 public void method(int x) { 604 public void method(int x) {
557 mTestController.setIntValue(x); 605 mTestController.setIntValue(x);
558 } 606 }
559 } 607 }
560 class Derived extends Base { 608 class Derived extends Base {
561 } 609 }
562 injectObjectAndReload(new Derived(), "testObject"); 610 mActivityTestRule.injectObjectAndReload(new Derived(), "testObject");
563 assertEquals("function", executeJavaScriptAndGetStringResult("typeof tes tObject.method")); 611 Assert.assertEquals(
564 executeJavaScript("testObject.method(42)"); 612 "function", executeJavaScriptAndGetStringResult("typeof testObje ct.method"));
565 assertEquals(42, mTestController.waitForIntValue()); 613 mActivityTestRule.executeJavaScript("testObject.method(42)");
614 Assert.assertEquals(42, mTestController.waitForIntValue());
566 } 615 }
567 616
617 @Test
568 @SmallTest 618 @SmallTest
569 @Feature({"AndroidWebView", "Android-JavaBridge"}) 619 @Feature({"AndroidWebView", "Android-JavaBridge"})
570 public void testPrivateInheritedMethod() throws Throwable { 620 public void testPrivateInheritedMethod() throws Throwable {
571 class Base { 621 class Base {
572 private void method() {} 622 private void method() {}
573 } 623 }
574 class Derived extends Base { 624 class Derived extends Base {
575 } 625 }
576 injectObjectAndReload(new Derived(), "testObject"); 626 mActivityTestRule.injectObjectAndReload(new Derived(), "testObject");
577 assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof te stObject.method")); 627 Assert.assertEquals(
628 "undefined", executeJavaScriptAndGetStringResult("typeof testObj ect.method"));
578 } 629 }
579 630
631 @Test
580 @SmallTest 632 @SmallTest
581 @Feature({"AndroidWebView", "Android-JavaBridge"}) 633 @Feature({"AndroidWebView", "Android-JavaBridge"})
582 public void testOverriddenMethod() throws Throwable { 634 public void testOverriddenMethod() throws Throwable {
583 class Base { 635 class Base {
584 public void method() { 636 public void method() {
585 mTestController.setStringValue("base"); 637 mTestController.setStringValue("base");
586 } 638 }
587 } 639 }
588 class Derived extends Base { 640 class Derived extends Base {
589 @Override 641 @Override
590 public void method() { 642 public void method() {
591 mTestController.setStringValue("derived"); 643 mTestController.setStringValue("derived");
592 } 644 }
593 } 645 }
594 injectObjectAndReload(new Derived(), "testObject"); 646 mActivityTestRule.injectObjectAndReload(new Derived(), "testObject");
595 executeJavaScript("testObject.method()"); 647 mActivityTestRule.executeJavaScript("testObject.method()");
596 assertEquals("derived", mTestController.waitForStringValue()); 648 Assert.assertEquals("derived", mTestController.waitForStringValue());
597 } 649 }
598 650
651 @Test
599 @SmallTest 652 @SmallTest
600 @Feature({"AndroidWebView", "Android-JavaBridge"}) 653 @Feature({"AndroidWebView", "Android-JavaBridge"})
601 public void testEnumerateMembers() throws Throwable { 654 public void testEnumerateMembers() throws Throwable {
602 injectObjectAndReload(new Object() { 655 mActivityTestRule.injectObjectAndReload(new Object() {
603 public void method() {} 656 public void method() {}
604 private void privateMethod() {} 657 private void privateMethod() {}
605 @SuppressFBWarnings("UUF_UNUSED") 658 @SuppressFBWarnings("UUF_UNUSED")
606 public int field; 659 public int field;
607 @SuppressFBWarnings("UUF_UNUSED") 660 @SuppressFBWarnings("UUF_UNUSED")
608 private int mPrivateField; 661 private int mPrivateField;
609 }, "testObject"); 662 }, "testObject");
610 executeJavaScript( 663 mActivityTestRule.executeJavaScript("var result = \"\"; "
611 "var result = \"\"; "
612 + "for (x in testObject) { result += \" \" + x } " 664 + "for (x in testObject) { result += \" \" + x } "
613 + "testController.setStringValue(result);"); 665 + "testController.setStringValue(result);");
614 assertEquals(" equals getClass hashCode method notify notifyAll toString wait", 666 Assert.assertEquals(" equals getClass hashCode method notify notifyAll t oString wait",
615 mTestController.waitForStringValue()); 667 mTestController.waitForStringValue());
616 } 668 }
617 669
670 @Test
618 @SmallTest 671 @SmallTest
619 @Feature({"AndroidWebView", "Android-JavaBridge"}) 672 @Feature({"AndroidWebView", "Android-JavaBridge"})
620 public void testReflectPublicMethod() throws Throwable { 673 public void testReflectPublicMethod() throws Throwable {
621 injectObjectAndReload(new Object() { 674 mActivityTestRule.injectObjectAndReload(new Object() {
622 public Class<?> myGetClass() { 675 public Class<?> myGetClass() {
623 return getClass(); 676 return getClass();
624 } 677 }
625 678
626 public String method() { 679 public String method() {
627 return "foo"; 680 return "foo";
628 } 681 }
629 }, "testObject"); 682 }, "testObject");
630 assertEquals("foo", executeJavaScriptAndGetStringResult( 683 Assert.assertEquals("foo",
631 "testObject.myGetClass().getMethod('method', null).invoke(testOb ject, null)" 684 executeJavaScriptAndGetStringResult(
632 + ".toString()")); 685 "testObject.myGetClass().getMethod('method', null).invok e(testObject, null)"
686 + ".toString()"));
633 } 687 }
634 688
689 @Test
635 @SmallTest 690 @SmallTest
636 @Feature({"AndroidWebView", "Android-JavaBridge"}) 691 @Feature({"AndroidWebView", "Android-JavaBridge"})
637 public void testReflectPublicField() throws Throwable { 692 public void testReflectPublicField() throws Throwable {
638 injectObjectAndReload(new Object() { 693 mActivityTestRule.injectObjectAndReload(new Object() {
639 public Class<?> myGetClass() { 694 public Class<?> myGetClass() {
640 return getClass(); 695 return getClass();
641 } 696 }
642 697
643 public String field = "foo"; 698 public String field = "foo";
644 }, "testObject"); 699 }, "testObject");
645 assertEquals("foo", executeJavaScriptAndGetStringResult( 700 Assert.assertEquals("foo",
646 "testObject.myGetClass().getField('field').get(testObject).toStr ing()")); 701 executeJavaScriptAndGetStringResult(
702 "testObject.myGetClass().getField('field').get(testObjec t).toString()"));
647 } 703 }
648 704
705 @Test
649 @SmallTest 706 @SmallTest
650 @Feature({"AndroidWebView", "Android-JavaBridge"}) 707 @Feature({"AndroidWebView", "Android-JavaBridge"})
651 public void testReflectPrivateMethodRaisesException() throws Throwable { 708 public void testReflectPrivateMethodRaisesException() throws Throwable {
652 injectObjectAndReload(new Object() { 709 mActivityTestRule.injectObjectAndReload(new Object() {
653 public Class<?> myGetClass() { 710 public Class<?> myGetClass() {
654 return getClass(); 711 return getClass();
655 } 712 }
656 713
657 private void method() {}; 714 private void method() {};
658 }, "testObject"); 715 }, "testObject");
659 assertRaisesException("testObject.myGetClass().getMethod('method', null) "); 716 assertRaisesException("testObject.myGetClass().getMethod('method', null) ");
660 // getDeclaredMethod() is able to access a private method, but invoke() 717 // getDeclaredMethod() is able to access a private method, but invoke()
661 // throws a Java exception. 718 // throws a Java exception.
662 assertRaisesException( 719 assertRaisesException(
663 "testObject.myGetClass().getDeclaredMethod('method', null)." 720 "testObject.myGetClass().getDeclaredMethod('method', null)."
664 + "invoke(testObject, null)"); 721 + "invoke(testObject, null)");
665 } 722 }
666 723
724 @Test
667 @SmallTest 725 @SmallTest
668 @Feature({"AndroidWebView", "Android-JavaBridge"}) 726 @Feature({"AndroidWebView", "Android-JavaBridge"})
669 public void testReflectPrivateFieldRaisesException() throws Throwable { 727 public void testReflectPrivateFieldRaisesException() throws Throwable {
670 injectObjectAndReload(new Object() { 728 mActivityTestRule.injectObjectAndReload(new Object() {
671 public Class<?> myGetClass() { 729 public Class<?> myGetClass() {
672 return getClass(); 730 return getClass();
673 } 731 }
674 732
675 @SuppressFBWarnings("UUF_UNUSED") 733 @SuppressFBWarnings("UUF_UNUSED")
676 private int mField; 734 private int mField;
677 }, "testObject"); 735 }, "testObject");
678 String fieldName = "mField"; 736 String fieldName = "mField";
679 assertRaisesException("testObject.myGetClass().getField('" + fieldName + "')"); 737 assertRaisesException("testObject.myGetClass().getField('" + fieldName + "')");
680 // getDeclaredField() is able to access a private field, but getInt() 738 // getDeclaredField() is able to access a private field, but getInt()
681 // throws a Java exception. 739 // throws a Java exception.
682 assertNoRaisedException("testObject.myGetClass().getDeclaredField('" + f ieldName + "')"); 740 assertNoRaisedException("testObject.myGetClass().getDeclaredField('" + f ieldName + "')");
683 assertRaisesException( 741 assertRaisesException(
684 "testObject.myGetClass().getDeclaredField('" + fieldName + "').g etInt(testObject)"); 742 "testObject.myGetClass().getDeclaredField('" + fieldName + "').g etInt(testObject)");
685 } 743 }
686 744
745 @Test
687 @SmallTest 746 @SmallTest
688 @Feature({"AndroidWebView", "Android-JavaBridge"}) 747 @Feature({"AndroidWebView", "Android-JavaBridge"})
689 public void testAllowNonAnnotatedMethods() throws Throwable { 748 public void testAllowNonAnnotatedMethods() throws Throwable {
690 injectObjectAndReload(new Object() { 749 mActivityTestRule.injectObjectAndReload(new Object() {
691 public String allowed() { 750 public String allowed() {
692 return "foo"; 751 return "foo";
693 } 752 }
694 }, "testObject", null); 753 }, "testObject", null);
695 754
696 // Test calling a method of an explicitly inherited class (Base#allowed( )). 755 // Test calling a method of an explicitly inherited class (Base#allowed( )).
697 assertEquals("foo", executeJavaScriptAndGetStringResult("testObject.allo wed()")); 756 Assert.assertEquals("foo", executeJavaScriptAndGetStringResult("testObje ct.allowed()"));
698 757
699 // Test calling a method of an implicitly inherited class (Object#toStri ng()). 758 // Test calling a method of an implicitly inherited class (Object#toStri ng()).
700 assertEquals("string", executeJavaScriptAndGetStringResult("typeof testO bject.toString()")); 759 Assert.assertEquals(
760 "string", executeJavaScriptAndGetStringResult("typeof testObject .toString()"));
701 } 761 }
702 762
763 @Test
703 @SmallTest 764 @SmallTest
704 @Feature({"AndroidWebView", "Android-JavaBridge"}) 765 @Feature({"AndroidWebView", "Android-JavaBridge"})
705 public void testAllowOnlyAnnotatedMethods() throws Throwable { 766 public void testAllowOnlyAnnotatedMethods() throws Throwable {
706 injectObjectAndReload(new Object() { 767 mActivityTestRule.injectObjectAndReload(new Object() {
707 @JavascriptInterface 768 @JavascriptInterface
708 public String allowed() { 769 public String allowed() {
709 return "foo"; 770 return "foo";
710 } 771 }
711 772
712 public String disallowed() { 773 public String disallowed() {
713 return "bar"; 774 return "bar";
714 } 775 }
715 }, "testObject", JavascriptInterface.class); 776 }, "testObject", JavascriptInterface.class);
716 777
717 // getClass() is an Object method and does not have the @JavascriptInter face annotation and 778 // getClass() is an Object method and does not have the @JavascriptInter face annotation and
718 // should not be able to be called. 779 // should not be able to be called.
719 assertRaisesException("testObject.getClass()"); 780 assertRaisesException("testObject.getClass()");
720 assertEquals("undefined", executeJavaScriptAndGetStringResult( 781 Assert.assertEquals(
721 "typeof testObject.getClass")); 782 "undefined", executeJavaScriptAndGetStringResult("typeof testObj ect.getClass"));
722 783
723 // allowed() is marked with the @JavascriptInterface annotation and shou ld be allowed to be 784 // allowed() is marked with the @JavascriptInterface annotation and shou ld be allowed to be
724 // called. 785 // called.
725 assertEquals("foo", executeJavaScriptAndGetStringResult("testObject.allo wed()")); 786 Assert.assertEquals("foo", executeJavaScriptAndGetStringResult("testObje ct.allowed()"));
726 787
727 // disallowed() is not marked with the @JavascriptInterface annotation a nd should not be 788 // disallowed() is not marked with the @JavascriptInterface annotation a nd should not be
728 // able to be called. 789 // able to be called.
729 assertRaisesException("testObject.disallowed()"); 790 assertRaisesException("testObject.disallowed()");
730 assertEquals("undefined", executeJavaScriptAndGetStringResult( 791 Assert.assertEquals(
731 "typeof testObject.disallowed")); 792 "undefined", executeJavaScriptAndGetStringResult("typeof testObj ect.disallowed"));
732 } 793 }
733 794
795 @Test
734 @SmallTest 796 @SmallTest
735 @Feature({"AndroidWebView", "Android-JavaBridge"}) 797 @Feature({"AndroidWebView", "Android-JavaBridge"})
736 public void testAnnotationRequirementRetainsPropertyAcrossObjects() throws T hrowable { 798 public void testAnnotationRequirementRetainsPropertyAcrossObjects() throws T hrowable {
737 class Test { 799 class Test {
738 @JavascriptInterface 800 @JavascriptInterface
739 public String safe() { 801 public String safe() {
740 return "foo"; 802 return "foo";
741 } 803 }
742 804
743 public String unsafe() { 805 public String unsafe() {
744 return "bar"; 806 return "bar";
745 } 807 }
746 } 808 }
747 809
748 class TestReturner { 810 class TestReturner {
749 @JavascriptInterface 811 @JavascriptInterface
750 public Test getTest() { 812 public Test getTest() {
751 return new Test(); 813 return new Test();
752 } 814 }
753 } 815 }
754 816
755 // First test with safe mode off. 817 // First test with safe mode off.
756 injectObjectAndReload(new TestReturner(), "unsafeTestObject", null); 818 mActivityTestRule.injectObjectAndReload(new TestReturner(), "unsafeTestO bject", null);
757 819
758 // safe() should be able to be called regardless of whether or not we ar e in safe mode. 820 // safe() should be able to be called regardless of whether or not we ar e in safe mode.
759 assertEquals("foo", executeJavaScriptAndGetStringResult( 821 Assert.assertEquals(
760 "unsafeTestObject.getTest().safe()")); 822 "foo", executeJavaScriptAndGetStringResult("unsafeTestObject.get Test().safe()"));
761 // unsafe() should be able to be called because we are not in safe mode. 823 // unsafe() should be able to be called because we are not in safe mode.
762 assertEquals("bar", executeJavaScriptAndGetStringResult( 824 Assert.assertEquals(
763 "unsafeTestObject.getTest().unsafe()")); 825 "bar", executeJavaScriptAndGetStringResult("unsafeTestObject.get Test().unsafe()"));
764 826
765 // Now test with safe mode on. 827 // Now test with safe mode on.
766 injectObjectAndReload(new TestReturner(), "safeTestObject", JavascriptIn terface.class); 828 mActivityTestRule.injectObjectAndReload(
829 new TestReturner(), "safeTestObject", JavascriptInterface.class) ;
767 830
768 // safe() should be able to be called regardless of whether or not we ar e in safe mode. 831 // safe() should be able to be called regardless of whether or not we ar e in safe mode.
769 assertEquals("foo", executeJavaScriptAndGetStringResult( 832 Assert.assertEquals(
770 "safeTestObject.getTest().safe()")); 833 "foo", executeJavaScriptAndGetStringResult("safeTestObject.getTe st().safe()"));
771 // unsafe() should not be able to be called because we are in safe mode. 834 // unsafe() should not be able to be called because we are in safe mode.
772 assertRaisesException("safeTestObject.getTest().unsafe()"); 835 assertRaisesException("safeTestObject.getTest().unsafe()");
773 assertEquals("undefined", executeJavaScriptAndGetStringResult( 836 Assert.assertEquals("undefined",
774 "typeof safeTestObject.getTest().unsafe")); 837 executeJavaScriptAndGetStringResult("typeof safeTestObject.getTe st().unsafe"));
775 // getClass() is an Object method and does not have the @JavascriptInter face annotation and 838 // getClass() is an Object method and does not have the @JavascriptInter face annotation and
776 // should not be able to be called. 839 // should not be able to be called.
777 assertRaisesException("safeTestObject.getTest().getClass()"); 840 assertRaisesException("safeTestObject.getTest().getClass()");
778 assertEquals("undefined", executeJavaScriptAndGetStringResult( 841 Assert.assertEquals("undefined",
779 "typeof safeTestObject.getTest().getClass")); 842 executeJavaScriptAndGetStringResult("typeof safeTestObject.getTe st().getClass"));
780 } 843 }
781 844
845 @Test
782 @SmallTest 846 @SmallTest
783 @Feature({"AndroidWebView", "Android-JavaBridge"}) 847 @Feature({"AndroidWebView", "Android-JavaBridge"})
784 public void testAnnotationDoesNotGetInherited() throws Throwable { 848 public void testAnnotationDoesNotGetInherited() throws Throwable {
785 class Base { 849 class Base {
786 @JavascriptInterface 850 @JavascriptInterface
787 public void base() { } 851 public void base() { }
788 } 852 }
789 853
790 class Child extends Base { 854 class Child extends Base {
791 @Override 855 @Override
792 public void base() { } 856 public void base() { }
793 } 857 }
794 858
795 injectObjectAndReload(new Child(), "testObject", JavascriptInterface.cla ss); 859 mActivityTestRule.injectObjectAndReload(
860 new Child(), "testObject", JavascriptInterface.class);
796 861
797 // base() is inherited. The inherited method does not have the @Javascr iptInterface 862 // base() is inherited. The inherited method does not have the @Javascr iptInterface
798 // annotation and should not be able to be called. 863 // annotation and should not be able to be called.
799 assertRaisesException("testObject.base()"); 864 assertRaisesException("testObject.base()");
800 assertEquals("undefined", executeJavaScriptAndGetStringResult( 865 Assert.assertEquals(
801 "typeof testObject.base")); 866 "undefined", executeJavaScriptAndGetStringResult("typeof testObj ect.base"));
802 } 867 }
803 868
804 @SuppressWarnings("javadoc") 869 @SuppressWarnings("javadoc")
805 @Retention(RetentionPolicy.RUNTIME) 870 @Retention(RetentionPolicy.RUNTIME)
806 @Target({ElementType.METHOD}) 871 @Target({ElementType.METHOD})
807 @interface TestAnnotation { 872 @interface TestAnnotation {
808 } 873 }
809 874
875 @Test
810 @SmallTest 876 @SmallTest
811 @Feature({"AndroidWebView", "Android-JavaBridge"}) 877 @Feature({"AndroidWebView", "Android-JavaBridge"})
812 public void testCustomAnnotationRestriction() throws Throwable { 878 public void testCustomAnnotationRestriction() throws Throwable {
813 class Test { 879 class Test {
814 @TestAnnotation 880 @TestAnnotation
815 public String checkTestAnnotationFoo() { 881 public String checkTestAnnotationFoo() {
816 return "bar"; 882 return "bar";
817 } 883 }
818 884
819 @JavascriptInterface 885 @JavascriptInterface
820 public String checkJavascriptInterfaceFoo() { 886 public String checkJavascriptInterfaceFoo() {
821 return "bar"; 887 return "bar";
822 } 888 }
823 } 889 }
824 890
825 // Inject javascriptInterfaceObj and require the JavascriptInterface ann otation. 891 // Inject javascriptInterfaceObj and require the JavascriptInterface ann otation.
826 injectObjectAndReload(new Test(), "javascriptInterfaceObj", JavascriptIn terface.class); 892 mActivityTestRule.injectObjectAndReload(
893 new Test(), "javascriptInterfaceObj", JavascriptInterface.class) ;
827 894
828 // Test#testAnnotationFoo() should fail, as it isn't annotated with Java scriptInterface. 895 // Test#testAnnotationFoo() should fail, as it isn't annotated with Java scriptInterface.
829 assertRaisesException("javascriptInterfaceObj.checkTestAnnotationFoo()") ; 896 assertRaisesException("javascriptInterfaceObj.checkTestAnnotationFoo()") ;
830 assertEquals("undefined", executeJavaScriptAndGetStringResult( 897 Assert.assertEquals("undefined",
831 "typeof javascriptInterfaceObj.checkTestAnnotationFoo")); 898 executeJavaScriptAndGetStringResult(
899 "typeof javascriptInterfaceObj.checkTestAnnotationFoo")) ;
832 900
833 // Test#javascriptInterfaceFoo() should pass, as it is annotated with Ja vascriptInterface. 901 // Test#javascriptInterfaceFoo() should pass, as it is annotated with Ja vascriptInterface.
834 assertEquals("bar", executeJavaScriptAndGetStringResult( 902 Assert.assertEquals("bar",
835 "javascriptInterfaceObj.checkJavascriptInterfaceFoo()")); 903 executeJavaScriptAndGetStringResult(
904 "javascriptInterfaceObj.checkJavascriptInterfaceFoo()")) ;
836 905
837 // Inject testAnnotationObj and require the TestAnnotation annotation. 906 // Inject testAnnotationObj and require the TestAnnotation annotation.
838 injectObjectAndReload(new Test(), "testAnnotationObj", TestAnnotation.cl ass); 907 mActivityTestRule.injectObjectAndReload(
908 new Test(), "testAnnotationObj", TestAnnotation.class);
839 909
840 // Test#testAnnotationFoo() should pass, as it is annotated with TestAnn otation. 910 // Test#testAnnotationFoo() should pass, as it is annotated with TestAnn otation.
841 assertEquals("bar", executeJavaScriptAndGetStringResult( 911 Assert.assertEquals("bar",
842 "testAnnotationObj.checkTestAnnotationFoo()")); 912 executeJavaScriptAndGetStringResult("testAnnotationObj.checkTest AnnotationFoo()"));
843 913
844 // Test#javascriptInterfaceFoo() should fail, as it isn't annotated with TestAnnotation. 914 // Test#javascriptInterfaceFoo() should fail, as it isn't annotated with TestAnnotation.
845 assertRaisesException("testAnnotationObj.checkJavascriptInterfaceFoo()") ; 915 assertRaisesException("testAnnotationObj.checkJavascriptInterfaceFoo()") ;
846 assertEquals("undefined", executeJavaScriptAndGetStringResult( 916 Assert.assertEquals("undefined",
847 "typeof testAnnotationObj.checkJavascriptInterfaceFoo")); 917 executeJavaScriptAndGetStringResult(
918 "typeof testAnnotationObj.checkJavascriptInterfaceFoo")) ;
848 } 919 }
849 920
921 @Test
850 @SmallTest 922 @SmallTest
851 @Feature({"AndroidWebView", "Android-JavaBridge"}) 923 @Feature({"AndroidWebView", "Android-JavaBridge"})
852 public void testAddJavascriptInterfaceIsSafeByDefault() throws Throwable { 924 public void testAddJavascriptInterfaceIsSafeByDefault() throws Throwable {
853 class Test { 925 class Test {
854 public String blocked() { 926 public String blocked() {
855 return "bar"; 927 return "bar";
856 } 928 }
857 929
858 @JavascriptInterface 930 @JavascriptInterface
859 public String allowed() { 931 public String allowed() {
860 return "bar"; 932 return "bar";
861 } 933 }
862 } 934 }
863 935
864 // Manually inject the Test object, making sure to use the 936 // Manually inject the Test object, making sure to use the
865 // ContentViewCore#addJavascriptInterface, not the possibly unsafe versi on. 937 // ContentViewCore#addJavascriptInterface, not the possibly unsafe versi on.
866 TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper = 938 TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
867 getTestCallBackHelperContainer().getOnPageFinishedHelper(); 939 mActivityTestRule.getTestCallBackHelperContainer().getOnPageFini shedHelper();
868 int currentCallCount = onPageFinishedHelper.getCallCount(); 940 int currentCallCount = onPageFinishedHelper.getCallCount();
869 runTestOnUiThread(new Runnable() { 941 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable( ) {
870 @Override 942 @Override
871 public void run() { 943 public void run() {
872 getContentViewCore().addJavascriptInterface(new Test(), 944 mActivityTestRule.getContentViewCore().addJavascriptInterface(
873 "testObject"); 945 new Test(), "testObject");
874 getContentViewCore().getWebContents().getNavigationController(). reload(true); 946 mActivityTestRule.getContentViewCore()
947 .getWebContents()
948 .getNavigationController()
949 .reload(true);
875 } 950 }
876 }); 951 });
877 onPageFinishedHelper.waitForCallback(currentCallCount); 952 onPageFinishedHelper.waitForCallback(currentCallCount);
878 953
879 // Test#allowed() should pass, as it is annotated with JavascriptInterfa ce. 954 // Test#allowed() should pass, as it is annotated with JavascriptInterfa ce.
880 assertEquals("bar", executeJavaScriptAndGetStringResult( 955 Assert.assertEquals("bar", executeJavaScriptAndGetStringResult("testObje ct.allowed()"));
881 "testObject.allowed()"));
882 956
883 // Test#blocked() should fail, as it isn't annotated with JavascriptInte rface. 957 // Test#blocked() should fail, as it isn't annotated with JavascriptInte rface.
884 assertRaisesException("testObject.blocked()"); 958 assertRaisesException("testObject.blocked()");
885 assertEquals("undefined", executeJavaScriptAndGetStringResult( 959 Assert.assertEquals(
886 "typeof testObject.blocked")); 960 "undefined", executeJavaScriptAndGetStringResult("typeof testObj ect.blocked"));
887 } 961 }
888 962
963 @Test
889 @SmallTest 964 @SmallTest
890 @Feature({"AndroidWebView", "Android-JavaBridge"}) 965 @Feature({"AndroidWebView", "Android-JavaBridge"})
891 public void testObjectsInspection() throws Throwable { 966 public void testObjectsInspection() throws Throwable {
892 class Test { 967 class Test {
893 @JavascriptInterface 968 @JavascriptInterface
894 public String m1() { 969 public String m1() {
895 return "foo"; 970 return "foo";
896 } 971 }
897 972
898 @JavascriptInterface 973 @JavascriptInterface
899 public String m2() { 974 public String m2() {
900 return "bar"; 975 return "bar";
901 } 976 }
902 977
903 @JavascriptInterface 978 @JavascriptInterface
904 public String m2(int x) { 979 public String m2(int x) {
905 return "bar " + x; 980 return "bar " + x;
906 } 981 }
907 } 982 }
908 983
909 final String jsObjectKeysTestTemplate = "Object.keys(%s).toString()"; 984 final String jsObjectKeysTestTemplate = "Object.keys(%s).toString()";
910 final String jsForInTestTemplate = 985 final String jsForInTestTemplate =
911 "(function(){" 986 "(function(){"
912 + " var s=[]; for(var m in %s) s.push(m); return s.join(\",\")" 987 + " var s=[]; for(var m in %s) s.push(m); return s.join(\",\")"
913 + "})()"; 988 + "})()";
914 final String inspectableObjectName = "testObj1"; 989 final String inspectableObjectName = "testObj1";
915 final String nonInspectableObjectName = "testObj2"; 990 final String nonInspectableObjectName = "testObj2";
916 991
917 // Inspection is enabled by default. 992 // Inspection is enabled by default.
918 injectObjectAndReload(new Test(), inspectableObjectName, JavascriptInter face.class); 993 mActivityTestRule.injectObjectAndReload(
994 new Test(), inspectableObjectName, JavascriptInterface.class);
919 995
920 assertEquals("m1,m2", executeJavaScriptAndGetStringResult( 996 Assert.assertEquals("m1,m2",
997 executeJavaScriptAndGetStringResult(
921 String.format(jsObjectKeysTestTemplate, inspectableObjec tName))); 998 String.format(jsObjectKeysTestTemplate, inspectableObjec tName)));
922 assertEquals("m1,m2", executeJavaScriptAndGetStringResult( 999 Assert.assertEquals("m1,m2",
1000 executeJavaScriptAndGetStringResult(
923 String.format(jsForInTestTemplate, inspectableObjectName ))); 1001 String.format(jsForInTestTemplate, inspectableObjectName )));
924 1002
925 runTestOnUiThread(new Runnable() { 1003 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable( ) {
926 @Override 1004 @Override
927 public void run() { 1005 public void run() {
928 getContentViewCore().setAllowJavascriptInterfacesInspection(fals e); 1006 mActivityTestRule.getContentViewCore().setAllowJavascriptInterfa cesInspection(
1007 false);
929 } 1008 }
930 }); 1009 });
931 1010
932 injectObjectAndReload(new Test(), nonInspectableObjectName, JavascriptIn terface.class); 1011 mActivityTestRule.injectObjectAndReload(
1012 new Test(), nonInspectableObjectName, JavascriptInterface.class) ;
933 1013
934 assertEquals("", executeJavaScriptAndGetStringResult( 1014 Assert.assertEquals("",
1015 executeJavaScriptAndGetStringResult(
935 String.format(jsObjectKeysTestTemplate, nonInspectableOb jectName))); 1016 String.format(jsObjectKeysTestTemplate, nonInspectableOb jectName)));
936 assertEquals("", executeJavaScriptAndGetStringResult( 1017 Assert.assertEquals("",
1018 executeJavaScriptAndGetStringResult(
937 String.format(jsForInTestTemplate, nonInspectableObjectN ame))); 1019 String.format(jsForInTestTemplate, nonInspectableObjectN ame)));
938 } 1020 }
939 1021
1022 @Test
940 @SmallTest 1023 @SmallTest
941 @Feature({"AndroidWebView", "Android-JavaBridge"}) 1024 @Feature({"AndroidWebView", "Android-JavaBridge"})
942 public void testAccessToObjectGetClassIsBlocked() throws Throwable { 1025 public void testAccessToObjectGetClassIsBlocked() throws Throwable {
943 injectObjectAndReload(new Object(), "testObject"); 1026 mActivityTestRule.injectObjectAndReload(new Object(), "testObject");
944 assertEquals("function", executeJavaScriptAndGetStringResult("typeof tes tObject.getClass")); 1027 Assert.assertEquals(
1028 "function", executeJavaScriptAndGetStringResult("typeof testObje ct.getClass"));
945 assertRaisesException("testObject.getClass()"); 1029 assertRaisesException("testObject.getClass()");
946 } 1030 }
947 1031
1032 @Test
948 @SmallTest 1033 @SmallTest
949 @Feature({"AndroidWebView", "Android-JavaBridge"}) 1034 @Feature({"AndroidWebView", "Android-JavaBridge"})
950 public void testReplaceJavascriptInterface() throws Throwable { 1035 public void testReplaceJavascriptInterface() throws Throwable {
951 class Test { 1036 class Test {
952 public Test(int value) { 1037 public Test(int value) {
953 mValue = value; 1038 mValue = value;
954 } 1039 }
955 @JavascriptInterface 1040 @JavascriptInterface
956 public int getValue() { 1041 public int getValue() {
957 return mValue; 1042 return mValue;
958 } 1043 }
959 private int mValue; 1044 private int mValue;
960 } 1045 }
961 injectObjectAndReload(new Test(13), "testObject"); 1046 mActivityTestRule.injectObjectAndReload(new Test(13), "testObject");
962 assertEquals("13", executeJavaScriptAndGetStringResult("testObject.getVa lue()")); 1047 Assert.assertEquals("13", executeJavaScriptAndGetStringResult("testObjec t.getValue()"));
963 // The documentation doesn't specify, what happens if the embedder is tr ying 1048 // The documentation doesn't specify, what happens if the embedder is tr ying
964 // to inject a different object under the same name. The current impleme ntation 1049 // to inject a different object under the same name. The current impleme ntation
965 // simply replaces the old object with the new one. 1050 // simply replaces the old object with the new one.
966 injectObjectAndReload(new Test(42), "testObject"); 1051 mActivityTestRule.injectObjectAndReload(new Test(42), "testObject");
967 assertEquals("42", executeJavaScriptAndGetStringResult("testObject.getVa lue()")); 1052 Assert.assertEquals("42", executeJavaScriptAndGetStringResult("testObjec t.getValue()"));
968 } 1053 }
969 1054
1055 @Test
970 @SmallTest 1056 @SmallTest
971 @Feature({"AndroidWebView", "Android-JavaBridge"}) 1057 @Feature({"AndroidWebView", "Android-JavaBridge"})
972 public void testMethodCalledOnAnotherInstance() throws Throwable { 1058 public void testMethodCalledOnAnotherInstance() throws Throwable {
973 class TestObject { 1059 class TestObject {
974 private int mIndex; 1060 private int mIndex;
975 TestObject(int index) { 1061 TestObject(int index) {
976 mIndex = index; 1062 mIndex = index;
977 } 1063 }
978 public void method() { 1064 public void method() {
979 mTestController.setIntValue(mIndex); 1065 mTestController.setIntValue(mIndex);
980 } 1066 }
981 } 1067 }
982 final TestObject testObject1 = new TestObject(1); 1068 final TestObject testObject1 = new TestObject(1);
983 final TestObject testObject2 = new TestObject(2); 1069 final TestObject testObject2 = new TestObject(2);
984 injectObjectsAndReload(testObject1, "testObject1", testObject2, "testObj ect2", null); 1070 mActivityTestRule.injectObjectsAndReload(
985 executeJavaScript("testObject1.method()"); 1071 testObject1, "testObject1", testObject2, "testObject2", null);
986 assertEquals(1, mTestController.waitForIntValue()); 1072 mActivityTestRule.executeJavaScript("testObject1.method()");
987 executeJavaScript("testObject2.method()"); 1073 Assert.assertEquals(1, mTestController.waitForIntValue());
988 assertEquals(2, mTestController.waitForIntValue()); 1074 mActivityTestRule.executeJavaScript("testObject2.method()");
989 executeJavaScript("testObject1.method.call(testObject2)"); 1075 Assert.assertEquals(2, mTestController.waitForIntValue());
990 assertEquals(2, mTestController.waitForIntValue()); 1076 mActivityTestRule.executeJavaScript("testObject1.method.call(testObject2 )");
991 executeJavaScript("testObject2.method.call(testObject1)"); 1077 Assert.assertEquals(2, mTestController.waitForIntValue());
992 assertEquals(1, mTestController.waitForIntValue()); 1078 mActivityTestRule.executeJavaScript("testObject2.method.call(testObject1 )");
1079 Assert.assertEquals(1, mTestController.waitForIntValue());
993 } 1080 }
994 } 1081 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698