AwSettingsTest.java revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5package org.chromium.android_webview.test; 6 7import android.content.Context; 8import android.graphics.Point; 9import android.os.Build; 10import android.os.SystemClock; 11import android.test.suitebuilder.annotation.LargeTest; 12import android.test.suitebuilder.annotation.MediumTest; 13import android.test.suitebuilder.annotation.SmallTest; 14import android.util.Pair; 15import android.view.MotionEvent; 16import android.view.WindowManager; 17import android.webkit.WebSettings; 18 19import org.apache.http.Header; 20import org.apache.http.HttpRequest; 21import org.chromium.android_webview.AndroidProtocolHandler; 22import org.chromium.android_webview.AwContents; 23import org.chromium.android_webview.AwSettings.LayoutAlgorithm; 24import org.chromium.android_webview.AwSettings; 25import org.chromium.android_webview.InterceptedRequestData; 26import org.chromium.android_webview.test.util.CommonResources; 27import org.chromium.android_webview.test.util.ImagePageGenerator; 28import org.chromium.android_webview.test.util.JavascriptEventObserver; 29import org.chromium.android_webview.test.util.VideoTestWebServer; 30import org.chromium.base.test.util.DisabledTest; 31import org.chromium.base.test.util.Feature; 32import org.chromium.base.test.util.TestFileUtil; 33import org.chromium.base.test.util.UrlUtils; 34import org.chromium.content.browser.ContentViewCore; 35import org.chromium.content.browser.test.util.CallbackHelper; 36import org.chromium.content.browser.test.util.Criteria; 37import org.chromium.content.browser.test.util.CriteriaHelper; 38import org.chromium.content.browser.test.util.HistoryUtils; 39import org.chromium.net.test.util.TestWebServer; 40import org.chromium.ui.gfx.DeviceDisplayInfo; 41 42import java.util.concurrent.Callable; 43import java.util.concurrent.TimeUnit; 44import java.util.regex.Matcher; 45import java.util.regex.Pattern; 46import java.util.ArrayList; 47import java.util.List; 48 49/** 50 * A test suite for AwSettings class. The key objective is to verify that each 51 * settings applies either to each individual view or to all views of the 52 * application 53 */ 54public class AwSettingsTest extends AwTestBase { 55 private static final long TEST_TIMEOUT = 20000L; 56 private static final int CHECK_INTERVAL = 100; 57 58 private static final boolean ENABLED = true; 59 private static final boolean DISABLED = false; 60 61 /** 62 * A helper class for testing a particular preference from AwSettings. 63 * The generic type T is the type of the setting. Usually, to test an 64 * effect of the preference, JS code is executed that sets document's title. 65 * In this case, requiresJsEnabled constructor argument must be set to true. 66 */ 67 abstract class AwSettingsTestHelper<T> { 68 protected final AwContents mAwContents; 69 protected final TestAwContentsClient mContentViewClient; 70 protected final AwSettings mAwSettings; 71 72 AwSettingsTestHelper(AwContents awContents, 73 TestAwContentsClient contentViewClient, 74 boolean requiresJsEnabled) throws Throwable { 75 mAwContents = awContents; 76 mContentViewClient = contentViewClient; 77 mAwSettings = AwSettingsTest.this.getAwSettingsOnUiThread(awContents); 78 if (requiresJsEnabled) { 79 mAwSettings.setJavaScriptEnabled(true); 80 } 81 } 82 83 void ensureSettingHasAlteredValue() throws Throwable { 84 ensureSettingHasValue(getAlteredValue()); 85 } 86 87 void ensureSettingHasInitialValue() throws Throwable { 88 ensureSettingHasValue(getInitialValue()); 89 } 90 91 void setAlteredSettingValue() throws Throwable { 92 setCurrentValue(getAlteredValue()); 93 } 94 95 void setInitialSettingValue() throws Throwable { 96 setCurrentValue(getInitialValue()); 97 } 98 99 protected abstract T getAlteredValue(); 100 101 protected abstract T getInitialValue(); 102 103 protected abstract T getCurrentValue(); 104 105 protected abstract void setCurrentValue(T value) throws Throwable; 106 107 protected abstract void doEnsureSettingHasValue(T value) throws Throwable; 108 109 protected String getTitleOnUiThread() throws Throwable { 110 return AwSettingsTest.this.getTitleOnUiThread(mAwContents); 111 } 112 113 protected void loadDataSync(String data) throws Throwable { 114 AwSettingsTest.this.loadDataSync( 115 mAwContents, 116 mContentViewClient.getOnPageFinishedHelper(), 117 data, 118 "text/html", 119 false); 120 } 121 122 protected void loadUrlSync(String url) throws Throwable { 123 AwSettingsTest.this.loadUrlSync( 124 mAwContents, 125 mContentViewClient.getOnPageFinishedHelper(), 126 url); 127 } 128 129 protected void loadUrlSyncAndExpectError(String url) throws Throwable { 130 AwSettingsTest.this.loadUrlSyncAndExpectError( 131 mAwContents, 132 mContentViewClient.getOnPageFinishedHelper(), 133 mContentViewClient.getOnReceivedErrorHelper(), 134 url); 135 } 136 137 protected String executeJavaScriptAndWaitForResult(String script) throws Throwable { 138 return AwSettingsTest.this.executeJavaScriptAndWaitForResult( 139 mAwContents, mContentViewClient, script); 140 } 141 142 private void ensureSettingHasValue(T value) throws Throwable { 143 assertEquals(value, getCurrentValue()); 144 doEnsureSettingHasValue(value); 145 } 146 } 147 148 class AwSettingsJavaScriptTestHelper extends AwSettingsTestHelper<Boolean> { 149 private static final String JS_ENABLED_STRING = "JS Enabled"; 150 private static final String JS_DISABLED_STRING = "JS Disabled"; 151 152 AwSettingsJavaScriptTestHelper(AwContents awContents, 153 TestAwContentsClient contentViewClient) throws Throwable { 154 super(awContents, contentViewClient, false); 155 } 156 157 @Override 158 protected Boolean getAlteredValue() { 159 return ENABLED; 160 } 161 162 @Override 163 protected Boolean getInitialValue() { 164 return DISABLED; 165 } 166 167 @Override 168 protected Boolean getCurrentValue() { 169 return mAwSettings.getJavaScriptEnabled(); 170 } 171 172 @Override 173 protected void setCurrentValue(Boolean value) { 174 mAwSettings.setJavaScriptEnabled(value); 175 } 176 177 @Override 178 protected void doEnsureSettingHasValue(Boolean value) throws Throwable { 179 loadDataSync(getData()); 180 assertEquals( 181 value == ENABLED ? JS_ENABLED_STRING : JS_DISABLED_STRING, 182 getTitleOnUiThread()); 183 } 184 185 private String getData() { 186 return "<html><head><title>" + JS_DISABLED_STRING + "</title>" 187 + "</head><body onload=\"document.title='" + JS_ENABLED_STRING 188 + "';\"></body></html>"; 189 } 190 } 191 192 // In contrast to AwSettingsJavaScriptTestHelper, doesn't reload the page when testing 193 // JavaScript state. 194 class AwSettingsJavaScriptDynamicTestHelper extends AwSettingsJavaScriptTestHelper { 195 AwSettingsJavaScriptDynamicTestHelper( 196 AwContents awContents, 197 TestAwContentsClient contentViewClient) throws Throwable { 198 super(awContents, contentViewClient); 199 // Load the page. 200 super.doEnsureSettingHasValue(getInitialValue()); 201 } 202 203 @Override 204 protected void doEnsureSettingHasValue(Boolean value) throws Throwable { 205 String oldTitle = getTitleOnUiThread(); 206 String newTitle = oldTitle + "_modified"; 207 executeJavaScriptAndWaitForResult(getScript(newTitle)); 208 assertEquals(value == ENABLED ? newTitle : oldTitle, getTitleOnUiThread()); 209 } 210 211 private String getScript(String title) { 212 return "document.title='" + title + "';"; 213 } 214 } 215 216 class AwSettingsPluginsTestHelper extends AwSettingsTestHelper<Boolean> { 217 private static final String PLUGINS_ENABLED_STRING = "Embed"; 218 private static final String PLUGINS_DISABLED_STRING = "NoEmbed"; 219 220 AwSettingsPluginsTestHelper(AwContents awContents, 221 TestAwContentsClient contentViewClient) throws Throwable { 222 super(awContents, contentViewClient, true); 223 } 224 225 @Override 226 protected Boolean getAlteredValue() { 227 return ENABLED; 228 } 229 230 @Override 231 protected Boolean getInitialValue() { 232 return DISABLED; 233 } 234 235 @Override 236 protected Boolean getCurrentValue() { 237 return mAwSettings.getPluginsEnabled(); 238 } 239 240 @Override 241 protected void setCurrentValue(Boolean value) { 242 mAwSettings.setPluginsEnabled(value); 243 } 244 245 @Override 246 protected void doEnsureSettingHasValue(Boolean value) throws Throwable { 247 loadDataSync(getData()); 248 assertEquals( 249 value == ENABLED ? PLUGINS_ENABLED_STRING : PLUGINS_DISABLED_STRING, 250 getTitleOnUiThread()); 251 } 252 253 private String getData() { 254 return "<html><body onload=\"document.title = document.body.innerText;\">" 255 + "<noembed>No</noembed><span>Embed</span></body></html>"; 256 } 257 } 258 259 class AwSettingsStandardFontFamilyTestHelper extends AwSettingsTestHelper<String> { 260 AwSettingsStandardFontFamilyTestHelper( 261 AwContents awContents, 262 TestAwContentsClient contentViewClient) throws Throwable { 263 super(awContents, contentViewClient, true); 264 } 265 266 @Override 267 protected String getAlteredValue() { 268 return "cursive"; 269 } 270 271 @Override 272 protected String getInitialValue() { 273 return "sans-serif"; 274 } 275 276 @Override 277 protected String getCurrentValue() { 278 return mAwSettings.getStandardFontFamily(); 279 } 280 281 @Override 282 protected void setCurrentValue(String value) { 283 mAwSettings.setStandardFontFamily(value); 284 } 285 286 @Override 287 protected void doEnsureSettingHasValue(String value) throws Throwable { 288 loadDataSync(getData()); 289 assertEquals(value, getTitleOnUiThread()); 290 } 291 292 private String getData() { 293 return "<html><body onload=\"document.title = " + 294 "getComputedStyle(document.body).getPropertyValue('font-family');\">" 295 + "</body></html>"; 296 } 297 } 298 299 class AwSettingsDefaultFontSizeTestHelper extends AwSettingsTestHelper<Integer> { 300 AwSettingsDefaultFontSizeTestHelper( 301 AwContents awContents, 302 TestAwContentsClient contentViewClient) throws Throwable { 303 super(awContents, contentViewClient, true); 304 } 305 306 @Override 307 protected Integer getAlteredValue() { 308 return 42; 309 } 310 311 @Override 312 protected Integer getInitialValue() { 313 return 16; 314 } 315 316 @Override 317 protected Integer getCurrentValue() { 318 return mAwSettings.getDefaultFontSize(); 319 } 320 321 @Override 322 protected void setCurrentValue(Integer value) { 323 mAwSettings.setDefaultFontSize(value); 324 } 325 326 @Override 327 protected void doEnsureSettingHasValue(Integer value) throws Throwable { 328 loadDataSync(getData()); 329 assertEquals(value.toString() + "px", getTitleOnUiThread()); 330 } 331 332 private String getData() { 333 return "<html><body onload=\"document.title = " + 334 "getComputedStyle(document.body).getPropertyValue('font-size');\">" 335 + "</body></html>"; 336 } 337 } 338 339 class AwSettingsLoadImagesAutomaticallyTestHelper extends AwSettingsTestHelper<Boolean> { 340 private ImagePageGenerator mGenerator; 341 342 AwSettingsLoadImagesAutomaticallyTestHelper( 343 AwContents awContents, 344 TestAwContentsClient contentViewClient, 345 ImagePageGenerator generator) throws Throwable { 346 super(awContents, contentViewClient, true); 347 mGenerator = generator; 348 } 349 350 @Override 351 protected Boolean getAlteredValue() { 352 return DISABLED; 353 } 354 355 @Override 356 protected Boolean getInitialValue() { 357 return ENABLED; 358 } 359 360 @Override 361 protected Boolean getCurrentValue() { 362 return mAwSettings.getLoadsImagesAutomatically(); 363 } 364 365 @Override 366 protected void setCurrentValue(Boolean value) { 367 mAwSettings.setLoadsImagesAutomatically(value); 368 } 369 370 @Override 371 protected void doEnsureSettingHasValue(Boolean value) throws Throwable { 372 loadDataSync(mGenerator.getPageSource()); 373 assertEquals(value == ENABLED ? 374 ImagePageGenerator.IMAGE_LOADED_STRING : 375 ImagePageGenerator.IMAGE_NOT_LOADED_STRING, 376 getTitleOnUiThread()); 377 } 378 } 379 380 class AwSettingsDefaultTextEncodingTestHelper extends AwSettingsTestHelper<String> { 381 AwSettingsDefaultTextEncodingTestHelper( 382 AwContents awContents, 383 TestAwContentsClient contentViewClient) throws Throwable { 384 super(awContents, contentViewClient, true); 385 } 386 387 @Override 388 protected String getAlteredValue() { 389 return "utf-8"; 390 } 391 392 @Override 393 protected String getInitialValue() { 394 return "Latin-1"; 395 } 396 397 @Override 398 protected String getCurrentValue() { 399 return mAwSettings.getDefaultTextEncodingName(); 400 } 401 402 @Override 403 protected void setCurrentValue(String value) { 404 mAwSettings.setDefaultTextEncodingName(value); 405 } 406 407 @Override 408 protected void doEnsureSettingHasValue(String value) throws Throwable { 409 loadDataSync(getData()); 410 assertEquals(value, getTitleOnUiThread()); 411 } 412 413 private String getData() { 414 return "<html><body onload='document.title=document.defaultCharset'></body></html>"; 415 } 416 } 417 418 class AwSettingsUserAgentStringTestHelper extends AwSettingsTestHelper<String> { 419 private final String mDefaultUa; 420 private static final String DEFAULT_UA = ""; 421 private static final String CUSTOM_UA = "ChromeViewTest"; 422 423 AwSettingsUserAgentStringTestHelper( 424 AwContents awContents, 425 TestAwContentsClient contentViewClient) throws Throwable { 426 super(awContents, contentViewClient, true); 427 mDefaultUa = mAwSettings.getUserAgentString(); 428 } 429 430 @Override 431 protected String getAlteredValue() { 432 return CUSTOM_UA; 433 } 434 435 @Override 436 protected String getInitialValue() { 437 return DEFAULT_UA; 438 } 439 440 @Override 441 protected String getCurrentValue() { 442 // The test framework expects that getXXX() == Z after setXXX(Z). 443 // But setUserAgentString("" / null) resets the UA string to default, 444 // and getUserAgentString returns the default UA string afterwards. 445 // To align with the framework, we return an empty string instead of 446 // the default UA. 447 String currentUa = mAwSettings.getUserAgentString(); 448 return mDefaultUa.equals(currentUa) ? DEFAULT_UA : currentUa; 449 } 450 451 @Override 452 protected void setCurrentValue(String value) { 453 mAwSettings.setUserAgentString(value); 454 } 455 456 @Override 457 protected void doEnsureSettingHasValue(String value) throws Throwable { 458 loadDataSync(getData()); 459 assertEquals( 460 DEFAULT_UA.equals(value) ? mDefaultUa : value, 461 getTitleOnUiThread()); 462 } 463 464 private String getData() { 465 return "<html><body onload='document.title=navigator.userAgent'></body></html>"; 466 } 467 } 468 469 class AwSettingsDomStorageEnabledTestHelper extends AwSettingsTestHelper<Boolean> { 470 private static final String NO_LOCAL_STORAGE = "No localStorage"; 471 private static final String HAS_LOCAL_STORAGE = "Has localStorage"; 472 473 AwSettingsDomStorageEnabledTestHelper( 474 AwContents awContents, 475 TestAwContentsClient contentViewClient) throws Throwable { 476 super(awContents, contentViewClient, true); 477 } 478 479 @Override 480 protected Boolean getAlteredValue() { 481 return ENABLED; 482 } 483 484 @Override 485 protected Boolean getInitialValue() { 486 return DISABLED; 487 } 488 489 @Override 490 protected Boolean getCurrentValue() { 491 return mAwSettings.getDomStorageEnabled(); 492 } 493 494 @Override 495 protected void setCurrentValue(Boolean value) { 496 mAwSettings.setDomStorageEnabled(value); 497 } 498 499 @Override 500 protected void doEnsureSettingHasValue(Boolean value) throws Throwable { 501 // It is not permitted to access localStorage from data URLs in WebKit, 502 // that is why a standalone page must be used. 503 loadUrlSync(UrlUtils.getTestFileUrl("webview/localStorage.html")); 504 assertEquals( 505 value == ENABLED ? HAS_LOCAL_STORAGE : NO_LOCAL_STORAGE, 506 getTitleOnUiThread()); 507 } 508 } 509 510 class AwSettingsDatabaseTestHelper extends AwSettingsTestHelper<Boolean> { 511 private static final String NO_DATABASE = "No database"; 512 private static final String HAS_DATABASE = "Has database"; 513 514 AwSettingsDatabaseTestHelper( 515 AwContents awContents, 516 TestAwContentsClient contentViewClient) throws Throwable { 517 super(awContents, contentViewClient, true); 518 } 519 520 @Override 521 protected Boolean getAlteredValue() { 522 return ENABLED; 523 } 524 525 @Override 526 protected Boolean getInitialValue() { 527 return DISABLED; 528 } 529 530 @Override 531 protected Boolean getCurrentValue() { 532 return mAwSettings.getDatabaseEnabled(); 533 } 534 535 @Override 536 protected void setCurrentValue(Boolean value) { 537 mAwSettings.setDatabaseEnabled(value); 538 } 539 540 @Override 541 protected void doEnsureSettingHasValue(Boolean value) throws Throwable { 542 // It seems accessing the database through a data scheme is not 543 // supported, and fails with a DOM exception (likely a cross-domain 544 // violation). 545 loadUrlSync(UrlUtils.getTestFileUrl("webview/database_access.html")); 546 assertEquals( 547 value == ENABLED ? HAS_DATABASE : NO_DATABASE, 548 getTitleOnUiThread()); 549 } 550 } 551 552 class AwSettingsUniversalAccessFromFilesTestHelper extends AwSettingsTestHelper<Boolean> { 553 // TODO(mnaganov): Change to "Exception" once 554 // https://bugs.webkit.org/show_bug.cgi?id=43504 is fixed. 555 private static final String ACCESS_DENIED_TITLE = "undefined"; 556 557 AwSettingsUniversalAccessFromFilesTestHelper( 558 AwContents awContents, 559 TestAwContentsClient contentViewClient) throws Throwable { 560 super(awContents, contentViewClient, true); 561 mIframeContainerUrl = UrlUtils.getTestFileUrl("webview/iframe_access.html"); 562 mIframeUrl = UrlUtils.getTestFileUrl("webview/hello_world.html"); 563 // The value of the setting depends on the SDK version. 564 mAwSettings.setAllowUniversalAccessFromFileURLs(false); 565 // If universal access is true, the value of file access doesn't 566 // matter. While if universal access is false, having file access 567 // enabled will allow file loading. 568 mAwSettings.setAllowFileAccessFromFileURLs(false); 569 } 570 571 @Override 572 protected Boolean getAlteredValue() { 573 return ENABLED; 574 } 575 576 @Override 577 protected Boolean getInitialValue() { 578 return DISABLED; 579 } 580 581 @Override 582 protected Boolean getCurrentValue() { 583 return mAwSettings.getAllowUniversalAccessFromFileURLs(); 584 } 585 586 @Override 587 protected void setCurrentValue(Boolean value) { 588 mAwSettings.setAllowUniversalAccessFromFileURLs(value); 589 } 590 591 @Override 592 protected void doEnsureSettingHasValue(Boolean value) throws Throwable { 593 loadUrlSync(mIframeContainerUrl); 594 assertEquals( 595 value == ENABLED ? mIframeUrl : ACCESS_DENIED_TITLE, 596 getTitleOnUiThread()); 597 } 598 599 private final String mIframeContainerUrl; 600 private final String mIframeUrl; 601 } 602 603 class AwSettingsFileAccessFromFilesIframeTestHelper extends AwSettingsTestHelper<Boolean> { 604 // TODO(mnaganov): Change to "Exception" once 605 // https://bugs.webkit.org/show_bug.cgi?id=43504 is fixed. 606 private static final String ACCESS_DENIED_TITLE = "undefined"; 607 608 AwSettingsFileAccessFromFilesIframeTestHelper( 609 AwContents awContents, 610 TestAwContentsClient contentViewClient) throws Throwable { 611 super(awContents, contentViewClient, true); 612 mIframeContainerUrl = UrlUtils.getTestFileUrl("webview/iframe_access.html"); 613 mIframeUrl = UrlUtils.getTestFileUrl("webview/hello_world.html"); 614 mAwSettings.setAllowUniversalAccessFromFileURLs(false); 615 // The value of the setting depends on the SDK version. 616 mAwSettings.setAllowFileAccessFromFileURLs(false); 617 } 618 619 @Override 620 protected Boolean getAlteredValue() { 621 return ENABLED; 622 } 623 624 @Override 625 protected Boolean getInitialValue() { 626 return DISABLED; 627 } 628 629 @Override 630 protected Boolean getCurrentValue() { 631 return mAwSettings.getAllowFileAccessFromFileURLs(); 632 } 633 634 @Override 635 protected void setCurrentValue(Boolean value) { 636 mAwSettings.setAllowFileAccessFromFileURLs(value); 637 } 638 639 @Override 640 protected void doEnsureSettingHasValue(Boolean value) throws Throwable { 641 loadUrlSync(mIframeContainerUrl); 642 assertEquals( 643 value == ENABLED ? mIframeUrl : ACCESS_DENIED_TITLE, 644 getTitleOnUiThread()); 645 } 646 647 private final String mIframeContainerUrl; 648 private final String mIframeUrl; 649 } 650 651 class AwSettingsFileAccessFromFilesXhrTestHelper extends AwSettingsTestHelper<Boolean> { 652 private static final String ACCESS_GRANTED_TITLE = "Hello, World!"; 653 private static final String ACCESS_DENIED_TITLE = "Exception"; 654 655 AwSettingsFileAccessFromFilesXhrTestHelper( 656 AwContents awContents, 657 TestAwContentsClient contentViewClient) throws Throwable { 658 super(awContents, contentViewClient, true); 659 mXhrContainerUrl = UrlUtils.getTestFileUrl("webview/xhr_access.html"); 660 mAwSettings.setAllowUniversalAccessFromFileURLs(false); 661 // The value of the setting depends on the SDK version. 662 mAwSettings.setAllowFileAccessFromFileURLs(false); 663 } 664 665 @Override 666 protected Boolean getAlteredValue() { 667 return ENABLED; 668 } 669 670 @Override 671 protected Boolean getInitialValue() { 672 return DISABLED; 673 } 674 675 @Override 676 protected Boolean getCurrentValue() { 677 return mAwSettings.getAllowFileAccessFromFileURLs(); 678 } 679 680 @Override 681 protected void setCurrentValue(Boolean value) { 682 mAwSettings.setAllowFileAccessFromFileURLs(value); 683 } 684 685 @Override 686 protected void doEnsureSettingHasValue(Boolean value) throws Throwable { 687 loadUrlSync(mXhrContainerUrl); 688 assertEquals( 689 value == ENABLED ? ACCESS_GRANTED_TITLE : ACCESS_DENIED_TITLE, 690 getTitleOnUiThread()); 691 } 692 693 private final String mXhrContainerUrl; 694 } 695 696 class AwSettingsFileUrlAccessTestHelper extends AwSettingsTestHelper<Boolean> { 697 private static final String ACCESS_GRANTED_TITLE = "Hello, World!"; 698 699 AwSettingsFileUrlAccessTestHelper( 700 AwContents awContents, 701 TestAwContentsClient contentViewClient, 702 int startIndex) throws Throwable { 703 super(awContents, contentViewClient, true); 704 mIndex = startIndex; 705 } 706 707 @Override 708 protected Boolean getAlteredValue() { 709 return DISABLED; 710 } 711 712 @Override 713 protected Boolean getInitialValue() { 714 return ENABLED; 715 } 716 717 @Override 718 protected Boolean getCurrentValue() { 719 return mAwSettings.getAllowFileAccess(); 720 } 721 722 @Override 723 protected void setCurrentValue(Boolean value) { 724 mAwSettings.setAllowFileAccess(value); 725 } 726 727 @Override 728 protected void doEnsureSettingHasValue(Boolean value) throws Throwable { 729 // Use query parameters to avoid hitting a cached page. 730 String fileUrl = UrlUtils.getTestFileUrl("webview/hello_world.html?id=" + mIndex); 731 mIndex += 2; 732 if (value == ENABLED) { 733 loadUrlSync(fileUrl); 734 assertEquals(ACCESS_GRANTED_TITLE, getTitleOnUiThread()); 735 } else { 736 loadUrlSyncAndExpectError(fileUrl); 737 } 738 } 739 740 private int mIndex; 741 } 742 743 class AwSettingsContentUrlAccessTestHelper extends AwSettingsTestHelper<Boolean> { 744 745 AwSettingsContentUrlAccessTestHelper( 746 AwContents awContents, 747 TestAwContentsClient contentViewClient, 748 int index) throws Throwable { 749 super(awContents, contentViewClient, true); 750 mTarget = "content_access_" + index; 751 } 752 753 @Override 754 protected Boolean getAlteredValue() { 755 return DISABLED; 756 } 757 758 @Override 759 protected Boolean getInitialValue() { 760 return ENABLED; 761 } 762 763 @Override 764 protected Boolean getCurrentValue() { 765 return mAwSettings.getAllowContentAccess(); 766 } 767 768 @Override 769 protected void setCurrentValue(Boolean value) { 770 mAwSettings.setAllowContentAccess(value); 771 } 772 773 @Override 774 protected void doEnsureSettingHasValue(Boolean value) throws Throwable { 775 AwSettingsTest.this.resetResourceRequestCountInContentProvider(mTarget); 776 loadUrlSync(AwSettingsTest.this.createContentUrl(mTarget)); 777 if (value == ENABLED) { 778 AwSettingsTest.this.ensureResourceRequestCountInContentProvider(mTarget, 1); 779 } else { 780 AwSettingsTest.this.ensureResourceRequestCountInContentProvider(mTarget, 0); 781 } 782 } 783 784 private final String mTarget; 785 } 786 787 class AwSettingsContentUrlAccessFromFileTestHelper extends AwSettingsTestHelper<Boolean> { 788 private static final String TARGET = "content_from_file"; 789 790 AwSettingsContentUrlAccessFromFileTestHelper( 791 AwContents awContents, 792 TestAwContentsClient contentViewClient, 793 int index) throws Throwable { 794 super(awContents, contentViewClient, true); 795 mIndex = index; 796 mTempDir = getInstrumentation().getTargetContext().getCacheDir().getPath(); 797 } 798 799 @Override 800 protected Boolean getAlteredValue() { 801 return DISABLED; 802 } 803 804 @Override 805 protected Boolean getInitialValue() { 806 return ENABLED; 807 } 808 809 @Override 810 protected Boolean getCurrentValue() { 811 return mAwSettings.getAllowContentAccess(); 812 } 813 814 @Override 815 protected void setCurrentValue(Boolean value) { 816 mAwSettings.setAllowContentAccess(value); 817 } 818 819 @Override 820 protected void doEnsureSettingHasValue(Boolean value) throws Throwable { 821 AwSettingsTest.this.resetResourceRequestCountInContentProvider(TARGET); 822 final String fileName = mTempDir + "/" + TARGET + ".html"; 823 try { 824 TestFileUtil.createNewHtmlFile(fileName, 825 TARGET, 826 "<img src=\"" + 827 // Adding a query avoids hitting a cached image, and also verifies 828 // that content URL query parameters are ignored when accessing 829 // a content provider. 830 AwSettingsTest.this.createContentUrl(TARGET + "?id=" + mIndex) + "\">"); 831 mIndex += 2; 832 loadUrlSync("file://" + fileName); 833 if (value == ENABLED) { 834 AwSettingsTest.this.ensureResourceRequestCountInContentProvider(TARGET, 1); 835 } else { 836 AwSettingsTest.this.ensureResourceRequestCountInContentProvider(TARGET, 0); 837 } 838 } finally { 839 TestFileUtil.deleteFile(fileName); 840 } 841 } 842 843 private int mIndex; 844 private String mTempDir; 845 } 846 847 // This class provides helper methods for testing of settings related to 848 // the text autosizing feature. 849 abstract class AwSettingsTextAutosizingTestHelper<T> extends AwSettingsTestHelper<T> { 850 protected static final float PARAGRAPH_FONT_SIZE = 14.0f; 851 852 AwSettingsTextAutosizingTestHelper( 853 AwContents awContents, 854 TestAwContentsClient contentViewClient) throws Throwable { 855 super(awContents, contentViewClient, true); 856 mNeedToWaitForFontSizeChange = false; 857 loadDataSync(getData()); 858 } 859 860 @Override 861 protected void setCurrentValue(T value) throws Throwable { 862 mNeedToWaitForFontSizeChange = false; 863 if (value != getCurrentValue()) { 864 mOldFontSize = getActualFontSize(); 865 mNeedToWaitForFontSizeChange = true; 866 } 867 } 868 869 protected float getActualFontSize() throws Throwable { 870 if (!mNeedToWaitForFontSizeChange) { 871 executeJavaScriptAndWaitForResult("setTitleToActualFontSize()"); 872 } else { 873 final float oldFontSize = mOldFontSize; 874 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { 875 @Override 876 public boolean isSatisfied() { 877 try { 878 executeJavaScriptAndWaitForResult("setTitleToActualFontSize()"); 879 float newFontSize = Float.parseFloat(getTitleOnUiThread()); 880 return newFontSize != oldFontSize; 881 } catch (Throwable t) { 882 t.printStackTrace(); 883 fail("Failed to getTitleOnUiThread: " + t.toString()); 884 return false; 885 } 886 } 887 }, TEST_TIMEOUT, CHECK_INTERVAL)); 888 mNeedToWaitForFontSizeChange = false; 889 } 890 return Float.parseFloat(getTitleOnUiThread()); 891 } 892 893 protected String getData() { 894 StringBuilder sb = new StringBuilder(); 895 sb.append("<html>" + 896 "<head><script>" + 897 "function setTitleToActualFontSize() {" + 898 // parseFloat is used to trim out the "px" suffix. 899 " document.title = parseFloat(getComputedStyle(" + 900 " document.getElementById('par')).getPropertyValue('font-size'));" + 901 "}</script></head>" + 902 "<body>" + 903 "<p id=\"par\" style=\"font-size:"); 904 sb.append(PARAGRAPH_FONT_SIZE); 905 sb.append("px;\">"); 906 // Make the paragraph wide enough for being processed by the font autosizer. 907 for (int i = 0; i < 100; i++) { 908 sb.append("Hello, World! "); 909 } 910 sb.append("</p></body></html>"); 911 return sb.toString(); 912 } 913 914 private boolean mNeedToWaitForFontSizeChange; 915 private float mOldFontSize; 916 } 917 918 class AwSettingsLayoutAlgorithmTestHelper extends 919 AwSettingsTextAutosizingTestHelper<LayoutAlgorithm> { 920 921 AwSettingsLayoutAlgorithmTestHelper( 922 AwContents awContents, 923 TestAwContentsClient contentViewClient) throws Throwable { 924 super(awContents, contentViewClient); 925 // Font autosizing doesn't step in for narrow layout widths. 926 mAwSettings.setUseWideViewPort(true); 927 } 928 929 @Override 930 protected LayoutAlgorithm getAlteredValue() { 931 return LayoutAlgorithm.TEXT_AUTOSIZING; 932 } 933 934 @Override 935 protected LayoutAlgorithm getInitialValue() { 936 return LayoutAlgorithm.NARROW_COLUMNS; 937 } 938 939 @Override 940 protected LayoutAlgorithm getCurrentValue() { 941 return mAwSettings.getLayoutAlgorithm(); 942 } 943 944 @Override 945 protected void setCurrentValue(LayoutAlgorithm value) throws Throwable { 946 super.setCurrentValue(value); 947 mAwSettings.setLayoutAlgorithm(value); 948 } 949 950 @Override 951 protected void doEnsureSettingHasValue(LayoutAlgorithm value) throws Throwable { 952 final float actualFontSize = getActualFontSize(); 953 if (value == LayoutAlgorithm.TEXT_AUTOSIZING) { 954 assertFalse("Actual font size: " + actualFontSize, 955 actualFontSize == PARAGRAPH_FONT_SIZE); 956 } else { 957 assertTrue("Actual font size: " + actualFontSize, 958 actualFontSize == PARAGRAPH_FONT_SIZE); 959 } 960 } 961 } 962 963 class AwSettingsTextZoomTestHelper extends AwSettingsTextAutosizingTestHelper<Integer> { 964 private static final int INITIAL_TEXT_ZOOM = 100; 965 private final float mInitialActualFontSize; 966 967 AwSettingsTextZoomTestHelper( 968 AwContents awContents, 969 TestAwContentsClient contentViewClient) throws Throwable { 970 super(awContents, contentViewClient); 971 mInitialActualFontSize = getActualFontSize(); 972 } 973 974 @Override 975 protected Integer getAlteredValue() { 976 return INITIAL_TEXT_ZOOM * 2; 977 } 978 979 @Override 980 protected Integer getInitialValue() { 981 return INITIAL_TEXT_ZOOM; 982 } 983 984 @Override 985 protected Integer getCurrentValue() { 986 return mAwSettings.getTextZoom(); 987 } 988 989 @Override 990 protected void setCurrentValue(Integer value) throws Throwable { 991 super.setCurrentValue(value); 992 mAwSettings.setTextZoom(value); 993 } 994 995 @Override 996 protected void doEnsureSettingHasValue(Integer value) throws Throwable { 997 final float actualFontSize = getActualFontSize(); 998 // Ensure that actual vs. initial font size ratio is similar to actual vs. initial 999 // text zoom values ratio. 1000 final float ratiosDelta = Math.abs( 1001 (actualFontSize / mInitialActualFontSize) - 1002 (value / (float)INITIAL_TEXT_ZOOM)); 1003 assertTrue( 1004 "|(" + actualFontSize + " / " + mInitialActualFontSize + ") - (" + 1005 value + " / " + INITIAL_TEXT_ZOOM + ")| = " + ratiosDelta, 1006 ratiosDelta <= 0.2f); 1007 } 1008 } 1009 1010 class AwSettingsTextZoomAutosizingTestHelper 1011 extends AwSettingsTextAutosizingTestHelper<Integer> { 1012 private static final int INITIAL_TEXT_ZOOM = 100; 1013 private final float mInitialActualFontSize; 1014 1015 AwSettingsTextZoomAutosizingTestHelper( 1016 AwContents awContents, 1017 TestAwContentsClient contentViewClient) throws Throwable { 1018 super(awContents, contentViewClient); 1019 mAwSettings.setLayoutAlgorithm(LayoutAlgorithm.TEXT_AUTOSIZING); 1020 // The initial font size can be adjusted by font autosizer depending on the page's 1021 // viewport width. 1022 mInitialActualFontSize = getActualFontSize(); 1023 } 1024 1025 @Override 1026 protected Integer getAlteredValue() { 1027 return INITIAL_TEXT_ZOOM * 2; 1028 } 1029 1030 @Override 1031 protected Integer getInitialValue() { 1032 return INITIAL_TEXT_ZOOM; 1033 } 1034 1035 @Override 1036 protected Integer getCurrentValue() { 1037 return mAwSettings.getTextZoom(); 1038 } 1039 1040 @Override 1041 protected void setCurrentValue(Integer value) throws Throwable { 1042 super.setCurrentValue(value); 1043 mAwSettings.setTextZoom(value); 1044 } 1045 1046 @Override 1047 protected void doEnsureSettingHasValue(Integer value) throws Throwable { 1048 final float actualFontSize = getActualFontSize(); 1049 // Ensure that actual vs. initial font size ratio is similar to actual vs. initial 1050 // text zoom values ratio. 1051 final float ratiosDelta = Math.abs( 1052 (actualFontSize / mInitialActualFontSize) - 1053 (value / (float)INITIAL_TEXT_ZOOM)); 1054 assertTrue( 1055 "|(" + actualFontSize + " / " + mInitialActualFontSize + ") - (" + 1056 value + " / " + INITIAL_TEXT_ZOOM + ")| = " + ratiosDelta, 1057 ratiosDelta <= 0.2f); 1058 } 1059 } 1060 1061 class AwSettingsJavaScriptPopupsTestHelper extends AwSettingsTestHelper<Boolean> { 1062 static private final String POPUP_ENABLED = "Popup enabled"; 1063 static private final String POPUP_BLOCKED = "Popup blocked"; 1064 1065 AwSettingsJavaScriptPopupsTestHelper( 1066 AwContents awContents, 1067 TestAwContentsClient contentViewClient) throws Throwable { 1068 super(awContents, contentViewClient, true); 1069 } 1070 1071 @Override 1072 protected Boolean getAlteredValue() { 1073 return ENABLED; 1074 } 1075 1076 @Override 1077 protected Boolean getInitialValue() { 1078 return DISABLED; 1079 } 1080 1081 @Override 1082 protected Boolean getCurrentValue() { 1083 return mAwSettings.getJavaScriptCanOpenWindowsAutomatically(); 1084 } 1085 1086 @Override 1087 protected void setCurrentValue(Boolean value) { 1088 mAwSettings.setJavaScriptCanOpenWindowsAutomatically(value); 1089 } 1090 1091 @Override 1092 protected void doEnsureSettingHasValue(Boolean value) throws Throwable { 1093 loadDataSync(getData()); 1094 final boolean expectPopupEnabled = value; 1095 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { 1096 @Override 1097 public boolean isSatisfied() { 1098 try { 1099 String title = getTitleOnUiThread(); 1100 return expectPopupEnabled ? POPUP_ENABLED.equals(title) : 1101 POPUP_BLOCKED.equals(title); 1102 } catch (Throwable t) { 1103 t.printStackTrace(); 1104 fail("Failed to getTitleOnUiThread: " + t.toString()); 1105 return false; 1106 } 1107 } 1108 }, TEST_TIMEOUT, CHECK_INTERVAL)); 1109 assertEquals(value ? POPUP_ENABLED : POPUP_BLOCKED, getTitleOnUiThread()); 1110 } 1111 1112 private String getData() { 1113 return "<html><head>" + 1114 "<script>" + 1115 " function tryOpenWindow() {" + 1116 " var newWindow = window.open(" + 1117 " 'data:text/html;charset=utf-8," + 1118 " <html><head><title>" + POPUP_ENABLED + "</title></head></html>');" + 1119 " if (!newWindow) document.title = '" + POPUP_BLOCKED + "';" + 1120 " }" + 1121 "</script></head>" + 1122 "<body onload='tryOpenWindow()'></body></html>"; 1123 } 1124 } 1125 1126 class AwSettingsCacheModeTestHelper extends AwSettingsTestHelper<Integer> { 1127 1128 AwSettingsCacheModeTestHelper( 1129 AwContents awContents, 1130 TestAwContentsClient contentViewClient, 1131 int index, 1132 TestWebServer webServer) throws Throwable { 1133 super(awContents, contentViewClient, true); 1134 mIndex = index; 1135 mWebServer = webServer; 1136 } 1137 1138 @Override 1139 protected Integer getAlteredValue() { 1140 // We use the value that results in a behaviour completely opposite to default. 1141 return WebSettings.LOAD_CACHE_ONLY; 1142 } 1143 1144 @Override 1145 protected Integer getInitialValue() { 1146 return WebSettings.LOAD_DEFAULT; 1147 } 1148 1149 @Override 1150 protected Integer getCurrentValue() { 1151 return mAwSettings.getCacheMode(); 1152 } 1153 1154 @Override 1155 protected void setCurrentValue(Integer value) { 1156 mAwSettings.setCacheMode(value); 1157 } 1158 1159 @Override 1160 protected void doEnsureSettingHasValue(Integer value) throws Throwable { 1161 final String htmlPath = "/cache_mode_" + mIndex + ".html"; 1162 mIndex += 2; 1163 final String url = mWebServer.setResponse(htmlPath, "response", null); 1164 assertEquals(0, mWebServer.getRequestCount(htmlPath)); 1165 if (value == WebSettings.LOAD_DEFAULT) { 1166 loadUrlSync(url); 1167 assertEquals(1, mWebServer.getRequestCount(htmlPath)); 1168 } else { 1169 loadUrlSyncAndExpectError(url); 1170 assertEquals(0, mWebServer.getRequestCount(htmlPath)); 1171 } 1172 } 1173 1174 private int mIndex; 1175 private TestWebServer mWebServer; 1176 } 1177 1178 // To verify whether UseWideViewport works, we check, if the page width specified 1179 // in the "meta viewport" tag is applied. When UseWideViewport is turned off, the 1180 // "viewport" tag is ignored, and the layout width is set to device width in DIP pixels. 1181 // We specify a very high width value to make sure that it doesn't intersect with 1182 // device screen widths (in DIP pixels). 1183 class AwSettingsUseWideViewportTestHelper extends AwSettingsTestHelper<Boolean> { 1184 static private final String VIEWPORT_TAG_LAYOUT_WIDTH = "3000"; 1185 1186 AwSettingsUseWideViewportTestHelper( 1187 AwContents awContents, 1188 TestAwContentsClient contentViewClient) throws Throwable { 1189 super(awContents, contentViewClient, true); 1190 } 1191 1192 @Override 1193 protected Boolean getAlteredValue() { 1194 return ENABLED; 1195 } 1196 1197 @Override 1198 protected Boolean getInitialValue() { 1199 return DISABLED; 1200 } 1201 1202 @Override 1203 protected Boolean getCurrentValue() { 1204 return mAwSettings.getUseWideViewPort(); 1205 } 1206 1207 @Override 1208 protected void setCurrentValue(Boolean value) { 1209 mAwSettings.setUseWideViewPort(value); 1210 } 1211 1212 @Override 1213 protected void doEnsureSettingHasValue(Boolean value) throws Throwable { 1214 loadDataSync(getData()); 1215 final String bodyWidth = getTitleOnUiThread(); 1216 if (value) { 1217 assertTrue(bodyWidth, VIEWPORT_TAG_LAYOUT_WIDTH.equals(bodyWidth)); 1218 } else { 1219 assertFalse(bodyWidth, VIEWPORT_TAG_LAYOUT_WIDTH.equals(bodyWidth)); 1220 } 1221 } 1222 1223 private String getData() { 1224 return "<html><head>" + 1225 "<meta name='viewport' content='width=" + VIEWPORT_TAG_LAYOUT_WIDTH + "' />" + 1226 "</head>" + 1227 "<body onload='document.title=document.body.clientWidth'></body></html>"; 1228 } 1229 } 1230 1231 class AwSettingsLoadWithOverviewModeTestHelper extends AwSettingsTestHelper<Boolean> { 1232 private static final float DEFAULT_PAGE_SCALE = 1.0f; 1233 1234 AwSettingsLoadWithOverviewModeTestHelper( 1235 AwContents awContents, 1236 TestAwContentsClient contentViewClient, 1237 boolean withViewPortTag) throws Throwable { 1238 super(awContents, contentViewClient, true); 1239 mWithViewPortTag = withViewPortTag; 1240 mAwSettings.setUseWideViewPort(true); 1241 } 1242 1243 @Override 1244 protected Boolean getAlteredValue() { 1245 return ENABLED; 1246 } 1247 1248 @Override 1249 protected Boolean getInitialValue() { 1250 return DISABLED; 1251 } 1252 1253 @Override 1254 protected Boolean getCurrentValue() { 1255 return mAwSettings.getLoadWithOverviewMode(); 1256 } 1257 1258 @Override 1259 protected void setCurrentValue(Boolean value) { 1260 mExpectScaleChange = mAwSettings.getLoadWithOverviewMode() != value; 1261 if (mExpectScaleChange) { 1262 mOnScaleChangedCallCount = 1263 mContentViewClient.getOnScaleChangedHelper().getCallCount(); 1264 } 1265 mAwSettings.setLoadWithOverviewMode(value); 1266 } 1267 1268 @Override 1269 protected void doEnsureSettingHasValue(Boolean value) throws Throwable { 1270 loadDataSync(getData()); 1271 if (mExpectScaleChange) { 1272 mContentViewClient.getOnScaleChangedHelper(). 1273 waitForCallback(mOnScaleChangedCallCount); 1274 mExpectScaleChange = false; 1275 } 1276 float currentScale = AwSettingsTest.this.getScaleOnUiThread(mAwContents); 1277 if (value) { 1278 assertTrue("Expected: " + currentScale + " < " + DEFAULT_PAGE_SCALE, 1279 currentScale < DEFAULT_PAGE_SCALE); 1280 } else { 1281 assertEquals(DEFAULT_PAGE_SCALE, currentScale); 1282 } 1283 } 1284 1285 private String getData() { 1286 return "<html><head>" + 1287 (mWithViewPortTag ? "<meta name='viewport' content='width=3000' />" : "") + 1288 "</head>" + 1289 "<body></body></html>"; 1290 } 1291 1292 private final boolean mWithViewPortTag; 1293 private boolean mExpectScaleChange; 1294 private int mOnScaleChangedCallCount; 1295 } 1296 1297 // The test verifies that JavaScript is disabled upon WebView 1298 // creation without accessing AwSettings. If the test passes, 1299 // it means that WebView-specific web preferences configuration 1300 // is applied on WebView creation. JS state is used, because it is 1301 // enabled by default in Chrome, but must be disabled by default 1302 // in WebView. 1303 @SmallTest 1304 @Feature({"AndroidWebView", "Preferences"}) 1305 public void testJavaScriptDisabledByDefault() throws Throwable { 1306 final String JS_ENABLED_STRING = "JS has run"; 1307 final String JS_DISABLED_STRING = "JS has not run"; 1308 final String TEST_PAGE_HTML = 1309 "<html><head><title>" + JS_DISABLED_STRING + "</title>" 1310 + "</head><body onload=\"document.title='" + JS_ENABLED_STRING 1311 + "';\"></body></html>"; 1312 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1313 final AwTestContainerView testContainerView = 1314 createAwTestContainerViewOnMainSync(contentClient); 1315 final AwContents awContents = testContainerView.getAwContents(); 1316 loadDataSync( 1317 awContents, 1318 contentClient.getOnPageFinishedHelper(), 1319 TEST_PAGE_HTML, 1320 "text/html", 1321 false); 1322 assertEquals(JS_DISABLED_STRING, getTitleOnUiThread(awContents)); 1323 } 1324 1325 @SmallTest 1326 @Feature({"AndroidWebView", "Preferences"}) 1327 public void testJavaScriptEnabledWithTwoViews() throws Throwable { 1328 ViewPair views = createViews(); 1329 runPerViewSettingsTest( 1330 new AwSettingsJavaScriptTestHelper(views.getContents0(), views.getClient0()), 1331 new AwSettingsJavaScriptTestHelper(views.getContents1(), views.getClient1())); 1332 } 1333 1334 @SmallTest 1335 @Feature({"AndroidWebView", "Preferences"}) 1336 public void testJavaScriptEnabledDynamicWithTwoViews() throws Throwable { 1337 ViewPair views = createViews(); 1338 runPerViewSettingsTest( 1339 new AwSettingsJavaScriptDynamicTestHelper(views.getContents0(), views.getClient0()), 1340 new AwSettingsJavaScriptDynamicTestHelper(views.getContents1(), views.getClient1())); 1341 } 1342 1343 @SmallTest 1344 @Feature({"AndroidWebView", "Preferences"}) 1345 public void testPluginsEnabledWithTwoViews() throws Throwable { 1346 ViewPair views = createViews(); 1347 runPerViewSettingsTest( 1348 new AwSettingsPluginsTestHelper(views.getContents0(), views.getClient0()), 1349 new AwSettingsPluginsTestHelper(views.getContents1(), views.getClient1())); 1350 } 1351 1352 @SmallTest 1353 @Feature({"AndroidWebView", "Preferences"}) 1354 public void testStandardFontFamilyWithTwoViews() throws Throwable { 1355 ViewPair views = createViews(); 1356 runPerViewSettingsTest( 1357 new AwSettingsStandardFontFamilyTestHelper(views.getContents0(), views.getClient0()), 1358 new AwSettingsStandardFontFamilyTestHelper(views.getContents1(), views.getClient1())); 1359 } 1360 1361 @SmallTest 1362 @Feature({"AndroidWebView", "Preferences"}) 1363 public void testDefaultFontSizeWithTwoViews() throws Throwable { 1364 ViewPair views = createViews(); 1365 runPerViewSettingsTest( 1366 new AwSettingsDefaultFontSizeTestHelper(views.getContents0(), views.getClient0()), 1367 new AwSettingsDefaultFontSizeTestHelper(views.getContents1(), views.getClient1())); 1368 } 1369 1370 // The test verifies that after changing the LoadsImagesAutomatically 1371 // setting value from false to true previously skipped images are 1372 // automatically loaded. 1373 @SmallTest 1374 @Feature({"AndroidWebView", "Preferences"}) 1375 public void testLoadsImagesAutomaticallyNoPageReload() throws Throwable { 1376 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1377 final AwTestContainerView testContainerView = 1378 createAwTestContainerViewOnMainSync(contentClient); 1379 final AwContents awContents = testContainerView.getAwContents(); 1380 AwSettings settings = getAwSettingsOnUiThread(awContents); 1381 settings.setJavaScriptEnabled(true); 1382 ImagePageGenerator generator = new ImagePageGenerator(0, false); 1383 settings.setLoadsImagesAutomatically(false); 1384 loadDataSync(awContents, 1385 contentClient.getOnPageFinishedHelper(), 1386 generator.getPageSource(), 1387 "text/html", false); 1388 assertEquals(ImagePageGenerator.IMAGE_NOT_LOADED_STRING, 1389 getTitleOnUiThread(awContents)); 1390 settings.setLoadsImagesAutomatically(true); 1391 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { 1392 @Override 1393 public boolean isSatisfied() { 1394 try { 1395 return !ImagePageGenerator.IMAGE_NOT_LOADED_STRING.equals( 1396 getTitleOnUiThread(awContents)); 1397 } catch (Throwable t) { 1398 t.printStackTrace(); 1399 fail("Failed to getTitleOnUiThread: " + t.toString()); 1400 return false; 1401 } 1402 } 1403 }, TEST_TIMEOUT, CHECK_INTERVAL)); 1404 assertEquals(ImagePageGenerator.IMAGE_LOADED_STRING, getTitleOnUiThread(awContents)); 1405 } 1406 1407 1408 @SmallTest 1409 @Feature({"AndroidWebView", "Preferences"}) 1410 public void testLoadsImagesAutomaticallyWithTwoViews() throws Throwable { 1411 ViewPair views = createViews(); 1412 runPerViewSettingsTest( 1413 new AwSettingsLoadImagesAutomaticallyTestHelper( 1414 views.getContents0(), views.getClient0(), new ImagePageGenerator(0, true)), 1415 new AwSettingsLoadImagesAutomaticallyTestHelper( 1416 views.getContents1(), views.getClient1(), new ImagePageGenerator(1, true))); 1417 } 1418 1419 @SmallTest 1420 @Feature({"AndroidWebView", "Preferences"}) 1421 public void testDefaultTextEncodingWithTwoViews() throws Throwable { 1422 ViewPair views = createViews(); 1423 runPerViewSettingsTest( 1424 new AwSettingsDefaultTextEncodingTestHelper(views.getContents0(), views.getClient0()), 1425 new AwSettingsDefaultTextEncodingTestHelper(views.getContents1(), views.getClient1())); 1426 } 1427 1428 // The test verifies that the default user agent string follows the format 1429 // defined in Android CTS tests: 1430 // 1431 // Mozilla/5.0 (Linux;[ U;] Android <version>;[ <language>-<country>;] 1432 // [<devicemodel>;] Build/<buildID>) AppleWebKit/<major>.<minor> (KHTML, like Gecko) 1433 // Version/<major>.<minor>[ Mobile] Safari/<major>.<minor> 1434 @SmallTest 1435 @Feature({"AndroidWebView", "Preferences"}) 1436 public void testUserAgentStringDefault() throws Throwable { 1437 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1438 final AwTestContainerView testContainerView = 1439 createAwTestContainerViewOnMainSync(contentClient); 1440 final AwContents awContents = testContainerView.getAwContents(); 1441 AwSettings settings = getAwSettingsOnUiThread(awContents); 1442 final String actualUserAgentString = settings.getUserAgentString(); 1443 final String patternString = 1444 "Mozilla/5\\.0 \\(Linux;( U;)? Android ([^;]+);( (\\w+)-(\\w+);)?" + 1445 "\\s?(.*)\\sBuild/(.+)\\) AppleWebKit/(\\d+)\\.(\\d+) \\(KHTML, like Gecko\\) " + 1446 "Version/\\d+\\.\\d+( Mobile)? Safari/(\\d+)\\.(\\d+)"; 1447 final Pattern userAgentExpr = Pattern.compile(patternString); 1448 Matcher patternMatcher = userAgentExpr.matcher(actualUserAgentString); 1449 assertTrue(String.format("User agent string did not match expected pattern. %nExpected " + 1450 "pattern:%n%s%nActual:%n%s", patternString, actualUserAgentString), 1451 patternMatcher.find()); 1452 // No country-language code token. 1453 assertEquals(null, patternMatcher.group(3)); 1454 if ("REL".equals(Build.VERSION.CODENAME)) { 1455 // Model is only added in release builds 1456 assertEquals(Build.MODEL, patternMatcher.group(6)); 1457 // Release version is valid only in release builds 1458 assertEquals(Build.VERSION.RELEASE, patternMatcher.group(2)); 1459 } 1460 assertEquals(Build.ID, patternMatcher.group(7)); 1461 } 1462 1463 @SmallTest 1464 @Feature({"AndroidWebView", "Preferences"}) 1465 public void testUserAgentStringOverride() throws Throwable { 1466 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1467 final AwTestContainerView testContainerView = 1468 createAwTestContainerViewOnMainSync(contentClient); 1469 final AwContents awContents = testContainerView.getAwContents(); 1470 AwSettings settings = getAwSettingsOnUiThread(awContents); 1471 final String defaultUserAgentString = settings.getUserAgentString(); 1472 1473 // Check that an attempt to reset the default UA string has no effect. 1474 settings.setUserAgentString(null); 1475 assertEquals(defaultUserAgentString, settings.getUserAgentString()); 1476 settings.setUserAgentString(""); 1477 assertEquals(defaultUserAgentString, settings.getUserAgentString()); 1478 1479 // Check that we can also set the default value. 1480 settings.setUserAgentString(defaultUserAgentString); 1481 assertEquals(defaultUserAgentString, settings.getUserAgentString()); 1482 1483 // Set a custom UA string, verify that it can be reset back to default. 1484 final String customUserAgentString = "AwSettingsTest"; 1485 settings.setUserAgentString(customUserAgentString); 1486 assertEquals(customUserAgentString, settings.getUserAgentString()); 1487 settings.setUserAgentString(null); 1488 assertEquals(defaultUserAgentString, settings.getUserAgentString()); 1489 } 1490 1491 // Verify that the current UA override setting has a priority over UA 1492 // overrides in navigation history entries. 1493 @SmallTest 1494 @Feature({"AndroidWebView", "Preferences"}) 1495 public void testUserAgentStringOverrideForHistory() throws Throwable { 1496 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1497 final AwTestContainerView testContainerView = 1498 createAwTestContainerViewOnMainSync(contentClient); 1499 final AwContents awContents = testContainerView.getAwContents(); 1500 final ContentViewCore contentView = testContainerView.getContentViewCore(); 1501 CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); 1502 AwSettings settings = getAwSettingsOnUiThread(awContents); 1503 settings.setJavaScriptEnabled(true); 1504 final String defaultUserAgentString = settings.getUserAgentString(); 1505 final String customUserAgentString = "AwSettingsTest"; 1506 // We are using different page titles to make sure that we are really 1507 // going back and forward between them. 1508 final String pageTemplate = 1509 "<html><head><title>%s</title></head>" + 1510 "<body onload='document.title+=navigator.userAgent'></body>" + 1511 "</html>"; 1512 final String page1Title = "Page1"; 1513 final String page2Title = "Page2"; 1514 final String page1 = String.format(pageTemplate, page1Title); 1515 final String page2 = String.format(pageTemplate, page2Title); 1516 settings.setUserAgentString(customUserAgentString); 1517 loadDataSync( 1518 awContents, onPageFinishedHelper, page1, "text/html", false); 1519 assertEquals(page1Title + customUserAgentString, getTitleOnUiThread(awContents)); 1520 loadDataSync( 1521 awContents, onPageFinishedHelper, page2, "text/html", false); 1522 assertEquals(page2Title + customUserAgentString, getTitleOnUiThread(awContents)); 1523 settings.setUserAgentString(null); 1524 // Must not cause any changes until the next page loading. 1525 assertEquals(page2Title + customUserAgentString, getTitleOnUiThread(awContents)); 1526 HistoryUtils.goBackSync(getInstrumentation(), contentView, onPageFinishedHelper); 1527 assertEquals(page1Title + defaultUserAgentString, getTitleOnUiThread(awContents)); 1528 HistoryUtils.goForwardSync(getInstrumentation(), contentView, 1529 onPageFinishedHelper); 1530 assertEquals(page2Title + defaultUserAgentString, getTitleOnUiThread(awContents)); 1531 } 1532 1533 @SmallTest 1534 @Feature({"AndroidWebView", "Preferences"}) 1535 public void testUserAgentStringWithTwoViews() throws Throwable { 1536 ViewPair views = createViews(); 1537 runPerViewSettingsTest( 1538 new AwSettingsUserAgentStringTestHelper(views.getContents0(), views.getClient0()), 1539 new AwSettingsUserAgentStringTestHelper(views.getContents1(), views.getClient1())); 1540 } 1541 1542 @SmallTest 1543 @Feature({"AndroidWebView", "Preferences"}) 1544 public void testUserAgentWithTestServer() throws Throwable { 1545 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1546 final AwTestContainerView testContainerView = 1547 createAwTestContainerViewOnMainSync(contentClient); 1548 AwContents awContents = testContainerView.getAwContents(); 1549 AwSettings settings = getAwSettingsOnUiThread(awContents); 1550 final String customUserAgentString = 1551 "testUserAgentWithTestServerUserAgent"; 1552 1553 TestWebServer webServer = null; 1554 String fileName = null; 1555 try { 1556 webServer = new TestWebServer(false); 1557 final String httpPath = "/testUserAgentWithTestServer.html"; 1558 final String url = webServer.setResponse(httpPath, "foo", null); 1559 1560 settings.setUserAgentString(customUserAgentString); 1561 loadUrlSync(awContents, 1562 contentClient.getOnPageFinishedHelper(), 1563 url); 1564 1565 assertEquals(1, webServer.getRequestCount(httpPath)); 1566 HttpRequest request = webServer.getLastRequest(httpPath); 1567 Header[] matchingHeaders = request.getHeaders("User-Agent"); 1568 assertEquals(1, matchingHeaders.length); 1569 1570 Header header = matchingHeaders[0]; 1571 assertEquals(customUserAgentString, header.getValue()); 1572 } finally { 1573 if (webServer != null) webServer.shutdown(); 1574 } 1575 } 1576 1577 @SmallTest 1578 @Feature({"AndroidWebView", "Preferences"}) 1579 public void testDomStorageEnabledWithTwoViews() throws Throwable { 1580 ViewPair views = createViews(); 1581 runPerViewSettingsTest( 1582 new AwSettingsDomStorageEnabledTestHelper(views.getContents0(), views.getClient0()), 1583 new AwSettingsDomStorageEnabledTestHelper(views.getContents1(), views.getClient1())); 1584 } 1585 1586 // Ideally, these three tests below should be combined into one, or tested using 1587 // runPerViewSettingsTest. However, it seems the database setting cannot be toggled 1588 // once set. Filed b/8186497. 1589 @SmallTest 1590 @Feature({"AndroidWebView", "Preferences"}) 1591 public void testDatabaseInitialValue() throws Throwable { 1592 TestAwContentsClient client = new TestAwContentsClient(); 1593 final AwTestContainerView testContainerView = 1594 createAwTestContainerViewOnMainSync(client); 1595 final AwContents awContents = testContainerView.getAwContents(); 1596 AwSettingsDatabaseTestHelper helper = new AwSettingsDatabaseTestHelper(awContents, client); 1597 helper.ensureSettingHasInitialValue(); 1598 } 1599 1600 @SmallTest 1601 @Feature({"AndroidWebView", "Preferences"}) 1602 public void testDatabaseEnabled() throws Throwable { 1603 TestAwContentsClient client = new TestAwContentsClient(); 1604 final AwTestContainerView testContainerView = 1605 createAwTestContainerViewOnMainSync(client); 1606 final AwContents awContents = testContainerView.getAwContents(); 1607 AwSettingsDatabaseTestHelper helper = new AwSettingsDatabaseTestHelper(awContents, client); 1608 helper.setAlteredSettingValue(); 1609 helper.ensureSettingHasAlteredValue(); 1610 } 1611 1612 @SmallTest 1613 @Feature({"AndroidWebView", "Preferences"}) 1614 public void testDatabaseDisabled() throws Throwable { 1615 TestAwContentsClient client = new TestAwContentsClient(); 1616 final AwTestContainerView testContainerView = 1617 createAwTestContainerViewOnMainSync(client); 1618 final AwContents awContents = testContainerView.getAwContents(); 1619 AwSettingsDatabaseTestHelper helper = new AwSettingsDatabaseTestHelper(awContents, client); 1620 helper.setInitialSettingValue(); 1621 helper.ensureSettingHasInitialValue(); 1622 } 1623 1624 @SmallTest 1625 @Feature({"AndroidWebView", "Preferences"}) 1626 public void testUniversalAccessFromFilesWithTwoViews() throws Throwable { 1627 ViewPair views = createViews(); 1628 runPerViewSettingsTest( 1629 new AwSettingsUniversalAccessFromFilesTestHelper(views.getContents0(), 1630 views.getClient0()), 1631 new AwSettingsUniversalAccessFromFilesTestHelper(views.getContents1(), 1632 views.getClient1())); 1633 } 1634 1635 // This test verifies that local image resources can be loaded from file: 1636 // URLs regardless of file access state. 1637 @SmallTest 1638 @Feature({"AndroidWebView", "Preferences"}) 1639 public void testFileAccessFromFilesImage() throws Throwable { 1640 final String imageContainerUrl = UrlUtils.getTestFileUrl("webview/image_access.html"); 1641 final String imageHeight = "16"; 1642 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1643 final AwTestContainerView testContainerView = 1644 createAwTestContainerViewOnMainSync(contentClient); 1645 final AwContents awContents = testContainerView.getAwContents(); 1646 AwSettings settings = getAwSettingsOnUiThread(awContents); 1647 settings.setJavaScriptEnabled(true); 1648 settings.setAllowUniversalAccessFromFileURLs(false); 1649 settings.setAllowFileAccessFromFileURLs(false); 1650 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), imageContainerUrl); 1651 assertEquals(imageHeight, getTitleOnUiThread(awContents)); 1652 } 1653 1654 @SmallTest 1655 @Feature({"AndroidWebView", "Preferences"}) 1656 public void testFileAccessFromFilesIframeWithTwoViews() throws Throwable { 1657 ViewPair views = createViews(); 1658 runPerViewSettingsTest( 1659 new AwSettingsFileAccessFromFilesIframeTestHelper( 1660 views.getContents0(), views.getClient0()), 1661 new AwSettingsFileAccessFromFilesIframeTestHelper( 1662 views.getContents1(), views.getClient1())); 1663 } 1664 1665 @SmallTest 1666 @Feature({"AndroidWebView", "Preferences"}) 1667 public void testFileAccessFromFilesXhrWithTwoViews() throws Throwable { 1668 ViewPair views = createViews(); 1669 runPerViewSettingsTest( 1670 new AwSettingsFileAccessFromFilesXhrTestHelper(views.getContents0(), 1671 views.getClient0()), 1672 new AwSettingsFileAccessFromFilesXhrTestHelper(views.getContents1(), 1673 views.getClient1())); 1674 } 1675 1676 @SmallTest 1677 @Feature({"AndroidWebView", "Preferences"}) 1678 public void testFileUrlAccessWithTwoViews() throws Throwable { 1679 ViewPair views = createViews(); 1680 runPerViewSettingsTest( 1681 new AwSettingsFileUrlAccessTestHelper(views.getContents0(), views.getClient0(), 0), 1682 new AwSettingsFileUrlAccessTestHelper(views.getContents1(), views.getClient1(), 1)); 1683 } 1684 1685 @SmallTest 1686 @Feature({"AndroidWebView", "Preferences"}) 1687 public void testContentUrlAccessWithTwoViews() throws Throwable { 1688 ViewPair views = createViews(); 1689 runPerViewSettingsTest( 1690 new AwSettingsContentUrlAccessTestHelper(views.getContents0(), views.getClient0(), 0), 1691 new AwSettingsContentUrlAccessTestHelper(views.getContents1(), views.getClient1(), 1)); 1692 } 1693 1694 @SmallTest 1695 @Feature({"AndroidWebView", "Preferences", "Navigation"}) 1696 public void testBlockingContentUrlsFromDataUrls() throws Throwable { 1697 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1698 final AwTestContainerView testContainerView = 1699 createAwTestContainerViewOnMainSync(contentClient); 1700 final AwContents awContents = testContainerView.getAwContents(); 1701 final String target = "content_from_data"; 1702 final String page = "<html><body>" + 1703 "<img src=\"" + 1704 createContentUrl(target) + "\">" + 1705 "</body></html>"; 1706 resetResourceRequestCountInContentProvider(target); 1707 loadDataSync( 1708 awContents, 1709 contentClient.getOnPageFinishedHelper(), 1710 page, 1711 "text/html", 1712 false); 1713 ensureResourceRequestCountInContentProvider(target, 0); 1714 } 1715 1716 @SmallTest 1717 @Feature({"AndroidWebView", "Preferences", "Navigation"}) 1718 public void testContentUrlFromFileWithTwoViews() throws Throwable { 1719 ViewPair views = createViews(); 1720 runPerViewSettingsTest( 1721 new AwSettingsContentUrlAccessFromFileTestHelper( 1722 views.getContents0(), views.getClient0(), 0), 1723 new AwSettingsContentUrlAccessFromFileTestHelper( 1724 views.getContents1(), views.getClient1(), 1)); 1725 } 1726 1727 @SmallTest 1728 @Feature({"AndroidWebView", "Preferences"}) 1729 public void testBlockNetworkImagesDoesNotBlockDataUrlImage() throws Throwable { 1730 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1731 final AwTestContainerView testContainerView = 1732 createAwTestContainerViewOnMainSync(contentClient); 1733 final AwContents awContents = testContainerView.getAwContents(); 1734 final AwSettings settings = getAwSettingsOnUiThread(awContents); 1735 ImagePageGenerator generator = new ImagePageGenerator(0, false); 1736 1737 settings.setJavaScriptEnabled(true); 1738 settings.setImagesEnabled(false); 1739 loadDataSync(awContents, 1740 contentClient.getOnPageFinishedHelper(), 1741 generator.getPageSource(), 1742 "text/html", 1743 false); 1744 assertEquals(ImagePageGenerator.IMAGE_LOADED_STRING, getTitleOnUiThread(awContents)); 1745 } 1746 1747 @SmallTest 1748 @Feature({"AndroidWebView", "Preferences"}) 1749 public void testBlockNetworkImagesBlocksNetworkImageAndReloadInPlace() throws Throwable { 1750 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1751 final AwTestContainerView testContainerView = 1752 createAwTestContainerViewOnMainSync(contentClient); 1753 final AwContents awContents = testContainerView.getAwContents(); 1754 final AwSettings settings = getAwSettingsOnUiThread(awContents); 1755 settings.setJavaScriptEnabled(true); 1756 ImagePageGenerator generator = new ImagePageGenerator(0, false); 1757 1758 TestWebServer webServer = null; 1759 try { 1760 webServer = new TestWebServer(false); 1761 final String imagePath = "/image.png"; 1762 webServer.setResponseBase64(imagePath, generator.getImageSourceNoAdvance(), 1763 CommonResources.getImagePngHeaders(false)); 1764 1765 final String pagePath = "/html_image.html"; 1766 final String httpUrlImageHtml = generator.getPageTemplateSource(imagePath); 1767 final String httpImageUrl = webServer.setResponse(pagePath, httpUrlImageHtml, null); 1768 1769 settings.setImagesEnabled(false); 1770 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), httpImageUrl); 1771 assertEquals(ImagePageGenerator.IMAGE_NOT_LOADED_STRING, 1772 getTitleOnUiThread(awContents)); 1773 1774 settings.setImagesEnabled(true); 1775 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { 1776 @Override 1777 public boolean isSatisfied() { 1778 try { 1779 return ImagePageGenerator.IMAGE_LOADED_STRING.equals( 1780 getTitleOnUiThread(awContents)); 1781 } catch (Throwable t) { 1782 t.printStackTrace(); 1783 fail("Failed to getTitleOnUIThread: " + t.toString()); 1784 return false; 1785 } 1786 } 1787 }, TEST_TIMEOUT, CHECK_INTERVAL)); 1788 } finally { 1789 if (webServer != null) webServer.shutdown(); 1790 } 1791 } 1792 1793 @SmallTest 1794 @Feature({"AndroidWebView", "Preferences"}) 1795 public void testBlockNetworkLoadsWithHttpResources() throws Throwable { 1796 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1797 final AwTestContainerView testContainer = 1798 createAwTestContainerViewOnMainSync(contentClient); 1799 final AwContents awContents = testContainer.getAwContents(); 1800 final AwSettings awSettings = getAwSettingsOnUiThread(awContents); 1801 awSettings.setJavaScriptEnabled(true); 1802 ImagePageGenerator generator = new ImagePageGenerator(0, false); 1803 1804 TestWebServer webServer = null; 1805 String fileName = null; 1806 try { 1807 // Set up http image. 1808 webServer = new TestWebServer(false); 1809 final String httpPath = "/image.png"; 1810 final String imageUrl = webServer.setResponseBase64( 1811 httpPath, generator.getImageSourceNoAdvance(), 1812 CommonResources.getImagePngHeaders(true)); 1813 1814 // Set up file html that loads http iframe. 1815 String pageHtml ="<img src='" + imageUrl + "' " + 1816 "onload=\"document.title='img_onload_fired';\" " + 1817 "onerror=\"document.title='img_onerror_fired';\" />"; 1818 Context context = getInstrumentation().getTargetContext(); 1819 fileName = context.getCacheDir() + "/block_network_loads_test.html"; 1820 TestFileUtil.deleteFile(fileName); // Remove leftover file if any. 1821 TestFileUtil.createNewHtmlFile(fileName, "unset", pageHtml); 1822 1823 // Actual test. Blocking should trigger onerror handler. 1824 awSettings.setBlockNetworkLoads(true); 1825 loadUrlSync( 1826 awContents, 1827 contentClient.getOnPageFinishedHelper(), 1828 "file:///" + fileName); 1829 assertEquals(0, webServer.getRequestCount(httpPath)); 1830 assertEquals("img_onerror_fired", getTitleOnUiThread(awContents)); 1831 1832 // Unblock should load normally. 1833 awSettings.setBlockNetworkLoads(false); 1834 loadUrlSync( 1835 awContents, 1836 contentClient.getOnPageFinishedHelper(), 1837 "file:///" + fileName); 1838 assertEquals(1, webServer.getRequestCount(httpPath)); 1839 assertEquals("img_onload_fired", getTitleOnUiThread(awContents)); 1840 } finally { 1841 if (fileName != null) TestFileUtil.deleteFile(fileName); 1842 if (webServer != null) webServer.shutdown(); 1843 } 1844 } 1845 1846 // Test an assert URL (file:///android_asset/) 1847 @SmallTest 1848 @Feature({"AndroidWebView", "Navigation"}) 1849 public void testAssetUrl() throws Throwable { 1850 // Note: this text needs to be kept in sync with the contents of the html file referenced 1851 // below. 1852 final String expectedTitle = "Asset File"; 1853 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1854 final AwTestContainerView testContainerView = 1855 createAwTestContainerViewOnMainSync(contentClient); 1856 final AwContents awContents = testContainerView.getAwContents(); 1857 loadUrlSync(awContents, 1858 contentClient.getOnPageFinishedHelper(), 1859 "file:///android_asset/asset_file.html"); 1860 assertEquals(expectedTitle, getTitleOnUiThread(awContents)); 1861 } 1862 1863 // Test a resource URL (file:///android_res/). 1864 @SmallTest 1865 @Feature({"AndroidWebView", "Navigation"}) 1866 public void testResourceUrl() throws Throwable { 1867 // Note: this text needs to be kept in sync with the contents of the html file referenced 1868 // below. 1869 final String expectedTitle = "Resource File"; 1870 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1871 final AwTestContainerView testContainerView = 1872 createAwTestContainerViewOnMainSync(contentClient); 1873 final AwContents awContents = testContainerView.getAwContents(); 1874 loadUrlSync(awContents, 1875 contentClient.getOnPageFinishedHelper(), 1876 "file:///android_res/raw/resource_file.html"); 1877 assertEquals(expectedTitle, getTitleOnUiThread(awContents)); 1878 } 1879 1880 // Test that the file URL access toggle does not affect asset URLs. 1881 @SmallTest 1882 @Feature({"AndroidWebView", "Navigation"}) 1883 public void testFileUrlAccessToggleDoesNotBlockAssetUrls() throws Throwable { 1884 // Note: this text needs to be kept in sync with the contents of the html file referenced 1885 // below. 1886 final String expectedTitle = "Asset File"; 1887 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1888 final AwTestContainerView testContainerView = 1889 createAwTestContainerViewOnMainSync(contentClient); 1890 final AwContents awContents = testContainerView.getAwContents(); 1891 final AwSettings settings = getAwSettingsOnUiThread(awContents); 1892 settings.setAllowFileAccess(false); 1893 loadUrlSync(awContents, 1894 contentClient.getOnPageFinishedHelper(), 1895 "file:///android_asset/asset_file.html"); 1896 assertEquals(expectedTitle, getTitleOnUiThread(awContents)); 1897 } 1898 1899 // Test that the file URL access toggle does not affect resource URLs. 1900 @SmallTest 1901 @Feature({"AndroidWebView", "Navigation"}) 1902 public void testFileUrlAccessToggleDoesNotBlockResourceUrls() throws Throwable { 1903 // Note: this text needs to be kept in sync with the contents of the html file referenced 1904 // below. 1905 final String expectedTitle = "Resource File"; 1906 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1907 final AwTestContainerView testContainerView = 1908 createAwTestContainerViewOnMainSync(contentClient); 1909 final AwContents awContents = testContainerView.getAwContents(); 1910 final AwSettings settings = getAwSettingsOnUiThread(awContents); 1911 settings.setAllowFileAccess(false); 1912 loadUrlSync(awContents, 1913 contentClient.getOnPageFinishedHelper(), 1914 "file:///android_res/raw/resource_file.html"); 1915 assertEquals(expectedTitle, getTitleOnUiThread(awContents)); 1916 } 1917 1918 @SmallTest 1919 @Feature({"AndroidWebView", "Preferences"}) 1920 public void testLayoutAlgorithmWithTwoViews() throws Throwable { 1921 ViewPair views = createViews(); 1922 runPerViewSettingsTest( 1923 new AwSettingsLayoutAlgorithmTestHelper(views.getContents0(), views.getClient0()), 1924 new AwSettingsLayoutAlgorithmTestHelper(views.getContents1(), views.getClient1())); 1925 } 1926 1927 @SmallTest 1928 @Feature({"AndroidWebView", "Preferences"}) 1929 public void testTextZoomWithTwoViews() throws Throwable { 1930 ViewPair views = createViews(); 1931 runPerViewSettingsTest( 1932 new AwSettingsTextZoomTestHelper(views.getContents0(), views.getClient0()), 1933 new AwSettingsTextZoomTestHelper(views.getContents1(), views.getClient1())); 1934 } 1935 1936 @SmallTest 1937 @Feature({"AndroidWebView", "Preferences"}) 1938 public void testTextZoomAutosizingWithTwoViews() throws Throwable { 1939 ViewPair views = createViews(); 1940 runPerViewSettingsTest( 1941 new AwSettingsTextZoomAutosizingTestHelper(views.getContents0(), views.getClient0()), 1942 new AwSettingsTextZoomAutosizingTestHelper(views.getContents1(), views.getClient1())); 1943 } 1944 1945 @SmallTest 1946 @Feature({"AndroidWebView", "Preferences"}) 1947 public void testJavaScriptPopupsWithTwoViews() throws Throwable { 1948 ViewPair views = createViews(); 1949 runPerViewSettingsTest( 1950 new AwSettingsJavaScriptPopupsTestHelper(views.getContents0(), views.getClient0()), 1951 new AwSettingsJavaScriptPopupsTestHelper(views.getContents1(), views.getClient1())); 1952 } 1953 1954 @SmallTest 1955 @Feature({"AndroidWebView", "Preferences"}) 1956 public void testCacheMode() throws Throwable { 1957 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1958 final AwTestContainerView testContainer = 1959 createAwTestContainerViewOnMainSync(contentClient); 1960 final AwContents awContents = testContainer.getAwContents(); 1961 final AwSettings awSettings = getAwSettingsOnUiThread(testContainer.getAwContents()); 1962 clearCacheOnUiThread(awContents, true); 1963 1964 assertEquals(WebSettings.LOAD_DEFAULT, awSettings.getCacheMode()); 1965 TestWebServer webServer = null; 1966 try { 1967 webServer = new TestWebServer(false); 1968 final String htmlPath = "/testCacheMode.html"; 1969 final String url = webServer.setResponse(htmlPath, "response", null); 1970 awSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); 1971 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); 1972 assertEquals(1, webServer.getRequestCount(htmlPath)); 1973 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); 1974 assertEquals(1, webServer.getRequestCount(htmlPath)); 1975 1976 awSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); 1977 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); 1978 assertEquals(2, webServer.getRequestCount(htmlPath)); 1979 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); 1980 assertEquals(3, webServer.getRequestCount(htmlPath)); 1981 1982 awSettings.setCacheMode(WebSettings.LOAD_CACHE_ONLY); 1983 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); 1984 assertEquals(3, webServer.getRequestCount(htmlPath)); 1985 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); 1986 assertEquals(3, webServer.getRequestCount(htmlPath)); 1987 1988 final String htmlNotInCachePath = "/testCacheMode-not-in-cache.html"; 1989 final String urlNotInCache = webServer.setResponse(htmlNotInCachePath, "", null); 1990 loadUrlSyncAndExpectError(awContents, 1991 contentClient.getOnPageFinishedHelper(), 1992 contentClient.getOnReceivedErrorHelper(), 1993 urlNotInCache); 1994 assertEquals(0, webServer.getRequestCount(htmlNotInCachePath)); 1995 } finally { 1996 if (webServer != null) webServer.shutdown(); 1997 } 1998 } 1999 2000 @SmallTest 2001 @Feature({"AndroidWebView", "Preferences"}) 2002 // As our implementation of network loads blocking uses the same net::URLRequest settings, make 2003 // sure that setting cache mode doesn't accidentally enable network loads. The reference 2004 // behaviour is that when network loads are blocked, setting cache mode has no effect. 2005 public void testCacheModeWithBlockedNetworkLoads() throws Throwable { 2006 final TestAwContentsClient contentClient = new TestAwContentsClient(); 2007 final AwTestContainerView testContainer = 2008 createAwTestContainerViewOnMainSync(contentClient); 2009 final AwContents awContents = testContainer.getAwContents(); 2010 final AwSettings awSettings = getAwSettingsOnUiThread(testContainer.getAwContents()); 2011 clearCacheOnUiThread(awContents, true); 2012 2013 assertEquals(WebSettings.LOAD_DEFAULT, awSettings.getCacheMode()); 2014 awSettings.setBlockNetworkLoads(true); 2015 TestWebServer webServer = null; 2016 try { 2017 webServer = new TestWebServer(false); 2018 final String htmlPath = "/testCacheModeWithBlockedNetworkLoads.html"; 2019 final String url = webServer.setResponse(htmlPath, "response", null); 2020 loadUrlSyncAndExpectError(awContents, 2021 contentClient.getOnPageFinishedHelper(), 2022 contentClient.getOnReceivedErrorHelper(), 2023 url); 2024 assertEquals(0, webServer.getRequestCount(htmlPath)); 2025 2026 awSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); 2027 loadUrlSyncAndExpectError(awContents, 2028 contentClient.getOnPageFinishedHelper(), 2029 contentClient.getOnReceivedErrorHelper(), 2030 url); 2031 assertEquals(0, webServer.getRequestCount(htmlPath)); 2032 2033 awSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); 2034 loadUrlSyncAndExpectError(awContents, 2035 contentClient.getOnPageFinishedHelper(), 2036 contentClient.getOnReceivedErrorHelper(), 2037 url); 2038 assertEquals(0, webServer.getRequestCount(htmlPath)); 2039 2040 awSettings.setCacheMode(WebSettings.LOAD_CACHE_ONLY); 2041 loadUrlSyncAndExpectError(awContents, 2042 contentClient.getOnPageFinishedHelper(), 2043 contentClient.getOnReceivedErrorHelper(), 2044 url); 2045 assertEquals(0, webServer.getRequestCount(htmlPath)); 2046 } finally { 2047 if (webServer != null) webServer.shutdown(); 2048 } 2049 } 2050 2051 @SmallTest 2052 @Feature({"AndroidWebView", "Preferences"}) 2053 public void testCacheModeWithTwoViews() throws Throwable { 2054 ViewPair views = createViews(); 2055 TestWebServer webServer = null; 2056 try { 2057 webServer = new TestWebServer(false); 2058 runPerViewSettingsTest( 2059 new AwSettingsCacheModeTestHelper( 2060 views.getContents0(), views.getClient0(), 0, webServer), 2061 new AwSettingsCacheModeTestHelper( 2062 views.getContents1(), views.getClient1(), 1, webServer)); 2063 } finally { 2064 if (webServer != null) webServer.shutdown(); 2065 } 2066 } 2067 2068 static class ManifestTestHelper { 2069 private final TestWebServer mWebServer; 2070 private final String mHtmlPath; 2071 private final String mHtmlUrl; 2072 private final String mManifestPath; 2073 2074 ManifestTestHelper( 2075 TestWebServer webServer, String htmlPageName, String manifestName) { 2076 mWebServer = webServer; 2077 mHtmlPath = "/" + htmlPageName; 2078 mHtmlUrl = webServer.setResponse( 2079 mHtmlPath, "<html manifest=\"" + manifestName + "\"></html>", null); 2080 mManifestPath = "/" + manifestName; 2081 webServer.setResponse( 2082 mManifestPath, 2083 "CACHE MANIFEST", 2084 CommonResources.getContentTypeAndCacheHeaders("text/cache-manifest", false)); 2085 } 2086 2087 String getHtmlPath() { 2088 return mHtmlPath; 2089 } 2090 2091 String getHtmlUrl() { 2092 return mHtmlUrl; 2093 } 2094 2095 String getManifestPath() { 2096 return mManifestPath; 2097 } 2098 2099 int waitUntilHtmlIsRequested(final int initialRequestCount) throws InterruptedException { 2100 return waitUntilResourceIsRequested(mHtmlPath, initialRequestCount); 2101 } 2102 2103 int waitUntilManifestIsRequested(final int initialRequestCount) 2104 throws InterruptedException { 2105 return waitUntilResourceIsRequested(mManifestPath, initialRequestCount); 2106 } 2107 2108 private int waitUntilResourceIsRequested( 2109 final String path, final int initialRequestCount) throws InterruptedException { 2110 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { 2111 @Override 2112 public boolean isSatisfied() { 2113 return mWebServer.getRequestCount(path) > initialRequestCount; 2114 } 2115 }, TEST_TIMEOUT, CHECK_INTERVAL)); 2116 return mWebServer.getRequestCount(path); 2117 } 2118 } 2119 2120 @SmallTest 2121 @Feature({"AndroidWebView", "Preferences", "AppCache"}) 2122 public void testAppCache() throws Throwable { 2123 final TestAwContentsClient contentClient = new TestAwContentsClient(); 2124 final AwTestContainerView testContainer = 2125 createAwTestContainerViewOnMainSync(contentClient); 2126 final AwContents awContents = testContainer.getAwContents(); 2127 final AwSettings settings = getAwSettingsOnUiThread(awContents); 2128 settings.setJavaScriptEnabled(true); 2129 // Note that the cache isn't actually enabled until the call to setAppCachePath. 2130 settings.setAppCacheEnabled(true); 2131 2132 TestWebServer webServer = null; 2133 try { 2134 webServer = new TestWebServer(false); 2135 ManifestTestHelper helper = new ManifestTestHelper( 2136 webServer, "testAppCache.html", "appcache.manifest"); 2137 loadUrlSync( 2138 awContents, 2139 contentClient.getOnPageFinishedHelper(), 2140 helper.getHtmlUrl()); 2141 helper.waitUntilHtmlIsRequested(0); 2142 // Unfortunately, there is no other good way of verifying that AppCache is 2143 // disabled, other than checking that it didn't try to fetch the manifest. 2144 Thread.sleep(1000); 2145 assertEquals(0, webServer.getRequestCount(helper.getManifestPath())); 2146 settings.setAppCachePath("whatever"); // Enables AppCache. 2147 loadUrlSync( 2148 awContents, 2149 contentClient.getOnPageFinishedHelper(), 2150 helper.getHtmlUrl()); 2151 helper.waitUntilManifestIsRequested(0); 2152 } finally { 2153 if (webServer != null) webServer.shutdown(); 2154 } 2155 } 2156 2157 /* 2158 * @SmallTest 2159 * @Feature({"AndroidWebView", "Preferences", "AppCache"}) 2160 * This test is flaky but the root cause is not found yet. See crbug.com/171765. 2161 */ 2162 @DisabledTest 2163 public void testAppCacheWithTwoViews() throws Throwable { 2164 // We don't use the test helper here, because making sure that AppCache 2165 // is disabled takes a lot of time, so running through the usual drill 2166 // will take about 20 seconds. 2167 ViewPair views = createViews(); 2168 2169 AwSettings settings0 = getAwSettingsOnUiThread(views.getContents0()); 2170 settings0.setJavaScriptEnabled(true); 2171 settings0.setAppCachePath("whatever"); 2172 settings0.setAppCacheEnabled(true); 2173 AwSettings settings1 = getAwSettingsOnUiThread(views.getContents1()); 2174 settings1.setJavaScriptEnabled(true); 2175 // AppCachePath setting is global, no need to set it for the second view. 2176 settings1.setAppCacheEnabled(true); 2177 2178 TestWebServer webServer = null; 2179 try { 2180 webServer = new TestWebServer(false); 2181 ManifestTestHelper helper0 = new ManifestTestHelper( 2182 webServer, "testAppCache_0.html", "appcache.manifest_0"); 2183 loadUrlSync( 2184 views.getContents0(), 2185 views.getClient0().getOnPageFinishedHelper(), 2186 helper0.getHtmlUrl()); 2187 int manifestRequests0 = helper0.waitUntilManifestIsRequested(0); 2188 ManifestTestHelper helper1 = new ManifestTestHelper( 2189 webServer, "testAppCache_1.html", "appcache.manifest_1"); 2190 loadUrlSync( 2191 views.getContents1(), 2192 views.getClient1().getOnPageFinishedHelper(), 2193 helper1.getHtmlUrl()); 2194 helper1.waitUntilManifestIsRequested(0); 2195 settings1.setAppCacheEnabled(false); 2196 loadUrlSync( 2197 views.getContents0(), 2198 views.getClient0().getOnPageFinishedHelper(), 2199 helper0.getHtmlUrl()); 2200 helper0.waitUntilManifestIsRequested(manifestRequests0); 2201 final int prevManifestRequestCount = 2202 webServer.getRequestCount(helper1.getManifestPath()); 2203 int htmlRequests1 = webServer.getRequestCount(helper1.getHtmlPath()); 2204 loadUrlSync( 2205 views.getContents1(), 2206 views.getClient1().getOnPageFinishedHelper(), 2207 helper1.getHtmlUrl()); 2208 helper1.waitUntilHtmlIsRequested(htmlRequests1); 2209 // Unfortunately, there is no other good way of verifying that AppCache is 2210 // disabled, other than checking that it didn't try to fetch the manifest. 2211 Thread.sleep(1000); 2212 assertEquals( 2213 prevManifestRequestCount, webServer.getRequestCount(helper1.getManifestPath())); 2214 } finally { 2215 if (webServer != null) webServer.shutdown(); 2216 } 2217 } 2218 2219 @SmallTest 2220 @Feature({"AndroidWebView", "Preferences"}) 2221 public void testUseWideViewportWithTwoViews() throws Throwable { 2222 ViewPair views = createViews(); 2223 runPerViewSettingsTest( 2224 new AwSettingsUseWideViewportTestHelper(views.getContents0(), views.getClient0()), 2225 new AwSettingsUseWideViewportTestHelper(views.getContents1(), views.getClient1())); 2226 } 2227 2228 @SmallTest 2229 @Feature({"AndroidWebView", "Preferences"}) 2230 public void testUseWideViewportLayoutWidth() throws Throwable { 2231 final TestAwContentsClient contentClient = new TestAwContentsClient(); 2232 final AwTestContainerView testContainerView = 2233 createAwTestContainerViewOnMainSync(contentClient); 2234 final AwContents awContents = testContainerView.getAwContents(); 2235 AwSettings settings = getAwSettingsOnUiThread(awContents); 2236 CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); 2237 2238 final String pageTemplate = "<html><head>%s</head>" + 2239 "<body onload='document.title=document.body.clientWidth'></body></html>"; 2240 final String pageNoViewport = String.format(pageTemplate, ""); 2241 final String pageViewportDeviceWidth = String.format( 2242 pageTemplate, 2243 "<meta name='viewport' content='width=device-width' />"); 2244 final String viewportTagSpecifiedWidth = "3000"; 2245 final String pageViewportSpecifiedWidth = String.format( 2246 pageTemplate, 2247 "<meta name='viewport' content='width=" + viewportTagSpecifiedWidth + "' />"); 2248 2249 DeviceDisplayInfo deviceInfo = 2250 DeviceDisplayInfo.create(getInstrumentation().getTargetContext()); 2251 int displayWidth = (int) (deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale()); 2252 2253 settings.setJavaScriptEnabled(true); 2254 assertFalse(settings.getUseWideViewPort()); 2255 // When UseWideViewPort is off, "width" setting of "meta viewport" 2256 // tags is ignored, and the layout width is set to device width in CSS pixels. 2257 // Thus, all 3 pages will have the same body width. 2258 loadDataSync(awContents, onPageFinishedHelper, pageNoViewport, "text/html", false); 2259 int actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); 2260 // Avoid rounding errors. 2261 assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth, 2262 Math.abs(displayWidth - actualWidth) <= 1); 2263 loadDataSync(awContents, onPageFinishedHelper, pageViewportDeviceWidth, "text/html", false); 2264 actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); 2265 assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth, 2266 Math.abs(displayWidth - actualWidth) <= 1); 2267 loadDataSync( 2268 awContents, onPageFinishedHelper, pageViewportSpecifiedWidth, "text/html", false); 2269 actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); 2270 assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth, 2271 Math.abs(displayWidth - actualWidth) <= 1); 2272 2273 settings.setUseWideViewPort(true); 2274 // When UseWideViewPort is on, "meta viewport" tag is used. 2275 // If there is no viewport tag, or width isn't specified, 2276 // then layout width is set to max(980, <device-width-in-DIP-pixels>) 2277 loadDataSync(awContents, onPageFinishedHelper, pageNoViewport, "text/html", false); 2278 actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); 2279 assertTrue("Expected: >= 980 , Actual: " + actualWidth, actualWidth >= 980); 2280 loadDataSync(awContents, onPageFinishedHelper, pageViewportDeviceWidth, "text/html", false); 2281 actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); 2282 assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth, 2283 Math.abs(displayWidth - actualWidth) <= 1); 2284 loadDataSync( 2285 awContents, onPageFinishedHelper, pageViewportSpecifiedWidth, "text/html", false); 2286 assertEquals(viewportTagSpecifiedWidth, getTitleOnUiThread(awContents)); 2287 } 2288 2289 /* 2290 @MediumTest 2291 @Feature({"AndroidWebView", "Preferences"}) 2292 http://crbug.com/239144 2293 */ 2294 @DisabledTest 2295 public void testUseWideViewportControlsDoubleTabToZoom() throws Throwable { 2296 final TestAwContentsClient contentClient = new TestAwContentsClient(); 2297 final AwTestContainerView testContainerView = 2298 createAwTestContainerViewOnMainSync(contentClient); 2299 final AwContents awContents = testContainerView.getAwContents(); 2300 AwSettings settings = getAwSettingsOnUiThread(awContents); 2301 CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); 2302 2303 final String page = "<html><body>Page Text</body></html>"; 2304 assertFalse(settings.getUseWideViewPort()); 2305 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); 2306 final float initialScale = getScaleOnUiThread(awContents); 2307 simulateDoubleTapCenterOfWebViewOnUiThread(testContainerView); 2308 Thread.sleep(1000); 2309 assertEquals(initialScale, getScaleOnUiThread(awContents)); 2310 2311 settings.setUseWideViewPort(true); 2312 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); 2313 int onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount(); 2314 simulateDoubleTapCenterOfWebViewOnUiThread(testContainerView); 2315 contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount); 2316 final float zoomedOutScale = getScaleOnUiThread(awContents); 2317 assertTrue("zoomedOut: " + zoomedOutScale + ", initial: " + initialScale, 2318 zoomedOutScale < initialScale); 2319 } 2320 2321 /* 2322 @SmallTest 2323 @Feature({"AndroidWebView", "Preferences"}) 2324 http://crbug.com/239144 2325 */ 2326 @DisabledTest 2327 public void testLoadWithOverviewModeWithTwoViews() throws Throwable { 2328 ViewPair views = createViews(); 2329 runPerViewSettingsTest( 2330 new AwSettingsLoadWithOverviewModeTestHelper( 2331 views.getContents0(), views.getClient0(), false), 2332 new AwSettingsLoadWithOverviewModeTestHelper( 2333 views.getContents1(), views.getClient1(), false)); 2334 } 2335 2336 /* 2337 @SmallTest 2338 @Feature({"AndroidWebView", "Preferences"}) 2339 http://crbug.com/239144 2340 */ 2341 @DisabledTest 2342 public void testLoadWithOverviewModeViewportTagWithTwoViews() throws Throwable { 2343 ViewPair views = createViews(); 2344 runPerViewSettingsTest( 2345 new AwSettingsLoadWithOverviewModeTestHelper( 2346 views.getContents0(), views.getClient0(), true), 2347 new AwSettingsLoadWithOverviewModeTestHelper( 2348 views.getContents1(), views.getClient1(), true)); 2349 } 2350 2351 @SmallTest 2352 @Feature({"AndroidWebView", "Preferences"}) 2353 public void testSetInitialScale() throws Throwable { 2354 final TestAwContentsClient contentClient = new TestAwContentsClient(); 2355 final AwTestContainerView testContainerView = 2356 createAwTestContainerViewOnMainSync(contentClient); 2357 final AwContents awContents = testContainerView.getAwContents(); 2358 final AwSettings awSettings = getAwSettingsOnUiThread(awContents); 2359 CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); 2360 2361 WindowManager wm = (WindowManager) getInstrumentation().getTargetContext() 2362 .getSystemService(Context.WINDOW_SERVICE); 2363 Point screenSize = new Point(); 2364 wm.getDefaultDisplay().getSize(screenSize); 2365 // Make sure after 50% scale, page width still larger than screen. 2366 int height = screenSize.y * 2 + 1; 2367 int width = screenSize.x * 2 + 1; 2368 final String page = "<html><body>" + 2369 "<p style='height:"+ height + "px;width:" + width + "px'>" + 2370 "testSetInitialScale</p></body></html>"; 2371 final float defaultScale = 2372 getInstrumentation().getTargetContext().getResources().getDisplayMetrics().density; 2373 2374 assertEquals(defaultScale, getPixelScaleOnUiThread(awContents), .01f); 2375 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); 2376 assertEquals(defaultScale, getPixelScaleOnUiThread(awContents), .01f); 2377 2378 int onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount(); 2379 awSettings.setInitialPageScale(50); 2380 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); 2381 contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount); 2382 assertEquals(0.5f, getPixelScaleOnUiThread(awContents), .01f); 2383 2384 onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount(); 2385 awSettings.setInitialPageScale(500); 2386 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); 2387 contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount); 2388 assertEquals(5.0f, getPixelScaleOnUiThread(awContents), .01f); 2389 2390 onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount(); 2391 awSettings.setInitialPageScale(0); 2392 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); 2393 contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount); 2394 assertEquals(defaultScale, getPixelScaleOnUiThread(awContents), .01f); 2395 } 2396 2397 /** 2398 * Run video test. 2399 * @param requiredUserGesture the settings of MediaPlaybackRequiresUserGesture. 2400 * @param waitTime time for waiting event happen, -1 means forever. 2401 * @return true if the event happened, 2402 * @throws Throwable throw exception if timeout. 2403 */ 2404 private boolean runVideoTest(final boolean requiredUserGesture, long waitTime) 2405 throws Throwable { 2406 final JavascriptEventObserver observer = new JavascriptEventObserver(); 2407 TestAwContentsClient client = new TestAwContentsClient(); 2408 final AwContents awContents = createAwTestContainerViewOnMainSync(client).getAwContents(); 2409 getInstrumentation().runOnMainSync(new Runnable() { 2410 @Override 2411 public void run() { 2412 AwSettings awSettings = awContents.getSettings(); 2413 awSettings.setJavaScriptEnabled(true); 2414 awSettings.setMediaPlaybackRequiresUserGesture(requiredUserGesture); 2415 observer.register(awContents.getContentViewCore(), "javaObserver"); 2416 } 2417 }); 2418 VideoTestWebServer webServer = new VideoTestWebServer(getActivity()); 2419 try { 2420 String data = "<html><head><script>" + 2421 "addEventListener('DOMContentLoaded', function() { " + 2422 " document.getElementById('video').addEventListener('play', function() { " + 2423 " javaObserver.notifyJava(); " + 2424 " }, false); " + 2425 "}, false); " + 2426 "</script></head><body>" + 2427 "<video id='video' autoplay control src='" + 2428 webServer.getOnePixelOneFrameWebmURL() + "' /> </body></html>"; 2429 loadDataAsync(awContents, data, "text/html", false); 2430 if (waitTime == -1) { 2431 observer.waitForEvent(); 2432 return true; 2433 } 2434 else { 2435 return observer.waitForEvent(waitTime); 2436 } 2437 } finally { 2438 if (webServer != null && webServer.getTestWebServer() != null) 2439 webServer.getTestWebServer().shutdown(); 2440 } 2441 } 2442 2443 /* 2444 @LargeTest 2445 @Feature({"AndroidWebView", "Preferences"}) 2446 Disabled until video is working. crbug.com/239760 2447 */ 2448 @DisabledTest 2449 public void testMediaPlaybackWithoutUserGesture() throws Throwable { 2450 assertTrue(runVideoTest(false, -1)); 2451 } 2452 2453 /* 2454 @SmallTest 2455 @Feature({"AndroidWebView", "Preferences"}) 2456 Disabled until video is working. crbug.com/239760 2457 */ 2458 @DisabledTest 2459 public void testMediaPlaybackWithUserGesture() throws Throwable { 2460 // Wait for 5 second to see if video played. 2461 assertFalse(runVideoTest(true, 5000)); 2462 } 2463 2464 @SmallTest 2465 @Feature({"AndroidWebView", "Preferences"}) 2466 public void testDefaultVideoPosterURL() throws Throwable { 2467 final CallbackHelper videoPosterAccessedCallbackHelper = new CallbackHelper(); 2468 final String DEFAULT_VIDEO_POSTER_URL = "http://default_video_poster/"; 2469 TestAwContentsClient client = new TestAwContentsClient() { 2470 @Override 2471 public InterceptedRequestData shouldInterceptRequest(String url) { 2472 if (url.equals(DEFAULT_VIDEO_POSTER_URL)) { 2473 videoPosterAccessedCallbackHelper.notifyCalled(); 2474 } 2475 return null; 2476 } 2477 }; 2478 final AwContents awContents = createAwTestContainerViewOnMainSync(client).getAwContents(); 2479 getInstrumentation().runOnMainSync(new Runnable() { 2480 @Override 2481 public void run() { 2482 AwSettings awSettings = awContents.getSettings(); 2483 awSettings.setDefaultVideoPosterURL(DEFAULT_VIDEO_POSTER_URL); 2484 } 2485 }); 2486 VideoTestWebServer webServer = new VideoTestWebServer( 2487 getInstrumentation().getTargetContext()); 2488 try { 2489 String data = "<html><head><body>" + 2490 "<video id='video' control src='" + 2491 webServer.getOnePixelOneFrameWebmURL() + "' /> </body></html>"; 2492 loadDataAsync(awContents, data, "text/html", false); 2493 videoPosterAccessedCallbackHelper.waitForCallback(0, 1, 20, TimeUnit.SECONDS); 2494 } finally { 2495 if (webServer.getTestWebServer() != null) 2496 webServer.getTestWebServer().shutdown(); 2497 } 2498 } 2499 2500 static class ViewPair { 2501 private final AwContents contents0; 2502 private final TestAwContentsClient client0; 2503 private final AwContents contents1; 2504 private final TestAwContentsClient client1; 2505 2506 ViewPair(AwContents contents0, TestAwContentsClient client0, 2507 AwContents contents1, TestAwContentsClient client1) { 2508 this.contents0 = contents0; 2509 this.client0 = client0; 2510 this.contents1 = contents1; 2511 this.client1 = client1; 2512 } 2513 2514 AwContents getContents0() { 2515 return contents0; 2516 } 2517 2518 TestAwContentsClient getClient0() { 2519 return client0; 2520 } 2521 2522 AwContents getContents1() { 2523 return contents1; 2524 } 2525 2526 TestAwContentsClient getClient1() { 2527 return client1; 2528 } 2529 } 2530 2531 /** 2532 * Verifies the following statements about a setting: 2533 * - initially, the setting has a default value; 2534 * - the setting can be switched to an alternate value and back; 2535 * - switching a setting in the first WebView doesn't affect the setting 2536 * state in the second WebView and vice versa. 2537 * 2538 * @param helper0 Test helper for the first ContentView 2539 * @param helper1 Test helper for the second ContentView 2540 * @throws Throwable 2541 */ 2542 private void runPerViewSettingsTest(AwSettingsTestHelper helper0, 2543 AwSettingsTestHelper helper1) throws Throwable { 2544 helper0.ensureSettingHasInitialValue(); 2545 helper1.ensureSettingHasInitialValue(); 2546 2547 helper1.setAlteredSettingValue(); 2548 helper0.ensureSettingHasInitialValue(); 2549 helper1.ensureSettingHasAlteredValue(); 2550 2551 helper1.setInitialSettingValue(); 2552 helper0.ensureSettingHasInitialValue(); 2553 helper1.ensureSettingHasInitialValue(); 2554 2555 helper0.setAlteredSettingValue(); 2556 helper0.ensureSettingHasAlteredValue(); 2557 helper1.ensureSettingHasInitialValue(); 2558 2559 helper0.setInitialSettingValue(); 2560 helper0.ensureSettingHasInitialValue(); 2561 helper1.ensureSettingHasInitialValue(); 2562 2563 helper0.setAlteredSettingValue(); 2564 helper0.ensureSettingHasAlteredValue(); 2565 helper1.ensureSettingHasInitialValue(); 2566 2567 helper1.setAlteredSettingValue(); 2568 helper0.ensureSettingHasAlteredValue(); 2569 helper1.ensureSettingHasAlteredValue(); 2570 2571 helper0.setInitialSettingValue(); 2572 helper0.ensureSettingHasInitialValue(); 2573 helper1.ensureSettingHasAlteredValue(); 2574 2575 helper1.setInitialSettingValue(); 2576 helper0.ensureSettingHasInitialValue(); 2577 helper1.ensureSettingHasInitialValue(); 2578 } 2579 2580 private ViewPair createViews() throws Throwable { 2581 TestAwContentsClient client0 = new TestAwContentsClient(); 2582 TestAwContentsClient client1 = new TestAwContentsClient(); 2583 return new ViewPair( 2584 createAwTestContainerViewOnMainSync(client0).getAwContents(), 2585 client0, 2586 createAwTestContainerViewOnMainSync(client1).getAwContents(), 2587 client1); 2588 } 2589 2590 /** 2591 * Verifies the number of resource requests made to the content provider. 2592 * @param resource Resource name 2593 * @param expectedCount Expected resource requests count 2594 */ 2595 private void ensureResourceRequestCountInContentProvider(String resource, int expectedCount) { 2596 Context context = getInstrumentation().getTargetContext(); 2597 int actualCount = TestContentProvider.getResourceRequestCount(context, resource); 2598 assertEquals(expectedCount, actualCount); 2599 } 2600 2601 private void resetResourceRequestCountInContentProvider(String resource) { 2602 Context context = getInstrumentation().getTargetContext(); 2603 TestContentProvider.resetResourceRequestCount(context, resource); 2604 } 2605 2606 private String createContentUrl(final String target) { 2607 return TestContentProvider.createContentUrl(target); 2608 } 2609 2610 /** 2611 * Returns pure page scale. 2612 */ 2613 private float getScaleOnUiThread(final AwContents awContents) throws Throwable { 2614 return runTestOnUiThreadAndGetResult(new Callable<Float>() { 2615 @Override 2616 public Float call() throws Exception { 2617 return awContents.getContentViewCore().getScale(); 2618 } 2619 }); 2620 } 2621 2622 /** 2623 * Returns page scale multiplied by the screen density. 2624 */ 2625 private float getPixelScaleOnUiThread(final AwContents awContents) throws Throwable { 2626 return runTestOnUiThreadAndGetResult(new Callable<Float>() { 2627 @Override 2628 public Float call() throws Exception { 2629 return awContents.getScale(); 2630 } 2631 }); 2632 } 2633 2634 private void simulateDoubleTapCenterOfWebViewOnUiThread(final AwTestContainerView webView) 2635 throws Throwable { 2636 final AwContents awContents = webView.getAwContents(); 2637 runTestOnUiThread(new Runnable() { 2638 @Override 2639 public void run() { 2640 long firstTapTime = SystemClock.uptimeMillis(); 2641 float x = (float)(webView.getRight() - webView.getLeft()) / 2; 2642 float y = (float)(webView.getBottom() - webView.getTop()) / 2; 2643 awContents.onTouchEvent(MotionEvent.obtain( 2644 firstTapTime, firstTapTime, MotionEvent.ACTION_DOWN, 2645 x, y, 0)); 2646 awContents.onTouchEvent(MotionEvent.obtain( 2647 firstTapTime, firstTapTime, MotionEvent.ACTION_UP, 2648 x, y, 0)); 2649 long secondTapTime = firstTapTime + 200; 2650 awContents.onTouchEvent(MotionEvent.obtain( 2651 secondTapTime, secondTapTime, MotionEvent.ACTION_DOWN, 2652 x, y, 0)); 2653 awContents.onTouchEvent(MotionEvent.obtain( 2654 secondTapTime, secondTapTime, MotionEvent.ACTION_UP, 2655 x, y, 0)); 2656 } 2657 }); 2658 } 2659} 2660