| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.content_shell; |
| 6 |
| 7 import android.test.suitebuilder.annotation.SmallTest; |
| 8 |
| 9 import org.chromium.base.test.Feature; |
| 10 import org.chromium.content.browser.JavascriptInterface; |
| 11 import org.chromium.content.browser.test.TestContentViewClient; |
| 12 |
| 13 /** |
| 14 * Part of the test suite for the Java Bridge. Tests a number of features includ
ing ... |
| 15 * - The type of injected objects |
| 16 * - The type of their methods |
| 17 * - Replacing objects |
| 18 * - Removing objects |
| 19 * - Access control |
| 20 * - Calling methods on returned objects |
| 21 * - Multiply injected objects |
| 22 * - Threading |
| 23 * - Inheritance |
| 24 */ |
| 25 public class JavaBridgeBasicsTest extends JavaBridgeTestBase { |
| 26 private class TestController extends Controller { |
| 27 private int mIntValue; |
| 28 private long mLongValue; |
| 29 private String mStringValue; |
| 30 private boolean mBooleanValue; |
| 31 |
| 32 public synchronized void setIntValue(int x) { |
| 33 mIntValue = x; |
| 34 notifyResultIsReady(); |
| 35 } |
| 36 public synchronized void setLongValue(long x) { |
| 37 mLongValue = x; |
| 38 notifyResultIsReady(); |
| 39 } |
| 40 public synchronized void setStringValue(String x) { |
| 41 mStringValue = x; |
| 42 notifyResultIsReady(); |
| 43 } |
| 44 public synchronized void setBooleanValue(boolean x) { |
| 45 mBooleanValue = x; |
| 46 notifyResultIsReady(); |
| 47 } |
| 48 |
| 49 public synchronized int waitForIntValue() { |
| 50 waitForResult(); |
| 51 return mIntValue; |
| 52 } |
| 53 public synchronized long waitForLongValue() { |
| 54 waitForResult(); |
| 55 return mLongValue; |
| 56 } |
| 57 public synchronized String waitForStringValue() { |
| 58 waitForResult(); |
| 59 return mStringValue; |
| 60 } |
| 61 public synchronized boolean waitForBooleanValue() { |
| 62 waitForResult(); |
| 63 return mBooleanValue; |
| 64 } |
| 65 } |
| 66 |
| 67 private static class ObjectWithStaticMethod { |
| 68 public static String staticMethod() { |
| 69 return "foo"; |
| 70 } |
| 71 } |
| 72 |
| 73 TestController mTestController; |
| 74 |
| 75 @Override |
| 76 protected void setUp() throws Exception { |
| 77 super.setUp(); |
| 78 mTestController = new TestController(); |
| 79 setUpContentView(mTestController, "testController"); |
| 80 } |
| 81 |
| 82 // Note that this requires that we can pass a JavaScript string to Java. |
| 83 protected String executeJavaScriptAndGetStringResult(String script) throws T
hrowable { |
| 84 executeJavaScript("testController.setStringValue(" + script + ");"); |
| 85 return mTestController.waitForStringValue(); |
| 86 } |
| 87 |
| 88 protected void injectObjectAndReload(final Object object, final String name)
throws Throwable { |
| 89 injectObjectAndReload(object, name, false); |
| 90 } |
| 91 |
| 92 protected void injectObjectAndReload(final Object object, final String name, |
| 93 final boolean requireAnnotation) throws Throwable { |
| 94 TestContentViewClient.OnPageFinishedHelper onPageFinishedHelper = |
| 95 mContentViewClient.getOnPageFinishedHelper(); |
| 96 int currentCallCount = onPageFinishedHelper.getCallCount(); |
| 97 runTestOnUiThread(new Runnable() { |
| 98 @Override |
| 99 public void run() { |
| 100 getContentView().getContentViewCore().addJavascriptInterface(obj
ect, name, |
| 101 requireAnnotation); |
| 102 getContentView().reload(); |
| 103 } |
| 104 }); |
| 105 onPageFinishedHelper.waitForCallback(currentCallCount); |
| 106 } |
| 107 |
| 108 // Note that this requires that we can pass a JavaScript boolean to Java. |
| 109 private void assertRaisesException(String script) throws Throwable { |
| 110 executeJavaScript("try {" + |
| 111 script + ";" + |
| 112 " testController.setBooleanValue(false);" + |
| 113 "} catch (exception) {" + |
| 114 " testController.setBooleanValue(true);" + |
| 115 "}"); |
| 116 assertTrue(mTestController.waitForBooleanValue()); |
| 117 } |
| 118 |
| 119 @SmallTest |
| 120 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 121 public void testTypeOfInjectedObject() throws Throwable { |
| 122 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testC
ontroller")); |
| 123 } |
| 124 |
| 125 @SmallTest |
| 126 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 127 public void testAdditionNotReflectedUntilReload() throws Throwable { |
| 128 assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof te
stObject")); |
| 129 runTestOnUiThread(new Runnable() { |
| 130 @Override |
| 131 public void run() { |
| 132 getContentView().getContentViewCore().addJavascriptInterface(new
Object(), |
| 133 "te
stObject", false); |
| 134 } |
| 135 }); |
| 136 assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof te
stObject")); |
| 137 TestContentViewClient.OnPageFinishedHelper onPageFinishedHelper = |
| 138 mContentViewClient.getOnPageFinishedHelper(); |
| 139 int currentCallCount = onPageFinishedHelper.getCallCount(); |
| 140 runTestOnUiThread(new Runnable() { |
| 141 @Override |
| 142 public void run() { |
| 143 getContentView().reload(); |
| 144 } |
| 145 }); |
| 146 onPageFinishedHelper.waitForCallback(currentCallCount); |
| 147 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testO
bject")); |
| 148 } |
| 149 |
| 150 @SmallTest |
| 151 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 152 public void testRemovalNotReflectedUntilReload() throws Throwable { |
| 153 injectObjectAndReload(new Object(), "testObject"); |
| 154 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testO
bject")); |
| 155 runTestOnUiThread(new Runnable() { |
| 156 @Override |
| 157 public void run() { |
| 158 getContentView().getContentViewCore().removeJavascriptInterface(
"testObject"); |
| 159 } |
| 160 }); |
| 161 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testO
bject")); |
| 162 TestContentViewClient.OnPageFinishedHelper onPageFinishedHelper = |
| 163 mContentViewClient.getOnPageFinishedHelper(); |
| 164 int currentCallCount = onPageFinishedHelper.getCallCount(); |
| 165 runTestOnUiThread(new Runnable() { |
| 166 @Override |
| 167 public void run() { |
| 168 getContentView().reload(); |
| 169 } |
| 170 }); |
| 171 onPageFinishedHelper.waitForCallback(currentCallCount); |
| 172 assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof te
stObject")); |
| 173 } |
| 174 |
| 175 @SmallTest |
| 176 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 177 public void testRemoveObjectNotAdded() throws Throwable { |
| 178 TestContentViewClient.OnPageFinishedHelper onPageFinishedHelper = |
| 179 mContentViewClient.getOnPageFinishedHelper(); |
| 180 int currentCallCount = onPageFinishedHelper.getCallCount(); |
| 181 runTestOnUiThread(new Runnable() { |
| 182 @Override |
| 183 public void run() { |
| 184 getContentView().getContentViewCore().removeJavascriptInterface(
"foo"); |
| 185 getContentView().reload(); |
| 186 } |
| 187 }); |
| 188 onPageFinishedHelper.waitForCallback(currentCallCount); |
| 189 assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof fo
o")); |
| 190 } |
| 191 |
| 192 @SmallTest |
| 193 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 194 public void testTypeOfMethod() throws Throwable { |
| 195 assertEquals("function", |
| 196 executeJavaScriptAndGetStringResult("typeof testController.setSt
ringValue")); |
| 197 } |
| 198 |
| 199 @SmallTest |
| 200 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 201 public void testTypeOfInvalidMethod() throws Throwable { |
| 202 assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof te
stController.foo")); |
| 203 } |
| 204 |
| 205 @SmallTest |
| 206 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 207 public void testCallingInvalidMethodRaisesException() throws Throwable { |
| 208 assertRaisesException("testController.foo()"); |
| 209 } |
| 210 |
| 211 @SmallTest |
| 212 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 213 public void testUncaughtJavaExceptionRaisesJavaScriptException() throws Thro
wable { |
| 214 injectObjectAndReload(new Object() { |
| 215 public void method() { throw new RuntimeException("foo"); } |
| 216 }, "testObject"); |
| 217 assertRaisesException("testObject.method()"); |
| 218 } |
| 219 |
| 220 // Note that this requires that we can pass a JavaScript string to Java. |
| 221 @SmallTest |
| 222 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 223 public void testTypeOfStaticMethod() throws Throwable { |
| 224 injectObjectAndReload(new ObjectWithStaticMethod(), "testObject"); |
| 225 executeJavaScript("testController.setStringValue(typeof testObject.stati
cMethod)"); |
| 226 assertEquals("function", mTestController.waitForStringValue()); |
| 227 } |
| 228 |
| 229 // Note that this requires that we can pass a JavaScript string to Java. |
| 230 @SmallTest |
| 231 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 232 public void testCallStaticMethod() throws Throwable { |
| 233 injectObjectAndReload(new ObjectWithStaticMethod(), "testObject"); |
| 234 executeJavaScript("testController.setStringValue(testObject.staticMethod
())"); |
| 235 assertEquals("foo", mTestController.waitForStringValue()); |
| 236 } |
| 237 |
| 238 @SmallTest |
| 239 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 240 public void testPrivateMethodNotExposed() throws Throwable { |
| 241 injectObjectAndReload(new Object() { |
| 242 private void method() {} |
| 243 protected void method2() {} |
| 244 }, "testObject"); |
| 245 assertEquals("undefined", |
| 246 executeJavaScriptAndGetStringResult("typeof testObject.method"))
; |
| 247 assertEquals("undefined", |
| 248 executeJavaScriptAndGetStringResult("typeof testObject.method2")
); |
| 249 } |
| 250 |
| 251 @SmallTest |
| 252 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 253 public void testReplaceInjectedObject() throws Throwable { |
| 254 injectObjectAndReload(new Object() { |
| 255 public void method() { mTestController.setStringValue("object 1"); } |
| 256 }, "testObject"); |
| 257 executeJavaScript("testObject.method()"); |
| 258 assertEquals("object 1", mTestController.waitForStringValue()); |
| 259 |
| 260 injectObjectAndReload(new Object() { |
| 261 public void method() { mTestController.setStringValue("object 2"); } |
| 262 }, "testObject"); |
| 263 executeJavaScript("testObject.method()"); |
| 264 assertEquals("object 2", mTestController.waitForStringValue()); |
| 265 } |
| 266 |
| 267 @SmallTest |
| 268 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 269 public void testInjectNullObjectIsIgnored() throws Throwable { |
| 270 injectObjectAndReload(null, "testObject"); |
| 271 assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof te
stObject")); |
| 272 } |
| 273 |
| 274 @SmallTest |
| 275 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 276 public void testReplaceInjectedObjectWithNullObjectIsIgnored() throws Throwa
ble { |
| 277 injectObjectAndReload(new Object(), "testObject"); |
| 278 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testO
bject")); |
| 279 injectObjectAndReload(null, "testObject"); |
| 280 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testO
bject")); |
| 281 } |
| 282 |
| 283 @SmallTest |
| 284 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 285 public void testCallOverloadedMethodWithDifferentNumberOfArguments() throws
Throwable { |
| 286 injectObjectAndReload(new Object() { |
| 287 public void method() { mTestController.setStringValue("0 args"); } |
| 288 public void method(int x) { mTestController.setStringValue("1 arg");
} |
| 289 public void method(int x, int y) { mTestController.setStringValue("2
args"); } |
| 290 }, "testObject"); |
| 291 executeJavaScript("testObject.method()"); |
| 292 assertEquals("0 args", mTestController.waitForStringValue()); |
| 293 executeJavaScript("testObject.method(42)"); |
| 294 assertEquals("1 arg", mTestController.waitForStringValue()); |
| 295 executeJavaScript("testObject.method(null)"); |
| 296 assertEquals("1 arg", mTestController.waitForStringValue()); |
| 297 executeJavaScript("testObject.method(undefined)"); |
| 298 assertEquals("1 arg", mTestController.waitForStringValue()); |
| 299 executeJavaScript("testObject.method(42, 42)"); |
| 300 assertEquals("2 args", mTestController.waitForStringValue()); |
| 301 } |
| 302 |
| 303 @SmallTest |
| 304 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 305 public void testCallMethodWithWrongNumberOfArgumentsRaisesException() throws
Throwable { |
| 306 assertRaisesException("testController.setIntValue()"); |
| 307 assertRaisesException("testController.setIntValue(42, 42)"); |
| 308 } |
| 309 |
| 310 @SmallTest |
| 311 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 312 public void testObjectPersistsAcrossPageLoads() throws Throwable { |
| 313 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testC
ontroller")); |
| 314 TestContentViewClient.OnPageFinishedHelper onPageFinishedHelper = |
| 315 mContentViewClient.getOnPageFinishedHelper(); |
| 316 int currentCallCount = onPageFinishedHelper.getCallCount(); |
| 317 runTestOnUiThread(new Runnable() { |
| 318 @Override |
| 319 public void run() { |
| 320 getContentView().reload(); |
| 321 } |
| 322 }); |
| 323 onPageFinishedHelper.waitForCallback(currentCallCount); |
| 324 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testC
ontroller")); |
| 325 } |
| 326 |
| 327 @SmallTest |
| 328 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 329 public void testSameObjectInjectedMultipleTimes() throws Throwable { |
| 330 class TestObject { |
| 331 private int mNumMethodInvocations; |
| 332 public void method() { mTestController.setIntValue(++mNumMethodInvoc
ations); } |
| 333 } |
| 334 final TestObject testObject = new TestObject(); |
| 335 TestContentViewClient.OnPageFinishedHelper onPageFinishedHelper = |
| 336 mContentViewClient.getOnPageFinishedHelper(); |
| 337 int currentCallCount = onPageFinishedHelper.getCallCount(); |
| 338 runTestOnUiThread(new Runnable() { |
| 339 @Override |
| 340 public void run() { |
| 341 getContentView().getContentViewCore().addJavascriptInterface(tes
tObject, |
| 342 "te
stObject1", false); |
| 343 getContentView().getContentViewCore().addJavascriptInterface(tes
tObject, |
| 344 "te
stObject2", false); |
| 345 getContentView().reload(); |
| 346 } |
| 347 }); |
| 348 onPageFinishedHelper.waitForCallback(currentCallCount); |
| 349 executeJavaScript("testObject1.method()"); |
| 350 assertEquals(1, mTestController.waitForIntValue()); |
| 351 executeJavaScript("testObject2.method()"); |
| 352 assertEquals(2, mTestController.waitForIntValue()); |
| 353 } |
| 354 |
| 355 @SmallTest |
| 356 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 357 public void testCallMethodOnReturnedObject() throws Throwable { |
| 358 injectObjectAndReload(new Object() { |
| 359 public Object getInnerObject() { |
| 360 return new Object() { |
| 361 public void method(int x) { mTestController.setIntValue(x);
} |
| 362 }; |
| 363 } |
| 364 }, "testObject"); |
| 365 executeJavaScript("testObject.getInnerObject().method(42)"); |
| 366 assertEquals(42, mTestController.waitForIntValue()); |
| 367 } |
| 368 |
| 369 @SmallTest |
| 370 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 371 public void testReturnedObjectInjectedElsewhere() throws Throwable { |
| 372 class InnerObject { |
| 373 private int mNumMethodInvocations; |
| 374 public void method() { mTestController.setIntValue(++mNumMethodInvoc
ations); } |
| 375 } |
| 376 final InnerObject innerObject = new InnerObject(); |
| 377 final Object object = new Object() { |
| 378 public InnerObject getInnerObject() { |
| 379 return innerObject; |
| 380 } |
| 381 }; |
| 382 TestContentViewClient.OnPageFinishedHelper onPageFinishedHelper = |
| 383 mContentViewClient.getOnPageFinishedHelper(); |
| 384 int currentCallCount = onPageFinishedHelper.getCallCount(); |
| 385 runTestOnUiThread(new Runnable() { |
| 386 @Override |
| 387 public void run() { |
| 388 getContentView().getContentViewCore().addJavascriptInterface(obj
ect, "testObject", |
| 389 fal
se); |
| 390 getContentView().getContentViewCore().addJavascriptInterface(inn
erObject, |
| 391 "in
nerObject", false); |
| 392 getContentView().reload(); |
| 393 } |
| 394 }); |
| 395 onPageFinishedHelper.waitForCallback(currentCallCount); |
| 396 executeJavaScript("testObject.getInnerObject().method()"); |
| 397 assertEquals(1, mTestController.waitForIntValue()); |
| 398 executeJavaScript("innerObject.method()"); |
| 399 assertEquals(2, mTestController.waitForIntValue()); |
| 400 } |
| 401 |
| 402 @SmallTest |
| 403 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 404 public void testMethodInvokedOnBackgroundThread() throws Throwable { |
| 405 injectObjectAndReload(new Object() { |
| 406 public void captureThreadId() { |
| 407 mTestController.setLongValue(Thread.currentThread().getId()); |
| 408 } |
| 409 }, "testObject"); |
| 410 executeJavaScript("testObject.captureThreadId()"); |
| 411 final long threadId = mTestController.waitForLongValue(); |
| 412 assertFalse(threadId == Thread.currentThread().getId()); |
| 413 runTestOnUiThread(new Runnable() { |
| 414 @Override |
| 415 public void run() { |
| 416 assertFalse(threadId == Thread.currentThread().getId()); |
| 417 } |
| 418 }); |
| 419 } |
| 420 |
| 421 @SmallTest |
| 422 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 423 public void testPublicInheritedMethod() throws Throwable { |
| 424 class Base { |
| 425 public void method(int x) { mTestController.setIntValue(x); } |
| 426 } |
| 427 class Derived extends Base { |
| 428 } |
| 429 injectObjectAndReload(new Derived(), "testObject"); |
| 430 assertEquals("function", executeJavaScriptAndGetStringResult("typeof tes
tObject.method")); |
| 431 executeJavaScript("testObject.method(42)"); |
| 432 assertEquals(42, mTestController.waitForIntValue()); |
| 433 } |
| 434 |
| 435 @SmallTest |
| 436 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 437 public void testPrivateInheritedMethod() throws Throwable { |
| 438 class Base { |
| 439 private void method() {} |
| 440 } |
| 441 class Derived extends Base { |
| 442 } |
| 443 injectObjectAndReload(new Derived(), "testObject"); |
| 444 assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof te
stObject.method")); |
| 445 } |
| 446 |
| 447 @SmallTest |
| 448 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 449 public void testOverriddenMethod() throws Throwable { |
| 450 class Base { |
| 451 public void method() { mTestController.setStringValue("base"); } |
| 452 } |
| 453 class Derived extends Base { |
| 454 public void method() { mTestController.setStringValue("derived"); } |
| 455 } |
| 456 injectObjectAndReload(new Derived(), "testObject"); |
| 457 executeJavaScript("testObject.method()"); |
| 458 assertEquals("derived", mTestController.waitForStringValue()); |
| 459 } |
| 460 |
| 461 @SmallTest |
| 462 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 463 public void testEnumerateMembers() throws Throwable { |
| 464 injectObjectAndReload(new Object() { |
| 465 public void method() {} |
| 466 private void privateMethod() {} |
| 467 public int field; |
| 468 private int privateField; |
| 469 }, "testObject"); |
| 470 executeJavaScript( |
| 471 "var result = \"\"; " + |
| 472 "for (x in testObject) { result += \" \" + x } " + |
| 473 "testController.setStringValue(result);"); |
| 474 // LIVECONNECT_COMPLIANCE: Should be able to enumerate members. |
| 475 assertEquals("", mTestController.waitForStringValue()); |
| 476 } |
| 477 |
| 478 @SmallTest |
| 479 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 480 public void testReflectPublicMethod() throws Throwable { |
| 481 injectObjectAndReload(new Object() { |
| 482 public String method() { return "foo"; } |
| 483 }, "testObject"); |
| 484 assertEquals("foo", executeJavaScriptAndGetStringResult( |
| 485 "testObject.getClass().getMethod('method', null).invoke(testObje
ct, null)" + |
| 486 ".toString()")); |
| 487 } |
| 488 |
| 489 @SmallTest |
| 490 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 491 public void testReflectPublicField() throws Throwable { |
| 492 injectObjectAndReload(new Object() { |
| 493 public String field = "foo"; |
| 494 }, "testObject"); |
| 495 assertEquals("foo", executeJavaScriptAndGetStringResult( |
| 496 "testObject.getClass().getField('field').get(testObject).toStrin
g()")); |
| 497 } |
| 498 |
| 499 @SmallTest |
| 500 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 501 public void testReflectPrivateMethodRaisesException() throws Throwable { |
| 502 injectObjectAndReload(new Object() { |
| 503 private void method() {}; |
| 504 }, "testObject"); |
| 505 assertRaisesException("testObject.getClass().getMethod('method', null)")
; |
| 506 // getDeclaredMethod() is able to access a private method, but invoke() |
| 507 // throws a Java exception. |
| 508 assertRaisesException( |
| 509 "testObject.getClass().getDeclaredMethod('method', null).invoke(
testObject, null)"); |
| 510 } |
| 511 |
| 512 @SmallTest |
| 513 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 514 public void testReflectPrivateFieldRaisesException() throws Throwable { |
| 515 injectObjectAndReload(new Object() { |
| 516 private int field; |
| 517 }, "testObject"); |
| 518 assertRaisesException("testObject.getClass().getField('field')"); |
| 519 // getDeclaredField() is able to access a private field, but getInt() |
| 520 // throws a Java exception. |
| 521 assertRaisesException( |
| 522 "testObject.getClass().getDeclaredField('field').getInt(testObje
ct)"); |
| 523 } |
| 524 |
| 525 @SmallTest |
| 526 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 527 public void testAllowNonAnnotatedMethods() throws Throwable { |
| 528 injectObjectAndReload(new Object() { |
| 529 public String allowed() { return "foo"; } |
| 530 }, "testObject", false); |
| 531 |
| 532 // Test calling a method of an explicitly inherited class (Base#allowed(
)). |
| 533 assertEquals("foo", executeJavaScriptAndGetStringResult("testObject.allo
wed()")); |
| 534 |
| 535 // Test calling a method of an implicitly inherited class (Object#getCla
ss()). |
| 536 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testO
bject.getClass()")); |
| 537 } |
| 538 |
| 539 @SmallTest |
| 540 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 541 public void testAllowOnlyAnnotatedMethods() throws Throwable { |
| 542 class Test { |
| 543 public String allowed() { return "foo"; } |
| 544 } |
| 545 |
| 546 injectObjectAndReload(new Object() { |
| 547 @JavascriptInterface |
| 548 public String allowed() { return "foo"; } |
| 549 |
| 550 public String disallowed() { return "bar"; } |
| 551 }, "testObject", true); |
| 552 |
| 553 // getClass() is an Object method and does not have the @JavascriptInter
face annotation and |
| 554 // should not be able to be called. |
| 555 assertRaisesException("testObject.getClass()"); |
| 556 assertEquals("undefined", executeJavaScriptAndGetStringResult( |
| 557 "typeof testObject.getClass")); |
| 558 |
| 559 // allowed() is marked with the @JavascriptInterface annotation and shou
ld be allowed to be |
| 560 // called. |
| 561 assertEquals("foo", executeJavaScriptAndGetStringResult("testObject.allo
wed()")); |
| 562 |
| 563 // disallowed() is not marked with the @JavascriptInterface annotation a
nd should not be |
| 564 // able to be called. |
| 565 assertRaisesException("testObject.disallowed()"); |
| 566 assertEquals("undefined", executeJavaScriptAndGetStringResult( |
| 567 "typeof testObject.disallowed")); |
| 568 } |
| 569 |
| 570 @SmallTest |
| 571 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 572 public void testAnnotationRequirementRetainsPropertyAcrossObjects() throws T
hrowable { |
| 573 class Test { |
| 574 @JavascriptInterface |
| 575 public String safe() { return "foo"; } |
| 576 |
| 577 public String unsafe() { return "bar"; } |
| 578 } |
| 579 |
| 580 class TestReturner { |
| 581 @JavascriptInterface |
| 582 public Test getTest() { return new Test(); } |
| 583 } |
| 584 |
| 585 // First test with safe mode off. |
| 586 injectObjectAndReload(new TestReturner(), "unsafeTestObject", false); |
| 587 |
| 588 // safe() should be able to be called regardless of whether or not we ar
e in safe mode. |
| 589 assertEquals("foo", executeJavaScriptAndGetStringResult( |
| 590 "unsafeTestObject.getTest().safe()")); |
| 591 // unsafe() should be able to be called because we are not in safe mode. |
| 592 assertEquals("bar", executeJavaScriptAndGetStringResult( |
| 593 "unsafeTestObject.getTest().unsafe()")); |
| 594 |
| 595 // Now test with safe mode on. |
| 596 injectObjectAndReload(new TestReturner(), "safeTestObject", true); |
| 597 |
| 598 // safe() should be able to be called regardless of whether or not we ar
e in safe mode. |
| 599 assertEquals("foo", executeJavaScriptAndGetStringResult( |
| 600 "safeTestObject.getTest().safe()")); |
| 601 // unsafe() should not be able to be called because we are in safe mode. |
| 602 assertRaisesException("safeTestObject.getTest().unsafe()"); |
| 603 assertEquals("undefined", executeJavaScriptAndGetStringResult( |
| 604 "typeof safeTestObject.getTest().unsafe")); |
| 605 // getClass() is an Object method and does not have the @JavascriptInter
face annotation and |
| 606 // should not be able to be called. |
| 607 assertRaisesException("safeTestObject.getTest().getClass()"); |
| 608 assertEquals("undefined", executeJavaScriptAndGetStringResult( |
| 609 "typeof safeTestObject.getTest().getClass")); |
| 610 } |
| 611 |
| 612 @SmallTest |
| 613 @Feature({"Android-WebView", "Android-JavaBridge"}) |
| 614 public void testAnnotationDoesNotGetInherited() throws Throwable { |
| 615 class Base { |
| 616 @JavascriptInterface |
| 617 public void base() { } |
| 618 } |
| 619 |
| 620 class Child extends Base { |
| 621 @Override |
| 622 public void base() { } |
| 623 } |
| 624 |
| 625 injectObjectAndReload(new Child(), "testObject", true); |
| 626 |
| 627 // base() is inherited. The inherited method does not have the @Javascr
iptInterface |
| 628 // annotation and should not be able to be called. |
| 629 assertRaisesException("testObject.base()"); |
| 630 assertEquals("undefined", executeJavaScriptAndGetStringResult( |
| 631 "typeof testObject.base")); |
| 632 } |
| 633 } |
| OLD | NEW |