125df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller// Copyright 2015 The Chromium Authors. All rights reserved.
225df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller// Use of this source code is governed by a BSD-style license that can be
325df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller// found in the LICENSE file.
425df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
525df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Millerpackage org.chromium.webview_shell;
625df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
725df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Millerimport android.app.Activity;
825df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Millerimport android.os.Bundle;
925df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
1025df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Millerimport android.webkit.ConsoleMessage;
1125df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Millerimport android.webkit.GeolocationPermissions;
1225df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Millerimport android.webkit.PermissionRequest;
1325df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Millerimport android.webkit.WebChromeClient;
1425df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Millerimport android.webkit.WebSettings;
1525df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Millerimport android.webkit.WebView;
1625df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Millerimport android.webkit.WebViewClient;
1725df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
1825df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Millerimport java.util.concurrent.TimeUnit;
1925df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Millerimport java.util.concurrent.TimeoutException;
2025df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
2125df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller/**
2225df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller * This activity is used for running layout tests using webview. The activity
2325df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller * creates a webview instance, loads url and captures console messages from
2425df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller * JavaScript until the test is finished.
2525df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller * provides a blocking callback.
2625df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller */
2725df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Millerpublic class WebViewLayoutTestActivity extends Activity {
2825df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
2925df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    private final StringBuilder mConsoleLog = new StringBuilder();
3025df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    private final Object mLock = new Object();
3125df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    private static final String TEST_FINISHED_SENTINEL = "TEST FINISHED";
3225df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
3325df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    private WebView mWebView;
3425df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    private boolean mFinished = false;
3525df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
3625df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    private static final String[] AUTOMATICALLY_GRANT =
3725df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            { PermissionRequest.RESOURCE_VIDEO_CAPTURE, PermissionRequest.RESOURCE_AUDIO_CAPTURE };
3825df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
3925df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    @Override
4025df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    public void onCreate(Bundle savedInstanceState) {
4125df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        super.onCreate(savedInstanceState);
4225df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        setContentView(R.layout.activity_webview);
4325df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        mWebView = (WebView) findViewById(R.id.webview);
4425df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        WebSettings settings = mWebView.getSettings();
4525df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        initializeSettings(settings);
4625df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
4725df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        mWebView.setWebViewClient(new WebViewClient() {
4825df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            @Override
4925df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            public boolean shouldOverrideUrlLoading(WebView webView, String url) {
5025df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller                return false;
5125df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            }
5225df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        });
5325df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
5425df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        mWebView.setWebChromeClient(new WebChromeClient() {
5525df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            @Override
5625df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            public void onGeolocationPermissionsShowPrompt(String origin,
5725df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller                    GeolocationPermissions.Callback callback) {
5825df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller                callback.invoke(origin, true, false);
5925df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            }
6025df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
6125df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            @Override
6225df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            public void onPermissionRequest(PermissionRequest request) {
6325df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller                request.grant(AUTOMATICALLY_GRANT);
6425df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            }
6525df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
6625df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            @Override
6725df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
6825df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller                // TODO(timvolodine): put log and warnings in separate string builders.
6925df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller                mConsoleLog.append(consoleMessage.message() + "\n");
7025df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller                if (consoleMessage.message().equals(TEST_FINISHED_SENTINEL)) {
7125df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller                    finishTest();
7225df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller                }
7325df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller                return true;
7425df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            }
7525df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        });
7625df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    }
7725df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
7825df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    public void waitForFinish(long timeout, TimeUnit unit) throws InterruptedException,
7925df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            TimeoutException {
8025df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        synchronized (mLock) {
8125df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            long deadline = System.currentTimeMillis() + unit.toMillis(timeout);
8225df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            while (!mFinished && System.currentTimeMillis() < deadline) {
8325df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller                mLock.wait(deadline - System.currentTimeMillis());
8425df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            }
8525df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            if (!mFinished) {
8625df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller                throw new TimeoutException("timeout");
8725df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            }
8825df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        }
8925df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    }
9025df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
9125df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    public String getTestResult() {
9225df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        return mConsoleLog.toString();
9325df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    }
9425df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
9525df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    public void loadUrl(String url) {
9625df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        mWebView.loadUrl(url);
9725df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        mWebView.requestFocus();
9825df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    }
9925df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
10025df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    private void initializeSettings(WebSettings settings) {
10125df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        settings.setJavaScriptEnabled(true);
10225df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        settings.setGeolocationEnabled(true);
10325df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    }
10425df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller
10525df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    private void finishTest() {
10625df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        mFinished = true;
10725df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        synchronized (mLock) {
10825df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller            mLock.notifyAll();
10925df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller        }
11025df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller    }
11125df6673f1c51e755dd4d08cf64666cdff5e0f18Paul Miller}
112