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