1d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block/*
2d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block * Copyright (C) 2011 The Android Open Source Project
3d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block *
4d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block * Licensed under the Apache License, Version 2.0 (the "License");
5d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block * you may not use this file except in compliance with the License.
6d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block * You may obtain a copy of the License at
7d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block *
8d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block *      http://www.apache.org/licenses/LICENSE-2.0
9d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block *
10d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block * Unless required by applicable law or agreed to in writing, software
11d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block * distributed under the License is distributed on an "AS IS" BASIS,
12d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block * See the License for the specific language governing permissions and
14d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block * limitations under the License.
15d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block */
16d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block
17d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block/**
18d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block * Common functionality for testing the WebView's Java Bridge.
19d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block */
20d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block
21d100cdbcc8033e59c405e0ce6855e81778f29132Steve Blockpackage com.android.webviewtests;
22d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block
23d100cdbcc8033e59c405e0ce6855e81778f29132Steve Blockimport android.test.ActivityInstrumentationTestCase2;
24d100cdbcc8033e59c405e0ce6855e81778f29132Steve Blockimport android.util.Log;
25d100cdbcc8033e59c405e0ce6855e81778f29132Steve Blockimport android.webkit.WebView;
26d100cdbcc8033e59c405e0ce6855e81778f29132Steve Blockimport android.webkit.WebViewClient;
27d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block
28d100cdbcc8033e59c405e0ce6855e81778f29132Steve Blockimport junit.framework.Assert;
29d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block
30d100cdbcc8033e59c405e0ce6855e81778f29132Steve Blockpublic class JavaBridgeTestBase extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
31f7e26448c3591989840efa65f4f3f93a294b991eSteve Block    protected class TestWebViewClient extends WebViewClient {
32d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        private boolean mIsPageFinished;
33d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        @Override
34d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        public synchronized void onPageFinished(WebView webView, String url) {
35d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block            mIsPageFinished = true;
36d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block            notify();
37d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        }
38d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        public synchronized void waitForOnPageFinished() throws RuntimeException {
39d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block            while (!mIsPageFinished) {
40d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                try {
41d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                    wait(5000);
42d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                } catch (Exception e) {
43d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                    continue;
44d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                }
45d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                if (!mIsPageFinished) {
46d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                    throw new RuntimeException("Timed out waiting for onPageFinished()");
47d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                }
48d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block            }
49d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block            mIsPageFinished = false;
50d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        }
51d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block    }
52d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block
53d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block    protected class Controller {
54d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        private boolean mIsResultReady;
55d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block
56d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        protected synchronized void notifyResultIsReady() {
57d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block            mIsResultReady = true;
58d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block            notify();
59d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        }
60d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        protected synchronized void waitForResult() {
61d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block            while (!mIsResultReady) {
62d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                try {
63d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                    wait(5000);
64d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                } catch (Exception e) {
65d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                    continue;
66d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                }
67d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                if (!mIsResultReady) {
68d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                    Assert.fail("Wait timed out");
69d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                }
70d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block            }
71d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block            mIsResultReady = false;
72d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        }
73d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block    }
74d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block
75f7e26448c3591989840efa65f4f3f93a294b991eSteve Block    protected TestWebViewClient mWebViewClient;
76d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block
77d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block    public JavaBridgeTestBase() {
78d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        super(WebViewStubActivity.class);
79d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block    }
80d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block
81d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block    // Sets up the WebView and injects the supplied object. Intended to be called from setUp().
82d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block    protected void setUpWebView(final Object object, final String name) throws Exception {
83d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        mWebViewClient = new TestWebViewClient();
84d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        // This starts the activity, so must be called on the test thread.
85d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        final WebViewStubActivity activity = getActivity();
86d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        // On the UI thread, load an empty page and wait for it to finish
87d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        // loading so that the Java object is injected.
88d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        try {
89d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block            runTestOnUiThread(new Runnable() {
90d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                @Override
91d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                public void run() {
92d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                    WebView webView = activity.getWebView();
93d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                    webView.addJavascriptInterface(object, name);
94d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                    webView.getSettings().setJavaScriptEnabled(true);
95d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                    webView.setWebViewClient(mWebViewClient);
9647538c081d2900d6e6bbf58da69a3173287cc73fSteve Block                    webView.loadData("<!DOCTYPE html><title></title>", "text/html", null);
97d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block                }
98d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block            });
99d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block            mWebViewClient.waitForOnPageFinished();
100d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        } catch (Throwable e) {
101d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block            throw new RuntimeException("Failed to set up WebView: " + Log.getStackTraceString(e));
102d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        }
103d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block    }
104d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block
105d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block    protected void executeJavaScript(final String script) throws Throwable {
106d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        runTestOnUiThread(new Runnable() {
107d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block            @Override
108d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block            public void run() {
109830698b1d94fc7215bd7a8ec50f884141a29212fSteve Block                // When a JavaScript URL is executed, if the value of the last
110830698b1d94fc7215bd7a8ec50f884141a29212fSteve Block                // expression evaluated is not 'undefined', this value is
111830698b1d94fc7215bd7a8ec50f884141a29212fSteve Block                // converted to a string and used as the new document for the
112830698b1d94fc7215bd7a8ec50f884141a29212fSteve Block                // frame. We don't want this behaviour, so wrap the script in
113830698b1d94fc7215bd7a8ec50f884141a29212fSteve Block                // an anonymous function.
114830698b1d94fc7215bd7a8ec50f884141a29212fSteve Block                getWebView().loadUrl("javascript:(function() { " + script + " })()");
115d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block            }
116d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block        });
117d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block    }
118f7e26448c3591989840efa65f4f3f93a294b991eSteve Block
119f7e26448c3591989840efa65f4f3f93a294b991eSteve Block    protected WebView getWebView() {
120f7e26448c3591989840efa65f4f3f93a294b991eSteve Block        return getActivity().getWebView();
121f7e26448c3591989840efa65f4f3f93a294b991eSteve Block    }
122d100cdbcc8033e59c405e0ce6855e81778f29132Steve Block}
123