ReliabilityTestActivity.java revision 40d87ee4867baa25fd7a824f324ea7040bf5bc23
1package com.android.dumprendertree;
2
3import android.app.Activity;
4import android.app.ActivityThread;
5import android.graphics.Bitmap;
6import android.net.http.SslError;
7import android.os.Bundle;
8import android.os.Handler;
9import android.os.Message;
10import android.util.Log;
11import android.view.ViewGroup;
12import android.webkit.HttpAuthHandler;
13import android.webkit.JsPromptResult;
14import android.webkit.JsResult;
15import android.webkit.SslErrorHandler;
16import android.webkit.WebChromeClient;
17import android.webkit.WebView;
18import android.webkit.WebViewClient;
19import android.webkit.WebSettings.LayoutAlgorithm;
20import android.widget.LinearLayout;
21import android.widget.LinearLayout.LayoutParams;
22
23public class ReliabilityTestActivity extends Activity {
24
25    public static final String TEST_URL_ACTION = "com.andrdoid.dumprendertree.TestUrlAction";
26    public static final String PARAM_URL = "URL";
27    public static final String PARAM_TIMEOUT = "Timeout";
28    public static final int RESULT_TIMEOUT = 0xDEAD;
29    public static final int MSG_TIMEOUT = 0xC001;
30    public static final int MSG_NAVIGATE = 0xC002;
31
32    private static final String LOGTAG = "ReliabilityTestActivity";
33
34    private WebView webView;
35    private SimpleWebViewClient webViewClient;
36    private SimpleChromeClient chromeClient;
37    private Handler handler;
38    private boolean timeoutFlag;
39    private boolean pageDone;
40    private Object pageDoneLock;
41    private int pageStartCount;
42
43    @Override
44    protected void onCreate(Bundle savedInstanceState) {
45        super.onCreate(savedInstanceState);
46
47        Log.v(LOGTAG, "onCreate, inst=" + Integer.toHexString(hashCode()));
48
49        LinearLayout contentView = new LinearLayout(this);
50        contentView.setOrientation(LinearLayout.VERTICAL);
51        setContentView(contentView);
52        setTitle("Idle");
53
54        webView = new WebView(this);
55        webView.getSettings().setJavaScriptEnabled(true);
56        webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(false);
57        webView.getSettings().setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
58
59        webViewClient = new SimpleWebViewClient();
60        chromeClient = new SimpleChromeClient();
61        webView.setWebViewClient(webViewClient);
62        webView.setWebChromeClient(chromeClient);
63
64        contentView.addView(webView, new LayoutParams(
65                ViewGroup.LayoutParams.FILL_PARENT,
66                ViewGroup.LayoutParams.FILL_PARENT, 0.0f));
67
68        handler = new Handler() {
69            @Override
70            public void handleMessage(Message msg) {
71                switch (msg.what) {
72                    case MSG_TIMEOUT:
73                        handleTimeout();
74                        return;
75                    case MSG_NAVIGATE:
76                        navigate((String)msg.obj, msg.arg1);
77                        return;
78                }
79            }
80        };
81
82        pageDoneLock = new Object();
83    }
84
85    public void reset() {
86        synchronized (pageDoneLock) {
87            pageDone = false;
88        }
89        timeoutFlag = false;
90        pageStartCount = 0;
91        chromeClient.resetJsTimeout();
92    }
93
94    private void navigate(String url, int timeout) {
95        if(url == null) {
96            Log.v(LOGTAG, "URL is null, cancelling...");
97            finish();
98        }
99        webView.stopLoading();
100        Log.v(LOGTAG, "Navigating to URL: " + url);
101        webView.loadUrl(url);
102
103        if(timeout != 0) {
104            //set a timer with specified timeout (in ms)
105            handler.sendMessageDelayed(handler.obtainMessage(MSG_TIMEOUT),
106                    timeout);
107        }
108    }
109
110    @Override
111    protected void onDestroy() {
112        Log.v(LOGTAG, "onDestroy, inst=" + Integer.toHexString(hashCode()));
113        super.onDestroy();
114    }
115
116    private boolean isPageDone() {
117        synchronized (pageDoneLock) {
118            return pageDone;
119        }
120    }
121
122    private void setPageDone(boolean pageDone) {
123        synchronized (pageDoneLock) {
124            this.pageDone = pageDone;
125            pageDoneLock.notifyAll();
126        }
127    }
128
129    private void handleTimeout() {
130        int progress = webView.getProgress();
131        webView.stopLoading();
132        Log.v(LOGTAG, "Page timeout triggered, progress = " + progress);
133        timeoutFlag = true;
134    }
135
136    public boolean waitUntilDone() {
137        validateNotAppThread();
138        synchronized (pageDoneLock) {
139            while(!isPageDone()) {
140                try {
141                    pageDoneLock.wait();
142                } catch (InterruptedException ie) {
143                    //no-op
144                }
145            }
146        }
147        return timeoutFlag;
148    }
149
150    public Handler getHandler() {
151        return handler;
152    }
153
154    private final void validateNotAppThread() {
155        if (ActivityThread.currentActivityThread() != null) {
156            throw new RuntimeException(
157                "This method can not be called from the main application thread");
158        }
159    }
160
161    class SimpleWebViewClient extends WebViewClient {
162
163        @Override
164        public void onReceivedError(WebView view, int errorCode, String description,
165                String failingUrl) {
166            Log.v(LOGTAG, "Received WebCore error: code=" + errorCode
167                    + ", description=" + description
168                    + ", url=" + failingUrl);
169        }
170
171        @Override
172        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
173            //ignore certificate error
174            Log.v(LOGTAG, "Received SSL error: " + error.toString());
175            handler.proceed();
176        }
177
178        @Override
179        public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host,
180                String realm) {
181            //cancel http auth request
182            handler.cancel();
183        }
184
185        @Override
186        public void onPageStarted(WebView view, String url, Bitmap favicon) {
187            pageStartCount++;
188            Log.v(LOGTAG, "onPageStarted: " + url);
189        }
190
191        @Override
192        public void onPageFinished(WebView view, String url) {
193            Log.v(LOGTAG, "onPageFinished: " + url);
194            handler.postDelayed(new WebViewStatusChecker(), 500);
195        }
196    }
197
198    class SimpleChromeClient extends WebChromeClient {
199
200        private int timeoutCounter = 0;
201
202        @Override
203        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
204            result.confirm();
205            return true;
206        }
207
208        @Override
209        public boolean onJsBeforeUnload(WebView view, String url, String message, JsResult result) {
210            result.confirm();
211            return true;
212        }
213
214        @Override
215        public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
216                JsPromptResult result) {
217            result.confirm();
218            return true;
219        }
220
221        @Override
222        public boolean onJsTimeout() {
223            timeoutCounter++;
224            Log.v(LOGTAG, "JavaScript timeout, count=" + timeoutCounter);
225            return timeoutCounter > 2;
226        }
227
228        public void resetJsTimeout() {
229            timeoutCounter = 0;
230        }
231
232        @Override
233        public void onReceivedTitle(WebView view, String title) {
234            ReliabilityTestActivity.this.setTitle(title);
235        }
236    }
237
238    class WebViewStatusChecker implements Runnable {
239
240        private int initialStartCount;
241
242        public WebViewStatusChecker() {
243            initialStartCount = pageStartCount;
244        }
245
246        public void run() {
247            if (initialStartCount == pageStartCount) {
248                //perform cleanup
249                webView.stopLoading();
250                Log.v(LOGTAG, "Finishing URL: " + webView.getUrl());
251                handler.removeMessages(MSG_TIMEOUT);
252                setPageDone(true);
253            }
254        }
255    }
256}
257