• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 package org.chromium.content.browser;
6 
7 import android.test.suitebuilder.annotation.SmallTest;
8 
9 import org.chromium.base.test.util.Feature;
10 
11 /**
12  * Part of the test suite for the WebView's Java Bridge.
13  *
14  * Ensures that injected objects are exposed to child frames as well as the
15  * main frame.
16  */
17 public class JavaBridgeChildFrameTest extends JavaBridgeTestBase {
18     private class TestController extends Controller {
19         private String mStringValue;
20 
21     @SuppressWarnings("unused")  // Called via reflection
setStringValue(String x)22     public synchronized void setStringValue(String x) {
23             mStringValue = x;
24             notifyResultIsReady();
25         }
waitForStringValue()26        public synchronized String waitForStringValue() {
27             waitForResult();
28             return mStringValue;
29         }
30     }
31 
32     TestController mTestController;
33 
34     @Override
setUp()35     protected void setUp() throws Exception {
36         super.setUp();
37         mTestController = new TestController();
38         setUpContentView(mTestController, "testController");
39     }
40 
41     @SmallTest
42     @Feature({"AndroidWebView", "Android-JavaBridge"})
testInjectedObjectPresentInChildFrame()43     public void testInjectedObjectPresentInChildFrame() throws Throwable {
44         loadDataSync(getContentViewCore(),
45                 "<html><body><iframe></iframe></body></html>", "text/html", false);
46         // We are not executing this code as a part of page loading routine to avoid races
47         // with internal Blink events that notify Java Bridge about window object updates.
48         assertEquals("\"object\"", executeJavaScriptAndGetResult(
49                         getContentViewCore(), "typeof window.frames[0].testController"));
50         executeJavaScriptAndGetResult(
51                 getContentViewCore(), "window.frames[0].testController.setStringValue('PASS')");
52         assertEquals("PASS", mTestController.waitForStringValue());
53     }
54 
55     // Verify that loading an iframe doesn't ruin JS wrapper of the main page.
56     // This is a regression test for the problem described in b/15572824.
57     @SmallTest
58     @Feature({"AndroidWebView", "Android-JavaBridge"})
testMainPageWrapperIsNotBrokenByChildFrame()59     public void testMainPageWrapperIsNotBrokenByChildFrame() throws Throwable {
60         loadDataSync(getContentViewCore(),
61                 "<html><body><iframe></iframe></body></html>", "text/html", false);
62         // In case there is anything wrong with the JS wrapper, an attempt
63         // to look up its properties will result in an exception being thrown.
64         String script =
65                 "(function(){ try {" +
66                 "  return typeof testController.setStringValue;" +
67                 "} catch (e) {" +
68                 "  return e.toString();" +
69                 "} })()";
70         assertEquals("\"function\"",
71                 executeJavaScriptAndGetResult(getContentViewCore(), script));
72         // Make sure calling a method also works.
73         executeJavaScriptAndGetResult(getContentViewCore(),
74                 "testController.setStringValue('PASS');");
75         assertEquals("PASS", mTestController.waitForStringValue());
76     }
77 
78     // Verify that parent page and child frame each has own JS wrapper object.
79     // Failing to do so exposes parent's context to the child.
80     @SmallTest
81     @Feature({"AndroidWebView", "Android-JavaBridge"})
testWrapperIsNotSharedWithChildFrame()82     public void testWrapperIsNotSharedWithChildFrame() throws Throwable {
83         // Test by setting a custom property on the parent page's injected
84         // object and then checking that child frame doesn't see the property.
85         loadDataSync(getContentViewCore(),
86                 "<html><head>" +
87                 "<script>" +
88                 "  window.wProperty = 42;" +
89                 "  testController.tcProperty = 42;" +
90                 "  function queryProperties(w) {" +
91                 "    return w.wProperty + ' / ' + w.testController.tcProperty;" +
92                 "  }" +
93                 "</script>" +
94                 "</head><body><iframe></iframe></body></html>", "text/html", false);
95         assertEquals("\"42 / 42\"",
96                 executeJavaScriptAndGetResult(getContentViewCore(), "queryProperties(window)"));
97         assertEquals("\"undefined / undefined\"",
98                 executeJavaScriptAndGetResult(getContentViewCore(),
99                         "queryProperties(window.frames[0])"));
100     }
101 
executeJavaScriptAndGetResult(final ContentViewCore contentViewCore, final String script)102     private String executeJavaScriptAndGetResult(final ContentViewCore contentViewCore,
103             final String script) throws Throwable {
104         final String[] result = new String[1];
105         class ResultCallback extends JavaBridgeTestBase.Controller
106                 implements ContentViewCore.JavaScriptCallback {
107             @Override
108             public void handleJavaScriptResult(String jsonResult) {
109                 result[0] = jsonResult;
110                 notifyResultIsReady();
111             }
112         }
113         final ResultCallback resultCallback = new ResultCallback();
114         runTestOnUiThread(new Runnable() {
115             @Override
116             public void run() {
117                 contentViewCore.evaluateJavaScript(script, resultCallback);
118             }
119         });
120         resultCallback.waitForResult();
121         return result[0];
122     }
123 }
124