TestShellActivity.java revision fc4a69e9c13d7233876a0f507ebca2eec25a4215
1/*
2 * Copyright (C) 2007 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
17package com.android.dumprendertree;
18
19import com.android.dumprendertree.forwarder.ForwardService;
20
21import android.app.Activity;
22import android.app.AlertDialog;
23import android.content.Context;
24import android.content.DialogInterface;
25import android.content.Intent;
26import android.content.DialogInterface.OnClickListener;
27import android.graphics.Bitmap;
28import android.graphics.Canvas;
29import android.graphics.Bitmap.CompressFormat;
30import android.graphics.Bitmap.Config;
31import android.net.http.SslError;
32import android.os.Bundle;
33import android.os.Handler;
34import android.os.Message;
35import android.util.Log;
36import android.view.ViewGroup;
37import android.webkit.GeolocationPermissions;
38import android.webkit.HttpAuthHandler;
39import android.webkit.JsPromptResult;
40import android.webkit.JsResult;
41import android.webkit.SslErrorHandler;
42import android.webkit.WebChromeClient;
43import android.webkit.WebSettings;
44import android.webkit.WebStorage;
45import android.webkit.WebView;
46import android.webkit.WebViewClient;
47import android.widget.LinearLayout;
48
49import java.io.BufferedReader;
50import java.io.File;
51import java.io.FileOutputStream;
52import java.io.FileReader;
53import java.io.IOException;
54import java.net.MalformedURLException;
55import java.net.URL;
56import java.util.HashMap;
57import java.util.Map;
58import java.util.Vector;
59
60public class TestShellActivity extends Activity implements LayoutTestController {
61
62    static enum DumpDataType {DUMP_AS_TEXT, EXT_REPR, NO_OP}
63
64    public class AsyncHandler extends Handler {
65        @Override
66        public void handleMessage(Message msg) {
67            if (msg.what == MSG_TIMEOUT) {
68                mTimedOut = true;
69                if (mCallback != null)
70                    mCallback.timedOut(mWebView.getUrl());
71                if (!mRequestedWebKitData) {
72                    requestWebKitData();
73                } else {
74                    // if timed out and webkit data has been dumped before
75                    // finish directly
76                    finished();
77                }
78                return;
79            } else if (msg.what == MSG_WEBKIT_DATA) {
80                TestShellActivity.this.dump(mTimedOut, (String)msg.obj);
81                return;
82            }
83
84            super.handleMessage(msg);
85        }
86    }
87
88    public void requestWebKitData() {
89        Message callback = mHandler.obtainMessage(MSG_WEBKIT_DATA);
90
91        if (mRequestedWebKitData)
92            throw new AssertionError("Requested webkit data twice: " + mWebView.getUrl());
93
94        mRequestedWebKitData = true;
95        Log.v(LOGTAG, "message sent to WebView to dump text.");
96        switch (mDumpDataType) {
97            case DUMP_AS_TEXT:
98                mWebView.documentAsText(callback);
99                break;
100            case EXT_REPR:
101                mWebView.externalRepresentation(callback);
102                break;
103            default:
104                finished();
105                break;
106        }
107    }
108
109    public void clearCache() {
110      mWebView.freeMemory();
111    }
112
113    @Override
114    protected void onCreate(Bundle icicle) {
115        super.onCreate(icicle);
116
117        LinearLayout contentView = new LinearLayout(this);
118        contentView.setOrientation(LinearLayout.VERTICAL);
119        setContentView(contentView);
120
121        mWebView = new WebView(this);
122        mEventSender = new WebViewEventSender(mWebView);
123        mCallbackProxy = new CallbackProxy(mEventSender, this);
124
125        mWebView.addJavascriptInterface(mCallbackProxy, "layoutTestController");
126        mWebView.addJavascriptInterface(mCallbackProxy, "eventSender");
127        setupWebViewForLayoutTests(mWebView, mCallbackProxy);
128
129        contentView.addView(mWebView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 0.0f));
130
131        mWebView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
132
133        // Expose window.gc function to JavaScript. JSC build exposes
134        // this function by default, but V8 requires the flag to turn it on.
135        // WebView::setJsFlags is noop in JSC build.
136        mWebView.setJsFlags("--expose_gc");
137
138        mHandler = new AsyncHandler();
139
140        Intent intent = getIntent();
141        if (intent != null) {
142            executeIntent(intent);
143        }
144    }
145
146    @Override
147    protected void onNewIntent(Intent intent) {
148        super.onNewIntent(intent);
149        executeIntent(intent);
150    }
151
152    private void executeIntent(Intent intent) {
153        resetTestStatus();
154        if (!Intent.ACTION_VIEW.equals(intent.getAction())) {
155            return;
156        }
157
158        mTestUrl = intent.getStringExtra(TEST_URL);
159        if (mTestUrl == null) {
160            mUiAutoTestPath = intent.getStringExtra(UI_AUTO_TEST);
161            if(mUiAutoTestPath != null) {
162                beginUiAutoTest();
163            }
164            return;
165        }
166
167        mResultFile = intent.getStringExtra(RESULT_FILE);
168        mTimeoutInMillis = intent.getIntExtra(TIMEOUT_IN_MILLIS, 0);
169        mGetDrawtime = intent.getBooleanExtra(GET_DRAW_TIME, false);
170        mSaveImagePath = intent.getStringExtra(SAVE_IMAGE);
171
172        Log.v(LOGTAG, "  Loading " + mTestUrl);
173        mWebView.loadUrl(mTestUrl);
174
175        if (mTimeoutInMillis > 0) {
176            // Create a timeout timer
177            Message m = mHandler.obtainMessage(MSG_TIMEOUT);
178            mHandler.sendMessageDelayed(m, mTimeoutInMillis);
179        }
180    }
181
182    private void beginUiAutoTest() {
183        try {
184            mTestListReader = new BufferedReader(
185                    new FileReader(mUiAutoTestPath));
186        } catch (IOException ioe) {
187            Log.e(LOGTAG, "Failed to open test list for read.", ioe);
188            finishUiAutoTest();
189            return;
190        }
191        moveToNextTest();
192    }
193
194    private void finishUiAutoTest() {
195        try {
196            if(mTestListReader != null)
197                mTestListReader.close();
198        } catch (IOException ioe) {
199            Log.w(LOGTAG, "Failed to close test list file.", ioe);
200        }
201        ForwardService.getForwardService().stopForwardService();
202        finished();
203    }
204
205    private void moveToNextTest() {
206        String url = null;
207        try {
208            url = mTestListReader.readLine();
209        } catch (IOException ioe) {
210            Log.e(LOGTAG, "Failed to read next test.", ioe);
211            finishUiAutoTest();
212            return;
213        }
214        if (url == null) {
215            mUiAutoTestPath = null;
216            finishUiAutoTest();
217            AlertDialog.Builder builder = new AlertDialog.Builder(this);
218            builder.setMessage("All tests finished. Exit?")
219                   .setCancelable(false)
220                   .setPositiveButton("Yes", new OnClickListener(){
221                       public void onClick(DialogInterface dialog, int which) {
222                           TestShellActivity.this.finish();
223                       }
224                   })
225                   .setNegativeButton("No", new OnClickListener(){
226                       public void onClick(DialogInterface dialog, int which) {
227                           dialog.cancel();
228                       }
229                   });
230            builder.create().show();
231            return;
232        }
233        Intent intent = new Intent(Intent.ACTION_VIEW);
234        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
235        intent.putExtra(TestShellActivity.TEST_URL, FsUtils.getTestUrl(url));
236        intent.putExtra(TIMEOUT_IN_MILLIS, 10000);
237        executeIntent(intent);
238    }
239
240    @Override
241    protected void onStop() {
242        super.onStop();
243        mWebView.stopLoading();
244    }
245
246    @Override
247    protected void onDestroy() {
248        super.onDestroy();
249        mWebView.destroy();
250        mWebView = null;
251    }
252
253    @Override
254    public void onLowMemory() {
255        super.onLowMemory();
256        Log.e(LOGTAG, "Low memory, clearing caches");
257        mWebView.freeMemory();
258    }
259
260    // Dump the page
261    public void dump(boolean timeout, String webkitData) {
262        mDumpWebKitData = true;
263        if (mResultFile == null || mResultFile.length() == 0) {
264            finished();
265            return;
266        }
267
268        try {
269            File parentDir = new File(mResultFile).getParentFile();
270            if (!parentDir.exists()) {
271                parentDir.mkdirs();
272            }
273
274            FileOutputStream os = new FileOutputStream(mResultFile);
275            if (timeout) {
276                Log.w("Layout test: Timeout", mResultFile);
277                os.write(TIMEOUT_STR.getBytes());
278                os.write('\n');
279            }
280            if (mDumpTitleChanges)
281                os.write(mTitleChanges.toString().getBytes());
282            if (mDialogStrings != null)
283                os.write(mDialogStrings.toString().getBytes());
284            mDialogStrings = null;
285            if (mDatabaseCallbackStrings != null)
286                os.write(mDatabaseCallbackStrings.toString().getBytes());
287            mDatabaseCallbackStrings = null;
288            if (mConsoleMessages != null)
289                os.write(mConsoleMessages.toString().getBytes());
290            mConsoleMessages = null;
291            if (webkitData != null)
292                os.write(webkitData.getBytes());
293            os.flush();
294            os.close();
295        } catch (IOException ex) {
296            Log.e(LOGTAG, "Cannot write to " + mResultFile + ", " + ex.getMessage());
297        }
298
299        finished();
300    }
301
302    public void setCallback(TestShellCallback callback) {
303        mCallback = callback;
304    }
305
306    public boolean finished() {
307        if (canMoveToNextTest()) {
308            mHandler.removeMessages(MSG_TIMEOUT);
309            if (mUiAutoTestPath != null) {
310                //don't really finish here
311                moveToNextTest();
312            } else {
313                if (mCallback != null) {
314                    mCallback.finished();
315                }
316            }
317            return true;
318        }
319        return false;
320    }
321
322    public void setDefaultDumpDataType(DumpDataType defaultDumpDataType) {
323        mDefaultDumpDataType = defaultDumpDataType;
324    }
325
326    // .......................................
327    // LayoutTestController Functions
328    public void dumpAsText() {
329        mDumpDataType = DumpDataType.DUMP_AS_TEXT;
330        if (mWebView != null) {
331            String url = mWebView.getUrl();
332            Log.v(LOGTAG, "dumpAsText called: "+url);
333        }
334    }
335
336    public void waitUntilDone() {
337        mWaitUntilDone = true;
338        String url = mWebView.getUrl();
339        Log.v(LOGTAG, "waitUntilDone called: " + url);
340    }
341
342    public void notifyDone() {
343        String url = mWebView.getUrl();
344        Log.v(LOGTAG, "notifyDone called: " + url);
345        if (mWaitUntilDone) {
346            mWaitUntilDone = false;
347            mChromeClient.onProgressChanged(mWebView, 101);
348        }
349    }
350
351    public void display() {
352        mWebView.invalidate();
353    }
354
355    public void clearBackForwardList() {
356        mWebView.clearHistory();
357
358    }
359
360    public void dumpBackForwardList() {
361        //printf("\n============== Back Forward List ==============\n");
362        // mWebHistory
363        //printf("===============================================\n");
364
365    }
366
367    public void dumpChildFrameScrollPositions() {
368        // TODO Auto-generated method stub
369
370    }
371
372    public void dumpEditingCallbacks() {
373        // TODO Auto-generated method stub
374
375    }
376
377    public void dumpSelectionRect() {
378        // TODO Auto-generated method stub
379
380    }
381
382    public void dumpTitleChanges() {
383        if (!mDumpTitleChanges) {
384            mTitleChanges = new StringBuffer();
385        }
386        mDumpTitleChanges = true;
387    }
388
389    public void keepWebHistory() {
390        if (!mKeepWebHistory) {
391            mWebHistory = new Vector();
392        }
393        mKeepWebHistory = true;
394    }
395
396    public void queueBackNavigation(int howfar) {
397        // TODO Auto-generated method stub
398
399    }
400
401    public void queueForwardNavigation(int howfar) {
402        // TODO Auto-generated method stub
403
404    }
405
406    public void queueLoad(String Url, String frameTarget) {
407        // TODO Auto-generated method stub
408
409    }
410
411    public void queueReload() {
412        mWebView.reload();
413    }
414
415    public void queueScript(String scriptToRunInCurrentContext) {
416        mWebView.loadUrl("javascript:"+scriptToRunInCurrentContext);
417    }
418
419    public void repaintSweepHorizontally() {
420        // TODO Auto-generated method stub
421
422    }
423
424    public void setAcceptsEditing(boolean b) {
425        // TODO Auto-generated method stub
426
427    }
428
429    public void setMainFrameIsFirstResponder(boolean b) {
430        // TODO Auto-generated method stub
431
432    }
433
434    public void setWindowIsKey(boolean b) {
435        // This is meant to show/hide the window. The best I can find
436        // is setEnabled()
437        mWebView.setEnabled(b);
438    }
439
440    public void testRepaint() {
441        mWebView.invalidate();
442    }
443
444    public void dumpDatabaseCallbacks() {
445        Log.v(LOGTAG, "dumpDatabaseCallbacks called.");
446        mDumpDatabaseCallbacks = true;
447    }
448
449    public void setCanOpenWindows() {
450        Log.v(LOGTAG, "setCanOpenWindows called.");
451        mCanOpenWindows = true;
452    }
453
454    /**
455     * Sets the Geolocation permission state to be used for all future requests.
456     */
457    public void setGeolocationPermission(boolean allow) {
458        mGeolocationPermissionSet = true;
459        mGeolocationPermission = allow;
460    }
461
462    private final WebViewClient mViewClient = new WebViewClient(){
463        @Override
464        public void onPageFinished(WebView view, String url) {
465            Log.v(LOGTAG, "onPageFinished, url=" + url);
466            mPageFinished = true;
467            // get page draw time
468            if (FsUtils.isTestPageUrl(url)) {
469                if (mGetDrawtime) {
470                    long[] times = new long[DRAW_RUNS];
471                    times = getDrawWebViewTime(mWebView, DRAW_RUNS);
472                    FsUtils.writeDrawTime(DRAW_TIME_LOG, url, times);
473                }
474                if (mSaveImagePath != null) {
475                    String name = FsUtils.getLastSegmentInPath(url);
476                    drawPageToFile(mSaveImagePath + "/" + name + ".png", mWebView);
477                }
478            }
479            // Calling finished() will check if we've met all the conditions for completing
480            // this test and move to the next one if we are ready.
481            if (finished()) {
482                return;
483            }
484            super.onPageFinished(view, url);
485        }
486
487        @Override
488        public void onPageStarted(WebView view, String url, Bitmap favicon) {
489            Log.v(LOGTAG, "onPageStarted, url=" + url);
490            mPageFinished = false;
491            super.onPageStarted(view, url, favicon);
492        }
493
494        @Override
495        public void onReceivedError(WebView view, int errorCode, String description,
496                String failingUrl) {
497            Log.v(LOGTAG, "onReceivedError, errorCode=" + errorCode
498                    + ", desc=" + description + ", url=" + failingUrl);
499            super.onReceivedError(view, errorCode, description, failingUrl);
500        }
501
502        @Override
503        public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler,
504                String host, String realm) {
505            handler.cancel();
506        }
507
508        @Override
509        public void onReceivedSslError(WebView view, SslErrorHandler handler,
510                SslError error) {
511            handler.proceed();
512        }
513    };
514
515
516    private final WebChromeClient mChromeClient = new WebChromeClient() {
517        @Override
518        public void onProgressChanged(WebView view, int newProgress) {
519
520            // notifyDone calls this with 101%. We only want to update this flag if this
521            // is the real call from WebCore.
522            if (newProgress == 100) {
523                mOneHundredPercentComplete = true;
524            }
525
526            // With the flag updated, we can now proceed as normal whether the progress update came from
527            // WebCore or notifyDone.
528            if (newProgress >= 100) {
529                // finished() will check if we are ready to move to the next test and do so if we are.
530                if (finished()) {
531                    return;
532                }
533
534                if (!mTimedOut && !mWaitUntilDone && !mRequestedWebKitData) {
535                    String url = mWebView.getUrl();
536                    Log.v(LOGTAG, "Finished: "+ url);
537                    requestWebKitData();
538                } else {
539                    String url = mWebView.getUrl();
540                    if (mTimedOut) {
541                        Log.v(LOGTAG, "Timed out before finishing: " + url);
542                    } else if (mWaitUntilDone) {
543                        Log.v(LOGTAG, "Waiting for notifyDone: " + url);
544                    } else if (mRequestedWebKitData) {
545                        Log.v(LOGTAG, "Requested webkit data ready: " + url);
546                    }
547                }
548            }
549        }
550
551        @Override
552        public void onReceivedTitle(WebView view, String title) {
553            if (title.length() > 30)
554                title = "..."+title.substring(title.length()-30);
555            setTitle(title);
556            if (mDumpTitleChanges) {
557                mTitleChanges.append("TITLE CHANGED: ");
558                mTitleChanges.append(title);
559                mTitleChanges.append("\n");
560            }
561        }
562
563        @Override
564        public boolean onJsAlert(WebView view, String url, String message,
565                JsResult result) {
566            if (mDialogStrings == null) {
567                mDialogStrings = new StringBuffer();
568            }
569            mDialogStrings.append("ALERT: ");
570            mDialogStrings.append(message);
571            mDialogStrings.append('\n');
572            result.confirm();
573            return true;
574        }
575
576        @Override
577        public boolean onJsConfirm(WebView view, String url, String message,
578                JsResult result) {
579            if (mDialogStrings == null) {
580                mDialogStrings = new StringBuffer();
581            }
582            mDialogStrings.append("CONFIRM: ");
583            mDialogStrings.append(message);
584            mDialogStrings.append('\n');
585            result.confirm();
586            return true;
587        }
588
589        @Override
590        public boolean onJsPrompt(WebView view, String url, String message,
591                String defaultValue, JsPromptResult result) {
592            if (mDialogStrings == null) {
593                mDialogStrings = new StringBuffer();
594            }
595            mDialogStrings.append("PROMPT: ");
596            mDialogStrings.append(message);
597            mDialogStrings.append(", default text: ");
598            mDialogStrings.append(defaultValue);
599            mDialogStrings.append('\n');
600            result.confirm();
601            return true;
602        }
603
604        @Override
605        public boolean onJsTimeout() {
606            Log.v(LOGTAG, "JavaScript timeout");
607            return false;
608        }
609
610        @Override
611        public void onExceededDatabaseQuota(String url_str,
612                String databaseIdentifier, long currentQuota,
613                long estimatedSize, long totalUsedQuota,
614                WebStorage.QuotaUpdater callback) {
615            if (mDumpDatabaseCallbacks) {
616                if (mDatabaseCallbackStrings == null) {
617                    mDatabaseCallbackStrings = new StringBuffer();
618                }
619
620                String protocol = "";
621                String host = "";
622                int port = 0;
623
624                try {
625                    URL url = new URL(url_str);
626                    protocol = url.getProtocol();
627                    host = url.getHost();
628                    if (url.getPort() > -1) {
629                        port = url.getPort();
630                    }
631                } catch (MalformedURLException e) {}
632
633                String databaseCallbackString =
634                        "UI DELEGATE DATABASE CALLBACK: " +
635                        "exceededDatabaseQuotaForSecurityOrigin:{" + protocol +
636                        ", " + host + ", " + port + "} database:" +
637                        databaseIdentifier + "\n";
638                Log.v(LOGTAG, "LOG: "+databaseCallbackString);
639                mDatabaseCallbackStrings.append(databaseCallbackString);
640            }
641            // Give 5MB more quota.
642            callback.updateQuota(currentQuota + 1024 * 1024 * 5);
643        }
644
645        /**
646         * Instructs the client to show a prompt to ask the user to set the
647         * Geolocation permission state for the specified origin.
648         */
649        @Override
650        public void onGeolocationPermissionsShowPrompt(String origin,
651                GeolocationPermissions.Callback callback) {
652            if (mGeolocationPermissionSet) {
653                callback.invoke(origin, mGeolocationPermission, false);
654            }
655        }
656
657        @Override
658        public void onConsoleMessage(String message, int lineNumber,
659                String sourceID) {
660            if (mConsoleMessages == null) {
661                mConsoleMessages = new StringBuffer();
662            }
663            String consoleMessage = "CONSOLE MESSAGE: line "
664                    + lineNumber +": "+ message +"\n";
665            mConsoleMessages.append(consoleMessage);
666            Log.v(LOGTAG, "LOG: "+consoleMessage);
667        }
668
669        @Override
670        public boolean onCreateWindow(WebView view, boolean dialog,
671                boolean userGesture, Message resultMsg) {
672            if (!mCanOpenWindows) {
673                // We can't open windows, so just send null back.
674                WebView.WebViewTransport transport =
675                        (WebView.WebViewTransport) resultMsg.obj;
676                transport.setWebView(null);
677                resultMsg.sendToTarget();
678                return true;
679            }
680
681            // We never display the new window, just create the view and
682            // allow it's content to execute and be recorded by the test
683            // runner.
684
685            HashMap<String, Object> jsIfaces = new HashMap<String, Object>();
686            jsIfaces.put("layoutTestController", mCallbackProxy);
687            jsIfaces.put("eventSender", mCallbackProxy);
688            WebView newWindowView = new NewWindowWebView(TestShellActivity.this, jsIfaces);
689            setupWebViewForLayoutTests(newWindowView, mCallbackProxy);
690            WebView.WebViewTransport transport =
691                    (WebView.WebViewTransport) resultMsg.obj;
692            transport.setWebView(newWindowView);
693            resultMsg.sendToTarget();
694            return true;
695        }
696
697        @Override
698        public void onCloseWindow(WebView view) {
699            view.destroy();
700        }
701    };
702
703    private static class NewWindowWebView extends WebView {
704        public NewWindowWebView(Context context, Map<String, Object> jsIfaces) {
705            super(context, null, 0, jsIfaces);
706        }
707    }
708
709    private void resetTestStatus() {
710        mWaitUntilDone = false;
711        mDumpDataType = mDefaultDumpDataType;
712        mTimedOut = false;
713        mDumpTitleChanges = false;
714        mRequestedWebKitData = false;
715        mDumpDatabaseCallbacks = false;
716        mCanOpenWindows = false;
717        mEventSender.resetMouse();
718        mEventSender.clearTouchPoints();
719        mPageFinished = false;
720        mOneHundredPercentComplete = false;
721        mDumpWebKitData = false;
722        mGetDrawtime = false;
723        mSaveImagePath = null;
724    }
725
726    private long[] getDrawWebViewTime(WebView view, int count) {
727        if (count == 0)
728            return null;
729        long[] ret = new long[count];
730        long start;
731        Canvas canvas = new Canvas();
732        Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Config.ARGB_8888);
733        canvas.setBitmap(bitmap);
734        for (int i = 0; i < count; i++) {
735            start = System.currentTimeMillis();
736            view.draw(canvas);
737            ret[i] = System.currentTimeMillis() - start;
738        }
739        return ret;
740    }
741
742    private void drawPageToFile(String fileName, WebView view) {
743        Canvas canvas = new Canvas();
744        Bitmap bitmap = Bitmap.createBitmap(view.getContentWidth(), view.getContentHeight(),
745                Config.ARGB_8888);
746        canvas.setBitmap(bitmap);
747        view.drawPage(canvas);
748        try {
749            FileOutputStream fos = new FileOutputStream(fileName);
750            if(!bitmap.compress(CompressFormat.PNG, 90, fos)) {
751                Log.w(LOGTAG, "Failed to compress and save image.");
752            }
753        } catch (IOException ioe) {
754            Log.e(LOGTAG, "", ioe);
755        }
756        bitmap.recycle();
757    }
758
759    private boolean canMoveToNextTest() {
760        return (mDumpWebKitData && mOneHundredPercentComplete && mPageFinished && !mWaitUntilDone) || mTimedOut;
761    }
762
763    private void setupWebViewForLayoutTests(WebView webview, CallbackProxy callbackProxy) {
764        if (webview == null) {
765            return;
766        }
767
768        WebSettings settings = webview.getSettings();
769        settings.setAppCacheEnabled(true);
770        settings.setAppCachePath(getApplicationContext().getCacheDir().getPath());
771        settings.setAppCacheMaxSize(Long.MAX_VALUE);
772        settings.setJavaScriptEnabled(true);
773        settings.setJavaScriptCanOpenWindowsAutomatically(true);
774        settings.setSupportMultipleWindows(true);
775        settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
776        settings.setDatabaseEnabled(true);
777        settings.setDatabasePath(getDir("databases",0).getAbsolutePath());
778        settings.setDomStorageEnabled(true);
779        settings.setWorkersEnabled(false);
780
781        webview.setWebChromeClient(mChromeClient);
782        webview.setWebViewClient(mViewClient);
783        // Setting a touch interval of -1 effectively disables the optimisation in WebView
784        // that stops repeated touch events flooding WebCore. The Event Sender only sends a
785        // single event rather than a stream of events (like what would generally happen in
786        // a real use of touch events in a WebView)  and so if the WebView drops the event,
787        // the test will fail as the test expects one callback for every touch it synthesizes.
788        webview.setTouchInterval(-1);
789    }
790
791    private WebView mWebView;
792    private WebViewEventSender mEventSender;
793    private AsyncHandler mHandler;
794    private TestShellCallback mCallback;
795
796    private CallbackProxy mCallbackProxy;
797
798    private String mTestUrl;
799    private String mResultFile;
800    private int mTimeoutInMillis;
801    private String mUiAutoTestPath;
802    private String mSaveImagePath;
803    private BufferedReader mTestListReader;
804    private boolean mGetDrawtime;
805
806    // States
807    private boolean mTimedOut;
808    private boolean mRequestedWebKitData;
809    private boolean mFinishedRunning;
810
811    // Layout test controller variables.
812    private DumpDataType mDumpDataType;
813    private DumpDataType mDefaultDumpDataType = DumpDataType.EXT_REPR;
814    private boolean mWaitUntilDone;
815    private boolean mDumpTitleChanges;
816    private StringBuffer mTitleChanges;
817    private StringBuffer mDialogStrings;
818    private boolean mKeepWebHistory;
819    private Vector mWebHistory;
820    private boolean mDumpDatabaseCallbacks;
821    private StringBuffer mDatabaseCallbackStrings;
822    private StringBuffer mConsoleMessages;
823    private boolean mCanOpenWindows;
824
825    private boolean mPageFinished = false;
826    private boolean mDumpWebKitData = false;
827    private boolean mOneHundredPercentComplete = false;
828
829    static final String TIMEOUT_STR = "**Test timeout";
830
831    static final int MSG_TIMEOUT = 0;
832    static final int MSG_WEBKIT_DATA = 1;
833
834    static final String LOGTAG="TestShell";
835
836    static final String TEST_URL = "TestUrl";
837    static final String RESULT_FILE = "ResultFile";
838    static final String TIMEOUT_IN_MILLIS = "TimeoutInMillis";
839    static final String UI_AUTO_TEST = "UiAutoTest";
840    static final String GET_DRAW_TIME = "GetDrawTime";
841    static final String SAVE_IMAGE = "SaveImage";
842
843    static final int DRAW_RUNS = 5;
844    static final String DRAW_TIME_LOG = "/sdcard/android/page_draw_time.txt";
845
846    private boolean mGeolocationPermissionSet;
847    private boolean mGeolocationPermission;
848}
849