16bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu/*
26bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * Copyright (C) 2009 The Android Open Source Project
36bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu *
46bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * Licensed under the Apache License, Version 2.0 (the "License");
56bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * you may not use this file except in compliance with the License.
66bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * You may obtain a copy of the License at
76bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu *
86bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu *      http://www.apache.org/licenses/LICENSE-2.0
96bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu *
106bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * Unless required by applicable law or agreed to in writing, software
116bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * distributed under the License is distributed on an "AS IS" BASIS,
126bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * See the License for the specific language governing permissions and
146bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu * limitations under the License.
156bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu */
166bf18bae60ae1ff0bf2407e8db115cbbab6f1b84Guang Zhu
1765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhupackage com.android.dumprendertree;
1865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu
1965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.app.Activity;
2065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.app.ActivityThread;
2165455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.graphics.Bitmap;
2265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.net.http.SslError;
2365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.os.Bundle;
2465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.os.Handler;
2565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.os.Message;
2665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.util.Log;
2765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.view.ViewGroup;
2865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.webkit.HttpAuthHandler;
2965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.webkit.JsPromptResult;
3065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.webkit.JsResult;
3165455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.webkit.SslErrorHandler;
3265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.webkit.WebChromeClient;
3365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.webkit.WebView;
3465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.webkit.WebViewClient;
3565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.webkit.WebSettings.LayoutAlgorithm;
3665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.widget.LinearLayout;
3765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhuimport android.widget.LinearLayout.LayoutParams;
3865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu
3965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhupublic class ReliabilityTestActivity extends Activity {
402ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
4165455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    public static final String TEST_URL_ACTION = "com.andrdoid.dumprendertree.TestUrlAction";
4265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    public static final String PARAM_URL = "URL";
4365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    public static final String PARAM_TIMEOUT = "Timeout";
4465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    public static final int RESULT_TIMEOUT = 0xDEAD;
4565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    public static final int MSG_TIMEOUT = 0xC001;
4665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    public static final int MSG_NAVIGATE = 0xC002;
472ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu    public static final String MSG_NAV_URL = "url";
482ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu    public static final String MSG_NAV_LOGTIME = "logtime";
492ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
5065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    private static final String LOGTAG = "ReliabilityTestActivity";
512ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
5265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    private WebView webView;
5365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    private SimpleWebViewClient webViewClient;
5465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    private SimpleChromeClient chromeClient;
5565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    private Handler handler;
5665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    private boolean timeoutFlag;
572ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu    private boolean logTime;
5865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    private boolean pageDone;
5965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    private Object pageDoneLock;
6065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    private int pageStartCount;
613e8950c0c73f9c1574ce3388c754009edf6bc930Guang Zhu    private int manualDelay;
622ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu    private long startTime;
632ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu    private long pageLoadTime;
643e8950c0c73f9c1574ce3388c754009edf6bc930Guang Zhu    private PageDoneRunner pageDoneRunner = new PageDoneRunner();
652ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
6665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    @Override
6765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    protected void onCreate(Bundle savedInstanceState) {
6865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        super.onCreate(savedInstanceState);
6965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu
7065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        Log.v(LOGTAG, "onCreate, inst=" + Integer.toHexString(hashCode()));
712ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
7265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        LinearLayout contentView = new LinearLayout(this);
7365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        contentView.setOrientation(LinearLayout.VERTICAL);
7465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        setContentView(contentView);
7565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        setTitle("Idle");
762ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
7765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        webView = new WebView(this);
7865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        webView.getSettings().setJavaScriptEnabled(true);
7965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(false);
8065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        webView.getSettings().setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
812ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
8265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        webViewClient = new SimpleWebViewClient();
8365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        chromeClient = new SimpleChromeClient();
8465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        webView.setWebViewClient(webViewClient);
8565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        webView.setWebChromeClient(chromeClient);
862ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
8765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        contentView.addView(webView, new LayoutParams(
88980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy                ViewGroup.LayoutParams.MATCH_PARENT,
89980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy                ViewGroup.LayoutParams.MATCH_PARENT, 0.0f));
902ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
9165455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        handler = new Handler() {
9265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            @Override
9365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            public void handleMessage(Message msg) {
9465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                switch (msg.what) {
9565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                    case MSG_TIMEOUT:
9665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                        handleTimeout();
9765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                        return;
9865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                    case MSG_NAVIGATE:
993e8950c0c73f9c1574ce3388c754009edf6bc930Guang Zhu                        manualDelay = msg.arg2;
1002ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu                        navigate(msg.getData().getString(MSG_NAV_URL), msg.arg1);
1012ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu                        logTime = msg.getData().getBoolean(MSG_NAV_LOGTIME);
10265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                        return;
10365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                }
10465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            }
10565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        };
1062ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
10765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        pageDoneLock = new Object();
10865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    }
1092ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
11065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    public void reset() {
11165455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        synchronized (pageDoneLock) {
11265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            pageDone = false;
11365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
11465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        timeoutFlag = false;
11565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        pageStartCount = 0;
11665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        chromeClient.resetJsTimeout();
11765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    }
1182ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
11965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    private void navigate(String url, int timeout) {
12065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        if(url == null) {
12165455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            Log.v(LOGTAG, "URL is null, cancelling...");
12265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            finish();
12365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
12465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        webView.stopLoading();
1252ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu        if(logTime) {
1262ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu            webView.clearCache(true);
1272ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu        }
1282ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu        startTime = System.currentTimeMillis();
12965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        Log.v(LOGTAG, "Navigating to URL: " + url);
13065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        webView.loadUrl(url);
1312ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
13265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        if(timeout != 0) {
13365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            //set a timer with specified timeout (in ms)
13465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            handler.sendMessageDelayed(handler.obtainMessage(MSG_TIMEOUT),
13565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                    timeout);
13665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
13765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    }
1382ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
13965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    @Override
14065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    protected void onDestroy() {
14165455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        super.onDestroy();
1428c5b3e2fa60e29e45c97bf83b2aa8c6505987f82Guang Zhu        Log.v(LOGTAG, "onDestroy, inst=" + Integer.toHexString(hashCode()));
143c189b2ddd450f60167fcd4307ec826cc5f75f8faGuang Zhu        webView.clearCache(true);
1448c5b3e2fa60e29e45c97bf83b2aa8c6505987f82Guang Zhu        webView.destroy();
14565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    }
1462ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
14765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    private boolean isPageDone() {
14865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        synchronized (pageDoneLock) {
14965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            return pageDone;
15065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
15165455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    }
1522ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
15365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    private void setPageDone(boolean pageDone) {
15465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        synchronized (pageDoneLock) {
15565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            this.pageDone = pageDone;
15665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            pageDoneLock.notifyAll();
15765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
15865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    }
1592ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
16065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    private void handleTimeout() {
16165455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        int progress = webView.getProgress();
16265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        webView.stopLoading();
16365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        Log.v(LOGTAG, "Page timeout triggered, progress = " + progress);
16465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        timeoutFlag = true;
1657757656a11ba7050274c337fd2dc2f18f9e7806fGuang Zhu        handler.postDelayed(pageDoneRunner, manualDelay);
16665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    }
1672ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
16865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    public boolean waitUntilDone() {
16965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        validateNotAppThread();
17065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        synchronized (pageDoneLock) {
17165455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            while(!isPageDone()) {
17265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                try {
17365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                    pageDoneLock.wait();
17465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                } catch (InterruptedException ie) {
17565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                    //no-op
17665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                }
17765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            }
17865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
17965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        return timeoutFlag;
18065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    }
1812ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
18265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    public Handler getHandler() {
18365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        return handler;
18465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    }
1852ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
18665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    private final void validateNotAppThread() {
18765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        if (ActivityThread.currentActivityThread() != null) {
18865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            throw new RuntimeException(
18965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                "This method can not be called from the main application thread");
19065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
19165455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    }
19265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu
1932ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu    public long getPageLoadTime() {
1942ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu        return pageLoadTime;
1952ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu    }
1962ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
19765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    class SimpleWebViewClient extends WebViewClient {
1982ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
19965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        @Override
20065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        public void onReceivedError(WebView view, int errorCode, String description,
20165455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                String failingUrl) {
20265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            Log.v(LOGTAG, "Received WebCore error: code=" + errorCode
20365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                    + ", description=" + description
20465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                    + ", url=" + failingUrl);
20565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
2062ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
20765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        @Override
20865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
20965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            //ignore certificate error
21065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            Log.v(LOGTAG, "Received SSL error: " + error.toString());
21165455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            handler.proceed();
21265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
2132ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
21465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        @Override
21565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host,
21665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                String realm) {
2177757656a11ba7050274c337fd2dc2f18f9e7806fGuang Zhu            // cancel http auth request
21865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            handler.cancel();
21965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
2202ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
22165455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        @Override
22265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        public void onPageStarted(WebView view, String url, Bitmap favicon) {
22365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            pageStartCount++;
22465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            Log.v(LOGTAG, "onPageStarted: " + url);
22565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
2262ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
22765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        @Override
22865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        public void onPageFinished(WebView view, String url) {
22965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            Log.v(LOGTAG, "onPageFinished: " + url);
2307757656a11ba7050274c337fd2dc2f18f9e7806fGuang Zhu            // let handleTimeout take care of finishing the page
2317757656a11ba7050274c337fd2dc2f18f9e7806fGuang Zhu            if(!timeoutFlag)
2327757656a11ba7050274c337fd2dc2f18f9e7806fGuang Zhu                handler.postDelayed(new WebViewStatusChecker(), 500);
23365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
23465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    }
2352ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
23665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    class SimpleChromeClient extends WebChromeClient {
2372ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
23865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        private int timeoutCounter = 0;
2392ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
24065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        @Override
24165455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
24265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            result.confirm();
24365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            return true;
24465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
2452ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
24665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        @Override
24765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        public boolean onJsBeforeUnload(WebView view, String url, String message, JsResult result) {
24865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            result.confirm();
24965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            return true;
25065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
2512ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
25265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        @Override
253b9a39cd300998a1a4577ac7eb87f9b505b8621dcGuang Zhu        public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
254b9a39cd300998a1a4577ac7eb87f9b505b8621dcGuang Zhu            result.confirm();
255b9a39cd300998a1a4577ac7eb87f9b505b8621dcGuang Zhu            return true;
256b9a39cd300998a1a4577ac7eb87f9b505b8621dcGuang Zhu        }
257b9a39cd300998a1a4577ac7eb87f9b505b8621dcGuang Zhu
258b9a39cd300998a1a4577ac7eb87f9b505b8621dcGuang Zhu        @Override
25965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
26065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                JsPromptResult result) {
26165455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            result.confirm();
26265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            return true;
26365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
2642ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
26565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        @Override
26665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        public boolean onJsTimeout() {
26765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            timeoutCounter++;
26865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            Log.v(LOGTAG, "JavaScript timeout, count=" + timeoutCounter);
26965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            return timeoutCounter > 2;
27065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
2712ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
27265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        public void resetJsTimeout() {
27365455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            timeoutCounter = 0;
27465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
2752ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
27665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        @Override
27765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        public void onReceivedTitle(WebView view, String title) {
27865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            ReliabilityTestActivity.this.setTitle(title);
27965455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
28065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    }
2812ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
28265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    class WebViewStatusChecker implements Runnable {
2832ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
28465455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        private int initialStartCount;
2852ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
28665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        public WebViewStatusChecker() {
28765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            initialStartCount = pageStartCount;
28865455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
2892ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
29065455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        public void run() {
2918c5b3e2fa60e29e45c97bf83b2aa8c6505987f82Guang Zhu            if (initialStartCount == pageStartCount && !isPageDone()) {
29265455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu                handler.removeMessages(MSG_TIMEOUT);
2933e8950c0c73f9c1574ce3388c754009edf6bc930Guang Zhu                webView.stopLoading();
2943e8950c0c73f9c1574ce3388c754009edf6bc930Guang Zhu                handler.postDelayed(pageDoneRunner, manualDelay);
29565455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu            }
29665455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu        }
29765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu    }
2982ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
2993e8950c0c73f9c1574ce3388c754009edf6bc930Guang Zhu    class PageDoneRunner implements Runnable {
3002ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu
3013e8950c0c73f9c1574ce3388c754009edf6bc930Guang Zhu        public void run() {
3023e8950c0c73f9c1574ce3388c754009edf6bc930Guang Zhu            Log.v(LOGTAG, "Finishing URL: " + webView.getUrl());
3032ab6f1fe0b17d281ea215f8ca412a5e1992011ccGuang Zhu            pageLoadTime = System.currentTimeMillis() - startTime;
3043e8950c0c73f9c1574ce3388c754009edf6bc930Guang Zhu            setPageDone(true);
3053e8950c0c73f9c1574ce3388c754009edf6bc930Guang Zhu        }
3063e8950c0c73f9c1574ce3388c754009edf6bc930Guang Zhu    }
30765455a1a46e3bec020befd27ff5ad6bfdab61a7dGuang Zhu}
308