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