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