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 5 package org.chromium.android_webview.test; 6 7 import android.content.Context; 8 import android.graphics.Point; 9 import android.net.http.SslError; 10 import android.os.Build; 11 import android.os.SystemClock; 12 import android.test.suitebuilder.annotation.MediumTest; 13 import android.test.suitebuilder.annotation.SmallTest; 14 import android.view.WindowManager; 15 import android.webkit.JavascriptInterface; 16 import android.webkit.ValueCallback; 17 import android.webkit.WebSettings; 18 19 import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout; 20 21 import org.apache.http.Header; 22 import org.apache.http.HttpRequest; 23 import org.chromium.android_webview.AwContents; 24 import org.chromium.android_webview.AwContentsClient.ShouldInterceptRequestParams; 25 import org.chromium.android_webview.AwSettings; 26 import org.chromium.android_webview.AwSettings.LayoutAlgorithm; 27 import org.chromium.android_webview.AwWebResourceResponse; 28 import org.chromium.android_webview.test.util.CommonResources; 29 import org.chromium.android_webview.test.util.ImagePageGenerator; 30 import org.chromium.android_webview.test.util.VideoTestUtil; 31 import org.chromium.android_webview.test.util.VideoTestWebServer; 32 import org.chromium.base.test.util.DisabledTest; 33 import org.chromium.base.test.util.Feature; 34 import org.chromium.base.test.util.TestFileUtil; 35 import org.chromium.base.test.util.UrlUtils; 36 import org.chromium.content.browser.test.util.CallbackHelper; 37 import org.chromium.content.browser.test.util.HistoryUtils; 38 import org.chromium.content_public.browser.WebContents; 39 import org.chromium.net.test.util.TestWebServer; 40 import org.chromium.ui.gfx.DeviceDisplayInfo; 41 42 import java.io.File; 43 import java.util.concurrent.Callable; 44 import java.util.concurrent.TimeUnit; 45 import java.util.regex.Matcher; 46 import 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 */ 53 public 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 "Latin-1"; 438 } 439 440 @Override 441 protected String getInitialValue() { 442 return "UTF-8"; 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 class AwSettingsForceZeroLayoutHeightTestHelper extends AwSettingsTestHelper<Boolean> { 1359 1360 AwSettingsForceZeroLayoutHeightTestHelper( 1361 AwTestContainerView containerView, 1362 TestAwContentsClient contentViewClient, 1363 boolean withViewPortTag) throws Throwable { 1364 super(containerView, contentViewClient, true); 1365 mWithViewPortTag = withViewPortTag; 1366 mAwSettings.setUseWideViewPort(true); 1367 } 1368 1369 @Override 1370 protected Boolean getAlteredValue() { 1371 return ENABLED; 1372 } 1373 1374 @Override 1375 protected Boolean getInitialValue() { 1376 return DISABLED; 1377 } 1378 1379 @Override 1380 protected Boolean getCurrentValue() { 1381 return mAwSettings.getForceZeroLayoutHeight(); 1382 } 1383 1384 @Override 1385 protected void setCurrentValue(Boolean value) { 1386 mAwSettings.setForceZeroLayoutHeight(value); 1387 } 1388 1389 @Override 1390 protected void doEnsureSettingHasValue(Boolean value) throws Throwable { 1391 loadDataSync(getData()); 1392 int height = Integer.parseInt(getTitleOnUiThread()); 1393 if (value) { 1394 assertEquals(0, height); 1395 } else { 1396 assertTrue("Div should be at least 50px high, was: " + height, height >= 50); 1397 } 1398 } 1399 1400 private String getData() { 1401 return "<html><head>" + 1402 (mWithViewPortTag ? "<meta name='viewport' content='height=3000' />" : "") + 1403 " <script type='text/javascript'> " + 1404 " window.addEventListener('load', function(event) { " + 1405 " document.title = document.getElementById('testDiv').clientHeight; " + 1406 " }); " + 1407 " </script> " + 1408 "</head>" + 1409 "<body> " + 1410 " <div style='height:50px;'>test</div> " + 1411 " <div id='testDiv' style='height:100%;'></div> " + 1412 "</body></html>"; 1413 } 1414 1415 private final boolean mWithViewPortTag; 1416 } 1417 1418 class AwSettingsZeroLayoutHeightDisablesViewportQuirkTestHelper extends 1419 AwSettingsTestHelper<Boolean> { 1420 1421 AwSettingsZeroLayoutHeightDisablesViewportQuirkTestHelper( 1422 AwTestContainerView containerView, 1423 TestAwContentsClient contentViewClient) throws Throwable { 1424 super(containerView, contentViewClient, true); 1425 mAwSettings.setUseWideViewPort(true); 1426 mAwSettings.setForceZeroLayoutHeight(true); 1427 } 1428 1429 @Override 1430 protected Boolean getAlteredValue() { 1431 return ENABLED; 1432 } 1433 1434 @Override 1435 protected Boolean getInitialValue() { 1436 return DISABLED; 1437 } 1438 1439 @Override 1440 protected Boolean getCurrentValue() { 1441 return mAwSettings.getZeroLayoutHeightDisablesViewportQuirk(); 1442 } 1443 1444 @Override 1445 protected void setCurrentValue(Boolean value) { 1446 mAwSettings.setZeroLayoutHeightDisablesViewportQuirk(value); 1447 } 1448 1449 @Override 1450 protected void doEnsureSettingHasValue(Boolean value) throws Throwable { 1451 DeviceDisplayInfo deviceInfo = DeviceDisplayInfo.create(mContext); 1452 int displayWidth = (int) (deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale()); 1453 1454 loadDataSync(getData()); 1455 int width = Integer.parseInt(getTitleOnUiThread()); 1456 if (value) { 1457 assertEquals(displayWidth, width); 1458 } else { 1459 assertEquals(3000, width); 1460 } 1461 } 1462 1463 private String getData() { 1464 return "<html><head>" + 1465 "<meta name='viewport' content='width=3000' />" + 1466 " <script type='text/javascript'> " + 1467 " window.addEventListener('load', function(event) { " + 1468 " document.title = document.documentElement.clientWidth; " + 1469 " }); " + 1470 " </script> " + 1471 "</head>" + 1472 "<body> " + 1473 " <div style='height:50px;'>test</div> " + 1474 " <div id='testDiv' style='height:100%;'></div> " + 1475 "</body></html>"; 1476 } 1477 } 1478 1479 // The test verifies that JavaScript is disabled upon WebView 1480 // creation without accessing AwSettings. If the test passes, 1481 // it means that WebView-specific web preferences configuration 1482 // is applied on WebView creation. JS state is used, because it is 1483 // enabled by default in Chrome, but must be disabled by default 1484 // in WebView. 1485 @SmallTest 1486 @Feature({"AndroidWebView", "Preferences"}) 1487 public void testJavaScriptDisabledByDefault() throws Throwable { 1488 final String jsEnabledString = "JS has run"; 1489 final String jsDisabledString = "JS has not run"; 1490 final String testPageHtml = 1491 "<html><head><title>" + jsDisabledString + "</title>" 1492 + "</head><body onload=\"document.title='" + jsEnabledString 1493 + "';\"></body></html>"; 1494 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1495 final AwTestContainerView testContainerView = 1496 createAwTestContainerViewOnMainSync(contentClient); 1497 final AwContents awContents = testContainerView.getAwContents(); 1498 loadDataSync( 1499 awContents, 1500 contentClient.getOnPageFinishedHelper(), 1501 testPageHtml, 1502 "text/html", 1503 false); 1504 assertEquals(jsDisabledString, getTitleOnUiThread(awContents)); 1505 } 1506 1507 @SmallTest 1508 @Feature({"AndroidWebView", "Preferences"}) 1509 public void testJavaScriptEnabledWithTwoViews() throws Throwable { 1510 ViewPair views = createViews(); 1511 runPerViewSettingsTest( 1512 new AwSettingsJavaScriptTestHelper(views.getContainer0(), views.getClient0()), 1513 new AwSettingsJavaScriptTestHelper(views.getContainer1(), views.getClient1())); 1514 } 1515 1516 @SmallTest 1517 @Feature({"AndroidWebView", "Preferences"}) 1518 public void testJavaScriptEnabledDynamicWithTwoViews() throws Throwable { 1519 ViewPair views = createViews(); 1520 runPerViewSettingsTest( 1521 new AwSettingsJavaScriptDynamicTestHelper(views.getContainer0(), views.getClient0()), 1522 new AwSettingsJavaScriptDynamicTestHelper(views.getContainer1(), views.getClient1())); 1523 } 1524 1525 @SmallTest 1526 @Feature({"AndroidWebView", "Preferences"}) 1527 public void testPluginsEnabledWithTwoViews() throws Throwable { 1528 ViewPair views = createViews(); 1529 runPerViewSettingsTest( 1530 new AwSettingsPluginsTestHelper(views.getContainer0(), views.getClient0()), 1531 new AwSettingsPluginsTestHelper(views.getContainer1(), views.getClient1())); 1532 } 1533 1534 @SmallTest 1535 @Feature({"AndroidWebView", "Preferences"}) 1536 public void testStandardFontFamilyWithTwoViews() throws Throwable { 1537 ViewPair views = createViews(); 1538 runPerViewSettingsTest( 1539 new AwSettingsStandardFontFamilyTestHelper(views.getContainer0(), views.getClient0()), 1540 new AwSettingsStandardFontFamilyTestHelper(views.getContainer1(), views.getClient1())); 1541 } 1542 1543 @SmallTest 1544 @Feature({"AndroidWebView", "Preferences"}) 1545 public void testDefaultFontSizeWithTwoViews() throws Throwable { 1546 ViewPair views = createViews(); 1547 runPerViewSettingsTest( 1548 new AwSettingsDefaultFontSizeTestHelper(views.getContainer0(), views.getClient0()), 1549 new AwSettingsDefaultFontSizeTestHelper(views.getContainer1(), views.getClient1())); 1550 } 1551 1552 // The test verifies that after changing the LoadsImagesAutomatically 1553 // setting value from false to true previously skipped images are 1554 // automatically loaded. 1555 @SmallTest 1556 @Feature({"AndroidWebView", "Preferences"}) 1557 public void testLoadsImagesAutomaticallyNoPageReload() throws Throwable { 1558 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1559 final AwTestContainerView testContainerView = 1560 createAwTestContainerViewOnMainSync(contentClient); 1561 final AwContents awContents = testContainerView.getAwContents(); 1562 AwSettings settings = getAwSettingsOnUiThread(awContents); 1563 settings.setJavaScriptEnabled(true); 1564 ImagePageGenerator generator = new ImagePageGenerator(0, false); 1565 settings.setLoadsImagesAutomatically(false); 1566 loadDataSync(awContents, 1567 contentClient.getOnPageFinishedHelper(), 1568 generator.getPageSource(), 1569 "text/html", false); 1570 assertEquals(ImagePageGenerator.IMAGE_NOT_LOADED_STRING, 1571 getTitleOnUiThread(awContents)); 1572 settings.setLoadsImagesAutomatically(true); 1573 poll(new Callable<Boolean>() { 1574 @Override 1575 public Boolean call() throws Exception { 1576 return !ImagePageGenerator.IMAGE_NOT_LOADED_STRING.equals( 1577 getTitleOnUiThread(awContents)); 1578 } 1579 }); 1580 assertEquals(ImagePageGenerator.IMAGE_LOADED_STRING, getTitleOnUiThread(awContents)); 1581 } 1582 1583 1584 @SmallTest 1585 @Feature({"AndroidWebView", "Preferences"}) 1586 public void testLoadsImagesAutomaticallyWithTwoViews() throws Throwable { 1587 ViewPair views = createViews(); 1588 runPerViewSettingsTest( 1589 new AwSettingsLoadImagesAutomaticallyTestHelper( 1590 views.getContainer0(), views.getClient0(), new ImagePageGenerator(0, true)), 1591 new AwSettingsLoadImagesAutomaticallyTestHelper( 1592 views.getContainer1(), views.getClient1(), new ImagePageGenerator(1, true))); 1593 } 1594 1595 @SmallTest 1596 @Feature({"AndroidWebView", "Preferences"}) 1597 public void testDefaultTextEncodingWithTwoViews() throws Throwable { 1598 ViewPair views = createViews(); 1599 runPerViewSettingsTest( 1600 new AwSettingsDefaultTextEncodingTestHelper(views.getContainer0(), views.getClient0()), 1601 new AwSettingsDefaultTextEncodingTestHelper(views.getContainer1(), views.getClient1())); 1602 } 1603 1604 // The test verifies that the default user agent string follows the format 1605 // defined in Android CTS tests: 1606 // 1607 // Mozilla/5.0 (Linux;[ U;] Android <version>;[ <language>-<country>;] 1608 // [<devicemodel>;] Build/<buildID>) AppleWebKit/<major>.<minor> (KHTML, like Gecko) 1609 // Version/<major>.<minor>[ Mobile] Safari/<major>.<minor> 1610 @SmallTest 1611 @Feature({"AndroidWebView", "Preferences"}) 1612 public void testUserAgentStringDefault() throws Throwable { 1613 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1614 final AwTestContainerView testContainerView = 1615 createAwTestContainerViewOnMainSync(contentClient); 1616 final AwContents awContents = testContainerView.getAwContents(); 1617 AwSettings settings = getAwSettingsOnUiThread(awContents); 1618 final String actualUserAgentString = settings.getUserAgentString(); 1619 assertEquals(actualUserAgentString, AwSettings.getDefaultUserAgent()); 1620 final String patternString = 1621 "Mozilla/5\\.0 \\(Linux;( U;)? Android ([^;]+);( (\\w+)-(\\w+);)?" + 1622 "\\s?(.*)\\sBuild/(.+)\\) AppleWebKit/(\\d+)\\.(\\d+) \\(KHTML, like Gecko\\) " + 1623 "Version/\\d+\\.\\d Chrome/\\d+\\.\\d+\\.\\d+\\.\\d+" + 1624 "( Mobile)? Safari/(\\d+)\\.(\\d+)"; 1625 final Pattern userAgentExpr = Pattern.compile(patternString); 1626 Matcher patternMatcher = userAgentExpr.matcher(actualUserAgentString); 1627 assertTrue(String.format("User agent string did not match expected pattern. %nExpected " + 1628 "pattern:%n%s%nActual:%n%s", patternString, actualUserAgentString), 1629 patternMatcher.find()); 1630 // No country-language code token. 1631 assertEquals(null, patternMatcher.group(3)); 1632 if ("REL".equals(Build.VERSION.CODENAME)) { 1633 // Model is only added in release builds 1634 assertEquals(Build.MODEL, patternMatcher.group(6)); 1635 // Release version is valid only in release builds 1636 assertEquals(Build.VERSION.RELEASE, patternMatcher.group(2)); 1637 } 1638 assertEquals(Build.ID, patternMatcher.group(7)); 1639 } 1640 1641 @SmallTest 1642 @Feature({"AndroidWebView", "Preferences"}) 1643 public void testUserAgentStringOverride() throws Throwable { 1644 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1645 final AwTestContainerView testContainerView = 1646 createAwTestContainerViewOnMainSync(contentClient); 1647 final AwContents awContents = testContainerView.getAwContents(); 1648 AwSettings settings = getAwSettingsOnUiThread(awContents); 1649 final String defaultUserAgentString = settings.getUserAgentString(); 1650 1651 // Check that an attempt to reset the default UA string has no effect. 1652 settings.setUserAgentString(null); 1653 assertEquals(defaultUserAgentString, settings.getUserAgentString()); 1654 settings.setUserAgentString(""); 1655 assertEquals(defaultUserAgentString, settings.getUserAgentString()); 1656 1657 // Check that we can also set the default value. 1658 settings.setUserAgentString(defaultUserAgentString); 1659 assertEquals(defaultUserAgentString, settings.getUserAgentString()); 1660 1661 // Set a custom UA string, verify that it can be reset back to default. 1662 final String customUserAgentString = "AwSettingsTest"; 1663 settings.setUserAgentString(customUserAgentString); 1664 assertEquals(customUserAgentString, settings.getUserAgentString()); 1665 settings.setUserAgentString(null); 1666 assertEquals(defaultUserAgentString, settings.getUserAgentString()); 1667 } 1668 1669 // Verify that the current UA override setting has a priority over UA 1670 // overrides in navigation history entries. 1671 @SmallTest 1672 @Feature({"AndroidWebView", "Preferences"}) 1673 public void testUserAgentStringOverrideForHistory() throws Throwable { 1674 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1675 final AwTestContainerView testContainerView = 1676 createAwTestContainerViewOnMainSync(contentClient); 1677 final AwContents awContents = testContainerView.getAwContents(); 1678 final WebContents webContents = awContents.getWebContents(); 1679 CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); 1680 AwSettings settings = getAwSettingsOnUiThread(awContents); 1681 settings.setJavaScriptEnabled(true); 1682 final String defaultUserAgentString = settings.getUserAgentString(); 1683 final String customUserAgentString = "AwSettingsTest"; 1684 // We are using different page titles to make sure that we are really 1685 // going back and forward between them. 1686 final String pageTemplate = 1687 "<html><head><title>%s</title></head>" + 1688 "<body onload='document.title+=navigator.userAgent'></body>" + 1689 "</html>"; 1690 final String page1Title = "Page1"; 1691 final String page2Title = "Page2"; 1692 final String page1 = String.format(pageTemplate, page1Title); 1693 final String page2 = String.format(pageTemplate, page2Title); 1694 settings.setUserAgentString(customUserAgentString); 1695 loadDataSync( 1696 awContents, onPageFinishedHelper, page1, "text/html", false); 1697 assertEquals(page1Title + customUserAgentString, getTitleOnUiThread(awContents)); 1698 loadDataSync( 1699 awContents, onPageFinishedHelper, page2, "text/html", false); 1700 assertEquals(page2Title + customUserAgentString, getTitleOnUiThread(awContents)); 1701 settings.setUserAgentString(null); 1702 // Must not cause any changes until the next page loading. 1703 assertEquals(page2Title + customUserAgentString, getTitleOnUiThread(awContents)); 1704 HistoryUtils.goBackSync(getInstrumentation(), webContents, onPageFinishedHelper); 1705 assertEquals(page1Title + defaultUserAgentString, getTitleOnUiThread(awContents)); 1706 HistoryUtils.goForwardSync(getInstrumentation(), webContents, 1707 onPageFinishedHelper); 1708 assertEquals(page2Title + defaultUserAgentString, getTitleOnUiThread(awContents)); 1709 } 1710 1711 @SmallTest 1712 @Feature({"AndroidWebView", "Preferences"}) 1713 public void testUserAgentStringWithTwoViews() throws Throwable { 1714 ViewPair views = createViews(); 1715 runPerViewSettingsTest( 1716 new AwSettingsUserAgentStringTestHelper(views.getContainer0(), views.getClient0()), 1717 new AwSettingsUserAgentStringTestHelper(views.getContainer1(), views.getClient1())); 1718 } 1719 1720 @SmallTest 1721 @Feature({"AndroidWebView", "Preferences"}) 1722 public void testUserAgentWithTestServer() throws Throwable { 1723 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1724 final AwTestContainerView testContainerView = 1725 createAwTestContainerViewOnMainSync(contentClient); 1726 AwContents awContents = testContainerView.getAwContents(); 1727 AwSettings settings = getAwSettingsOnUiThread(awContents); 1728 final String customUserAgentString = 1729 "testUserAgentWithTestServerUserAgent"; 1730 1731 TestWebServer webServer = null; 1732 String fileName = null; 1733 try { 1734 webServer = new TestWebServer(false); 1735 final String httpPath = "/testUserAgentWithTestServer.html"; 1736 final String url = webServer.setResponse(httpPath, "foo", null); 1737 1738 settings.setUserAgentString(customUserAgentString); 1739 loadUrlSync(awContents, 1740 contentClient.getOnPageFinishedHelper(), 1741 url); 1742 1743 assertEquals(1, webServer.getRequestCount(httpPath)); 1744 HttpRequest request = webServer.getLastRequest(httpPath); 1745 Header[] matchingHeaders = request.getHeaders("User-Agent"); 1746 assertEquals(1, matchingHeaders.length); 1747 1748 Header header = matchingHeaders[0]; 1749 assertEquals(customUserAgentString, header.getValue()); 1750 } finally { 1751 if (webServer != null) webServer.shutdown(); 1752 } 1753 } 1754 1755 @SmallTest 1756 @Feature({"AndroidWebView", "Preferences"}) 1757 public void testDomStorageEnabledWithTwoViews() throws Throwable { 1758 ViewPair views = createViews(); 1759 runPerViewSettingsTest( 1760 new AwSettingsDomStorageEnabledTestHelper(views.getContainer0(), views.getClient0()), 1761 new AwSettingsDomStorageEnabledTestHelper(views.getContainer1(), views.getClient1())); 1762 } 1763 1764 // Ideally, these three tests below should be combined into one, or tested using 1765 // runPerViewSettingsTest. However, it seems the database setting cannot be toggled 1766 // once set. Filed b/8186497. 1767 @SmallTest 1768 @Feature({"AndroidWebView", "Preferences"}) 1769 public void testDatabaseInitialValue() throws Throwable { 1770 TestAwContentsClient client = new TestAwContentsClient(); 1771 final AwTestContainerView testContainerView = 1772 createAwTestContainerViewOnMainSync(client); 1773 AwSettingsDatabaseTestHelper helper = 1774 new AwSettingsDatabaseTestHelper(testContainerView, client); 1775 helper.ensureSettingHasInitialValue(); 1776 } 1777 1778 @SmallTest 1779 @Feature({"AndroidWebView", "Preferences"}) 1780 public void testDatabaseEnabled() throws Throwable { 1781 TestAwContentsClient client = new TestAwContentsClient(); 1782 final AwTestContainerView testContainerView = 1783 createAwTestContainerViewOnMainSync(client); 1784 AwSettingsDatabaseTestHelper helper = 1785 new AwSettingsDatabaseTestHelper(testContainerView, client); 1786 helper.setAlteredSettingValue(); 1787 helper.ensureSettingHasAlteredValue(); 1788 } 1789 1790 @SmallTest 1791 @Feature({"AndroidWebView", "Preferences"}) 1792 public void testDatabaseDisabled() throws Throwable { 1793 TestAwContentsClient client = new TestAwContentsClient(); 1794 final AwTestContainerView testContainerView = 1795 createAwTestContainerViewOnMainSync(client); 1796 AwSettingsDatabaseTestHelper helper = 1797 new AwSettingsDatabaseTestHelper(testContainerView, client); 1798 helper.setInitialSettingValue(); 1799 helper.ensureSettingHasInitialValue(); 1800 } 1801 1802 @SmallTest 1803 @Feature({"AndroidWebView", "Preferences"}) 1804 public void testUniversalAccessFromFilesWithTwoViews() throws Throwable { 1805 ViewPair views = createViews(); 1806 runPerViewSettingsTest( 1807 new AwSettingsUniversalAccessFromFilesTestHelper(views.getContainer0(), 1808 views.getClient0()), 1809 new AwSettingsUniversalAccessFromFilesTestHelper(views.getContainer1(), 1810 views.getClient1())); 1811 } 1812 1813 // This test verifies that local image resources can be loaded from file: 1814 // URLs regardless of file access state. 1815 @SmallTest 1816 @Feature({"AndroidWebView", "Preferences"}) 1817 public void testFileAccessFromFilesImage() throws Throwable { 1818 final String testFile = "webview/image_access.html"; 1819 assertFileIsReadable(UrlUtils.getTestFilePath(testFile)); 1820 final String imageContainerUrl = UrlUtils.getTestFileUrl(testFile); 1821 final String imageHeight = "16"; 1822 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1823 final AwTestContainerView testContainerView = 1824 createAwTestContainerViewOnMainSync(contentClient); 1825 final AwContents awContents = testContainerView.getAwContents(); 1826 AwSettings settings = getAwSettingsOnUiThread(awContents); 1827 settings.setJavaScriptEnabled(true); 1828 settings.setAllowUniversalAccessFromFileURLs(false); 1829 settings.setAllowFileAccessFromFileURLs(false); 1830 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), imageContainerUrl); 1831 assertEquals(imageHeight, getTitleOnUiThread(awContents)); 1832 } 1833 1834 @SmallTest 1835 @Feature({"AndroidWebView", "Preferences"}) 1836 public void testFileAccessFromFilesIframeWithTwoViews() throws Throwable { 1837 ViewPair views = createViews(); 1838 runPerViewSettingsTest( 1839 new AwSettingsFileAccessFromFilesIframeTestHelper( 1840 views.getContainer0(), views.getClient0()), 1841 new AwSettingsFileAccessFromFilesIframeTestHelper( 1842 views.getContainer1(), views.getClient1())); 1843 } 1844 1845 @SmallTest 1846 @Feature({"AndroidWebView", "Preferences"}) 1847 public void testFileAccessFromFilesXhrWithTwoViews() throws Throwable { 1848 ViewPair views = createViews(); 1849 runPerViewSettingsTest( 1850 new AwSettingsFileAccessFromFilesXhrTestHelper(views.getContainer0(), 1851 views.getClient0()), 1852 new AwSettingsFileAccessFromFilesXhrTestHelper(views.getContainer1(), 1853 views.getClient1())); 1854 } 1855 1856 @SmallTest 1857 @Feature({"AndroidWebView", "Preferences"}) 1858 public void testFileUrlAccessWithTwoViews() throws Throwable { 1859 ViewPair views = createViews(); 1860 runPerViewSettingsTest( 1861 new AwSettingsFileUrlAccessTestHelper(views.getContainer0(), views.getClient0(), 0), 1862 new AwSettingsFileUrlAccessTestHelper(views.getContainer1(), views.getClient1(), 1)); 1863 } 1864 1865 @SmallTest 1866 @Feature({"AndroidWebView", "Preferences"}) 1867 public void testContentUrlAccessWithTwoViews() throws Throwable { 1868 ViewPair views = createViews(); 1869 runPerViewSettingsTest( 1870 new AwSettingsContentUrlAccessTestHelper(views.getContainer0(), views.getClient0(), 0), 1871 new AwSettingsContentUrlAccessTestHelper(views.getContainer1(), views.getClient1(), 1)); 1872 } 1873 1874 @SmallTest 1875 @Feature({"AndroidWebView", "Preferences", "Navigation"}) 1876 public void testBlockingContentUrlsFromDataUrls() throws Throwable { 1877 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1878 final AwTestContainerView testContainerView = 1879 createAwTestContainerViewOnMainSync(contentClient); 1880 final AwContents awContents = testContainerView.getAwContents(); 1881 final String target = "content_from_data"; 1882 final String page = "<html><body>" + 1883 "<img src=\"" + 1884 createContentUrl(target) + "\">" + 1885 "</body></html>"; 1886 resetResourceRequestCountInContentProvider(target); 1887 loadDataSync( 1888 awContents, 1889 contentClient.getOnPageFinishedHelper(), 1890 page, 1891 "text/html", 1892 false); 1893 ensureResourceRequestCountInContentProvider(target, 0); 1894 } 1895 1896 @SmallTest 1897 @Feature({"AndroidWebView", "Preferences", "Navigation"}) 1898 public void testContentUrlFromFileWithTwoViews() throws Throwable { 1899 ViewPair views = createViews(); 1900 runPerViewSettingsTest( 1901 new AwSettingsContentUrlAccessFromFileTestHelper( 1902 views.getContainer0(), views.getClient0(), 0), 1903 new AwSettingsContentUrlAccessFromFileTestHelper( 1904 views.getContainer1(), views.getClient1(), 1)); 1905 } 1906 1907 @SmallTest 1908 @Feature({"AndroidWebView", "Preferences"}) 1909 public void testBlockNetworkImagesDoesNotBlockDataUrlImage() throws Throwable { 1910 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1911 final AwTestContainerView testContainerView = 1912 createAwTestContainerViewOnMainSync(contentClient); 1913 final AwContents awContents = testContainerView.getAwContents(); 1914 final AwSettings settings = getAwSettingsOnUiThread(awContents); 1915 ImagePageGenerator generator = new ImagePageGenerator(0, false); 1916 1917 settings.setJavaScriptEnabled(true); 1918 settings.setImagesEnabled(false); 1919 loadDataSync(awContents, 1920 contentClient.getOnPageFinishedHelper(), 1921 generator.getPageSource(), 1922 "text/html", 1923 false); 1924 assertEquals(ImagePageGenerator.IMAGE_LOADED_STRING, getTitleOnUiThread(awContents)); 1925 } 1926 1927 @SmallTest 1928 @Feature({"AndroidWebView", "Preferences"}) 1929 public void testBlockNetworkImagesBlocksNetworkImageAndReloadInPlace() throws Throwable { 1930 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1931 final AwTestContainerView testContainerView = 1932 createAwTestContainerViewOnMainSync(contentClient); 1933 final AwContents awContents = testContainerView.getAwContents(); 1934 final AwSettings settings = getAwSettingsOnUiThread(awContents); 1935 settings.setJavaScriptEnabled(true); 1936 ImagePageGenerator generator = new ImagePageGenerator(0, false); 1937 1938 TestWebServer webServer = null; 1939 try { 1940 webServer = new TestWebServer(false); 1941 final String httpImageUrl = generator.getPageUrl(webServer); 1942 1943 settings.setImagesEnabled(false); 1944 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), httpImageUrl); 1945 assertEquals(ImagePageGenerator.IMAGE_NOT_LOADED_STRING, 1946 getTitleOnUiThread(awContents)); 1947 1948 settings.setImagesEnabled(true); 1949 poll(new Callable<Boolean>() { 1950 @Override 1951 public Boolean call() throws Exception { 1952 return ImagePageGenerator.IMAGE_LOADED_STRING.equals( 1953 getTitleOnUiThread(awContents)); 1954 } 1955 }); 1956 } finally { 1957 if (webServer != null) webServer.shutdown(); 1958 } 1959 } 1960 1961 @SmallTest 1962 @Feature({"AndroidWebView", "Preferences"}) 1963 public void testBlockNetworkImagesWithTwoViews() throws Throwable { 1964 ViewPair views = createViews(); 1965 TestWebServer webServer = null; 1966 try { 1967 webServer = new TestWebServer(false); 1968 runPerViewSettingsTest( 1969 new AwSettingsImagesEnabledHelper( 1970 views.getContainer0(), 1971 views.getClient0(), 1972 webServer, 1973 new ImagePageGenerator(0, true)), 1974 new AwSettingsImagesEnabledHelper( 1975 views.getContainer1(), 1976 views.getClient1(), 1977 webServer, 1978 new ImagePageGenerator(1, true))); 1979 } finally { 1980 if (webServer != null) webServer.shutdown(); 1981 } 1982 } 1983 1984 @SmallTest 1985 @Feature({"AndroidWebView", "Preferences"}) 1986 public void testBlockNetworkLoadsWithHttpResources() throws Throwable { 1987 final TestAwContentsClient contentClient = new TestAwContentsClient(); 1988 final AwTestContainerView testContainer = 1989 createAwTestContainerViewOnMainSync(contentClient); 1990 final AwContents awContents = testContainer.getAwContents(); 1991 final AwSettings awSettings = getAwSettingsOnUiThread(awContents); 1992 awSettings.setJavaScriptEnabled(true); 1993 ImagePageGenerator generator = new ImagePageGenerator(0, false); 1994 1995 TestWebServer webServer = null; 1996 String fileName = null; 1997 try { 1998 // Set up http image. 1999 webServer = new TestWebServer(false); 2000 final String httpPath = "/image.png"; 2001 final String imageUrl = webServer.setResponseBase64( 2002 httpPath, generator.getImageSourceNoAdvance(), 2003 CommonResources.getImagePngHeaders(true)); 2004 2005 // Set up file html that loads http iframe. 2006 String pageHtml = "<img src='" + imageUrl + "' " + 2007 "onload=\"document.title='img_onload_fired';\" " + 2008 "onerror=\"document.title='img_onerror_fired';\" />"; 2009 Context context = getInstrumentation().getTargetContext(); 2010 fileName = context.getCacheDir() + "/block_network_loads_test.html"; 2011 TestFileUtil.deleteFile(fileName); // Remove leftover file if any. 2012 TestFileUtil.createNewHtmlFile(fileName, "unset", pageHtml); 2013 2014 // Actual test. Blocking should trigger onerror handler. 2015 awSettings.setBlockNetworkLoads(true); 2016 loadUrlSync( 2017 awContents, 2018 contentClient.getOnPageFinishedHelper(), 2019 "file:///" + fileName); 2020 assertEquals(0, webServer.getRequestCount(httpPath)); 2021 assertEquals("img_onerror_fired", getTitleOnUiThread(awContents)); 2022 2023 // Unblock should load normally. 2024 awSettings.setBlockNetworkLoads(false); 2025 loadUrlSync( 2026 awContents, 2027 contentClient.getOnPageFinishedHelper(), 2028 "file:///" + fileName); 2029 assertEquals(1, webServer.getRequestCount(httpPath)); 2030 assertEquals("img_onload_fired", getTitleOnUiThread(awContents)); 2031 } finally { 2032 if (fileName != null) TestFileUtil.deleteFile(fileName); 2033 if (webServer != null) webServer.shutdown(); 2034 } 2035 } 2036 2037 private static class AudioEvent { 2038 private CallbackHelper mCallback; 2039 public AudioEvent(CallbackHelper callback) { 2040 mCallback = callback; 2041 } 2042 2043 @JavascriptInterface 2044 public void onCanPlay() { 2045 mCallback.notifyCalled(); 2046 } 2047 2048 @JavascriptInterface 2049 public void onError() { 2050 mCallback.notifyCalled(); 2051 } 2052 } 2053 2054 @SmallTest 2055 @Feature({"AndroidWebView", "Preferences"}) 2056 public void testBlockNetworkLoadsWithAudio() throws Throwable { 2057 final TestAwContentsClient contentClient = new TestAwContentsClient(); 2058 final AwTestContainerView testContainer = 2059 createAwTestContainerViewOnMainSync(contentClient); 2060 final AwContents awContents = testContainer.getAwContents(); 2061 final AwSettings awSettings = getAwSettingsOnUiThread(awContents); 2062 final CallbackHelper callback = new CallbackHelper(); 2063 awSettings.setJavaScriptEnabled(true); 2064 2065 TestWebServer webServer = null; 2066 try { 2067 webServer = new TestWebServer(false); 2068 final String httpPath = "/audio.mp3"; 2069 // Don't care about the response is correct or not, just want 2070 // to know whether Url is accessed. 2071 final String audioUrl = webServer.setResponse(httpPath, "1", null); 2072 2073 String pageHtml = "<html><body><audio controls src='" + audioUrl + "' " + 2074 "oncanplay=\"AudioEvent.onCanPlay();\" " + 2075 "onerror=\"AudioEvent.onError();\" /> </body></html>"; 2076 // Actual test. Blocking should trigger onerror handler. 2077 awSettings.setBlockNetworkLoads(true); 2078 runTestOnUiThread(new Runnable() { 2079 @Override 2080 public void run() { 2081 awContents.addPossiblyUnsafeJavascriptInterface( 2082 new AudioEvent(callback), "AudioEvent", null); 2083 } 2084 }); 2085 int count = callback.getCallCount(); 2086 loadDataSync(awContents, contentClient.getOnPageFinishedHelper(), pageHtml, 2087 "text/html", false); 2088 callback.waitForCallback(count, 1); 2089 assertEquals(0, webServer.getRequestCount(httpPath)); 2090 2091 // The below test failed in Nexus Galaxy. 2092 // See https://code.google.com/p/chromium/issues/detail?id=313463 2093 // Unblock should load normally. 2094 /* 2095 awSettings.setBlockNetworkLoads(false); 2096 count = callback.getCallCount(); 2097 loadDataSync(awContents, contentClient.getOnPageFinishedHelper(), pageHtml, 2098 "text/html", false); 2099 callback.waitForCallback(count, 1); 2100 assertTrue(0 != webServer.getRequestCount(httpPath)); 2101 */ 2102 } finally { 2103 if (webServer != null) webServer.shutdown(); 2104 } 2105 } 2106 2107 // Test an assert URL (file:///android_asset/) 2108 @SmallTest 2109 @Feature({"AndroidWebView", "Navigation"}) 2110 public void testAssetUrl() throws Throwable { 2111 // Note: this text needs to be kept in sync with the contents of the html file referenced 2112 // below. 2113 final String expectedTitle = "Asset File"; 2114 final TestAwContentsClient contentClient = new TestAwContentsClient(); 2115 final AwTestContainerView testContainerView = 2116 createAwTestContainerViewOnMainSync(contentClient); 2117 final AwContents awContents = testContainerView.getAwContents(); 2118 loadUrlSync(awContents, 2119 contentClient.getOnPageFinishedHelper(), 2120 "file:///android_asset/asset_file.html"); 2121 assertEquals(expectedTitle, getTitleOnUiThread(awContents)); 2122 } 2123 2124 // Test a resource URL (file:///android_res/). 2125 @SmallTest 2126 @Feature({"AndroidWebView", "Navigation"}) 2127 public void testResourceUrl() throws Throwable { 2128 // Note: this text needs to be kept in sync with the contents of the html file referenced 2129 // below. 2130 final String expectedTitle = "Resource File"; 2131 final TestAwContentsClient contentClient = new TestAwContentsClient(); 2132 final AwTestContainerView testContainerView = 2133 createAwTestContainerViewOnMainSync(contentClient); 2134 final AwContents awContents = testContainerView.getAwContents(); 2135 loadUrlSync(awContents, 2136 contentClient.getOnPageFinishedHelper(), 2137 "file:///android_res/raw/resource_file.html"); 2138 assertEquals(expectedTitle, getTitleOnUiThread(awContents)); 2139 } 2140 2141 // Test that the file URL access toggle does not affect asset URLs. 2142 @SmallTest 2143 @Feature({"AndroidWebView", "Navigation"}) 2144 public void testFileUrlAccessToggleDoesNotBlockAssetUrls() throws Throwable { 2145 // Note: this text needs to be kept in sync with the contents of the html file referenced 2146 // below. 2147 final String expectedTitle = "Asset File"; 2148 final TestAwContentsClient contentClient = new TestAwContentsClient(); 2149 final AwTestContainerView testContainerView = 2150 createAwTestContainerViewOnMainSync(contentClient); 2151 final AwContents awContents = testContainerView.getAwContents(); 2152 final AwSettings settings = getAwSettingsOnUiThread(awContents); 2153 settings.setAllowFileAccess(false); 2154 loadUrlSync(awContents, 2155 contentClient.getOnPageFinishedHelper(), 2156 "file:///android_asset/asset_file.html"); 2157 assertEquals(expectedTitle, getTitleOnUiThread(awContents)); 2158 } 2159 2160 // Test that the file URL access toggle does not affect resource URLs. 2161 @SmallTest 2162 @Feature({"AndroidWebView", "Navigation"}) 2163 public void testFileUrlAccessToggleDoesNotBlockResourceUrls() throws Throwable { 2164 // Note: this text needs to be kept in sync with the contents of the html file referenced 2165 // below. 2166 final String expectedTitle = "Resource File"; 2167 final TestAwContentsClient contentClient = new TestAwContentsClient(); 2168 final AwTestContainerView testContainerView = 2169 createAwTestContainerViewOnMainSync(contentClient); 2170 final AwContents awContents = testContainerView.getAwContents(); 2171 final AwSettings settings = getAwSettingsOnUiThread(awContents); 2172 settings.setAllowFileAccess(false); 2173 loadUrlSync(awContents, 2174 contentClient.getOnPageFinishedHelper(), 2175 "file:///android_res/raw/resource_file.html"); 2176 assertEquals(expectedTitle, getTitleOnUiThread(awContents)); 2177 } 2178 2179 @SmallTest 2180 @Feature({"AndroidWebView", "Preferences"}) 2181 public void testLayoutAlgorithmWithTwoViews() throws Throwable { 2182 ViewPair views = createViews(); 2183 runPerViewSettingsTest( 2184 new AwSettingsLayoutAlgorithmTestHelper(views.getContainer0(), views.getClient0()), 2185 new AwSettingsLayoutAlgorithmTestHelper(views.getContainer1(), views.getClient1())); 2186 } 2187 2188 @SmallTest 2189 @Feature({"AndroidWebView", "Preferences"}) 2190 public void testTextZoomWithTwoViews() throws Throwable { 2191 ViewPair views = createViews(); 2192 runPerViewSettingsTest( 2193 new AwSettingsTextZoomTestHelper(views.getContainer0(), views.getClient0()), 2194 new AwSettingsTextZoomTestHelper(views.getContainer1(), views.getClient1())); 2195 } 2196 2197 @SmallTest 2198 @Feature({"AndroidWebView", "Preferences"}) 2199 public void testTextZoomAutosizingWithTwoViews() throws Throwable { 2200 ViewPair views = createViews(); 2201 runPerViewSettingsTest( 2202 new AwSettingsTextZoomAutosizingTestHelper(views.getContainer0(), views.getClient0()), 2203 new AwSettingsTextZoomAutosizingTestHelper(views.getContainer1(), views.getClient1())); 2204 } 2205 2206 @SmallTest 2207 @Feature({"AndroidWebView", "Preferences"}) 2208 public void testJavaScriptPopupsWithTwoViews() throws Throwable { 2209 ViewPair views = createViews(); 2210 runPerViewSettingsTest( 2211 new AwSettingsJavaScriptPopupsTestHelper(views.getContainer0(), views.getClient0()), 2212 new AwSettingsJavaScriptPopupsTestHelper(views.getContainer1(), views.getClient1())); 2213 } 2214 2215 @SmallTest 2216 @Feature({"AndroidWebView", "Preferences"}) 2217 public void testCacheMode() throws Throwable { 2218 final TestAwContentsClient contentClient = new TestAwContentsClient(); 2219 final AwTestContainerView testContainer = 2220 createAwTestContainerViewOnMainSync(contentClient); 2221 final AwContents awContents = testContainer.getAwContents(); 2222 final AwSettings awSettings = getAwSettingsOnUiThread(testContainer.getAwContents()); 2223 clearCacheOnUiThread(awContents, true); 2224 2225 assertEquals(WebSettings.LOAD_DEFAULT, awSettings.getCacheMode()); 2226 TestWebServer webServer = null; 2227 try { 2228 webServer = new TestWebServer(false); 2229 final String htmlPath = "/testCacheMode.html"; 2230 final String url = webServer.setResponse(htmlPath, "response", null); 2231 awSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); 2232 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); 2233 assertEquals(1, webServer.getRequestCount(htmlPath)); 2234 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); 2235 assertEquals(1, webServer.getRequestCount(htmlPath)); 2236 2237 awSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); 2238 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); 2239 assertEquals(2, webServer.getRequestCount(htmlPath)); 2240 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); 2241 assertEquals(3, webServer.getRequestCount(htmlPath)); 2242 2243 awSettings.setCacheMode(WebSettings.LOAD_CACHE_ONLY); 2244 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); 2245 assertEquals(3, webServer.getRequestCount(htmlPath)); 2246 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url); 2247 assertEquals(3, webServer.getRequestCount(htmlPath)); 2248 2249 final String htmlNotInCachePath = "/testCacheMode-not-in-cache.html"; 2250 final String urlNotInCache = webServer.setResponse(htmlNotInCachePath, "", null); 2251 loadUrlSyncAndExpectError(awContents, 2252 contentClient.getOnPageFinishedHelper(), 2253 contentClient.getOnReceivedErrorHelper(), 2254 urlNotInCache); 2255 assertEquals(0, webServer.getRequestCount(htmlNotInCachePath)); 2256 } finally { 2257 if (webServer != null) webServer.shutdown(); 2258 } 2259 } 2260 2261 @SmallTest 2262 @Feature({"AndroidWebView", "Preferences"}) 2263 // As our implementation of network loads blocking uses the same net::URLRequest settings, make 2264 // sure that setting cache mode doesn't accidentally enable network loads. The reference 2265 // behaviour is that when network loads are blocked, setting cache mode has no effect. 2266 public void testCacheModeWithBlockedNetworkLoads() throws Throwable { 2267 final TestAwContentsClient contentClient = new TestAwContentsClient(); 2268 final AwTestContainerView testContainer = 2269 createAwTestContainerViewOnMainSync(contentClient); 2270 final AwContents awContents = testContainer.getAwContents(); 2271 final AwSettings awSettings = getAwSettingsOnUiThread(testContainer.getAwContents()); 2272 clearCacheOnUiThread(awContents, true); 2273 2274 assertEquals(WebSettings.LOAD_DEFAULT, awSettings.getCacheMode()); 2275 awSettings.setBlockNetworkLoads(true); 2276 TestWebServer webServer = null; 2277 try { 2278 webServer = new TestWebServer(false); 2279 final String htmlPath = "/testCacheModeWithBlockedNetworkLoads.html"; 2280 final String url = webServer.setResponse(htmlPath, "response", null); 2281 loadUrlSyncAndExpectError(awContents, 2282 contentClient.getOnPageFinishedHelper(), 2283 contentClient.getOnReceivedErrorHelper(), 2284 url); 2285 assertEquals(0, webServer.getRequestCount(htmlPath)); 2286 2287 awSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); 2288 loadUrlSyncAndExpectError(awContents, 2289 contentClient.getOnPageFinishedHelper(), 2290 contentClient.getOnReceivedErrorHelper(), 2291 url); 2292 assertEquals(0, webServer.getRequestCount(htmlPath)); 2293 2294 awSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); 2295 loadUrlSyncAndExpectError(awContents, 2296 contentClient.getOnPageFinishedHelper(), 2297 contentClient.getOnReceivedErrorHelper(), 2298 url); 2299 assertEquals(0, webServer.getRequestCount(htmlPath)); 2300 2301 awSettings.setCacheMode(WebSettings.LOAD_CACHE_ONLY); 2302 loadUrlSyncAndExpectError(awContents, 2303 contentClient.getOnPageFinishedHelper(), 2304 contentClient.getOnReceivedErrorHelper(), 2305 url); 2306 assertEquals(0, webServer.getRequestCount(htmlPath)); 2307 } finally { 2308 if (webServer != null) webServer.shutdown(); 2309 } 2310 } 2311 2312 @SmallTest 2313 @Feature({"AndroidWebView", "Preferences"}) 2314 public void testCacheModeWithTwoViews() throws Throwable { 2315 ViewPair views = createViews(); 2316 TestWebServer webServer = null; 2317 try { 2318 webServer = new TestWebServer(false); 2319 runPerViewSettingsTest( 2320 new AwSettingsCacheModeTestHelper( 2321 views.getContainer0(), views.getClient0(), 0, webServer), 2322 new AwSettingsCacheModeTestHelper( 2323 views.getContainer1(), views.getClient1(), 1, webServer)); 2324 } finally { 2325 if (webServer != null) webServer.shutdown(); 2326 } 2327 } 2328 2329 static class ManifestTestHelper { 2330 private final TestWebServer mWebServer; 2331 private final String mHtmlPath; 2332 private final String mHtmlUrl; 2333 private final String mManifestPath; 2334 2335 ManifestTestHelper( 2336 TestWebServer webServer, String htmlPageName, String manifestName) { 2337 mWebServer = webServer; 2338 mHtmlPath = "/" + htmlPageName; 2339 mHtmlUrl = webServer.setResponse( 2340 mHtmlPath, "<html manifest=\"" + manifestName + "\"></html>", null); 2341 mManifestPath = "/" + manifestName; 2342 webServer.setResponse( 2343 mManifestPath, 2344 "CACHE MANIFEST", 2345 CommonResources.getContentTypeAndCacheHeaders("text/cache-manifest", false)); 2346 } 2347 2348 String getHtmlPath() { 2349 return mHtmlPath; 2350 } 2351 2352 String getHtmlUrl() { 2353 return mHtmlUrl; 2354 } 2355 2356 String getManifestPath() { 2357 return mManifestPath; 2358 } 2359 2360 int waitUntilHtmlIsRequested(final int initialRequestCount) throws Exception { 2361 return waitUntilResourceIsRequested(mHtmlPath, initialRequestCount); 2362 } 2363 2364 int waitUntilManifestIsRequested(final int initialRequestCount) throws Exception { 2365 return waitUntilResourceIsRequested(mManifestPath, initialRequestCount); 2366 } 2367 2368 private int waitUntilResourceIsRequested( 2369 final String path, final int initialRequestCount) throws Exception { 2370 poll(new Callable<Boolean>() { 2371 @Override 2372 public Boolean call() throws Exception { 2373 return mWebServer.getRequestCount(path) > initialRequestCount; 2374 } 2375 }); 2376 return mWebServer.getRequestCount(path); 2377 } 2378 } 2379 2380 @SmallTest 2381 @Feature({"AndroidWebView", "Preferences", "AppCache"}) 2382 public void testAppCache() throws Throwable { 2383 final TestAwContentsClient contentClient = new TestAwContentsClient(); 2384 final AwTestContainerView testContainer = 2385 createAwTestContainerViewOnMainSync(contentClient); 2386 final AwContents awContents = testContainer.getAwContents(); 2387 final AwSettings settings = getAwSettingsOnUiThread(awContents); 2388 settings.setJavaScriptEnabled(true); 2389 // Note that the cache isn't actually enabled until the call to setAppCachePath. 2390 settings.setAppCacheEnabled(true); 2391 2392 TestWebServer webServer = null; 2393 try { 2394 webServer = new TestWebServer(false); 2395 ManifestTestHelper helper = new ManifestTestHelper( 2396 webServer, "testAppCache.html", "appcache.manifest"); 2397 loadUrlSync( 2398 awContents, 2399 contentClient.getOnPageFinishedHelper(), 2400 helper.getHtmlUrl()); 2401 helper.waitUntilHtmlIsRequested(0); 2402 // Unfortunately, there is no other good way of verifying that AppCache is 2403 // disabled, other than checking that it didn't try to fetch the manifest. 2404 Thread.sleep(1000); 2405 assertEquals(0, webServer.getRequestCount(helper.getManifestPath())); 2406 settings.setAppCachePath("whatever"); // Enables AppCache. 2407 loadUrlSync( 2408 awContents, 2409 contentClient.getOnPageFinishedHelper(), 2410 helper.getHtmlUrl()); 2411 helper.waitUntilManifestIsRequested(0); 2412 } finally { 2413 if (webServer != null) webServer.shutdown(); 2414 } 2415 } 2416 2417 @SmallTest 2418 @Feature({"AndroidWebView", "Preferences", "AppCache"}) 2419 public void testAppCacheWithTwoViews() throws Throwable { 2420 // We don't use the test helper here, because making sure that AppCache 2421 // is disabled takes a lot of time, so running through the usual drill 2422 // will take about 20 seconds. 2423 ViewPair views = createViews(); 2424 2425 AwSettings settings0 = getAwSettingsOnUiThread(views.getContents0()); 2426 settings0.setJavaScriptEnabled(true); 2427 settings0.setAppCachePath("whatever"); 2428 settings0.setAppCacheEnabled(true); 2429 AwSettings settings1 = getAwSettingsOnUiThread(views.getContents1()); 2430 settings1.setJavaScriptEnabled(true); 2431 // AppCachePath setting is global, no need to set it for the second view. 2432 settings1.setAppCacheEnabled(true); 2433 2434 TestWebServer webServer = null; 2435 try { 2436 webServer = new TestWebServer(false); 2437 ManifestTestHelper helper0 = new ManifestTestHelper( 2438 webServer, "testAppCache_0.html", "appcache.manifest_0"); 2439 loadUrlSync( 2440 views.getContents0(), 2441 views.getClient0().getOnPageFinishedHelper(), 2442 helper0.getHtmlUrl()); 2443 int manifestRequests0 = helper0.waitUntilManifestIsRequested(0); 2444 ManifestTestHelper helper1 = new ManifestTestHelper( 2445 webServer, "testAppCache_1.html", "appcache.manifest_1"); 2446 loadUrlSync( 2447 views.getContents1(), 2448 views.getClient1().getOnPageFinishedHelper(), 2449 helper1.getHtmlUrl()); 2450 helper1.waitUntilManifestIsRequested(0); 2451 settings1.setAppCacheEnabled(false); 2452 loadUrlSync( 2453 views.getContents0(), 2454 views.getClient0().getOnPageFinishedHelper(), 2455 helper0.getHtmlUrl()); 2456 helper0.waitUntilManifestIsRequested(manifestRequests0); 2457 final int prevManifestRequestCount = 2458 webServer.getRequestCount(helper1.getManifestPath()); 2459 int htmlRequests1 = webServer.getRequestCount(helper1.getHtmlPath()); 2460 loadUrlSync( 2461 views.getContents1(), 2462 views.getClient1().getOnPageFinishedHelper(), 2463 helper1.getHtmlUrl()); 2464 helper1.waitUntilHtmlIsRequested(htmlRequests1); 2465 // Unfortunately, there is no other good way of verifying that AppCache is 2466 // disabled, other than checking that it didn't try to fetch the manifest. 2467 Thread.sleep(1000); 2468 assertEquals( 2469 prevManifestRequestCount, webServer.getRequestCount(helper1.getManifestPath())); 2470 } finally { 2471 if (webServer != null) webServer.shutdown(); 2472 } 2473 } 2474 2475 @SmallTest 2476 @Feature({"AndroidWebView", "Preferences"}) 2477 public void testUseWideViewportWithTwoViews() throws Throwable { 2478 ViewPair views = createViews(true); 2479 runPerViewSettingsTest( 2480 new AwSettingsUseWideViewportTestHelper(views.getContainer0(), views.getClient0()), 2481 new AwSettingsUseWideViewportTestHelper(views.getContainer1(), views.getClient1())); 2482 } 2483 2484 @SmallTest 2485 @Feature({"AndroidWebView", "Preferences"}) 2486 public void testUseWideViewportWithTwoViewsNoQuirks() throws Throwable { 2487 ViewPair views = createViews(); 2488 runPerViewSettingsTest( 2489 new AwSettingsUseWideViewportTestHelper(views.getContainer0(), views.getClient0()), 2490 new AwSettingsUseWideViewportTestHelper(views.getContainer1(), views.getClient1())); 2491 } 2492 2493 private void useWideViewportLayoutWidthTest( 2494 AwTestContainerView testContainer, CallbackHelper onPageFinishedHelper) 2495 throws Throwable { 2496 final AwContents awContents = testContainer.getAwContents(); 2497 AwSettings settings = getAwSettingsOnUiThread(awContents); 2498 2499 final String pageTemplate = "<html><head>%s</head>" + 2500 "<body onload='document.title=document.body.clientWidth'></body></html>"; 2501 final String pageNoViewport = String.format(pageTemplate, ""); 2502 final String pageViewportDeviceWidth = String.format( 2503 pageTemplate, 2504 "<meta name='viewport' content='width=device-width' />"); 2505 final String viewportTagSpecifiedWidth = "3000"; 2506 final String pageViewportSpecifiedWidth = String.format( 2507 pageTemplate, 2508 "<meta name='viewport' content='width=" + viewportTagSpecifiedWidth + "' />"); 2509 2510 DeviceDisplayInfo deviceInfo = DeviceDisplayInfo.create(testContainer.getContext()); 2511 int displayWidth = (int) (deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale()); 2512 2513 settings.setJavaScriptEnabled(true); 2514 assertFalse(settings.getUseWideViewPort()); 2515 // When UseWideViewPort is off, "width" setting of "meta viewport" 2516 // tags is ignored, and the layout width is set to device width in CSS pixels. 2517 // Thus, all 3 pages will have the same body width. 2518 loadDataSync(awContents, onPageFinishedHelper, pageNoViewport, "text/html", false); 2519 int actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); 2520 // Avoid rounding errors. 2521 assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth, 2522 Math.abs(displayWidth - actualWidth) <= 1); 2523 loadDataSync(awContents, onPageFinishedHelper, pageViewportDeviceWidth, "text/html", false); 2524 actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); 2525 assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth, 2526 Math.abs(displayWidth - actualWidth) <= 1); 2527 loadDataSync( 2528 awContents, onPageFinishedHelper, pageViewportSpecifiedWidth, "text/html", false); 2529 actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); 2530 assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth, 2531 Math.abs(displayWidth - actualWidth) <= 1); 2532 2533 settings.setUseWideViewPort(true); 2534 // When UseWideViewPort is on, "meta viewport" tag is used. 2535 // If there is no viewport tag, or width isn't specified, 2536 // then layout width is set to max(980, <device-width-in-DIP-pixels>) 2537 loadDataSync(awContents, onPageFinishedHelper, pageNoViewport, "text/html", false); 2538 actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); 2539 assertTrue("Expected: >= 980 , Actual: " + actualWidth, actualWidth >= 980); 2540 loadDataSync(awContents, onPageFinishedHelper, pageViewportDeviceWidth, "text/html", false); 2541 actualWidth = Integer.parseInt(getTitleOnUiThread(awContents)); 2542 assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth, 2543 Math.abs(displayWidth - actualWidth) <= 1); 2544 loadDataSync( 2545 awContents, onPageFinishedHelper, pageViewportSpecifiedWidth, "text/html", false); 2546 assertEquals(viewportTagSpecifiedWidth, getTitleOnUiThread(awContents)); 2547 } 2548 2549 @SmallTest 2550 @Feature({"AndroidWebView", "Preferences"}) 2551 public void testUseWideViewportLayoutWidth() throws Throwable { 2552 TestAwContentsClient contentClient = new TestAwContentsClient(); 2553 AwTestContainerView testContainerView = 2554 createAwTestContainerViewOnMainSync(contentClient); 2555 useWideViewportLayoutWidthTest(testContainerView, contentClient.getOnPageFinishedHelper()); 2556 } 2557 2558 @SmallTest 2559 @Feature({"AndroidWebView", "Preferences"}) 2560 public void testUseWideViewportLayoutWidthNoQuirks() throws Throwable { 2561 TestAwContentsClient contentClient = new TestAwContentsClient(); 2562 AwTestContainerView testContainerView = 2563 createAwTestContainerViewOnMainSync(contentClient, false); 2564 useWideViewportLayoutWidthTest(testContainerView, contentClient.getOnPageFinishedHelper()); 2565 } 2566 2567 @MediumTest 2568 @Feature({"AndroidWebView", "Preferences"}) 2569 public void testUseWideViewportControlsDoubleTabToZoom() throws Throwable { 2570 final TestAwContentsClient contentClient = new TestAwContentsClient(); 2571 final AwTestContainerView testContainerView = 2572 createAwTestContainerViewOnMainSync(contentClient); 2573 final AwContents awContents = testContainerView.getAwContents(); 2574 CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); 2575 AwSettings settings = getAwSettingsOnUiThread(awContents); 2576 settings.setBuiltInZoomControls(true); 2577 2578 DeviceDisplayInfo deviceInfo = 2579 DeviceDisplayInfo.create(testContainerView.getContext()); 2580 int displayWidth = (int) (deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale()); 2581 int layoutWidth = displayWidth * 2; 2582 final String page = "<html>" + 2583 "<head><meta name='viewport' content='width=" + layoutWidth + "'>" + 2584 "<style> body { width: " + layoutWidth + "px; }</style></head>" + 2585 "<body>Page Text</body></html>"; 2586 2587 assertFalse(settings.getUseWideViewPort()); 2588 // Without wide viewport the <meta viewport> tag will be ignored by WebView, 2589 // but it doesn't really matter as we don't expect double tap to change the scale. 2590 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); 2591 final float initialScale = getScaleOnUiThread(awContents); 2592 simulateDoubleTapCenterOfWebViewOnUiThread(testContainerView); 2593 Thread.sleep(1000); 2594 assertEquals(initialScale, getScaleOnUiThread(awContents)); 2595 2596 settings.setUseWideViewPort(true); 2597 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); 2598 int onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount(); 2599 simulateDoubleTapCenterOfWebViewOnUiThread(testContainerView); 2600 contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount); 2601 final float zoomedOutScale = getScaleOnUiThread(awContents); 2602 assertTrue("zoomedOut: " + zoomedOutScale + ", initial: " + initialScale, 2603 zoomedOutScale < initialScale); 2604 } 2605 2606 @SmallTest 2607 @Feature({"AndroidWebView", "Preferences"}) 2608 public void testForceZeroLayoutHeightWithTwoViews() throws Throwable { 2609 ViewPair views = createViews(); 2610 runPerViewSettingsTest( 2611 new AwSettingsForceZeroLayoutHeightTestHelper( 2612 views.getContainer0(), views.getClient0(), false), 2613 new AwSettingsForceZeroLayoutHeightTestHelper( 2614 views.getContainer1(), views.getClient1(), false)); 2615 } 2616 2617 @SmallTest 2618 @Feature({"AndroidWebView", "Preferences"}) 2619 public void testForceZeroLayoutHeightViewportTagWithTwoViews() throws Throwable { 2620 ViewPair views = createViews(); 2621 runPerViewSettingsTest( 2622 new AwSettingsForceZeroLayoutHeightTestHelper( 2623 views.getContainer0(), views.getClient0(), true), 2624 new AwSettingsForceZeroLayoutHeightTestHelper( 2625 views.getContainer1(), views.getClient1(), true)); 2626 } 2627 2628 @SmallTest 2629 @Feature({"AndroidWebView", "Preferences"}) 2630 public void testZeroLayoutHeightDisablesViewportQuirkWithTwoViews() throws Throwable { 2631 ViewPair views = createViews(); 2632 runPerViewSettingsTest( 2633 new AwSettingsZeroLayoutHeightDisablesViewportQuirkTestHelper( 2634 views.getContainer0(), views.getClient0()), 2635 new AwSettingsZeroLayoutHeightDisablesViewportQuirkTestHelper( 2636 views.getContainer1(), views.getClient1())); 2637 } 2638 2639 @SmallTest 2640 @Feature({"AndroidWebView", "Preferences"}) 2641 public void testLoadWithOverviewModeWithTwoViews() throws Throwable { 2642 ViewPair views = createViews(); 2643 runPerViewSettingsTest( 2644 new AwSettingsLoadWithOverviewModeTestHelper( 2645 views.getContainer0(), views.getClient0(), false), 2646 new AwSettingsLoadWithOverviewModeTestHelper( 2647 views.getContainer1(), views.getClient1(), false)); 2648 } 2649 2650 @SmallTest 2651 @Feature({"AndroidWebView", "Preferences"}) 2652 public void testLoadWithOverviewModeViewportTagWithTwoViews() throws Throwable { 2653 ViewPair views = createViews(); 2654 runPerViewSettingsTest( 2655 new AwSettingsLoadWithOverviewModeTestHelper( 2656 views.getContainer0(), views.getClient0(), true), 2657 new AwSettingsLoadWithOverviewModeTestHelper( 2658 views.getContainer1(), views.getClient1(), true)); 2659 } 2660 2661 @SmallTest 2662 @Feature({"AndroidWebView", "Preferences"}) 2663 public void testSetInitialScale() throws Throwable { 2664 final TestAwContentsClient contentClient = new TestAwContentsClient(); 2665 final AwTestContainerView testContainerView = 2666 createAwTestContainerViewOnMainSync(contentClient); 2667 final AwContents awContents = testContainerView.getAwContents(); 2668 final AwSettings awSettings = getAwSettingsOnUiThread(awContents); 2669 CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper(); 2670 2671 WindowManager wm = (WindowManager) getInstrumentation().getTargetContext() 2672 .getSystemService(Context.WINDOW_SERVICE); 2673 Point screenSize = new Point(); 2674 wm.getDefaultDisplay().getSize(screenSize); 2675 // Make sure after 50% scale, page width still larger than screen. 2676 int height = screenSize.y * 2 + 1; 2677 int width = screenSize.x * 2 + 1; 2678 final String page = "<html><body>" + 2679 "<p style='height:" + height + "px;width:" + width + "px'>" + 2680 "testSetInitialScale</p></body></html>"; 2681 final float defaultScale = 2682 getInstrumentation().getTargetContext().getResources().getDisplayMetrics().density; 2683 2684 assertEquals(defaultScale, getPixelScaleOnUiThread(awContents), .01f); 2685 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); 2686 assertEquals(defaultScale, getPixelScaleOnUiThread(awContents), .01f); 2687 2688 int onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount(); 2689 awSettings.setInitialPageScale(50); 2690 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); 2691 contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount); 2692 assertEquals(0.5f, getPixelScaleOnUiThread(awContents), .01f); 2693 2694 onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount(); 2695 awSettings.setInitialPageScale(500); 2696 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); 2697 contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount); 2698 assertEquals(5.0f, getPixelScaleOnUiThread(awContents), .01f); 2699 2700 onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount(); 2701 awSettings.setInitialPageScale(0); 2702 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false); 2703 contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount); 2704 assertEquals(defaultScale, getPixelScaleOnUiThread(awContents), .01f); 2705 } 2706 2707 /* 2708 @LargeTest 2709 @Feature({"AndroidWebView", "Preferences"}) 2710 http://crbug.com/304549 2711 */ 2712 @DisabledTest 2713 public void testMediaPlaybackWithoutUserGesture() throws Throwable { 2714 assertTrue(VideoTestUtil.runVideoTest(this, false, WAIT_TIMEOUT_MS)); 2715 } 2716 2717 @SmallTest 2718 @Feature({"AndroidWebView", "Preferences"}) 2719 public void testMediaPlaybackWithUserGesture() throws Throwable { 2720 // Wait for 5 second to see if video played. 2721 assertFalse(VideoTestUtil.runVideoTest(this, true, scaleTimeout(5000))); 2722 } 2723 2724 @SmallTest 2725 @Feature({"AndroidWebView", "Preferences"}) 2726 public void testDefaultVideoPosterURL() throws Throwable { 2727 final CallbackHelper videoPosterAccessedCallbackHelper = new CallbackHelper(); 2728 final String defaultVideoPosterUrl = "http://default_video_poster/"; 2729 TestAwContentsClient client = new TestAwContentsClient() { 2730 @Override 2731 public AwWebResourceResponse shouldInterceptRequest( 2732 ShouldInterceptRequestParams params) { 2733 if (params.url.equals(defaultVideoPosterUrl)) { 2734 videoPosterAccessedCallbackHelper.notifyCalled(); 2735 } 2736 return null; 2737 } 2738 }; 2739 final AwContents awContents = createAwTestContainerViewOnMainSync(client).getAwContents(); 2740 getInstrumentation().runOnMainSync(new Runnable() { 2741 @Override 2742 public void run() { 2743 AwSettings awSettings = awContents.getSettings(); 2744 awSettings.setDefaultVideoPosterURL(defaultVideoPosterUrl); 2745 } 2746 }); 2747 VideoTestWebServer webServer = new VideoTestWebServer( 2748 getInstrumentation().getTargetContext()); 2749 try { 2750 String data = "<html><head><body>" + 2751 "<video id='video' control src='" + 2752 webServer.getOnePixelOneFrameWebmURL() + "' /> </body></html>"; 2753 loadDataAsync(awContents, data, "text/html", false); 2754 videoPosterAccessedCallbackHelper.waitForCallback(0, 1, 20, TimeUnit.SECONDS); 2755 } finally { 2756 if (webServer.getTestWebServer() != null) 2757 webServer.getTestWebServer().shutdown(); 2758 } 2759 } 2760 2761 @SmallTest 2762 @Feature({"AndroidWebView", "Preferences"}) 2763 public void testAllowMixedMode() throws Throwable { 2764 final TestAwContentsClient contentClient = new TestAwContentsClient() { 2765 @Override 2766 public void onReceivedSslError(ValueCallback<Boolean> callback, SslError error) { 2767 callback.onReceiveValue(true); 2768 } 2769 }; 2770 final AwTestContainerView testContainerView = 2771 createAwTestContainerViewOnMainSync(contentClient); 2772 final AwContents awContents = testContainerView.getAwContents(); 2773 final AwSettings awSettings = getAwSettingsOnUiThread(awContents); 2774 2775 awSettings.setJavaScriptEnabled(true); 2776 2777 TestWebServer httpsServer = null; 2778 TestWebServer httpServer = null; 2779 try { 2780 httpsServer = new TestWebServer(true); 2781 httpServer = new TestWebServer(false); 2782 2783 final String jsUrl = "/insecure.js"; 2784 final String imageUrl = "/insecure.png"; 2785 final String secureUrl = "/secure.html"; 2786 httpServer.setResponse(jsUrl, "window.loaded_js = 42;", null); 2787 httpServer.setResponseBase64(imageUrl, CommonResources.FAVICON_DATA_BASE64, null); 2788 2789 final String jsHtml = "<script src=\"" + httpServer.getResponseUrl(jsUrl) + 2790 "\"></script>"; 2791 final String imageHtml = "<img src=\"" + httpServer.getResponseUrl(imageUrl) + "\" />"; 2792 final String secureHtml = "<body>" + imageHtml + " " + jsHtml + "</body>"; 2793 2794 String fullSecureUrl = httpsServer.setResponse(secureUrl, secureHtml, null); 2795 2796 awSettings.setMixedContentMode(AwSettings.MIXED_CONTENT_NEVER_ALLOW); 2797 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), fullSecureUrl); 2798 assertEquals(1, httpsServer.getRequestCount(secureUrl)); 2799 assertEquals(0, httpServer.getRequestCount(jsUrl)); 2800 assertEquals(0, httpServer.getRequestCount(imageUrl)); 2801 2802 awSettings.setMixedContentMode(AwSettings.MIXED_CONTENT_ALWAYS_ALLOW); 2803 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), fullSecureUrl); 2804 assertEquals(2, httpsServer.getRequestCount(secureUrl)); 2805 assertEquals(1, httpServer.getRequestCount(jsUrl)); 2806 assertEquals(1, httpServer.getRequestCount(imageUrl)); 2807 2808 awSettings.setMixedContentMode(AwSettings.MIXED_CONTENT_COMPATIBILITY_MODE); 2809 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), fullSecureUrl); 2810 assertEquals(3, httpsServer.getRequestCount(secureUrl)); 2811 assertEquals(1, httpServer.getRequestCount(jsUrl)); 2812 assertEquals(2, httpServer.getRequestCount(imageUrl)); 2813 } finally { 2814 if (httpServer != null) { 2815 httpServer.shutdown(); 2816 } 2817 if (httpsServer != null) { 2818 httpsServer.shutdown(); 2819 } 2820 } 2821 } 2822 2823 2824 static class ViewPair { 2825 private final AwTestContainerView mContainer0; 2826 private final TestAwContentsClient mClient0; 2827 private final AwTestContainerView mContainer1; 2828 private final TestAwContentsClient mClient1; 2829 2830 ViewPair(AwTestContainerView container0, TestAwContentsClient client0, 2831 AwTestContainerView container1, TestAwContentsClient client1) { 2832 this.mContainer0 = container0; 2833 this.mClient0 = client0; 2834 this.mContainer1 = container1; 2835 this.mClient1 = client1; 2836 } 2837 2838 AwTestContainerView getContainer0() { 2839 return mContainer0; 2840 } 2841 2842 AwContents getContents0() { 2843 return mContainer0.getAwContents(); 2844 } 2845 2846 TestAwContentsClient getClient0() { 2847 return mClient0; 2848 } 2849 2850 AwTestContainerView getContainer1() { 2851 return mContainer1; 2852 } 2853 2854 AwContents getContents1() { 2855 return mContainer1.getAwContents(); 2856 } 2857 2858 TestAwContentsClient getClient1() { 2859 return mClient1; 2860 } 2861 } 2862 2863 /** 2864 * Verifies the following statements about a setting: 2865 * - initially, the setting has a default value; 2866 * - the setting can be switched to an alternate value and back; 2867 * - switching a setting in the first WebView doesn't affect the setting 2868 * state in the second WebView and vice versa. 2869 * 2870 * @param helper0 Test helper for the first ContentView 2871 * @param helper1 Test helper for the second ContentView 2872 * @throws Throwable 2873 */ 2874 private void runPerViewSettingsTest(AwSettingsTestHelper helper0, 2875 AwSettingsTestHelper helper1) throws Throwable { 2876 helper0.ensureSettingHasInitialValue(); 2877 helper1.ensureSettingHasInitialValue(); 2878 2879 helper1.setAlteredSettingValue(); 2880 helper0.ensureSettingHasInitialValue(); 2881 helper1.ensureSettingHasAlteredValue(); 2882 2883 helper1.setInitialSettingValue(); 2884 helper0.ensureSettingHasInitialValue(); 2885 helper1.ensureSettingHasInitialValue(); 2886 2887 helper0.setAlteredSettingValue(); 2888 helper0.ensureSettingHasAlteredValue(); 2889 helper1.ensureSettingHasInitialValue(); 2890 2891 helper0.setInitialSettingValue(); 2892 helper0.ensureSettingHasInitialValue(); 2893 helper1.ensureSettingHasInitialValue(); 2894 2895 helper0.setAlteredSettingValue(); 2896 helper0.ensureSettingHasAlteredValue(); 2897 helper1.ensureSettingHasInitialValue(); 2898 2899 helper1.setAlteredSettingValue(); 2900 helper0.ensureSettingHasAlteredValue(); 2901 helper1.ensureSettingHasAlteredValue(); 2902 2903 helper0.setInitialSettingValue(); 2904 helper0.ensureSettingHasInitialValue(); 2905 helper1.ensureSettingHasAlteredValue(); 2906 2907 helper1.setInitialSettingValue(); 2908 helper0.ensureSettingHasInitialValue(); 2909 helper1.ensureSettingHasInitialValue(); 2910 } 2911 2912 private ViewPair createViews() throws Throwable { 2913 return createViews(false); 2914 } 2915 2916 private ViewPair createViews(boolean supportsLegacyQuirks) throws Throwable { 2917 TestAwContentsClient client0 = new TestAwContentsClient(); 2918 TestAwContentsClient client1 = new TestAwContentsClient(); 2919 return new ViewPair( 2920 createAwTestContainerViewOnMainSync(client0, supportsLegacyQuirks), 2921 client0, 2922 createAwTestContainerViewOnMainSync(client1, supportsLegacyQuirks), 2923 client1); 2924 } 2925 2926 static void assertFileIsReadable(String filePath) { 2927 File file = new File(filePath); 2928 try { 2929 assertTrue("Test file \"" + filePath + "\" is not readable." + 2930 "Please make sure that files from android_webview/test/data/device_files/ " + 2931 "has been pushed to the device before testing", 2932 file.canRead()); 2933 } catch (SecurityException e) { 2934 fail("Got a SecurityException for \"" + filePath + "\": " + e.toString()); 2935 } 2936 } 2937 2938 /** 2939 * Verifies the number of resource requests made to the content provider. 2940 * @param resource Resource name 2941 * @param expectedCount Expected resource requests count 2942 */ 2943 private void ensureResourceRequestCountInContentProvider(String resource, int expectedCount) { 2944 Context context = getInstrumentation().getTargetContext(); 2945 int actualCount = TestContentProvider.getResourceRequestCount(context, resource); 2946 assertEquals(expectedCount, actualCount); 2947 } 2948 2949 private void resetResourceRequestCountInContentProvider(String resource) { 2950 Context context = getInstrumentation().getTargetContext(); 2951 TestContentProvider.resetResourceRequestCount(context, resource); 2952 } 2953 2954 private String createContentUrl(final String target) { 2955 return TestContentProvider.createContentUrl(target); 2956 } 2957 2958 private void simulateDoubleTapCenterOfWebViewOnUiThread(final AwTestContainerView webView) 2959 throws Throwable { 2960 final int x = (webView.getRight() - webView.getLeft()) / 2; 2961 final int y = (webView.getBottom() - webView.getTop()) / 2; 2962 final AwContents awContents = webView.getAwContents(); 2963 runTestOnUiThread(new Runnable() { 2964 @Override 2965 public void run() { 2966 awContents.getContentViewCore().sendDoubleTapForTest( 2967 SystemClock.uptimeMillis(), x, y); 2968 } 2969 }); 2970 } 2971 } 2972