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