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