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