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