| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.dumprendertree2; |
| |
| import android.app.Activity; |
| import android.content.ComponentName; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.ServiceConnection; |
| import android.net.Uri; |
| import android.net.http.SslError; |
| import android.os.Bundle; |
| import android.os.Environment; |
| import android.os.Handler; |
| import android.os.IBinder; |
| import android.os.Message; |
| import android.os.Messenger; |
| import android.os.PowerManager; |
| import android.os.Process; |
| import android.os.PowerManager.WakeLock; |
| import android.os.RemoteException; |
| import android.util.Log; |
| import android.view.Window; |
| import android.webkit.ConsoleMessage; |
| import android.webkit.GeolocationPermissions; |
| import android.webkit.HttpAuthHandler; |
| import android.webkit.JsPromptResult; |
| import android.webkit.JsResult; |
| import android.webkit.SslErrorHandler; |
| import android.webkit.WebChromeClient; |
| import android.webkit.WebSettings; |
| import android.webkit.WebStorage; |
| import android.webkit.WebStorage.QuotaUpdater; |
| import android.webkit.WebView; |
| import android.webkit.WebViewClient; |
| |
| import java.io.File; |
| import java.lang.Thread.UncaughtExceptionHandler; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * This activity executes the test. It contains WebView and logic of LayoutTestController |
| * functions. It runs in a separate process and sends the results of running the test |
| * to ManagerService. The reason why is to handle crashing (test that crashes brings down |
| * whole process with it). |
| */ |
| public class LayoutTestsExecutor extends Activity { |
| |
| private enum CurrentState { |
| IDLE, |
| RENDERING_PAGE, |
| WAITING_FOR_ASYNCHRONOUS_TEST, |
| OBTAINING_RESULT; |
| |
| public boolean isRunningState() { |
| return this == CurrentState.RENDERING_PAGE || |
| this == CurrentState.WAITING_FOR_ASYNCHRONOUS_TEST; |
| } |
| } |
| |
| private static final String LOG_TAG = "LayoutTestsExecutor"; |
| |
| public static final String EXTRA_TESTS_LIST = "TestsList"; |
| public static final String EXTRA_TEST_INDEX = "TestIndex"; |
| |
| private static final int MSG_ACTUAL_RESULT_OBTAINED = 0; |
| private static final int MSG_TEST_TIMED_OUT = 1; |
| |
| private static final int DEFAULT_TIME_OUT_MS = 15 * 1000; |
| |
| /** A list of tests that remain to run since last crash */ |
| private List<String> mTestsList; |
| |
| /** |
| * This is a number of currently running test. It is 0-based and doesn't reset after |
| * the crash. Initial index is passed to LayoutTestsExecuter in the intent that starts |
| * it. |
| */ |
| private int mCurrentTestIndex; |
| |
| /** The total number of tests to run, doesn't reset after crash */ |
| private int mTotalTestCount; |
| |
| private WebView mCurrentWebView; |
| private String mCurrentTestRelativePath; |
| private String mCurrentTestUri; |
| private CurrentState mCurrentState = CurrentState.IDLE; |
| |
| private boolean mCurrentTestTimedOut; |
| private AbstractResult mCurrentResult; |
| private AdditionalTextOutput mCurrentAdditionalTextOutput; |
| |
| private LayoutTestController mLayoutTestController = new LayoutTestController(this); |
| private boolean mCanOpenWindows; |
| private boolean mDumpDatabaseCallbacks; |
| private boolean mIsGeolocationPermissionSet; |
| private boolean mGeolocationPermission; |
| private Map<GeolocationPermissions.Callback, String> mPendingGeolocationPermissionCallbacks; |
| |
| private EventSender mEventSender = new EventSender(); |
| |
| private WakeLock mScreenDimLock; |
| |
| /** COMMUNICATION WITH ManagerService */ |
| |
| private Messenger mManagerServiceMessenger; |
| |
| private ServiceConnection mServiceConnection = new ServiceConnection() { |
| |
| @Override |
| public void onServiceConnected(ComponentName name, IBinder service) { |
| mManagerServiceMessenger = new Messenger(service); |
| startTests(); |
| } |
| |
| @Override |
| public void onServiceDisconnected(ComponentName name) { |
| /** TODO */ |
| } |
| }; |
| |
| private final Handler mResultHandler = new Handler() { |
| @Override |
| public void handleMessage(Message msg) { |
| switch (msg.what) { |
| case MSG_ACTUAL_RESULT_OBTAINED: |
| onActualResultsObtained(); |
| break; |
| |
| case MSG_TEST_TIMED_OUT: |
| onTestTimedOut(); |
| break; |
| |
| default: |
| break; |
| } |
| } |
| }; |
| |
| /** WEBVIEW CONFIGURATION */ |
| |
| private WebViewClient mWebViewClient = new WebViewClient() { |
| @Override |
| public void onPageFinished(WebView view, String url) { |
| /** Some tests fire up many page loads, we don't want to detect them */ |
| if (!url.equals(mCurrentTestUri)) { |
| return; |
| } |
| |
| if (mCurrentState == CurrentState.RENDERING_PAGE) { |
| onTestFinished(); |
| } |
| } |
| |
| @Override |
| public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, |
| String host, String realm) { |
| if (handler.useHttpAuthUsernamePassword() && view != null) { |
| String[] credentials = view.getHttpAuthUsernamePassword(host, realm); |
| if (credentials != null && credentials.length == 2) { |
| handler.proceed(credentials[0], credentials[1]); |
| return; |
| } |
| } |
| handler.cancel(); |
| } |
| |
| @Override |
| public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { |
| // We ignore SSL errors. In particular, the certificate used by the LayoutTests server |
| // produces an error as it lacks a CN field. |
| handler.proceed(); |
| } |
| }; |
| |
| private WebChromeClient mWebChromeClient = new WebChromeClient() { |
| @Override |
| public void onExceededDatabaseQuota(String url, String databaseIdentifier, |
| long currentQuota, long estimatedSize, long totalUsedQuota, |
| QuotaUpdater quotaUpdater) { |
| /** TODO: This should be recorded as part of the text result */ |
| /** TODO: The quota should also probably be reset somehow for every test? */ |
| if (mDumpDatabaseCallbacks) { |
| getCurrentAdditionalTextOutput().appendExceededDbQuotaMessage(url, |
| databaseIdentifier); |
| } |
| quotaUpdater.updateQuota(currentQuota + 5 * 1024 * 1024); |
| } |
| |
| @Override |
| public boolean onJsAlert(WebView view, String url, String message, JsResult result) { |
| getCurrentAdditionalTextOutput().appendJsAlert(message); |
| result.confirm(); |
| return true; |
| } |
| |
| @Override |
| public boolean onJsConfirm(WebView view, String url, String message, JsResult result) { |
| getCurrentAdditionalTextOutput().appendJsConfirm(message); |
| result.confirm(); |
| return true; |
| } |
| |
| @Override |
| public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, |
| JsPromptResult result) { |
| getCurrentAdditionalTextOutput().appendJsPrompt(message, defaultValue); |
| result.confirm(); |
| return true; |
| } |
| |
| @Override |
| public boolean onConsoleMessage(ConsoleMessage consoleMessage) { |
| getCurrentAdditionalTextOutput().appendConsoleMessage(consoleMessage); |
| return true; |
| } |
| |
| @Override |
| public boolean onCreateWindow(WebView view, boolean dialog, boolean userGesture, |
| Message resultMsg) { |
| WebView.WebViewTransport transport = (WebView.WebViewTransport)resultMsg.obj; |
| /** By default windows cannot be opened, so just send null back. */ |
| WebView newWindowWebView = null; |
| |
| if (mCanOpenWindows) { |
| /** |
| * We never display the new window, just create the view and allow it's content to |
| * execute and be recorded by the executor. |
| */ |
| newWindowWebView = createWebViewWithJavascriptInterfaces(); |
| setupWebView(newWindowWebView); |
| } |
| |
| transport.setWebView(newWindowWebView); |
| resultMsg.sendToTarget(); |
| return true; |
| } |
| |
| @Override |
| public void onGeolocationPermissionsShowPrompt(String origin, |
| GeolocationPermissions.Callback callback) { |
| if (mIsGeolocationPermissionSet) { |
| callback.invoke(origin, mGeolocationPermission, false); |
| return; |
| } |
| if (mPendingGeolocationPermissionCallbacks == null) { |
| mPendingGeolocationPermissionCallbacks = |
| new HashMap<GeolocationPermissions.Callback, String>(); |
| } |
| mPendingGeolocationPermissionCallbacks.put(callback, origin); |
| } |
| }; |
| |
| /** IMPLEMENTATION */ |
| |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| |
| /** |
| * It detects the crash by catching all the uncaught exceptions. However, we |
| * still have to kill the process, because after catching the exception the |
| * activity remains in a strange state, where intents don't revive it. |
| * However, we send the message to the service to speed up the rebooting |
| * (we don't have to wait for time-out to kick in). |
| */ |
| Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { |
| @Override |
| public void uncaughtException(Thread thread, Throwable e) { |
| Log.w(LOG_TAG, |
| "onTestCrashed(): " + mCurrentTestRelativePath + " thread=" + thread, e); |
| |
| try { |
| Message serviceMsg = |
| Message.obtain(null, ManagerService.MSG_CURRENT_TEST_CRASHED); |
| |
| mManagerServiceMessenger.send(serviceMsg); |
| } catch (RemoteException e2) { |
| Log.e(LOG_TAG, "mCurrentTestRelativePath=" + mCurrentTestRelativePath, e2); |
| } |
| |
| Process.killProcess(Process.myPid()); |
| } |
| }); |
| |
| requestWindowFeature(Window.FEATURE_PROGRESS); |
| |
| Intent intent = getIntent(); |
| mTestsList = intent.getStringArrayListExtra(EXTRA_TESTS_LIST); |
| mCurrentTestIndex = intent.getIntExtra(EXTRA_TEST_INDEX, -1); |
| mTotalTestCount = mCurrentTestIndex + mTestsList.size(); |
| |
| PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE); |
| mScreenDimLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK |
| | PowerManager.ON_AFTER_RELEASE, "WakeLock in LayoutTester"); |
| mScreenDimLock.acquire(); |
| |
| bindService(new Intent(this, ManagerService.class), mServiceConnection, |
| Context.BIND_AUTO_CREATE); |
| } |
| |
| private void reset() { |
| WebView previousWebView = mCurrentWebView; |
| |
| resetLayoutTestController(); |
| |
| mCurrentTestTimedOut = false; |
| mCurrentResult = null; |
| mCurrentAdditionalTextOutput = null; |
| |
| mCurrentWebView = createWebViewWithJavascriptInterfaces(); |
| // When we create the first WebView, we need to pause to wait for the WebView thread to spin |
| // and up and for it to register its message handlers. |
| if (previousWebView == null) { |
| try { |
| Thread.currentThread().sleep(1000); |
| } catch (Exception e) {} |
| } |
| setupWebView(mCurrentWebView); |
| |
| mEventSender.reset(mCurrentWebView); |
| |
| setContentView(mCurrentWebView); |
| if (previousWebView != null) { |
| Log.d(LOG_TAG + "::reset", "previousWebView != null"); |
| previousWebView.destroy(); |
| } |
| } |
| |
| private static class WebViewWithJavascriptInterfaces extends WebView { |
| public WebViewWithJavascriptInterfaces( |
| Context context, Map<String, Object> javascriptInterfaces) { |
| super(context, |
| null, // attribute set |
| 0, // default style resource ID |
| javascriptInterfaces, |
| false); // is private browsing |
| } |
| } |
| private WebView createWebViewWithJavascriptInterfaces() { |
| Map<String, Object> javascriptInterfaces = new HashMap<String, Object>(); |
| javascriptInterfaces.put("layoutTestController", mLayoutTestController); |
| javascriptInterfaces.put("eventSender", mEventSender); |
| return new WebViewWithJavascriptInterfaces(this, javascriptInterfaces); |
| } |
| |
| private void setupWebView(WebView webView) { |
| webView.setWebViewClient(mWebViewClient); |
| webView.setWebChromeClient(mWebChromeClient); |
| |
| /** |
| * Setting a touch interval of -1 effectively disables the optimisation in WebView |
| * that stops repeated touch events flooding WebCore. The Event Sender only sends a |
| * single event rather than a stream of events (like what would generally happen in |
| * a real use of touch events in a WebView) and so if the WebView drops the event, |
| * the test will fail as the test expects one callback for every touch it synthesizes. |
| */ |
| webView.setTouchInterval(-1); |
| |
| webView.clearCache(true); |
| webView.setDeferMultiTouch(true); |
| |
| WebSettings webViewSettings = webView.getSettings(); |
| webViewSettings.setAppCacheEnabled(true); |
| webViewSettings.setAppCachePath(getApplicationContext().getCacheDir().getPath()); |
| // Use of larger values causes unexplained AppCache database corruption. |
| // TODO: Investigate what's really going on here. |
| webViewSettings.setAppCacheMaxSize(100 * 1024 * 1024); |
| webViewSettings.setJavaScriptEnabled(true); |
| webViewSettings.setJavaScriptCanOpenWindowsAutomatically(true); |
| webViewSettings.setSupportMultipleWindows(true); |
| webViewSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL); |
| webViewSettings.setDatabaseEnabled(true); |
| webViewSettings.setDatabasePath(getDir("databases", 0).getAbsolutePath()); |
| webViewSettings.setDomStorageEnabled(true); |
| webViewSettings.setWorkersEnabled(false); |
| webViewSettings.setXSSAuditorEnabled(false); |
| webViewSettings.setPageCacheCapacity(0); |
| |
| // This is asynchronous, but it gets processed by WebCore before it starts loading pages. |
| mCurrentWebView.useMockDeviceOrientation(); |
| |
| // Must do this after setting the AppCache path. |
| WebStorage.getInstance().deleteAllData(); |
| } |
| |
| private void startTests() { |
| try { |
| Message serviceMsg = |
| Message.obtain(null, ManagerService.MSG_FIRST_TEST); |
| |
| Bundle bundle = new Bundle(); |
| if (!mTestsList.isEmpty()) { |
| bundle.putString("firstTest", mTestsList.get(0)); |
| bundle.putInt("index", mCurrentTestIndex); |
| } |
| |
| serviceMsg.setData(bundle); |
| mManagerServiceMessenger.send(serviceMsg); |
| } catch (RemoteException e) { |
| Log.e(LOG_TAG, "mCurrentTestRelativePath=" + mCurrentTestRelativePath, e); |
| } |
| |
| runNextTest(); |
| } |
| |
| private void runNextTest() { |
| assert mCurrentState == CurrentState.IDLE : "mCurrentState = " + mCurrentState.name(); |
| |
| if (mTestsList.isEmpty()) { |
| onAllTestsFinished(); |
| return; |
| } |
| |
| mCurrentTestRelativePath = mTestsList.remove(0); |
| |
| Log.i(LOG_TAG, "runNextTest(): Start: " + mCurrentTestRelativePath + |
| " (" + mCurrentTestIndex + ")"); |
| |
| mCurrentTestUri = FileFilter.getUrl(mCurrentTestRelativePath).toString(); |
| |
| reset(); |
| |
| /** Start time-out countdown and the test */ |
| mCurrentState = CurrentState.RENDERING_PAGE; |
| mResultHandler.sendEmptyMessageDelayed(MSG_TEST_TIMED_OUT, DEFAULT_TIME_OUT_MS); |
| mCurrentWebView.loadUrl(mCurrentTestUri); |
| } |
| |
| private void onTestTimedOut() { |
| assert mCurrentState.isRunningState() : "mCurrentState = " + mCurrentState.name(); |
| |
| Log.w(LOG_TAG, "onTestTimedOut(): " + mCurrentTestRelativePath); |
| mCurrentTestTimedOut = true; |
| |
| /** |
| * While it is theoretically possible that the test times out because |
| * of webview becoming unresponsive, it is very unlikely. Therefore it's |
| * assumed that obtaining results (that calls various webview methods) |
| * will not itself hang. |
| */ |
| obtainActualResultsFromWebView(); |
| } |
| |
| private void onTestFinished() { |
| assert mCurrentState.isRunningState() : "mCurrentState = " + mCurrentState.name(); |
| |
| Log.i(LOG_TAG, "onTestFinished(): " + mCurrentTestRelativePath); |
| mResultHandler.removeMessages(MSG_TEST_TIMED_OUT); |
| obtainActualResultsFromWebView(); |
| } |
| |
| private void obtainActualResultsFromWebView() { |
| /** |
| * If the result has not been set by the time the test finishes we create |
| * a default type of result. |
| */ |
| if (mCurrentResult == null) { |
| /** TODO: Default type should be RenderTreeResult. We don't support it now. */ |
| mCurrentResult = new TextResult(mCurrentTestRelativePath); |
| } |
| |
| mCurrentState = CurrentState.OBTAINING_RESULT; |
| |
| if (mCurrentTestTimedOut) { |
| mCurrentResult.setDidTimeOut(); |
| } |
| mCurrentResult.obtainActualResults(mCurrentWebView, |
| mResultHandler.obtainMessage(MSG_ACTUAL_RESULT_OBTAINED)); |
| } |
| |
| private void onActualResultsObtained() { |
| assert mCurrentState == CurrentState.OBTAINING_RESULT |
| : "mCurrentState = " + mCurrentState.name(); |
| |
| Log.i(LOG_TAG, "onActualResultsObtained(): " + mCurrentTestRelativePath); |
| mCurrentState = CurrentState.IDLE; |
| |
| reportResultToService(); |
| mCurrentTestIndex++; |
| updateProgressBar(); |
| runNextTest(); |
| } |
| |
| private void reportResultToService() { |
| if (mCurrentAdditionalTextOutput != null) { |
| mCurrentResult.setAdditionalTextOutputString(mCurrentAdditionalTextOutput.toString()); |
| } |
| |
| try { |
| Message serviceMsg = |
| Message.obtain(null, ManagerService.MSG_PROCESS_ACTUAL_RESULTS); |
| |
| Bundle bundle = mCurrentResult.getBundle(); |
| bundle.putInt("testIndex", mCurrentTestIndex); |
| if (!mTestsList.isEmpty()) { |
| bundle.putString("nextTest", mTestsList.get(0)); |
| } |
| |
| serviceMsg.setData(bundle); |
| mManagerServiceMessenger.send(serviceMsg); |
| } catch (RemoteException e) { |
| Log.e(LOG_TAG, "mCurrentTestRelativePath=" + mCurrentTestRelativePath, e); |
| } |
| } |
| |
| private void updateProgressBar() { |
| getWindow().setFeatureInt(Window.FEATURE_PROGRESS, |
| mCurrentTestIndex * Window.PROGRESS_END / mTotalTestCount); |
| setTitle(mCurrentTestIndex * 100 / mTotalTestCount + "% " + |
| "(" + mCurrentTestIndex + "/" + mTotalTestCount + ")"); |
| } |
| |
| private void onAllTestsFinished() { |
| mScreenDimLock.release(); |
| |
| try { |
| Message serviceMsg = |
| Message.obtain(null, ManagerService.MSG_ALL_TESTS_FINISHED); |
| mManagerServiceMessenger.send(serviceMsg); |
| } catch (RemoteException e) { |
| Log.e(LOG_TAG, "mCurrentTestRelativePath=" + mCurrentTestRelativePath, e); |
| } |
| |
| unbindService(mServiceConnection); |
| } |
| |
| private AdditionalTextOutput getCurrentAdditionalTextOutput() { |
| if (mCurrentAdditionalTextOutput == null) { |
| mCurrentAdditionalTextOutput = new AdditionalTextOutput(); |
| } |
| return mCurrentAdditionalTextOutput; |
| } |
| |
| /** LAYOUT TEST CONTROLLER */ |
| |
| private static final int MSG_WAIT_UNTIL_DONE = 0; |
| private static final int MSG_NOTIFY_DONE = 1; |
| private static final int MSG_DUMP_AS_TEXT = 2; |
| private static final int MSG_DUMP_CHILD_FRAMES_AS_TEXT = 3; |
| private static final int MSG_SET_CAN_OPEN_WINDOWS = 4; |
| private static final int MSG_DUMP_DATABASE_CALLBACKS = 5; |
| private static final int MSG_SET_GEOLOCATION_PERMISSION = 6; |
| private static final int MSG_OVERRIDE_PREFERENCE = 7; |
| private static final int MSG_SET_XSS_AUDITOR_ENABLED = 8; |
| |
| /** String constants for use with layoutTestController.overridePreference() */ |
| private final String WEBKIT_OFFLINE_WEB_APPLICATION_CACHE_ENABLED = |
| "WebKitOfflineWebApplicationCacheEnabled"; |
| private final String WEBKIT_USES_PAGE_CACHE_PREFERENCE_KEY = "WebKitUsesPageCachePreferenceKey"; |
| |
| Handler mLayoutTestControllerHandler = new Handler() { |
| @Override |
| public void handleMessage(Message msg) { |
| assert mCurrentState.isRunningState() : "mCurrentState = " + mCurrentState.name(); |
| |
| switch (msg.what) { |
| case MSG_DUMP_AS_TEXT: |
| if (mCurrentResult == null) { |
| mCurrentResult = new TextResult(mCurrentTestRelativePath); |
| } |
| assert mCurrentResult instanceof TextResult |
| : "mCurrentResult instanceof" + mCurrentResult.getClass().getName(); |
| break; |
| |
| case MSG_DUMP_CHILD_FRAMES_AS_TEXT: |
| /** If dumpAsText was not called we assume that the result should be text */ |
| if (mCurrentResult == null) { |
| mCurrentResult = new TextResult(mCurrentTestRelativePath); |
| } |
| |
| assert mCurrentResult instanceof TextResult |
| : "mCurrentResult instanceof" + mCurrentResult.getClass().getName(); |
| |
| ((TextResult)mCurrentResult).setDumpChildFramesAsText(true); |
| break; |
| |
| case MSG_DUMP_DATABASE_CALLBACKS: |
| mDumpDatabaseCallbacks = true; |
| break; |
| |
| case MSG_NOTIFY_DONE: |
| if (mCurrentState == CurrentState.WAITING_FOR_ASYNCHRONOUS_TEST) { |
| onTestFinished(); |
| } |
| break; |
| |
| case MSG_OVERRIDE_PREFERENCE: |
| /** |
| * TODO: We should look up the correct WebView for the frame which |
| * called the layoutTestController method. Currently, we just use the |
| * WebView for the main frame. EventSender suffers from the same |
| * problem. |
| */ |
| String key = msg.getData().getString("key"); |
| boolean value = msg.getData().getBoolean("value"); |
| if (WEBKIT_OFFLINE_WEB_APPLICATION_CACHE_ENABLED.equals(key)) { |
| mCurrentWebView.getSettings().setAppCacheEnabled(value); |
| } else if (WEBKIT_USES_PAGE_CACHE_PREFERENCE_KEY.equals(key)) { |
| // Cache the maximum possible number of pages. |
| mCurrentWebView.getSettings().setPageCacheCapacity(Integer.MAX_VALUE); |
| } else { |
| Log.w(LOG_TAG, "LayoutTestController.overridePreference(): " + |
| "Unsupported preference '" + key + "'"); |
| } |
| break; |
| |
| case MSG_SET_CAN_OPEN_WINDOWS: |
| mCanOpenWindows = true; |
| break; |
| |
| case MSG_SET_GEOLOCATION_PERMISSION: |
| mIsGeolocationPermissionSet = true; |
| mGeolocationPermission = msg.arg1 == 1; |
| |
| if (mPendingGeolocationPermissionCallbacks != null) { |
| Iterator<GeolocationPermissions.Callback> iter = |
| mPendingGeolocationPermissionCallbacks.keySet().iterator(); |
| while (iter.hasNext()) { |
| GeolocationPermissions.Callback callback = iter.next(); |
| String origin = mPendingGeolocationPermissionCallbacks.get(callback); |
| callback.invoke(origin, mGeolocationPermission, false); |
| } |
| mPendingGeolocationPermissionCallbacks = null; |
| } |
| break; |
| |
| case MSG_SET_XSS_AUDITOR_ENABLED: |
| mCurrentWebView.getSettings().setXSSAuditorEnabled(msg.arg1 == 1); |
| break; |
| |
| case MSG_WAIT_UNTIL_DONE: |
| mCurrentState = CurrentState.WAITING_FOR_ASYNCHRONOUS_TEST; |
| break; |
| |
| default: |
| assert false : "msg.what=" + msg.what; |
| break; |
| } |
| } |
| }; |
| |
| private void resetLayoutTestController() { |
| mCanOpenWindows = false; |
| mDumpDatabaseCallbacks = false; |
| mIsGeolocationPermissionSet = false; |
| mPendingGeolocationPermissionCallbacks = null; |
| } |
| |
| public void dumpAsText(boolean enablePixelTest) { |
| Log.i(LOG_TAG, mCurrentTestRelativePath + ": dumpAsText(" + enablePixelTest + ") called"); |
| /** TODO: Implement */ |
| if (enablePixelTest) { |
| Log.w(LOG_TAG, "enablePixelTest not implemented, switching to false"); |
| } |
| mLayoutTestControllerHandler.sendEmptyMessage(MSG_DUMP_AS_TEXT); |
| } |
| |
| public void dumpChildFramesAsText() { |
| Log.i(LOG_TAG, mCurrentTestRelativePath + ": dumpChildFramesAsText() called"); |
| mLayoutTestControllerHandler.sendEmptyMessage(MSG_DUMP_CHILD_FRAMES_AS_TEXT); |
| } |
| |
| public void dumpDatabaseCallbacks() { |
| Log.i(LOG_TAG, mCurrentTestRelativePath + ": dumpDatabaseCallbacks() called"); |
| mLayoutTestControllerHandler.sendEmptyMessage(MSG_DUMP_DATABASE_CALLBACKS); |
| } |
| |
| public void notifyDone() { |
| Log.i(LOG_TAG, mCurrentTestRelativePath + ": notifyDone() called"); |
| mLayoutTestControllerHandler.sendEmptyMessage(MSG_NOTIFY_DONE); |
| } |
| |
| public void overridePreference(String key, boolean value) { |
| Log.i(LOG_TAG, mCurrentTestRelativePath + ": overridePreference(" + key + ", " + value + |
| ") called"); |
| Message msg = mLayoutTestControllerHandler.obtainMessage(MSG_OVERRIDE_PREFERENCE); |
| msg.getData().putString("key", key); |
| msg.getData().putBoolean("value", value); |
| msg.sendToTarget(); |
| } |
| |
| public void setCanOpenWindows() { |
| Log.i(LOG_TAG, mCurrentTestRelativePath + ": setCanOpenWindows() called"); |
| mLayoutTestControllerHandler.sendEmptyMessage(MSG_SET_CAN_OPEN_WINDOWS); |
| } |
| |
| public void setGeolocationPermission(boolean allow) { |
| Log.i(LOG_TAG, mCurrentTestRelativePath + ": setGeolocationPermission(" + allow + |
| ") called"); |
| Message msg = mLayoutTestControllerHandler.obtainMessage(MSG_SET_GEOLOCATION_PERMISSION); |
| msg.arg1 = allow ? 1 : 0; |
| msg.sendToTarget(); |
| } |
| |
| public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha, |
| boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma) { |
| Log.i(LOG_TAG, mCurrentTestRelativePath + ": setMockDeviceOrientation(" + canProvideAlpha + |
| ", " + alpha + ", " + canProvideBeta + ", " + beta + ", " + canProvideGamma + |
| ", " + gamma + ")"); |
| mCurrentWebView.setMockDeviceOrientation(canProvideAlpha, alpha, canProvideBeta, beta, |
| canProvideGamma, gamma); |
| } |
| |
| public void setXSSAuditorEnabled(boolean flag) { |
| Log.i(LOG_TAG, mCurrentTestRelativePath + ": setXSSAuditorEnabled(" + flag + ") called"); |
| Message msg = mLayoutTestControllerHandler.obtainMessage(MSG_SET_XSS_AUDITOR_ENABLED); |
| msg.arg1 = flag ? 1 : 0; |
| msg.sendToTarget(); |
| } |
| |
| public void waitUntilDone() { |
| Log.i(LOG_TAG, mCurrentTestRelativePath + ": waitUntilDone() called"); |
| mLayoutTestControllerHandler.sendEmptyMessage(MSG_WAIT_UNTIL_DONE); |
| } |
| } |