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