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