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