1 /* 2 * Copyright (C) 2009 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 17 package android.webkit.cts; 18 19 import dalvik.annotation.BrokenTest; 20 import dalvik.annotation.TestLevel; 21 import dalvik.annotation.TestTargetClass; 22 import dalvik.annotation.TestTargetNew; 23 import dalvik.annotation.TestTargets; 24 import dalvik.annotation.ToBeFixed; 25 26 import android.content.Context; 27 import android.content.res.AssetManager; 28 import android.graphics.Bitmap; 29 import android.graphics.BitmapFactory; 30 import android.graphics.Canvas; 31 import android.graphics.Color; 32 import android.graphics.Picture; 33 import android.graphics.Rect; 34 import android.graphics.Bitmap.Config; 35 import android.net.http.SslCertificate; 36 import android.net.http.SslError; 37 import android.os.Bundle; 38 import android.os.Handler; 39 import android.os.Looper; 40 import android.os.Message; 41 import android.test.ActivityInstrumentationTestCase2; 42 import android.test.UiThreadTest; 43 import android.util.AttributeSet; 44 import android.util.DisplayMetrics; 45 import android.view.KeyEvent; 46 import android.view.MotionEvent; 47 import android.view.View; 48 import android.view.animation.cts.DelayedCheck; 49 import android.webkit.CacheManager; 50 import android.webkit.DownloadListener; 51 import android.webkit.SslErrorHandler; 52 import android.webkit.WebBackForwardList; 53 import android.webkit.WebChromeClient; 54 import android.webkit.WebSettings; 55 import android.webkit.WebView; 56 import android.webkit.WebViewClient; 57 import android.webkit.WebViewDatabase; 58 import android.webkit.WebView.HitTestResult; 59 import android.webkit.WebView.PictureListener; 60 import android.widget.AutoCompleteTextView; 61 import android.widget.LinearLayout; 62 63 import java.io.File; 64 import java.io.FileInputStream; 65 66 @TestTargetClass(android.webkit.WebView.class) 67 public class WebViewTest extends ActivityInstrumentationTestCase2<WebViewStubActivity> { 68 private static final int INITIAL_PROGRESS = 100; 69 private static long TEST_TIMEOUT = 20000L; 70 private static long TIME_FOR_LAYOUT = 1000L; 71 72 private WebView mWebView; 73 private CtsTestServer mWebServer; 74 75 public WebViewTest() { 76 super("com.android.cts.stub", WebViewStubActivity.class); 77 } 78 79 @Override 80 protected void setUp() throws Exception { 81 super.setUp(); 82 mWebView = getActivity().getWebView(); 83 File f = getActivity().getFileStreamPath("snapshot"); 84 if (f.exists()) { 85 f.delete(); 86 } 87 } 88 89 @Override 90 protected void tearDown() throws Exception { 91 mWebView.clearHistory(); 92 mWebView.clearCache(true); 93 if (mWebServer != null) { 94 mWebServer.shutdown(); 95 } 96 super.tearDown(); 97 } 98 99 private void startWebServer(boolean secure) throws Exception { 100 assertNull(mWebServer); 101 mWebServer = new CtsTestServer(getActivity(), secure); 102 } 103 104 @TestTargets({ 105 @TestTargetNew( 106 level = TestLevel.COMPLETE, 107 method = "WebView", 108 args = {Context.class} 109 ), 110 @TestTargetNew( 111 level = TestLevel.COMPLETE, 112 method = "WebView", 113 args = {Context.class, AttributeSet.class} 114 ), 115 @TestTargetNew( 116 level = TestLevel.COMPLETE, 117 method = "WebView", 118 args = {Context.class, AttributeSet.class, int.class} 119 ) 120 }) 121 public void testConstructor() { 122 new WebView(getActivity()); 123 new WebView(getActivity(), null); 124 new WebView(getActivity(), null, 0); 125 } 126 127 @TestTargetNew( 128 level = TestLevel.COMPLETE, 129 method = "findAddress", 130 args = {String.class} 131 ) 132 public void testFindAddress() { 133 /* 134 * Info about USPS 135 * http://en.wikipedia.org/wiki/Postal_address#United_States 136 * http://www.usps.com/ 137 */ 138 // full address 139 assertEquals("455 LARKSPUR DRIVE CALIFORNIA SPRINGS CALIFORNIA 92926", 140 WebView.findAddress("455 LARKSPUR DRIVE CALIFORNIA SPRINGS CALIFORNIA 92926")); 141 // full address ( with abbreviated street type and state) 142 assertEquals("455 LARKSPUR DR CALIFORNIA SPRINGS CA 92926", 143 WebView.findAddress("455 LARKSPUR DR CALIFORNIA SPRINGS CA 92926")); 144 // misspell the state ( CALIFORNIA -> CALIFONIA ) 145 assertNull(WebView.findAddress("455 LARKSPUR DRIVE CALIFORNIA SPRINGS CALIFONIA 92926")); 146 // without optional zip code 147 assertEquals("455 LARKSPUR DR CALIFORNIA SPRINGS CA", 148 WebView.findAddress("455 LARKSPUR DR CALIFORNIA SPRINGS CA")); 149 // house number, street name and street type are missing 150 assertNull(WebView.findAddress("CALIFORNIA SPRINGS CA")); 151 // city & state are missing 152 assertNull(WebView.findAddress("455 LARKSPUR DR")); 153 } 154 155 @TestTargets({ 156 @TestTargetNew( 157 level = TestLevel.SUFFICIENT, 158 method = "getZoomControls", 159 args = {} 160 ), 161 @TestTargetNew( 162 level = TestLevel.COMPLETE, 163 method = "getSettings", 164 args = {} 165 ) 166 }) 167 @SuppressWarnings("deprecation") 168 @UiThreadTest 169 public void testGetZoomControls() { 170 WebSettings settings = mWebView.getSettings(); 171 assertTrue(settings.supportZoom()); 172 View zoomControls = mWebView.getZoomControls(); 173 assertNotNull(zoomControls); 174 175 // disable zoom support 176 settings.setSupportZoom(false); 177 assertFalse(settings.supportZoom()); 178 assertNull(mWebView.getZoomControls()); 179 } 180 181 @TestTargetNew( 182 level = TestLevel.SUFFICIENT, 183 method = "invokeZoomPicker", 184 args = {}, 185 notes = "Cannot test the effect of this method" 186 ) 187 public void testInvokeZoomPicker() throws Exception { 188 WebSettings settings = mWebView.getSettings(); 189 assertTrue(settings.supportZoom()); 190 startWebServer(false); 191 String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 192 assertLoadUrlSuccessfully(mWebView, url); 193 mWebView.invokeZoomPicker(); 194 } 195 196 @TestTargets({ 197 @TestTargetNew( 198 level = TestLevel.COMPLETE, 199 method = "zoomIn", 200 args = {} 201 ), 202 @TestTargetNew( 203 level = TestLevel.COMPLETE, 204 method = "zoomOut", 205 args = {} 206 ), 207 @TestTargetNew( 208 level = TestLevel.COMPLETE, 209 method = "getScale", 210 args = {} 211 ), 212 @TestTargetNew( 213 level = TestLevel.COMPLETE, 214 method = "getSettings", 215 args = {} 216 ) 217 }) 218 @UiThreadTest 219 public void testZoom() { 220 WebSettings settings = mWebView.getSettings(); 221 settings.setSupportZoom(false); 222 assertFalse(settings.supportZoom()); 223 float currScale = mWebView.getScale(); 224 float previousScale = currScale; 225 226 // can zoom in or out although zoom support is disabled in web settings 227 assertTrue(mWebView.zoomIn()); 228 currScale = mWebView.getScale(); 229 assertTrue(currScale > previousScale); 230 231 // zoom in 232 assertTrue(mWebView.zoomOut()); 233 previousScale = currScale; 234 currScale = mWebView.getScale(); 235 assertTrue(currScale < previousScale); 236 237 // enable zoom support 238 settings.setSupportZoom(true); 239 assertTrue(settings.supportZoom()); 240 currScale = mWebView.getScale(); 241 242 assertTrue(mWebView.zoomIn()); 243 previousScale = currScale; 244 currScale = mWebView.getScale(); 245 assertTrue(currScale > previousScale); 246 247 // zoom in until it reaches maximum scale 248 while (currScale > previousScale) { 249 mWebView.zoomIn(); 250 previousScale = currScale; 251 currScale = mWebView.getScale(); 252 } 253 254 // can not zoom in further 255 assertFalse(mWebView.zoomIn()); 256 previousScale = currScale; 257 currScale = mWebView.getScale(); 258 assertEquals(currScale, previousScale); 259 260 // zoom out 261 assertTrue(mWebView.zoomOut()); 262 previousScale = currScale; 263 currScale = mWebView.getScale(); 264 assertTrue(currScale < previousScale); 265 266 // zoom out until it reaches minimum scale 267 while (currScale < previousScale) { 268 mWebView.zoomOut(); 269 previousScale = currScale; 270 currScale = mWebView.getScale(); 271 } 272 273 // can not zoom out further 274 assertFalse(mWebView.zoomOut()); 275 previousScale = currScale; 276 currScale = mWebView.getScale(); 277 assertEquals(currScale, previousScale); 278 } 279 280 @TestTargets({ 281 @TestTargetNew( 282 level = TestLevel.COMPLETE, 283 method = "setScrollBarStyle", 284 args = {int.class} 285 ), 286 @TestTargetNew( 287 level = TestLevel.COMPLETE, 288 method = "overlayHorizontalScrollbar", 289 args = {} 290 ), 291 @TestTargetNew( 292 level = TestLevel.COMPLETE, 293 method = "overlayVerticalScrollbar", 294 args = {} 295 ) 296 }) 297 @UiThreadTest 298 public void testSetScrollBarStyle() { 299 mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET); 300 assertFalse(mWebView.overlayHorizontalScrollbar()); 301 assertFalse(mWebView.overlayVerticalScrollbar()); 302 303 mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); 304 assertTrue(mWebView.overlayHorizontalScrollbar()); 305 assertTrue(mWebView.overlayVerticalScrollbar()); 306 307 mWebView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_INSET); 308 assertFalse(mWebView.overlayHorizontalScrollbar()); 309 assertFalse(mWebView.overlayVerticalScrollbar()); 310 311 mWebView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY); 312 assertTrue(mWebView.overlayHorizontalScrollbar()); 313 assertTrue(mWebView.overlayVerticalScrollbar()); 314 } 315 316 @TestTargets({ 317 @TestTargetNew( 318 level = TestLevel.COMPLETE, 319 method = "setHorizontalScrollbarOverlay", 320 args = {boolean.class} 321 ), 322 @TestTargetNew( 323 level = TestLevel.COMPLETE, 324 method = "setVerticalScrollbarOverlay", 325 args = {boolean.class} 326 ), 327 @TestTargetNew( 328 level = TestLevel.COMPLETE, 329 method = "overlayHorizontalScrollbar", 330 args = {} 331 ), 332 @TestTargetNew( 333 level = TestLevel.COMPLETE, 334 method = "overlayVerticalScrollbar", 335 args = {} 336 ) 337 }) 338 public void testScrollBarOverlay() throws Throwable { 339 DisplayMetrics metrics = mWebView.getContext().getResources().getDisplayMetrics(); 340 int dimension = 2 * Math.max(metrics.widthPixels, metrics.heightPixels); 341 342 String p = "<p style=\"height:" + dimension + "px;" + 343 "width:" + dimension + "px;margin:0px auto;\">Test scroll bar overlay.</p>"; 344 mWebView.loadData("<html><body>" + p + "</body></html>", "text/html", "UTF-8"); 345 waitForLoadComplete(mWebView, TEST_TIMEOUT); 346 assertTrue(mWebView.overlayHorizontalScrollbar()); 347 assertFalse(mWebView.overlayVerticalScrollbar()); 348 int startX = mWebView.getScrollX(); 349 int startY = mWebView.getScrollY(); 350 351 final int bigVelocity = 10000; 352 // fling to the max and wait for ending scroll 353 runTestOnUiThread(new Runnable() { 354 public void run() { 355 mWebView.flingScroll(bigVelocity, bigVelocity); 356 } 357 }); 358 getInstrumentation().waitForIdleSync(); 359 360 int overlayOffsetX = mWebView.getScrollX() - startX; 361 int insetOffsetY = mWebView.getScrollY() - startY; 362 363 // scroll back 364 runTestOnUiThread(new Runnable() { 365 public void run() { 366 mWebView.flingScroll(-bigVelocity, -bigVelocity); 367 } 368 }); 369 getInstrumentation().waitForIdleSync(); 370 371 mWebView.setHorizontalScrollbarOverlay(false); 372 mWebView.setVerticalScrollbarOverlay(true); 373 assertFalse(mWebView.overlayHorizontalScrollbar()); 374 assertTrue(mWebView.overlayVerticalScrollbar()); 375 376 // fling to the max and wait for ending scroll 377 runTestOnUiThread(new Runnable() { 378 public void run() { 379 mWebView.flingScroll(bigVelocity, bigVelocity); 380 } 381 }); 382 getInstrumentation().waitForIdleSync(); 383 384 int insetOffsetX = mWebView.getScrollX() - startX; 385 int overlayOffsetY = mWebView.getScrollY() - startY; 386 387 assertTrue(overlayOffsetY > insetOffsetY); 388 assertTrue(overlayOffsetX > insetOffsetX); 389 } 390 391 @TestTargets({ 392 @TestTargetNew( 393 level = TestLevel.COMPLETE, 394 method = "loadUrl", 395 args = {String.class} 396 ), 397 @TestTargetNew( 398 level = TestLevel.COMPLETE, 399 method = "getUrl", 400 args = {} 401 ), 402 @TestTargetNew( 403 level = TestLevel.COMPLETE, 404 method = "getOriginalUrl", 405 args = {} 406 ), 407 @TestTargetNew( 408 level = TestLevel.COMPLETE, 409 method = "getProgress", 410 args = {} 411 ) 412 }) 413 public void testLoadUrl() throws Exception { 414 assertNull(mWebView.getUrl()); 415 assertNull(mWebView.getOriginalUrl()); 416 assertEquals(INITIAL_PROGRESS, mWebView.getProgress()); 417 418 startWebServer(false); 419 String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 420 mWebView.loadUrl(url); 421 waitForLoadComplete(mWebView, TEST_TIMEOUT); 422 assertEquals(100, mWebView.getProgress()); 423 assertEquals(url, mWebView.getUrl()); 424 assertEquals(url, mWebView.getOriginalUrl()); 425 assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mWebView.getTitle()); 426 } 427 428 @TestTargets({ 429 @TestTargetNew( 430 level = TestLevel.COMPLETE, 431 method = "getUrl", 432 args = {} 433 ), 434 @TestTargetNew( 435 level = TestLevel.COMPLETE, 436 method = "getOriginalUrl", 437 args = {} 438 ) 439 }) 440 public void testGetOriginalUrl() throws Exception { 441 assertNull(mWebView.getUrl()); 442 assertNull(mWebView.getOriginalUrl()); 443 444 startWebServer(false); 445 String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 446 String redirect = mWebServer.getRedirectingAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 447 // set the web view client so that redirects are loaded in the WebView itself 448 mWebView.setWebViewClient(new WebViewClient()); 449 mWebView.loadUrl(redirect); 450 451 waitForLoadComplete(mWebView, TEST_TIMEOUT); 452 assertEquals(url, mWebView.getUrl()); 453 assertEquals(redirect, mWebView.getOriginalUrl()); 454 } 455 456 @TestTargetNew( 457 level = TestLevel.COMPLETE, 458 method = "stopLoading", 459 args = {} 460 ) 461 public void testStopLoading() throws Exception { 462 assertNull(mWebView.getUrl()); 463 assertEquals(INITIAL_PROGRESS, mWebView.getProgress()); 464 465 startWebServer(false); 466 String url = mWebServer.getDelayedAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 467 mWebView.loadUrl(url); 468 mWebView.stopLoading(); 469 new DelayedCheck() { 470 @Override 471 protected boolean check() { 472 return 100 == mWebView.getProgress(); 473 } 474 }.run(); 475 assertNull(mWebView.getUrl()); 476 } 477 478 @TestTargets({ 479 @TestTargetNew( 480 level = TestLevel.COMPLETE, 481 method = "canGoBack", 482 args = {} 483 ), 484 @TestTargetNew( 485 level = TestLevel.COMPLETE, 486 method = "canGoForward", 487 args = {} 488 ), 489 @TestTargetNew( 490 level = TestLevel.COMPLETE, 491 method = "canGoBackOrForward", 492 args = {int.class} 493 ), 494 @TestTargetNew( 495 level = TestLevel.COMPLETE, 496 method = "goBack", 497 args = {} 498 ), 499 @TestTargetNew( 500 level = TestLevel.COMPLETE, 501 method = "goForward", 502 args = {} 503 ), 504 @TestTargetNew( 505 level = TestLevel.COMPLETE, 506 method = "goBackOrForward", 507 args = {int.class} 508 ) 509 }) 510 public void testGoBackAndForward() throws Exception { 511 assertGoBackOrForwardBySteps(false, -1); 512 assertGoBackOrForwardBySteps(false, 1); 513 514 startWebServer(false); 515 String url1 = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL1); 516 String url2 = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL2); 517 String url3 = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL3); 518 519 assertLoadUrlSuccessfully(mWebView, url1); 520 delayedCheckWebBackForwardList(url1, 0, 1); 521 assertGoBackOrForwardBySteps(false, -1); 522 assertGoBackOrForwardBySteps(false, 1); 523 524 assertLoadUrlSuccessfully(mWebView, url2); 525 delayedCheckWebBackForwardList(url2, 1, 2); 526 assertGoBackOrForwardBySteps(true, -1); 527 assertGoBackOrForwardBySteps(false, 1); 528 529 assertLoadUrlSuccessfully(mWebView, url3); 530 delayedCheckWebBackForwardList(url3, 2, 3); 531 assertGoBackOrForwardBySteps(true, -2); 532 assertGoBackOrForwardBySteps(false, 1); 533 534 mWebView.goBack(); 535 delayedCheckWebBackForwardList(url2, 1, 3); 536 assertGoBackOrForwardBySteps(true, -1); 537 assertGoBackOrForwardBySteps(true, 1); 538 539 mWebView.goForward(); 540 delayedCheckWebBackForwardList(url3, 2, 3); 541 assertGoBackOrForwardBySteps(true, -2); 542 assertGoBackOrForwardBySteps(false, 1); 543 544 mWebView.goBackOrForward(-2); 545 delayedCheckWebBackForwardList(url1, 0, 3); 546 assertGoBackOrForwardBySteps(false, -1); 547 assertGoBackOrForwardBySteps(true, 2); 548 549 mWebView.goBackOrForward(2); 550 delayedCheckWebBackForwardList(url3, 2, 3); 551 assertGoBackOrForwardBySteps(true, -2); 552 assertGoBackOrForwardBySteps(false, 1); 553 } 554 555 @TestTargetNew( 556 level = TestLevel.COMPLETE, 557 method = "addJavascriptInterface", 558 args = {Object.class, String.class} 559 ) 560 public void testAddJavascriptInterface() throws Exception { 561 WebSettings settings = mWebView.getSettings(); 562 settings.setJavaScriptEnabled(true); 563 settings.setJavaScriptCanOpenWindowsAutomatically(true); 564 565 final DummyJavaScriptInterface obj = new DummyJavaScriptInterface(); 566 mWebView.addJavascriptInterface(obj, "dummy"); 567 assertFalse(obj.hasChangedTitle()); 568 569 startWebServer(false); 570 String url = mWebServer.getAssetUrl(TestHtmlConstants.ADD_JAVA_SCRIPT_INTERFACE_URL); 571 assertLoadUrlSuccessfully(mWebView, url); 572 new DelayedCheck() { 573 @Override 574 protected boolean check() { 575 return obj.hasChangedTitle(); 576 } 577 }.run(); 578 } 579 580 @TestTargets({ 581 @TestTargetNew( 582 level = TestLevel.COMPLETE, 583 method = "setBackgroundColor", 584 args = {int.class} 585 ), 586 @TestTargetNew( 587 level = TestLevel.COMPLETE, 588 method = "capturePicture", 589 args = {} 590 ), 591 @TestTargetNew( 592 level = TestLevel.COMPLETE, 593 method = "reload", 594 args = {} 595 ) 596 }) 597 public void testCapturePicture() throws Exception { 598 startWebServer(false); 599 String url = mWebServer.getAssetUrl(TestHtmlConstants.BLANK_PAGE_URL); 600 // showing the blank page will make the picture filled with background color 601 assertLoadUrlSuccessfully(mWebView, url); 602 Picture p = mWebView.capturePicture(); 603 Bitmap b = Bitmap.createBitmap(p.getWidth(), p.getHeight(), Config.ARGB_8888); 604 p.draw(new Canvas(b)); 605 // default color is white 606 assertBitmapFillWithColor(b, Color.WHITE); 607 608 mWebView.setBackgroundColor(Color.CYAN); 609 mWebView.reload(); 610 waitForLoadComplete(mWebView, TEST_TIMEOUT); 611 // the content of the picture will not be updated automatically 612 p.draw(new Canvas(b)); 613 assertBitmapFillWithColor(b, Color.WHITE); 614 // update the content 615 p = mWebView.capturePicture(); 616 p.draw(new Canvas(b)); 617 assertBitmapFillWithColor(b, Color.CYAN); 618 } 619 620 @TestTargetNew( 621 level = TestLevel.COMPLETE, 622 method = "setPictureListener", 623 args = {PictureListener.class} 624 ) 625 public void testSetPictureListener() throws Exception { 626 final MyPictureListener listener = new MyPictureListener(); 627 mWebView.setPictureListener(listener); 628 startWebServer(false); 629 String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 630 assertLoadUrlSuccessfully(mWebView, url); 631 new DelayedCheck(TEST_TIMEOUT) { 632 protected boolean check() { 633 return listener.callCount > 0; 634 } 635 }.run(); 636 assertEquals(mWebView, listener.webView); 637 assertNotNull(listener.picture); 638 639 final int oldCallCount = listener.callCount; 640 url = mWebServer.getAssetUrl(TestHtmlConstants.SMALL_IMG_URL); 641 assertLoadUrlSuccessfully(mWebView, url); 642 new DelayedCheck(TEST_TIMEOUT) { 643 protected boolean check() { 644 return listener.callCount > oldCallCount; 645 } 646 }.run(); 647 } 648 649 @TestTargets({ 650 @TestTargetNew( 651 level = TestLevel.COMPLETE, 652 method = "savePicture", 653 args = {Bundle.class, File.class} 654 ), 655 @TestTargetNew( 656 level = TestLevel.SUFFICIENT, 657 notes = "Cannot test whether picture has been restored correctly.", 658 method = "restorePicture", 659 args = {Bundle.class, File.class} 660 ), 661 @TestTargetNew( 662 level = TestLevel.COMPLETE, 663 method = "reload", 664 args = {} 665 ) 666 }) 667 public void testSaveAndRestorePicture() throws Throwable { 668 mWebView.setBackgroundColor(Color.CYAN); 669 startWebServer(false); 670 String url = mWebServer.getAssetUrl(TestHtmlConstants.BLANK_PAGE_URL); 671 assertLoadUrlSuccessfully(mWebView, url); 672 673 final Bundle bundle = new Bundle(); 674 final File f = getActivity().getFileStreamPath("snapshot"); 675 if (f.exists()) { 676 f.delete(); 677 } 678 679 try { 680 assertTrue(bundle.isEmpty()); 681 assertEquals(0, f.length()); 682 assertTrue(mWebView.savePicture(bundle, f)); 683 684 // File saving is done in a separate thread. 685 new DelayedCheck() { 686 @Override 687 protected boolean check() { 688 return f.length() > 0; 689 } 690 }.run(); 691 692 assertFalse(bundle.isEmpty()); 693 694 Picture p = Picture.createFromStream(new FileInputStream(f)); 695 Bitmap b = Bitmap.createBitmap(p.getWidth(), p.getHeight(), Config.ARGB_8888); 696 p.draw(new Canvas(b)); 697 assertBitmapFillWithColor(b, Color.CYAN); 698 699 mWebView.setBackgroundColor(Color.WHITE); 700 mWebView.reload(); 701 waitForLoadComplete(mWebView, TEST_TIMEOUT); 702 703 b = Bitmap.createBitmap(mWebView.getWidth(), mWebView.getHeight(), Config.ARGB_8888); 704 mWebView.draw(new Canvas(b)); 705 assertBitmapFillWithColor(b, Color.WHITE); 706 runTestOnUiThread(new Runnable() { 707 public void run() { 708 assertTrue(mWebView.restorePicture(bundle, f)); 709 } 710 }); 711 getInstrumentation().waitForIdleSync(); 712 // Cannot test whether the picture has been restored successfully. 713 // Drawing the webview into a canvas will draw white, but on the display it is cyan 714 } finally { 715 if (f.exists()) { 716 f.delete(); 717 } 718 } 719 } 720 721 @TestTargets({ 722 @TestTargetNew( 723 level = TestLevel.COMPLETE, 724 method = "setHttpAuthUsernamePassword", 725 args = {String.class, String.class, String.class, String.class} 726 ), 727 @TestTargetNew( 728 level = TestLevel.COMPLETE, 729 method = "getHttpAuthUsernamePassword", 730 args = {String.class, String.class} 731 ) 732 }) 733 public void testAccessHttpAuthUsernamePassword() { 734 try { 735 WebViewDatabase.getInstance(getActivity()).clearHttpAuthUsernamePassword(); 736 737 String host = "http://localhost:8080"; 738 String realm = "testrealm"; 739 String userName = "user"; 740 String password = "password"; 741 742 String[] result = mWebView.getHttpAuthUsernamePassword(host, realm); 743 assertNull(result); 744 745 mWebView.setHttpAuthUsernamePassword(host, realm, userName, password); 746 result = mWebView.getHttpAuthUsernamePassword(host, realm); 747 assertNotNull(result); 748 assertEquals(userName, result[0]); 749 assertEquals(password, result[1]); 750 751 String newPassword = "newpassword"; 752 mWebView.setHttpAuthUsernamePassword(host, realm, userName, newPassword); 753 result = mWebView.getHttpAuthUsernamePassword(host, realm); 754 assertNotNull(result); 755 assertEquals(userName, result[0]); 756 assertEquals(newPassword, result[1]); 757 758 String newUserName = "newuser"; 759 mWebView.setHttpAuthUsernamePassword(host, realm, newUserName, newPassword); 760 result = mWebView.getHttpAuthUsernamePassword(host, realm); 761 assertNotNull(result); 762 assertEquals(newUserName, result[0]); 763 assertEquals(newPassword, result[1]); 764 765 // the user is set to null, can not change any thing in the future 766 mWebView.setHttpAuthUsernamePassword(host, realm, null, password); 767 result = mWebView.getHttpAuthUsernamePassword(host, realm); 768 assertNotNull(result); 769 assertNull(result[0]); 770 assertEquals(password, result[1]); 771 772 mWebView.setHttpAuthUsernamePassword(host, realm, userName, null); 773 result = mWebView.getHttpAuthUsernamePassword(host, realm); 774 assertNotNull(result); 775 assertEquals(userName, result[0]); 776 assertEquals(null, result[1]); 777 778 mWebView.setHttpAuthUsernamePassword(host, realm, null, null); 779 result = mWebView.getHttpAuthUsernamePassword(host, realm); 780 assertNotNull(result); 781 assertNull(result[0]); 782 assertNull(result[1]); 783 784 mWebView.setHttpAuthUsernamePassword(host, realm, newUserName, newPassword); 785 result = mWebView.getHttpAuthUsernamePassword(host, realm); 786 assertNotNull(result); 787 assertEquals(newUserName, result[0]); 788 assertEquals(newPassword, result[1]); 789 } finally { 790 WebViewDatabase.getInstance(getActivity()).clearHttpAuthUsernamePassword(); 791 } 792 } 793 794 @TestTargetNew( 795 level = TestLevel.COMPLETE, 796 method = "savePassword", 797 args = {String.class, String.class, String.class} 798 ) 799 public void testSavePassword() { 800 WebViewDatabase db = WebViewDatabase.getInstance(getActivity()); 801 try { 802 db.clearUsernamePassword(); 803 804 String host = "http://localhost:8080"; 805 String userName = "user"; 806 String password = "password"; 807 assertFalse(db.hasUsernamePassword()); 808 mWebView.savePassword(host, userName, password); 809 assertTrue(db.hasUsernamePassword()); 810 } finally { 811 db.clearUsernamePassword(); 812 } 813 } 814 815 @TestTargets({ 816 @TestTargetNew( 817 level = TestLevel.COMPLETE, 818 method = "loadData", 819 args = {String.class, String.class, String.class} 820 ), 821 @TestTargetNew( 822 level = TestLevel.COMPLETE, 823 method = "getTitle", 824 args = {} 825 ), 826 @TestTargetNew( 827 level = TestLevel.COMPLETE, 828 method = "capturePicture", 829 args = {} 830 ), 831 @TestTargetNew( 832 level = TestLevel.COMPLETE, 833 method = "capturePicture", 834 args = {} 835 ) 836 }) 837 public void testLoadData() throws Exception { 838 assertNull(mWebView.getTitle()); 839 mWebView.loadData("<html><head><title>Hello,World!</title></head><body></body></html>", 840 "text/html", "UTF-8"); 841 waitForLoadComplete(mWebView, TEST_TIMEOUT); 842 assertEquals("Hello,World!", mWebView.getTitle()); 843 844 startWebServer(false); 845 String imgUrl = mWebServer.getAssetUrl(TestHtmlConstants.SMALL_IMG_URL); 846 mWebView.loadData("<html><body><img src=\"" + imgUrl + "\"/></body></html>", 847 "text/html", "UTF-8"); 848 waitForLoadComplete(mWebView, TEST_TIMEOUT); 849 850 AssetManager assets = getActivity().getAssets(); 851 Bitmap b1 = BitmapFactory.decodeStream(assets.open(TestHtmlConstants.SMALL_IMG_URL)); 852 b1 = b1.copy(Config.ARGB_8888, true); 853 854 Picture p = mWebView.capturePicture(); 855 Bitmap b2 = Bitmap.createBitmap(p.getWidth(), p.getHeight(), Config.ARGB_8888); 856 p.draw(new Canvas(b2)); 857 assertTrue(checkBitmapInsideAnother(b1, b2)); 858 } 859 860 @TestTargets({ 861 @TestTargetNew( 862 level = TestLevel.COMPLETE, 863 method = "loadDataWithBaseURL", 864 args = {String.class, String.class, String.class, String.class, String.class} 865 ), 866 @TestTargetNew( 867 level = TestLevel.COMPLETE, 868 method = "getTitle", 869 args = {} 870 ), 871 @TestTargetNew( 872 level = TestLevel.COMPLETE, 873 method = "getUrl", 874 args = {} 875 ) 876 }) 877 public void testLoadDataWithBaseUrl() throws Exception { 878 assertNull(mWebView.getTitle()); 879 assertNull(mWebView.getUrl()); 880 String imgUrl = TestHtmlConstants.SMALL_IMG_URL; // relative 881 882 startWebServer(false); 883 String baseUrl = mWebServer.getAssetUrl("foo.html"); 884 String failUrl = "random"; 885 mWebView.loadDataWithBaseURL(baseUrl, 886 "<html><body><img src=\"" + imgUrl + "\"/></body></html>", 887 "text/html", "UTF-8", failUrl); 888 waitForLoadComplete(mWebView, TEST_TIMEOUT); 889 // check that image was retrieved from the server 890 assertTrue(mWebServer.getLastRequestUrl().endsWith(imgUrl)); 891 // the fail URL is used for the history entry, even if the load succeeds 892 assertEquals(failUrl, mWebView.getUrl()); 893 894 imgUrl = TestHtmlConstants.LARGE_IMG_URL; 895 mWebView.loadDataWithBaseURL(baseUrl, 896 "<html><body><img src=\"" + imgUrl + "\"/></body></html>", 897 "text/html", "UTF-8", null); 898 waitForLoadComplete(mWebView, TEST_TIMEOUT); 899 // check that image was retrieved from the server 900 assertTrue(mWebServer.getLastRequestUrl().endsWith(imgUrl)); 901 // no history item saved, URL is still the last one 902 assertEquals("about:blank", mWebView.getUrl()); 903 } 904 905 @TestTargetNew( 906 level = TestLevel.SUFFICIENT, 907 method = "findAll", 908 args = {String.class}, 909 notes = "Cannot check highlighting" 910 ) 911 public void testFindAll() throws Throwable { 912 getActivity().runOnUiThread(new Runnable() { 913 public void run() { 914 String p = "<p>Find all instances of find on the page and highlight them.</p>"; 915 916 mWebView.loadData("<html><body>" + p +"</body></html>", "text/html", "UTF-8"); 917 } 918 }); 919 waitForLoadComplete(mWebView, TEST_TIMEOUT); 920 921 runTestOnUiThread(new Runnable() { 922 public void run() { 923 assertEquals(2, mWebView.findAll("find")); 924 } 925 }); 926 } 927 928 @TestTargets({ 929 @TestTargetNew( 930 level = TestLevel.COMPLETE, 931 method = "findNext", 932 args = {boolean.class} 933 ), 934 @TestTargetNew( 935 level = TestLevel.COMPLETE, 936 method = "findAll", 937 args = {String.class} 938 ), 939 @TestTargetNew( 940 level = TestLevel.COMPLETE, 941 method = "clearMatches", 942 args = {} 943 ) 944 }) 945 public void testFindNext() throws Throwable { 946 // Reset the scaling so that finding the next "all" text will require scrolling. 947 mWebView.setInitialScale(100); 948 949 DisplayMetrics metrics = mWebView.getContext().getResources().getDisplayMetrics(); 950 int dimension = Math.max(metrics.widthPixels, metrics.heightPixels); 951 // create a paragraph high enough to take up the entire screen 952 String p = "<p style=\"height:" + dimension + "px;\">" + 953 "Find all instances of a word on the page and highlight them.</p>"; 954 955 mWebView.loadData("<html><body>" + p + p + "</body></html>", "text/html", "UTF-8"); 956 waitForLoadComplete(mWebView, TEST_TIMEOUT); 957 958 // highlight all the strings found 959 runTestOnUiThread(new Runnable() { 960 public void run() { 961 mWebView.findAll("all"); 962 } 963 }); 964 getInstrumentation().waitForIdleSync(); 965 int previousScrollY = mWebView.getScrollY(); 966 967 // Can not use @UiThreadTest here as we need wait in other thread until the scroll in UI 968 // thread finishes 969 findNextOnUiThread(true); 970 delayedCheckStopScrolling(); 971 // assert that the view scrolls and focuses "all" in the second page 972 assertTrue(mWebView.getScrollY() > previousScrollY); 973 previousScrollY = mWebView.getScrollY(); 974 975 findNextOnUiThread(true); 976 delayedCheckStopScrolling(); 977 // assert that the view scrolls and focuses "all" in the first page 978 assertTrue(mWebView.getScrollY() < previousScrollY); 979 previousScrollY = mWebView.getScrollY(); 980 981 findNextOnUiThread(false); 982 delayedCheckStopScrolling(); 983 // assert that the view scrolls and focuses "all" in the second page 984 assertTrue(mWebView.getScrollY() > previousScrollY); 985 previousScrollY = mWebView.getScrollY(); 986 987 findNextOnUiThread(false); 988 delayedCheckStopScrolling(); 989 // assert that the view scrolls and focuses "all" in the first page 990 assertTrue(mWebView.getScrollY() < previousScrollY); 991 previousScrollY = mWebView.getScrollY(); 992 993 // clear the result 994 runTestOnUiThread(new Runnable() { 995 public void run() { 996 mWebView.clearMatches(); 997 } 998 }); 999 getInstrumentation().waitForIdleSync(); 1000 1001 // can not scroll any more 1002 findNextOnUiThread(false); 1003 delayedCheckStopScrolling(); 1004 assertTrue(mWebView.getScrollY() == previousScrollY); 1005 1006 findNextOnUiThread(true); 1007 delayedCheckStopScrolling(); 1008 1009 assertTrue(mWebView.getScrollY() == previousScrollY); 1010 } 1011 1012 @TestTargetNew( 1013 level = TestLevel.COMPLETE, 1014 method = "documentHasImages", 1015 args = {android.os.Message.class} 1016 ) 1017 public void testDocumentHasImages() throws Exception { 1018 startWebServer(false); 1019 String imgUrl = mWebServer.getAssetUrl(TestHtmlConstants.SMALL_IMG_URL); 1020 mWebView.loadData("<html><body><img src=\"" + imgUrl + "\"/></body></html>", 1021 "text/html", "UTF-8"); 1022 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1023 1024 // create the handler in other thread 1025 final DocumentHasImageCheckHandler handler = 1026 new DocumentHasImageCheckHandler(mWebView.getHandler().getLooper()); 1027 Message response = new Message(); 1028 response.setTarget(handler); 1029 assertFalse(handler.hasCalledHandleMessage()); 1030 mWebView.documentHasImages(response); 1031 new DelayedCheck() { 1032 @Override 1033 protected boolean check() { 1034 return handler.hasCalledHandleMessage(); 1035 } 1036 }.run(); 1037 assertEquals(1, handler.getMsgArg1()); 1038 } 1039 1040 @TestTargets({ 1041 @TestTargetNew( 1042 level = TestLevel.COMPLETE, 1043 method = "pageDown", 1044 args = {boolean.class} 1045 ), 1046 @TestTargetNew( 1047 level = TestLevel.COMPLETE, 1048 method = "pageUp", 1049 args = {boolean.class} 1050 ) 1051 }) 1052 public void testPageScroll() throws Throwable { 1053 DisplayMetrics metrics = mWebView.getContext().getResources().getDisplayMetrics(); 1054 int dimension = 2 * Math.max(metrics.widthPixels, metrics.heightPixels); 1055 String p = "<p style=\"height:" + dimension + "px;\">" + 1056 "Scroll by half the size of the page.</p>"; 1057 mWebView.loadData("<html><body>" + p + p + "</body></html>", "text/html", "UTF-8"); 1058 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1059 1060 assertTrue(pageDownOnUiThread(false)); 1061 1062 // scroll to the bottom 1063 while (pageDownOnUiThread(false)) { 1064 // do nothing 1065 } 1066 assertFalse(pageDownOnUiThread(false)); 1067 int bottomScrollY = mWebView.getScrollY(); 1068 1069 assertTrue(pageUpOnUiThread(false)); 1070 1071 // scroll to the top 1072 while (pageUpOnUiThread(false)) { 1073 // do nothing 1074 } 1075 assertFalse(pageUpOnUiThread(false)); 1076 int topScrollY = mWebView.getScrollY(); 1077 1078 // jump to the bottom 1079 assertTrue(pageDownOnUiThread(true)); 1080 assertEquals(bottomScrollY, mWebView.getScrollY()); 1081 1082 // jump to the top 1083 assertTrue(pageUpOnUiThread(true)); 1084 assertEquals(topScrollY, mWebView.getScrollY()); 1085 } 1086 1087 @TestTargetNew( 1088 level = TestLevel.COMPLETE, 1089 method = "getContentHeight", 1090 args = {} 1091 ) 1092 public void testGetContentHeight() throws InterruptedException { 1093 mWebView.loadData("<html><body></body></html>", "text/html", "UTF-8"); 1094 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1095 assertEquals(mWebView.getHeight(), mWebView.getContentHeight() * mWebView.getScale(), 2f); 1096 1097 final int pageHeight = 600; 1098 // set the margin to 0 1099 String p = "<p style=\"height:" + pageHeight + "px;margin:0px auto;\">Get the height of " 1100 + "HTML content.</p>"; 1101 mWebView.loadData("<html><body>" + p + "</body></html>", "text/html", "UTF-8"); 1102 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1103 assertTrue(mWebView.getContentHeight() > pageHeight); 1104 int extraSpace = mWebView.getContentHeight() - pageHeight; 1105 1106 mWebView.loadData("<html><body>" + p + p + "</body></html>", "text/html", "UTF-8"); 1107 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1108 assertEquals(pageHeight + pageHeight + extraSpace, mWebView.getContentHeight()); 1109 } 1110 1111 @TestTargetNew( 1112 level = TestLevel.SUFFICIENT, 1113 notes = "Cannot test whether the view is cleared.", 1114 method = "clearView", 1115 args = {} 1116 ) 1117 public void testClearView() throws Throwable { 1118 startWebServer(false); 1119 String imgUrl = mWebServer.getAssetUrl(TestHtmlConstants.SMALL_IMG_URL); 1120 mWebView.loadData("<html><body><img src=\"" + imgUrl + "\"/></body></html>", 1121 "text/html", "UTF-8"); 1122 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1123 1124 AssetManager assets = getActivity().getAssets(); 1125 Bitmap b1 = BitmapFactory.decodeStream(assets.open(TestHtmlConstants.SMALL_IMG_URL)); 1126 b1 = b1.copy(Config.ARGB_8888, true); 1127 1128 Picture p = mWebView.capturePicture(); 1129 Bitmap b2 = Bitmap.createBitmap(p.getWidth(), p.getHeight(), Config.ARGB_8888); 1130 p.draw(new Canvas(b2)); 1131 // the image is painted 1132 assertTrue(checkBitmapInsideAnother(b1, b2)); 1133 1134 mWebView.clearView(); 1135 runTestOnUiThread(new Runnable() { 1136 public void run() { 1137 mWebView.invalidate(); 1138 } 1139 }); 1140 getInstrumentation().waitForIdleSync(); 1141 // Can not check whether method clearView() take effect by automatic testing: 1142 // 1. Can not use getMeasuredHeight() and getMeasuredWidth() to 1143 // check that the onMeasure() returns 0 1144 // 2. Can not use capturePicture() to check that the content has been cleared. 1145 // The result of capturePicture() is not updated after clearView() is called. 1146 } 1147 1148 @TestTargetNew( 1149 level = TestLevel.SUFFICIENT, 1150 method = "clearCache", 1151 args = {boolean.class} 1152 ) 1153 public void testClearCache() throws Exception { 1154 final File cacheFileBaseDir = CacheManager.getCacheFileBaseDir(); 1155 mWebView.clearCache(true); 1156 assertEquals(0, cacheFileBaseDir.list().length); 1157 1158 startWebServer(false); 1159 mWebView.loadUrl(mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL)); 1160 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1161 int cacheFileCount = cacheFileBaseDir.list().length; 1162 assertTrue(cacheFileCount > 0); 1163 1164 mWebView.clearCache(false); 1165 // the cache files are still there 1166 // can not check other effects of the method 1167 assertEquals(cacheFileCount, cacheFileBaseDir.list().length); 1168 1169 mWebView.clearCache(true); 1170 // check the files are deleted 1171 new DelayedCheck(TEST_TIMEOUT) { 1172 @Override 1173 protected boolean check() { 1174 return cacheFileBaseDir.list().length == 0; 1175 } 1176 }.run(); 1177 } 1178 1179 @TestTargets({ 1180 @TestTargetNew( 1181 level = TestLevel.SUFFICIENT, 1182 method = "enablePlatformNotifications", 1183 args = {}, 1184 notes = "Cannot simulate data state or proxy changes" 1185 ), 1186 @TestTargetNew( 1187 level = TestLevel.SUFFICIENT, 1188 method = "disablePlatformNotifications", 1189 args = {}, 1190 notes = "Cannot simulate data state or proxy changes" 1191 ) 1192 }) 1193 public void testPlatformNotifications() { 1194 WebView.enablePlatformNotifications(); 1195 WebView.disablePlatformNotifications(); 1196 } 1197 1198 @TestTargets({ 1199 @TestTargetNew( 1200 level = TestLevel.SUFFICIENT, 1201 method = "getPluginList", 1202 args = {} 1203 ), 1204 @TestTargetNew( 1205 level = TestLevel.SUFFICIENT, 1206 method = "refreshPlugins", 1207 args = {boolean.class} 1208 ) 1209 }) 1210 public void testAccessPluginList() { 1211 assertNotNull(WebView.getPluginList()); 1212 1213 // can not find a way to install plugins 1214 mWebView.refreshPlugins(false); 1215 } 1216 1217 @TestTargetNew( 1218 level = TestLevel.SUFFICIENT, 1219 method = "destroy", 1220 args = {} 1221 ) 1222 public void testDestroy() { 1223 // Create a new WebView, since we cannot call destroy() on a view in the hierarchy 1224 WebView localWebView = new WebView(getActivity()); 1225 localWebView.destroy(); 1226 } 1227 1228 @TestTargetNew( 1229 level = TestLevel.COMPLETE, 1230 method = "flingScroll", 1231 args = {int.class, int.class} 1232 ) 1233 public void testFlingScroll() throws Throwable { 1234 DisplayMetrics metrics = mWebView.getContext().getResources().getDisplayMetrics(); 1235 int dimension = 2 * Math.max(metrics.widthPixels, metrics.heightPixels); 1236 String p = "<p style=\"height:" + dimension + "px;" + 1237 "width:" + dimension + "px\">Test fling scroll.</p>"; 1238 mWebView.loadData("<html><body>" + p + "</body></html>", "text/html", "UTF-8"); 1239 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1240 1241 int previousScrollX = mWebView.getScrollX(); 1242 int previousScrollY = mWebView.getScrollY(); 1243 runTestOnUiThread(new Runnable() { 1244 public void run() { 1245 mWebView.flingScroll(100, 100); 1246 } 1247 }); 1248 1249 int timeSlice = 500; 1250 Thread.sleep(timeSlice); 1251 assertTrue(mWebView.getScrollX() > previousScrollX); 1252 assertTrue(mWebView.getScrollY() > previousScrollY); 1253 1254 previousScrollY = mWebView.getScrollY(); 1255 previousScrollX = mWebView.getScrollX(); 1256 Thread.sleep(timeSlice); 1257 assertTrue(mWebView.getScrollX() >= previousScrollX); 1258 assertTrue(mWebView.getScrollY() >= previousScrollY); 1259 1260 previousScrollY = mWebView.getScrollY(); 1261 previousScrollX = mWebView.getScrollX(); 1262 Thread.sleep(timeSlice); 1263 assertTrue(mWebView.getScrollX() >= previousScrollX); 1264 assertTrue(mWebView.getScrollY() >= previousScrollY); 1265 } 1266 1267 @TestTargetNew( 1268 level = TestLevel.COMPLETE, 1269 method = "requestFocusNodeHref", 1270 args = {android.os.Message.class} 1271 ) 1272 public void testRequestFocusNodeHref() throws InterruptedException { 1273 String links = "<DL><p><DT><A HREF=\"" + TestHtmlConstants.HTML_URL1 1274 + "\">HTML_URL1</A><DT><A HREF=\"" + TestHtmlConstants.HTML_URL2 1275 + "\">HTML_URL2</A></DL><p>"; 1276 mWebView.loadData("<html><body>" + links + "</body></html>", "text/html", "UTF-8"); 1277 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1278 1279 final HrefCheckHandler handler = new HrefCheckHandler(mWebView.getHandler().getLooper()); 1280 Message hrefMsg = new Message(); 1281 hrefMsg.setTarget(handler); 1282 1283 // focus on first link 1284 handler.reset(); 1285 getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN); 1286 mWebView.requestFocusNodeHref(hrefMsg); 1287 new DelayedCheck() { 1288 @Override 1289 protected boolean check() { 1290 return handler.hasCalledHandleMessage(); 1291 } 1292 }.run(); 1293 assertEquals(TestHtmlConstants.HTML_URL1, handler.getResultUrl()); 1294 1295 // focus on second link 1296 handler.reset(); 1297 hrefMsg = new Message(); 1298 hrefMsg.setTarget(handler); 1299 getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN); 1300 mWebView.requestFocusNodeHref(hrefMsg); 1301 new DelayedCheck() { 1302 @Override 1303 protected boolean check() { 1304 return handler.hasCalledHandleMessage(); 1305 } 1306 }.run(); 1307 assertEquals(TestHtmlConstants.HTML_URL2, handler.getResultUrl()); 1308 1309 mWebView.requestFocusNodeHref(null); 1310 } 1311 1312 @TestTargetNew( 1313 level = TestLevel.COMPLETE, 1314 method = "requestImageRef", 1315 args = {android.os.Message.class} 1316 ) 1317 public void testRequestImageRef() throws Exception { 1318 AssetManager assets = getActivity().getAssets(); 1319 Bitmap bitmap = BitmapFactory.decodeStream(assets.open(TestHtmlConstants.LARGE_IMG_URL)); 1320 int imgWidth = bitmap.getWidth(); 1321 int imgHeight = bitmap.getHeight(); 1322 1323 startWebServer(false); 1324 String imgUrl = mWebServer.getAssetUrl(TestHtmlConstants.LARGE_IMG_URL); 1325 mWebView.loadData("<html><title>Title</title><body><img src=\"" + imgUrl 1326 + "\"/></body></html>", "text/html", "UTF-8"); 1327 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1328 1329 final HrefCheckHandler handler = new HrefCheckHandler(mWebView.getHandler().getLooper()); 1330 Message msg = new Message(); 1331 msg.setTarget(handler); 1332 1333 // touch the image 1334 handler.reset(); 1335 int[] location = new int[2]; 1336 mWebView.getLocationOnScreen(location); 1337 getInstrumentation().sendPointerSync( 1338 MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 1339 location[0] + imgWidth / 2, 1340 location[1] + imgHeight / 2, 0)); 1341 mWebView.requestImageRef(msg); 1342 new DelayedCheck() { 1343 @Override 1344 protected boolean check() { 1345 return handler.hasCalledHandleMessage(); 1346 } 1347 }.run(); 1348 assertEquals(imgUrl, handler.mResultUrl); 1349 } 1350 1351 @TestTargetNew( 1352 level = TestLevel.SUFFICIENT, 1353 method = "debugDump", 1354 args = {} 1355 ) 1356 public void testDebugDump() { 1357 mWebView.debugDump(); 1358 } 1359 1360 @TestTargetNew( 1361 level = TestLevel.COMPLETE, 1362 method = "getHitTestResult", 1363 args = {} 1364 ) 1365 public void testGetHitTestResult() throws Throwable { 1366 String anchor = "<p><a href=\"" + TestHtmlConstants.EXT_WEB_URL1 1367 + "\">normal anchor</a></p>"; 1368 String blankAnchor = "<p><a href=\"\">blank anchor</a></p>"; 1369 String form = "<p><form><input type=\"text\" name=\"Test\"><br>" 1370 + "<input type=\"submit\" value=\"Submit\"></form></p>"; 1371 String phoneNo = "3106984000"; 1372 String tel = "<p><a href=\"tel:" + phoneNo + "\">Phone</a></p>"; 1373 String email = "test (at) gmail.com"; 1374 String mailto = "<p><a href=\"mailto:" + email + "\">Email</a></p>"; 1375 String location = "shanghai"; 1376 String geo = "<p><a href=\"geo:0,0?q=" + location + "\">Location</a></p>"; 1377 mWebView.loadDataWithBaseURL("fake://home", "<html><body>" + anchor + blankAnchor + form 1378 + tel + mailto + geo + "</body></html>", "text/html", "UTF-8", null); 1379 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1380 1381 // anchor 1382 moveFocusDown(); 1383 HitTestResult result = mWebView.getHitTestResult(); 1384 assertEquals(HitTestResult.SRC_ANCHOR_TYPE, result.getType()); 1385 assertEquals(TestHtmlConstants.EXT_WEB_URL1, result.getExtra()); 1386 1387 // blank anchor 1388 moveFocusDown(); 1389 result = mWebView.getHitTestResult(); 1390 assertEquals(HitTestResult.SRC_ANCHOR_TYPE, result.getType()); 1391 assertEquals("fake://home", result.getExtra()); 1392 1393 // text field 1394 moveFocusDown(); 1395 result = mWebView.getHitTestResult(); 1396 assertEquals(HitTestResult.EDIT_TEXT_TYPE, result.getType()); 1397 assertNull(result.getExtra()); 1398 1399 // submit button 1400 moveFocusDown(); 1401 result = mWebView.getHitTestResult(); 1402 assertEquals(HitTestResult.UNKNOWN_TYPE, result.getType()); 1403 assertNull(result.getExtra()); 1404 1405 // phone number 1406 moveFocusDown(); 1407 result = mWebView.getHitTestResult(); 1408 assertEquals(HitTestResult.PHONE_TYPE, result.getType()); 1409 assertEquals(phoneNo, result.getExtra()); 1410 1411 // email 1412 moveFocusDown(); 1413 result = mWebView.getHitTestResult(); 1414 assertEquals(HitTestResult.EMAIL_TYPE, result.getType()); 1415 assertEquals(email, result.getExtra()); 1416 1417 // geo address 1418 moveFocusDown(); 1419 result = mWebView.getHitTestResult(); 1420 assertEquals(HitTestResult.GEO_TYPE, result.getType()); 1421 assertEquals(location, result.getExtra()); 1422 } 1423 1424 @TestTargetNew( 1425 level = TestLevel.COMPLETE, 1426 method = "setInitialScale", 1427 args = {int.class} 1428 ) 1429 public void testSetInitialScale() throws InterruptedException { 1430 String p = "<p style=\"height:1000px;width:1000px\">Test setInitialScale.</p>"; 1431 mWebView.loadData("<html><body>" + p + "</body></html>", "text/html", "UTF-8"); 1432 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1433 final float defaultScale = getInstrumentation().getTargetContext().getResources(). 1434 getDisplayMetrics().density; 1435 assertEquals(defaultScale, mWebView.getScale(), .01f); 1436 1437 mWebView.setInitialScale(0); 1438 // modify content to fool WebKit into re-loading 1439 mWebView.loadData("<html><body>" + p + "2" + "</body></html>", "text/html", "UTF-8"); 1440 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1441 assertEquals(defaultScale, mWebView.getScale(), .01f); 1442 1443 mWebView.setInitialScale(50); 1444 mWebView.loadData("<html><body>" + p + "3" + "</body></html>", "text/html", "UTF-8"); 1445 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1446 assertEquals(0.5f, mWebView.getScale(), .02f); 1447 1448 mWebView.setInitialScale(0); 1449 mWebView.loadData("<html><body>" + p + "4" + "</body></html>", "text/html", "UTF-8"); 1450 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1451 assertEquals(defaultScale, mWebView.getScale(), .01f); 1452 } 1453 1454 @TestTargetNew( 1455 level = TestLevel.SUFFICIENT, 1456 notes = "No API to trigger receiving an icon. Favicon not loaded automatically.", 1457 method = "getFavicon", 1458 args = {} 1459 ) 1460 @ToBeFixed(explanation = "Favicon is not loaded automatically.") 1461 public void testGetFavicon() throws Exception { 1462 startWebServer(false); 1463 String url = mWebServer.getAssetUrl(TestHtmlConstants.TEST_FAVICON_URL); 1464 assertLoadUrlSuccessfully(mWebView, url); 1465 mWebView.getFavicon(); 1466 // ToBeFixed: Favicon is not loaded automatically. 1467 // assertNotNull(mWebView.getFavicon()); 1468 } 1469 1470 @TestTargetNew( 1471 level = TestLevel.COMPLETE, 1472 method = "clearHistory", 1473 args = {} 1474 ) 1475 public void testClearHistory() throws Exception { 1476 startWebServer(false); 1477 String url1 = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL1); 1478 String url2 = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL2); 1479 String url3 = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL3); 1480 1481 assertLoadUrlSuccessfully(mWebView, url1); 1482 delayedCheckWebBackForwardList(url1, 0, 1); 1483 1484 assertLoadUrlSuccessfully(mWebView, url2); 1485 delayedCheckWebBackForwardList(url2, 1, 2); 1486 1487 assertLoadUrlSuccessfully(mWebView, url3); 1488 delayedCheckWebBackForwardList(url3, 2, 3); 1489 1490 mWebView.clearHistory(); 1491 1492 // only current URL is left after clearing 1493 delayedCheckWebBackForwardList(url3, 0, 1); 1494 } 1495 1496 @TestTargets({ 1497 @TestTargetNew( 1498 level = TestLevel.COMPLETE, 1499 method = "saveState", 1500 args = {Bundle.class} 1501 ), 1502 @TestTargetNew( 1503 level = TestLevel.COMPLETE, 1504 method = "restoreState", 1505 args = {Bundle.class} 1506 ), 1507 @TestTargetNew( 1508 level = TestLevel.COMPLETE, 1509 method = "copyBackForwardList", 1510 args = {} 1511 ) 1512 }) 1513 @ToBeFixed(explanation="Web history items do not get inflated after restore.") 1514 public void testSaveAndRestoreState() throws Throwable { 1515 // nothing to save 1516 assertNull(mWebView.saveState(new Bundle())); 1517 1518 startWebServer(false); 1519 String url1 = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL1); 1520 String url2 = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL2); 1521 String url3 = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL3); 1522 1523 // make a history list 1524 assertLoadUrlSuccessfully(mWebView, url1); 1525 delayedCheckWebBackForwardList(url1, 0, 1); 1526 assertLoadUrlSuccessfully(mWebView, url2); 1527 delayedCheckWebBackForwardList(url2, 1, 2); 1528 assertLoadUrlSuccessfully(mWebView, url3); 1529 delayedCheckWebBackForwardList(url3, 2, 3); 1530 1531 // save the list 1532 Bundle bundle = new Bundle(); 1533 WebBackForwardList saveList = mWebView.saveState(bundle); 1534 assertNotNull(saveList); 1535 assertEquals(3, saveList.getSize()); 1536 assertEquals(2, saveList.getCurrentIndex()); 1537 assertEquals(url1, saveList.getItemAtIndex(0).getUrl()); 1538 assertEquals(url2, saveList.getItemAtIndex(1).getUrl()); 1539 assertEquals(url3, saveList.getItemAtIndex(2).getUrl()); 1540 1541 // change the content to a new "blank" web view without history 1542 final WebView newWebView = new WebView(getActivity()); 1543 1544 WebBackForwardList copyListBeforeRestore = newWebView.copyBackForwardList(); 1545 assertNotNull(copyListBeforeRestore); 1546 assertEquals(0, copyListBeforeRestore.getSize()); 1547 1548 // restore the list 1549 final WebBackForwardList restoreList = newWebView.restoreState(bundle); 1550 assertNotNull(restoreList); 1551 assertEquals(3, restoreList.getSize()); 1552 assertEquals(2, saveList.getCurrentIndex()); 1553 /* ToBeFixed: The WebHistoryItems do not get inflated. Uncomment remaining tests when fixed. 1554 // wait for the list items to get inflated 1555 new DelayedCheck(TEST_TIMEOUT) { 1556 @Override 1557 protected boolean check() { 1558 return restoreList.getItemAtIndex(0).getUrl() != null && 1559 restoreList.getItemAtIndex(1).getUrl() != null && 1560 restoreList.getItemAtIndex(2).getUrl() != null; 1561 } 1562 }.run(); 1563 assertEquals(url1, restoreList.getItemAtIndex(0).getUrl()); 1564 assertEquals(url2, restoreList.getItemAtIndex(1).getUrl()); 1565 assertEquals(url3, restoreList.getItemAtIndex(2).getUrl()); 1566 1567 WebBackForwardList copyListAfterRestore = newWebView.copyBackForwardList(); 1568 assertNotNull(copyListAfterRestore); 1569 assertEquals(3, copyListAfterRestore.getSize()); 1570 assertEquals(2, copyListAfterRestore.getCurrentIndex()); 1571 assertEquals(url1, copyListAfterRestore.getItemAtIndex(0).getUrl()); 1572 assertEquals(url2, copyListAfterRestore.getItemAtIndex(1).getUrl()); 1573 assertEquals(url3, copyListAfterRestore.getItemAtIndex(2).getUrl()); 1574 */ 1575 } 1576 1577 @TestTargetNew( 1578 level = TestLevel.COMPLETE, 1579 method = "setWebViewClient", 1580 args = {WebViewClient.class} 1581 ) 1582 public void testSetWebViewClient() throws Throwable { 1583 final MockWebViewClient webViewClient = new MockWebViewClient(); 1584 mWebView.setWebViewClient(webViewClient); 1585 1586 assertFalse(webViewClient.onScaleChangedCalled()); 1587 runTestOnUiThread(new Runnable() { 1588 public void run() { 1589 mWebView.zoomIn(); 1590 } 1591 }); 1592 getInstrumentation().waitForIdleSync(); 1593 assertTrue(webViewClient.onScaleChangedCalled()); 1594 } 1595 1596 @TestTargets({ 1597 @TestTargetNew( 1598 level = TestLevel.COMPLETE, 1599 method = "setCertificate", 1600 args = {SslCertificate.class} 1601 ), 1602 @TestTargetNew( 1603 level = TestLevel.COMPLETE, 1604 method = "getCertificate", 1605 args = {} 1606 ) 1607 }) 1608 public void testAccessCertificate() throws Throwable { 1609 runTestOnUiThread(new Runnable() { 1610 public void run() { 1611 mWebView = new WebView(getActivity()); 1612 getActivity().setContentView(mWebView); 1613 } 1614 }); 1615 getInstrumentation().waitForIdleSync(); 1616 1617 // need the client to handle error 1618 mWebView.setWebViewClient(new MockWebViewClient()); 1619 1620 mWebView.setCertificate(null); 1621 startWebServer(true); 1622 String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 1623 // attempt to load the url. 1624 mWebView.loadUrl(url); 1625 new DelayedCheck(TEST_TIMEOUT) { 1626 @Override 1627 protected boolean check() { 1628 return mWebView.getCertificate() != null; 1629 } 1630 }.run(); 1631 SslCertificate cert = mWebView.getCertificate(); 1632 assertNotNull(cert); 1633 assertEquals("Android", cert.getIssuedTo().getUName()); 1634 } 1635 1636 @TestTargetNew( 1637 level = TestLevel.NOT_FEASIBLE, 1638 notes = "WebViewClient.onReceivedSslError() is hidden, cannot store SSL preferences.", 1639 method = "clearSslPreferences", 1640 args = {} 1641 ) 1642 public void testClearSslPreferences() { 1643 mWebView.clearSslPreferences(); 1644 } 1645 1646 @TestTargetNew( 1647 level = TestLevel.COMPLETE, 1648 method = "requestChildRectangleOnScreen", 1649 args = {View.class, Rect.class, boolean.class} 1650 ) 1651 public void testRequestChildRectangleOnScreen() throws Throwable { 1652 DisplayMetrics metrics = mWebView.getContext().getResources().getDisplayMetrics(); 1653 final int dimension = 2 * Math.max(metrics.widthPixels, metrics.heightPixels); 1654 String p = "<p style=\"height:" + dimension + "px;width:" + dimension + "px\"> </p>"; 1655 mWebView.loadData("<html><body>" + p + "</body></html>", "text/html", "UTF-8"); 1656 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1657 getInstrumentation().waitForIdleSync(); 1658 1659 runTestOnUiThread(new Runnable() { 1660 public void run() { 1661 int origX = mWebView.getScrollX(); 1662 int origY = mWebView.getScrollY(); 1663 1664 int half = dimension / 2; 1665 Rect rect = new Rect(half, half, half + 1, half + 1); 1666 assertTrue(mWebView.requestChildRectangleOnScreen(mWebView, rect, true)); 1667 assertTrue(mWebView.getScrollX() > origX); 1668 assertTrue(mWebView.getScrollY() > origY); 1669 } 1670 }); 1671 } 1672 1673 @TestTargets({ 1674 @TestTargetNew( 1675 level = TestLevel.COMPLETE, 1676 method = "setDownloadListener", 1677 args = {DownloadListener.class} 1678 ), 1679 @TestTargetNew( 1680 level = TestLevel.SUFFICIENT, 1681 method = "requestFocus", 1682 args = {int.class, Rect.class} 1683 ) 1684 }) 1685 @ToBeFixed(explanation="Mime type and content length passed to listener are incorrect.") 1686 public void testSetDownloadListener() throws Throwable { 1687 final String mimeType = "application/octet-stream"; 1688 final int length = 100; 1689 final MyDownloadListener listener = new MyDownloadListener(); 1690 1691 startWebServer(false); 1692 String url = mWebServer.getBinaryUrl(mimeType, length); 1693 mWebView.setWebViewClient(new WebViewClient()); 1694 mWebView.setDownloadListener(listener); 1695 mWebView.loadData("<html><body><a href=\"" + url + "\">link</a></body></html>", 1696 "text/html", "UTF-8"); 1697 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1698 // focus on the link 1699 runTestOnUiThread(new Runnable() { 1700 public void run() { 1701 assertTrue(mWebView.requestFocus(View.FOCUS_DOWN, null)); 1702 } 1703 }); 1704 getInstrumentation().waitForIdleSync(); 1705 getInstrumentation().sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER); 1706 new DelayedCheck(TEST_TIMEOUT) { 1707 @Override 1708 protected boolean check() { 1709 return listener.called; 1710 } 1711 }.run(); 1712 assertEquals(url, listener.url); 1713 assertTrue(listener.contentDisposition.contains("test.bin")); 1714 // ToBeFixed: uncomment the following tests after fixing the framework 1715 // assertEquals(mimeType, listener.mimeType); 1716 // assertEquals(length, listener.contentLength); 1717 } 1718 1719 @TestTargetNew( 1720 level = TestLevel.PARTIAL, 1721 method = "setLayoutParams", 1722 args = {android.view.ViewGroup.LayoutParams.class} 1723 ) 1724 @ToBeFixed(bug = "1695243", explanation = "the javadoc for setLayoutParams() is incomplete.") 1725 @UiThreadTest 1726 public void testSetLayoutParams() { 1727 LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(600, 800); 1728 mWebView.setLayoutParams(params); 1729 assertSame(params, mWebView.getLayoutParams()); 1730 } 1731 1732 @TestTargetNew( 1733 level = TestLevel.NOT_FEASIBLE, 1734 notes = "No documentation", 1735 method = "setMapTrackballToArrowKeys", 1736 args = {boolean.class} 1737 ) 1738 public void testSetMapTrackballToArrowKeys() { 1739 mWebView.setMapTrackballToArrowKeys(true); 1740 } 1741 1742 @TestTargetNew( 1743 level = TestLevel.COMPLETE, 1744 method = "setNetworkAvailable", 1745 args = {boolean.class} 1746 ) 1747 public void testSetNetworkAvailable() throws Exception { 1748 WebSettings settings = mWebView.getSettings(); 1749 settings.setJavaScriptEnabled(true); 1750 startWebServer(false); 1751 String url = mWebServer.getAssetUrl(TestHtmlConstants.NETWORK_STATE_URL); 1752 assertLoadUrlSuccessfully(mWebView, url); 1753 assertEquals("ONLINE", mWebView.getTitle()); 1754 1755 mWebView.setNetworkAvailable(false); 1756 mWebView.reload(); 1757 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1758 assertEquals("OFFLINE", mWebView.getTitle()); 1759 1760 mWebView.setNetworkAvailable(true); 1761 mWebView.reload(); 1762 waitForLoadComplete(mWebView, TEST_TIMEOUT); 1763 assertEquals("ONLINE", mWebView.getTitle()); 1764 } 1765 1766 @TestTargetNew( 1767 level = TestLevel.COMPLETE, 1768 method = "setWebChromeClient", 1769 args = {WebChromeClient.class} 1770 ) 1771 public void testSetWebChromeClient() throws Throwable { 1772 final MockWebChromeClient webChromeClient = new MockWebChromeClient(); 1773 mWebView.setWebChromeClient(webChromeClient); 1774 1775 assertFalse(webChromeClient.onProgressChangedCalled()); 1776 startWebServer(false); 1777 String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL); 1778 mWebView.loadUrl(url); 1779 1780 new DelayedCheck(TEST_TIMEOUT) { 1781 @Override 1782 protected boolean check() { 1783 return webChromeClient.onProgressChangedCalled(); 1784 } 1785 }.run(); 1786 } 1787 1788 @TestTargets({ 1789 @TestTargetNew( 1790 level = TestLevel.NOT_NECESSARY, 1791 method = "dispatchKeyEvent", 1792 args = {KeyEvent.class} 1793 ), 1794 @TestTargetNew( 1795 level = TestLevel.NOT_NECESSARY, 1796 method = "onAttachedToWindow", 1797 args = {} 1798 ), 1799 @TestTargetNew( 1800 level = TestLevel.NOT_NECESSARY, 1801 method = "onDetachedFromWindow", 1802 args = {} 1803 ), 1804 @TestTargetNew( 1805 level = TestLevel.NOT_NECESSARY, 1806 method = "onChildViewAdded", 1807 args = {View.class, View.class} 1808 ), 1809 @TestTargetNew( 1810 level = TestLevel.NOT_NECESSARY, 1811 method = "onChildViewRemoved", 1812 args = {View.class, View.class} 1813 ), 1814 @TestTargetNew( 1815 level = TestLevel.NOT_NECESSARY, 1816 method = "onDraw", 1817 args = {Canvas.class} 1818 ), 1819 @TestTargetNew( 1820 level = TestLevel.NOT_NECESSARY, 1821 method = "onFocusChanged", 1822 args = {boolean.class, int.class, Rect.class} 1823 ), 1824 @TestTargetNew( 1825 level = TestLevel.NOT_NECESSARY, 1826 method = "onGlobalFocusChanged", 1827 args = {View.class, View.class} 1828 ), 1829 @TestTargetNew( 1830 level = TestLevel.NOT_NECESSARY, 1831 method = "onKeyDown", 1832 args = {int.class, KeyEvent.class} 1833 ), 1834 @TestTargetNew( 1835 level = TestLevel.NOT_NECESSARY, 1836 method = "onKeyUp", 1837 args = {int.class, KeyEvent.class} 1838 ), 1839 @TestTargetNew( 1840 level = TestLevel.NOT_NECESSARY, 1841 method = "onMeasure", 1842 args = {int.class, int.class} 1843 ), 1844 @TestTargetNew( 1845 level = TestLevel.NOT_NECESSARY, 1846 method = "onScrollChanged", 1847 args = {int.class, int.class, int.class, int.class} 1848 ), 1849 @TestTargetNew( 1850 level = TestLevel.NOT_NECESSARY, 1851 method = "onSizeChanged", 1852 args = {int.class, int.class, int.class, int.class} 1853 ), 1854 @TestTargetNew( 1855 level = TestLevel.NOT_NECESSARY, 1856 method = "onTouchEvent", 1857 args = {MotionEvent.class} 1858 ), 1859 @TestTargetNew( 1860 level = TestLevel.NOT_NECESSARY, 1861 method = "onTrackballEvent", 1862 args = {MotionEvent.class} 1863 ), 1864 @TestTargetNew( 1865 level = TestLevel.NOT_NECESSARY, 1866 method = "onWindowFocusChanged", 1867 args = {boolean.class} 1868 ), 1869 @TestTargetNew( 1870 level = TestLevel.NOT_FEASIBLE, 1871 method = "computeScroll", 1872 args = {} 1873 ), 1874 @TestTargetNew( 1875 level = TestLevel.NOT_FEASIBLE, 1876 method = "computeHorizontalScrollRange", 1877 args = {} 1878 ), 1879 @TestTargetNew( 1880 level = TestLevel.NOT_FEASIBLE, 1881 method = "computeVerticalScrollRange", 1882 args = {} 1883 ) 1884 }) 1885 public void testInternals() { 1886 // Do not test these APIs. They are implementation details. 1887 } 1888 1889 private static class MockWebViewClient extends WebViewClient { 1890 private boolean mOnScaleChangedCalled = false; 1891 1892 public boolean onScaleChangedCalled() { 1893 return mOnScaleChangedCalled; 1894 } 1895 1896 @Override 1897 public void onScaleChanged(WebView view, float oldScale, float newScale) { 1898 super.onScaleChanged(view, oldScale, newScale); 1899 mOnScaleChangedCalled = true; 1900 } 1901 1902 @Override 1903 public void onReceivedSslError(WebView view, SslErrorHandler handler, 1904 SslError error) { 1905 handler.proceed(); 1906 } 1907 } 1908 1909 private static class MockWebChromeClient extends WebChromeClient { 1910 private boolean mOnProgressChanged = false; 1911 1912 public boolean onProgressChangedCalled() { 1913 return mOnProgressChanged; 1914 } 1915 1916 @Override 1917 public void onProgressChanged(WebView view, int newProgress) { 1918 super.onProgressChanged(view, newProgress); 1919 mOnProgressChanged = true; 1920 } 1921 } 1922 1923 private static class HrefCheckHandler extends Handler { 1924 private boolean mHadRecieved; 1925 1926 private String mResultUrl; 1927 1928 public HrefCheckHandler(Looper looper) { 1929 super(looper); 1930 } 1931 1932 public boolean hasCalledHandleMessage() { 1933 return mHadRecieved; 1934 } 1935 1936 public String getResultUrl() { 1937 return mResultUrl; 1938 } 1939 1940 public void reset(){ 1941 mResultUrl = null; 1942 mHadRecieved = false; 1943 } 1944 1945 @Override 1946 public void handleMessage(Message msg) { 1947 mHadRecieved = true; 1948 mResultUrl = msg.getData().getString("url"); 1949 } 1950 } 1951 1952 private static class DocumentHasImageCheckHandler extends Handler { 1953 private boolean mReceived; 1954 1955 private int mMsgArg1; 1956 1957 public DocumentHasImageCheckHandler(Looper looper) { 1958 super(looper); 1959 } 1960 1961 public boolean hasCalledHandleMessage() { 1962 return mReceived; 1963 } 1964 1965 public int getMsgArg1() { 1966 return mMsgArg1; 1967 } 1968 1969 public void reset(){ 1970 mMsgArg1 = -1; 1971 mReceived = false; 1972 } 1973 1974 @Override 1975 public void handleMessage(Message msg) { 1976 mReceived = true; 1977 mMsgArg1 = msg.arg1; 1978 } 1979 }; 1980 1981 private void findNextOnUiThread(final boolean forward) throws Throwable { 1982 runTestOnUiThread(new Runnable() { 1983 public void run() { 1984 mWebView.findNext(forward); 1985 } 1986 }); 1987 getInstrumentation().waitForIdleSync(); 1988 } 1989 1990 private void moveFocusDown() throws Throwable { 1991 // send down key and wait for idle 1992 sendKeys(KeyEvent.KEYCODE_DPAD_DOWN); 1993 // waiting for idle isn't always sufficient for the key to be fully processed 1994 Thread.sleep(500); 1995 } 1996 1997 private boolean pageDownOnUiThread(final boolean bottom) throws Throwable { 1998 PageDownRunner runner = new PageDownRunner(bottom); 1999 runTestOnUiThread(runner); 2000 getInstrumentation().waitForIdleSync(); 2001 return runner.mResult; 2002 } 2003 2004 private class PageDownRunner implements Runnable { 2005 private boolean mResult, mBottom; 2006 2007 public PageDownRunner(boolean bottom) { 2008 mBottom = bottom; 2009 } 2010 2011 public void run() { 2012 mResult = mWebView.pageDown(mBottom); 2013 } 2014 } 2015 2016 private boolean pageUpOnUiThread(final boolean top) throws Throwable { 2017 PageUpRunner runner = new PageUpRunner(top); 2018 runTestOnUiThread(runner); 2019 getInstrumentation().waitForIdleSync(); 2020 return runner.mResult; 2021 } 2022 2023 private class PageUpRunner implements Runnable { 2024 private boolean mResult, mTop; 2025 2026 public PageUpRunner(boolean top) { 2027 this.mTop = top; 2028 } 2029 2030 public void run() { 2031 mResult = mWebView.pageUp(mTop); 2032 } 2033 } 2034 2035 private void delayedCheckStopScrolling() { 2036 new DelayedCheck() { 2037 private int scrollY = mWebView.getScrollY(); 2038 2039 @Override 2040 protected boolean check() { 2041 if (scrollY == mWebView.getScrollY()){ 2042 return true; 2043 } else { 2044 scrollY = mWebView.getScrollY(); 2045 return false; 2046 } 2047 } 2048 }.run(); 2049 } 2050 2051 private void delayedCheckWebBackForwardList(final String currUrl, final int currIndex, 2052 final int size) { 2053 new DelayedCheck() { 2054 @Override 2055 protected boolean check() { 2056 WebBackForwardList list = mWebView.copyBackForwardList(); 2057 return checkWebBackForwardList(list, currUrl, currIndex, size); 2058 } 2059 }.run(); 2060 } 2061 2062 private boolean checkWebBackForwardList(WebBackForwardList list, String currUrl, 2063 int currIndex, int size) { 2064 return (list != null) 2065 && (list.getSize() == size) 2066 && (list.getCurrentIndex() == currIndex) 2067 && list.getItemAtIndex(currIndex).getUrl().equals(currUrl); 2068 } 2069 2070 private void assertGoBackOrForwardBySteps(boolean expected, int steps) { 2071 // skip if steps equals to 0 2072 if (steps == 0) 2073 return; 2074 2075 int start = steps > 0 ? 1 : steps; 2076 int end = steps > 0 ? steps : -1; 2077 2078 // check all the steps in the history 2079 for (int i = start; i <= end; i++) { 2080 assertEquals(expected, mWebView.canGoBackOrForward(i)); 2081 2082 // shortcut methods for one step 2083 if (i == 1) { 2084 assertEquals(expected, mWebView.canGoForward()); 2085 } else if (i == -1) { 2086 assertEquals(expected, mWebView.canGoBack()); 2087 } 2088 } 2089 } 2090 2091 private void assertBitmapFillWithColor(Bitmap bitmap, int color) { 2092 for (int i = 0; i < bitmap.getWidth(); i ++) 2093 for (int j = 0; j < bitmap.getHeight(); j ++) { 2094 assertEquals(color, bitmap.getPixel(i, j)); 2095 } 2096 } 2097 2098 // Find b1 inside b2 2099 private boolean checkBitmapInsideAnother(Bitmap b1, Bitmap b2) { 2100 int w = b1.getWidth(); 2101 int h = b1.getHeight(); 2102 2103 for (int i = 0; i < (b2.getWidth()-w+1); i++) { 2104 for (int j = 0; j < (b2.getHeight()-h+1); j++) { 2105 if (checkBitmapInsideAnother(b1, b2, i, j)) 2106 return true; 2107 } 2108 } 2109 return false; 2110 } 2111 2112 private boolean comparePixel(int p1, int p2, int maxError) { 2113 int err; 2114 err = Math.abs(((p1&0xff000000)>>>24) - ((p2&0xff000000)>>>24)); 2115 if (err > maxError) 2116 return false; 2117 2118 err = Math.abs(((p1&0x00ff0000)>>>16) - ((p2&0x00ff0000)>>>16)); 2119 if (err > maxError) 2120 return false; 2121 2122 err = Math.abs(((p1&0x0000ff00)>>>8) - ((p2&0x0000ff00)>>>8)); 2123 if (err > maxError) 2124 return false; 2125 2126 err = Math.abs(((p1&0x000000ff)>>>0) - ((p2&0x000000ff)>>>0)); 2127 if (err > maxError) 2128 return false; 2129 2130 return true; 2131 } 2132 2133 private boolean checkBitmapInsideAnother(Bitmap b1, Bitmap b2, int x, int y) { 2134 for (int i = 0; i < b1.getWidth(); i++) 2135 for (int j = 0; j < b1.getHeight(); j++) { 2136 if (!comparePixel(b1.getPixel(i, j), b2.getPixel(x + i, y + j), 10)) { 2137 return false; 2138 } 2139 } 2140 return true; 2141 } 2142 2143 private void assertLoadUrlSuccessfully(WebView webView, String url) 2144 throws InterruptedException { 2145 webView.loadUrl(url); 2146 waitForLoadComplete(webView, TEST_TIMEOUT); 2147 } 2148 2149 private void waitForLoadComplete(final WebView webView, long timeout) 2150 throws InterruptedException { 2151 new DelayedCheck(timeout) { 2152 @Override 2153 protected boolean check() { 2154 return webView.getProgress() == 100; 2155 } 2156 }.run(); 2157 Thread.sleep(TIME_FOR_LAYOUT); 2158 } 2159 2160 private final class DummyJavaScriptInterface { 2161 private boolean mTitleChanged; 2162 2163 private boolean hasChangedTitle() { 2164 return mTitleChanged; 2165 } 2166 2167 public void onLoad(String oldTitle) { 2168 mWebView.getHandler().post(new Runnable() { 2169 public void run() { 2170 mWebView.loadUrl("javascript:changeTitle(\"new title\")"); 2171 mTitleChanged = true; 2172 } 2173 }); 2174 } 2175 } 2176 2177 private final class MyDownloadListener implements DownloadListener { 2178 public String url; 2179 public String mimeType; 2180 public long contentLength; 2181 public String contentDisposition; 2182 public boolean called; 2183 2184 public void onDownloadStart(String url, String userAgent, String contentDisposition, 2185 String mimetype, long contentLength) { 2186 this.called = true; 2187 this.url = url; 2188 this.mimeType = mimetype; 2189 this.contentLength = contentLength; 2190 this.contentDisposition = contentDisposition; 2191 } 2192 } 2193 2194 private static class MyPictureListener implements PictureListener { 2195 public int callCount; 2196 public WebView webView; 2197 public Picture picture; 2198 2199 public void onNewPicture(WebView view, Picture picture) { 2200 this.callCount += 1; 2201 this.webView = view; 2202 this.picture = picture; 2203 } 2204 } 2205 } 2206