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.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 Loading... |
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 } |
OLD | NEW |