• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.dumprendertree;
18 
19 import android.app.Activity;
20 import android.app.ActivityThread;
21 import android.graphics.Bitmap;
22 import android.net.http.SslError;
23 import android.os.Bundle;
24 import android.os.Handler;
25 import android.os.Message;
26 import android.util.Log;
27 import android.view.ViewGroup;
28 import android.webkit.HttpAuthHandler;
29 import android.webkit.JsPromptResult;
30 import android.webkit.JsResult;
31 import android.webkit.SslErrorHandler;
32 import android.webkit.WebChromeClient;
33 import android.webkit.WebView;
34 import android.webkit.WebViewClient;
35 import android.webkit.WebSettings.LayoutAlgorithm;
36 import android.widget.LinearLayout;
37 import android.widget.LinearLayout.LayoutParams;
38 
39 public class ReliabilityTestActivity extends Activity {
40 
41     public static final String TEST_URL_ACTION = "com.andrdoid.dumprendertree.TestUrlAction";
42     public static final String PARAM_URL = "URL";
43     public static final String PARAM_TIMEOUT = "Timeout";
44     public static final int RESULT_TIMEOUT = 0xDEAD;
45     public static final int MSG_TIMEOUT = 0xC001;
46     public static final int MSG_NAVIGATE = 0xC002;
47     public static final String MSG_NAV_URL = "url";
48     public static final String MSG_NAV_LOGTIME = "logtime";
49 
50     private static final String LOGTAG = "ReliabilityTestActivity";
51 
52     private WebView webView;
53     private SimpleWebViewClient webViewClient;
54     private SimpleChromeClient chromeClient;
55     private Handler handler;
56     private boolean timeoutFlag;
57     private boolean logTime;
58     private boolean pageDone;
59     private Object pageDoneLock;
60     private int pageStartCount;
61     private int manualDelay;
62     private long startTime;
63     private long pageLoadTime;
64     private PageDoneRunner pageDoneRunner = new PageDoneRunner();
65 
66     @Override
onCreate(Bundle savedInstanceState)67     protected void onCreate(Bundle savedInstanceState) {
68         super.onCreate(savedInstanceState);
69 
70         Log.v(LOGTAG, "onCreate, inst=" + Integer.toHexString(hashCode()));
71 
72         LinearLayout contentView = new LinearLayout(this);
73         contentView.setOrientation(LinearLayout.VERTICAL);
74         setContentView(contentView);
75         setTitle("Idle");
76 
77         webView = new WebView(this);
78         webView.getSettings().setJavaScriptEnabled(true);
79         webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(false);
80         webView.getSettings().setLayoutAlgorithm(LayoutAlgorithm.NORMAL);
81 
82         webViewClient = new SimpleWebViewClient();
83         chromeClient = new SimpleChromeClient();
84         webView.setWebViewClient(webViewClient);
85         webView.setWebChromeClient(chromeClient);
86 
87         contentView.addView(webView, new LayoutParams(
88                 ViewGroup.LayoutParams.FILL_PARENT,
89                 ViewGroup.LayoutParams.FILL_PARENT, 0.0f));
90 
91         handler = new Handler() {
92             @Override
93             public void handleMessage(Message msg) {
94                 switch (msg.what) {
95                     case MSG_TIMEOUT:
96                         handleTimeout();
97                         return;
98                     case MSG_NAVIGATE:
99                         manualDelay = msg.arg2;
100                         navigate(msg.getData().getString(MSG_NAV_URL), msg.arg1);
101                         logTime = msg.getData().getBoolean(MSG_NAV_LOGTIME);
102                         return;
103                 }
104             }
105         };
106 
107         pageDoneLock = new Object();
108     }
109 
reset()110     public void reset() {
111         synchronized (pageDoneLock) {
112             pageDone = false;
113         }
114         timeoutFlag = false;
115         pageStartCount = 0;
116         chromeClient.resetJsTimeout();
117     }
118 
navigate(String url, int timeout)119     private void navigate(String url, int timeout) {
120         if(url == null) {
121             Log.v(LOGTAG, "URL is null, cancelling...");
122             finish();
123         }
124         webView.stopLoading();
125         if(logTime) {
126             webView.clearCache(true);
127         }
128         startTime = System.currentTimeMillis();
129         Log.v(LOGTAG, "Navigating to URL: " + url);
130         webView.loadUrl(url);
131 
132         if(timeout != 0) {
133             //set a timer with specified timeout (in ms)
134             handler.sendMessageDelayed(handler.obtainMessage(MSG_TIMEOUT),
135                     timeout);
136         }
137     }
138 
139     @Override
onDestroy()140     protected void onDestroy() {
141         super.onDestroy();
142         Log.v(LOGTAG, "onDestroy, inst=" + Integer.toHexString(hashCode()));
143         webView.clearCache(true);
144         webView.destroy();
145     }
146 
isPageDone()147     private boolean isPageDone() {
148         synchronized (pageDoneLock) {
149             return pageDone;
150         }
151     }
152 
setPageDone(boolean pageDone)153     private void setPageDone(boolean pageDone) {
154         synchronized (pageDoneLock) {
155             this.pageDone = pageDone;
156             pageDoneLock.notifyAll();
157         }
158     }
159 
handleTimeout()160     private void handleTimeout() {
161         int progress = webView.getProgress();
162         webView.stopLoading();
163         Log.v(LOGTAG, "Page timeout triggered, progress = " + progress);
164         timeoutFlag = true;
165         handler.postDelayed(pageDoneRunner, manualDelay);
166     }
167 
waitUntilDone()168     public boolean waitUntilDone() {
169         validateNotAppThread();
170         synchronized (pageDoneLock) {
171             while(!isPageDone()) {
172                 try {
173                     pageDoneLock.wait();
174                 } catch (InterruptedException ie) {
175                     //no-op
176                 }
177             }
178         }
179         return timeoutFlag;
180     }
181 
getHandler()182     public Handler getHandler() {
183         return handler;
184     }
185 
validateNotAppThread()186     private final void validateNotAppThread() {
187         if (ActivityThread.currentActivityThread() != null) {
188             throw new RuntimeException(
189                 "This method can not be called from the main application thread");
190         }
191     }
192 
getPageLoadTime()193     public long getPageLoadTime() {
194         return pageLoadTime;
195     }
196 
197     class SimpleWebViewClient extends WebViewClient {
198 
199         @Override
onReceivedError(WebView view, int errorCode, String description, String failingUrl)200         public void onReceivedError(WebView view, int errorCode, String description,
201                 String failingUrl) {
202             Log.v(LOGTAG, "Received WebCore error: code=" + errorCode
203                     + ", description=" + description
204                     + ", url=" + failingUrl);
205         }
206 
207         @Override
onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)208         public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
209             //ignore certificate error
210             Log.v(LOGTAG, "Received SSL error: " + error.toString());
211             handler.proceed();
212         }
213 
214         @Override
onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm)215         public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host,
216                 String realm) {
217             // cancel http auth request
218             handler.cancel();
219         }
220 
221         @Override
onPageStarted(WebView view, String url, Bitmap favicon)222         public void onPageStarted(WebView view, String url, Bitmap favicon) {
223             pageStartCount++;
224             Log.v(LOGTAG, "onPageStarted: " + url);
225         }
226 
227         @Override
onPageFinished(WebView view, String url)228         public void onPageFinished(WebView view, String url) {
229             Log.v(LOGTAG, "onPageFinished: " + url);
230             // let handleTimeout take care of finishing the page
231             if(!timeoutFlag)
232                 handler.postDelayed(new WebViewStatusChecker(), 500);
233         }
234     }
235 
236     class SimpleChromeClient extends WebChromeClient {
237 
238         private int timeoutCounter = 0;
239 
240         @Override
onJsAlert(WebView view, String url, String message, JsResult result)241         public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
242             result.confirm();
243             return true;
244         }
245 
246         @Override
onJsBeforeUnload(WebView view, String url, String message, JsResult result)247         public boolean onJsBeforeUnload(WebView view, String url, String message, JsResult result) {
248             result.confirm();
249             return true;
250         }
251 
252         @Override
onJsConfirm(WebView view, String url, String message, JsResult result)253         public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
254             result.confirm();
255             return true;
256         }
257 
258         @Override
onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)259         public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
260                 JsPromptResult result) {
261             result.confirm();
262             return true;
263         }
264 
265         @Override
onJsTimeout()266         public boolean onJsTimeout() {
267             timeoutCounter++;
268             Log.v(LOGTAG, "JavaScript timeout, count=" + timeoutCounter);
269             return timeoutCounter > 2;
270         }
271 
resetJsTimeout()272         public void resetJsTimeout() {
273             timeoutCounter = 0;
274         }
275 
276         @Override
onReceivedTitle(WebView view, String title)277         public void onReceivedTitle(WebView view, String title) {
278             ReliabilityTestActivity.this.setTitle(title);
279         }
280     }
281 
282     class WebViewStatusChecker implements Runnable {
283 
284         private int initialStartCount;
285 
WebViewStatusChecker()286         public WebViewStatusChecker() {
287             initialStartCount = pageStartCount;
288         }
289 
run()290         public void run() {
291             if (initialStartCount == pageStartCount && !isPageDone()) {
292                 handler.removeMessages(MSG_TIMEOUT);
293                 webView.stopLoading();
294                 handler.postDelayed(pageDoneRunner, manualDelay);
295             }
296         }
297     }
298 
299     class PageDoneRunner implements Runnable {
300 
run()301         public void run() {
302             Log.v(LOGTAG, "Finishing URL: " + webView.getUrl());
303             pageLoadTime = System.currentTimeMillis() - startTime;
304             setPageDone(true);
305         }
306     }
307 }
308