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

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

Issue 213693005: [Android] Block access to java.lang.Object.getClass in injected Java objects (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed tests Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/browser/renderer_host/java/java_bound_object.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.content.browser; 5 package org.chromium.content.browser;
6 6
7 import android.os.Handler;
8 import android.os.Looper;
7 import android.test.suitebuilder.annotation.SmallTest; 9 import android.test.suitebuilder.annotation.SmallTest;
8 10
9 import org.chromium.base.test.util.DisabledTest; 11 import org.chromium.base.test.util.DisabledTest;
10 import org.chromium.base.test.util.Feature; 12 import org.chromium.base.test.util.Feature;
11 import org.chromium.content.browser.test.util.TestCallbackHelperContainer; 13 import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
12 import org.chromium.content_shell_apk.ContentShellActivity; 14 import org.chromium.content_shell_apk.ContentShellActivity;
13 15
14 import java.lang.annotation.Annotation; 16 import java.lang.annotation.Annotation;
15 import java.lang.annotation.ElementType; 17 import java.lang.annotation.ElementType;
16 import java.lang.annotation.Retention; 18 import java.lang.annotation.Retention;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 return mLongValue; 65 return mLongValue;
64 } 66 }
65 public synchronized String waitForStringValue() { 67 public synchronized String waitForStringValue() {
66 waitForResult(); 68 waitForResult();
67 return mStringValue; 69 return mStringValue;
68 } 70 }
69 public synchronized boolean waitForBooleanValue() { 71 public synchronized boolean waitForBooleanValue() {
70 waitForResult(); 72 waitForResult();
71 return mBooleanValue; 73 return mBooleanValue;
72 } 74 }
75
76 public synchronized String getStringValue() {
77 return mStringValue;
78 }
73 } 79 }
74 80
75 private static class ObjectWithStaticMethod { 81 private static class ObjectWithStaticMethod {
76 public static String staticMethod() { 82 public static String staticMethod() {
77 return "foo"; 83 return "foo";
78 } 84 }
79 } 85 }
80 86
81 TestController mTestController; 87 TestController mTestController;
82 88
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 "for (x in testObject) { result += \" \" + x } " + 565 "for (x in testObject) { result += \" \" + x } " +
560 "testController.setStringValue(result);"); 566 "testController.setStringValue(result);");
561 assertEquals(" equals getClass hashCode method notify notifyAll toString wait", 567 assertEquals(" equals getClass hashCode method notify notifyAll toString wait",
562 mTestController.waitForStringValue()); 568 mTestController.waitForStringValue());
563 } 569 }
564 570
565 @SmallTest 571 @SmallTest
566 @Feature({"AndroidWebView", "Android-JavaBridge"}) 572 @Feature({"AndroidWebView", "Android-JavaBridge"})
567 public void testReflectPublicMethod() throws Throwable { 573 public void testReflectPublicMethod() throws Throwable {
568 injectObjectAndReload(new Object() { 574 injectObjectAndReload(new Object() {
575 public Class<?> myGetClass() { return getClass(); }
569 public String method() { return "foo"; } 576 public String method() { return "foo"; }
570 }, "testObject"); 577 }, "testObject");
571 assertEquals("foo", executeJavaScriptAndGetStringResult( 578 assertEquals("foo", executeJavaScriptAndGetStringResult(
572 "testObject.getClass().getMethod('method', null).invoke(testObje ct, null)" + 579 "testObject.myGetClass().getMethod('method', null).invoke(testOb ject, null)" +
573 ".toString()")); 580 ".toString()"));
574 } 581 }
575 582
576 @SmallTest 583 @SmallTest
577 @Feature({"AndroidWebView", "Android-JavaBridge"}) 584 @Feature({"AndroidWebView", "Android-JavaBridge"})
578 public void testReflectPublicField() throws Throwable { 585 public void testReflectPublicField() throws Throwable {
579 injectObjectAndReload(new Object() { 586 injectObjectAndReload(new Object() {
587 public Class<?> myGetClass() { return getClass(); }
580 public String field = "foo"; 588 public String field = "foo";
581 }, "testObject"); 589 }, "testObject");
582 assertEquals("foo", executeJavaScriptAndGetStringResult( 590 assertEquals("foo", executeJavaScriptAndGetStringResult(
583 "testObject.getClass().getField('field').get(testObject).toStrin g()")); 591 "testObject.myGetClass().getField('field').get(testObject).toStr ing()"));
584 } 592 }
585 593
586 @SmallTest 594 @SmallTest
587 @Feature({"AndroidWebView", "Android-JavaBridge"}) 595 @Feature({"AndroidWebView", "Android-JavaBridge"})
588 public void testReflectPrivateMethodRaisesException() throws Throwable { 596 public void testReflectPrivateMethodRaisesException() throws Throwable {
589 injectObjectAndReload(new Object() { 597 injectObjectAndReload(new Object() {
598 public Class<?> myGetClass() { return getClass(); }
590 private void method() {}; 599 private void method() {};
591 }, "testObject"); 600 }, "testObject");
592 assertRaisesException("testObject.getClass().getMethod('method', null)") ; 601 assertRaisesException("testObject.myGetClass().getMethod('method', null) ");
593 // getDeclaredMethod() is able to access a private method, but invoke() 602 // getDeclaredMethod() is able to access a private method, but invoke()
594 // throws a Java exception. 603 // throws a Java exception.
595 assertRaisesException( 604 assertRaisesException(
596 "testObject.getClass().getDeclaredMethod('method', null).invoke( testObject, null)"); 605 "testObject.myGetClass().getDeclaredMethod('method', null)." +
606 "invoke(testObject, null)");
597 } 607 }
598 608
599 @SmallTest 609 @SmallTest
600 @Feature({"AndroidWebView", "Android-JavaBridge"}) 610 @Feature({"AndroidWebView", "Android-JavaBridge"})
601 public void testReflectPrivateFieldRaisesException() throws Throwable { 611 public void testReflectPrivateFieldRaisesException() throws Throwable {
602 injectObjectAndReload(new Object() { 612 injectObjectAndReload(new Object() {
613 public Class<?> myGetClass() { return getClass(); }
603 private int field; 614 private int field;
604 }, "testObject"); 615 }, "testObject");
605 assertRaisesException("testObject.getClass().getField('field')"); 616 assertRaisesException("testObject.myGetClass().getField('field')");
606 // getDeclaredField() is able to access a private field, but getInt() 617 // getDeclaredField() is able to access a private field, but getInt()
607 // throws a Java exception. 618 // throws a Java exception.
608 assertRaisesException( 619 assertRaisesException(
609 "testObject.getClass().getDeclaredField('field').getInt(testObje ct)"); 620 "testObject.myGetClass().getDeclaredField('field').getInt(testOb ject)");
610 } 621 }
611 622
612 @SmallTest 623 @SmallTest
613 @Feature({"AndroidWebView", "Android-JavaBridge"}) 624 @Feature({"AndroidWebView", "Android-JavaBridge"})
614 public void testAllowNonAnnotatedMethods() throws Throwable { 625 public void testAllowNonAnnotatedMethods() throws Throwable {
615 injectObjectAndReload(new Object() { 626 injectObjectAndReload(new Object() {
616 public String allowed() { return "foo"; } 627 public String allowed() { return "foo"; }
617 }, "testObject", null); 628 }, "testObject", null);
618 629
619 // Test calling a method of an explicitly inherited class (Base#allowed( )). 630 // Test calling a method of an explicitly inherited class (Base#allowed( )).
620 assertEquals("foo", executeJavaScriptAndGetStringResult("testObject.allo wed()")); 631 assertEquals("foo", executeJavaScriptAndGetStringResult("testObject.allo wed()"));
621 632
622 // Test calling a method of an implicitly inherited class (Object#getCla ss()). 633 // Test calling a method of an implicitly inherited class (Object#toStri ng()).
623 assertEquals("object", executeJavaScriptAndGetStringResult("typeof testO bject.getClass()")); 634 assertEquals("string", executeJavaScriptAndGetStringResult("typeof testO bject.toString()"));
624 } 635 }
625 636
626 @SmallTest 637 @SmallTest
627 @Feature({"AndroidWebView", "Android-JavaBridge"}) 638 @Feature({"AndroidWebView", "Android-JavaBridge"})
628 public void testAllowOnlyAnnotatedMethods() throws Throwable { 639 public void testAllowOnlyAnnotatedMethods() throws Throwable {
629 injectObjectAndReload(new Object() { 640 injectObjectAndReload(new Object() {
630 @JavascriptInterface 641 @JavascriptInterface
631 public String allowed() { return "foo"; } 642 public String allowed() { return "foo"; }
632 643
633 public String disallowed() { return "bar"; } 644 public String disallowed() { return "bar"; }
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
828 } 839 }
829 }); 840 });
830 841
831 injectObjectAndReload(new Test(), nonInspectableObjectName, JavascriptIn terface.class); 842 injectObjectAndReload(new Test(), nonInspectableObjectName, JavascriptIn terface.class);
832 843
833 assertEquals("", executeJavaScriptAndGetStringResult( 844 assertEquals("", executeJavaScriptAndGetStringResult(
834 String.format(jsObjectKeysTestTemplate, nonInspectableOb jectName))); 845 String.format(jsObjectKeysTestTemplate, nonInspectableOb jectName)));
835 assertEquals("", executeJavaScriptAndGetStringResult( 846 assertEquals("", executeJavaScriptAndGetStringResult(
836 String.format(jsForInTestTemplate, nonInspectableObjectN ame))); 847 String.format(jsForInTestTemplate, nonInspectableObjectN ame)));
837 } 848 }
849
850 @SmallTest
851 @Feature({"AndroidWebView", "Android-JavaBridge"})
852 public void testAccessToObjectGetClassIsBlocked() throws Throwable {
853 injectObjectAndReload(new Object(), "testObject");
854 assertEquals("function", executeJavaScriptAndGetStringResult("typeof tes tObject.getClass"));
855 boolean securityExceptionThrown = false;
856 try {
857 final String result = executeJavaScriptAndWaitForExceptionSynchronou sly(
858 "typeof testObject.getClass()");
859 fail("A call to java.lang.Object.getClass has been allowed, result: '" + result + "'");
860 } catch (SecurityException exception) {
861 securityExceptionThrown = true;
862 }
863 assertTrue(securityExceptionThrown);
864 }
865
866 // Unlike executeJavaScriptAndGetStringResult, this method is sitting on the UI thread
867 // until a non-null result is obtained or a Java exception has been thrown. This method is
868 // capable of catching Java RuntimeExceptions happening on the UI thread asy nchronously.
869 private String executeJavaScriptAndWaitForExceptionSynchronously(final Strin g script)
870 throws Throwable {
871 class ExitLoopException extends RuntimeException {
872 }
873 mTestController.setStringValue(null);
874 runTestOnUiThread(new Runnable() {
875 @Override
876 public void run() {
877 getContentView().loadUrl(new LoadUrlParams("javascript:(function () { " +
878 "testController.setStringValue(" + script + ") } )()"));
879 do {
880 final Boolean[] deactivateExitLoopTask = new Boolean[1];
881 deactivateExitLoopTask[0] = false;
882 // We can't use Loop.quit(), as this is the main looper, so we throw
883 // an exception to bail out from the loop.
884 new Handler(Looper.myLooper()).post(new Runnable() {
885 @Override
886 public void run() {
887 if (!deactivateExitLoopTask[0]) {
888 throw new ExitLoopException();
889 }
890 }
891 });
892 try {
893 Looper.loop();
894 } catch (ExitLoopException e) {
895 // Intentionally empty.
896 } catch (RuntimeException e) {
897 // Prevent the task that throws the ExitLoopException fr om exploding
898 // on the main loop outside of this function.
899 deactivateExitLoopTask[0] = true;
900 throw e;
901 }
902 } while (mTestController.getStringValue() == null ||
903 // When an exception in an injected method happens, the function returns
904 // null. We ignore this and wait until the exception on the browser side
905 // will be thrown.
906 mTestController.getStringValue().equals("null"));
907 }
908 });
909 return mTestController.getStringValue();
910 }
838 } 911 }
OLDNEW
« no previous file with comments | « content/browser/renderer_host/java/java_bound_object.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698