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.
5 package org.chromium.android_webview.test;
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;
19 import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
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;
43 import java.util.concurrent.Callable;
44 import java.util.concurrent.TimeUnit;
45 import java.util.regex.Matcher;
46 import java.util.regex.Pattern;
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
53 public class AwSettingsTest extends AwTestBase {
54 private static final boolean ENABLED = true;
55 private static final boolean DISABLED = false;
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.
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;
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);
81 void ensureSettingHasAlteredValue() throws Throwable {
82 ensureSettingHasValue(getAlteredValue());
85 void ensureSettingHasInitialValue() throws Throwable {
86 ensureSettingHasValue(getInitialValue());
89 void setAlteredSettingValue() throws Throwable {
90 setCurrentValue(getAlteredValue());
93 void setInitialSettingValue() throws Throwable {
94 setCurrentValue(getInitialValue());
97 protected abstract T getAlteredValue();
99 protected abstract T getInitialValue();
101 protected abstract T getCurrentValue();
103 protected abstract void setCurrentValue(T value) throws Throwable;
105 protected abstract void doEnsureSettingHasValue(T value) throws Throwable;
107 protected String getTitleOnUiThread() throws Exception {
108 return AwSettingsTest.this.getTitleOnUiThread(mAwContents);
111 protected void loadDataSync(String data) throws Throwable {
112 AwSettingsTest.this.loadDataSync(
114 mContentViewClient.getOnPageFinishedHelper(),
120 protected void loadUrlSync(String url) throws Throwable {
121 AwSettingsTest.this.loadUrlSync(
123 mContentViewClient.getOnPageFinishedHelper(),
127 protected void loadUrlSyncAndExpectError(String url) throws Throwable {
128 AwSettingsTest.this.loadUrlSyncAndExpectError(
130 mContentViewClient.getOnPageFinishedHelper(),
131 mContentViewClient.getOnReceivedErrorHelper(),
135 protected String executeJavaScriptAndWaitForResult(String script) throws Exception {
136 return AwSettingsTest.this.executeJavaScriptAndWaitForResult(
137 mAwContents, mContentViewClient, script);
140 private void ensureSettingHasValue(T value) throws Throwable {
141 assertEquals(value, getCurrentValue());
142 doEnsureSettingHasValue(value);
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";
150 AwSettingsJavaScriptTestHelper(AwTestContainerView containerView,
151 TestAwContentsClient contentViewClient) throws Throwable {
152 super(containerView, contentViewClient, false);
156 protected Boolean getAlteredValue() {
161 protected Boolean getInitialValue() {
166 protected Boolean getCurrentValue() {
167 return mAwSettings.getJavaScriptEnabled();
171 protected void setCurrentValue(Boolean value) {
172 mAwSettings.setJavaScriptEnabled(value);
176 protected void doEnsureSettingHasValue(Boolean value) throws Throwable {
177 loadDataSync(getData());
179 value == ENABLED ? JS_ENABLED_STRING : JS_DISABLED_STRING,
180 getTitleOnUiThread());
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>";
190 // In contrast to AwSettingsJavaScriptTestHelper, doesn't reload the page when testing
192 class AwSettingsJavaScriptDynamicTestHelper extends AwSettingsJavaScriptTestHelper {
193 AwSettingsJavaScriptDynamicTestHelper(
194 AwTestContainerView containerView,
195 TestAwContentsClient contentViewClient) throws Throwable {
196 super(containerView, contentViewClient);
198 super.doEnsureSettingHasValue(getInitialValue());
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());
209 private String getScript(String title) {
210 return "document.title='" + title + "';";
214 class AwSettingsPluginsTestHelper extends AwSettingsTestHelper<Boolean> {
215 private static final String PLUGINS_ENABLED_STRING = "Embed";
216 private static final String PLUGINS_DISABLED_STRING = "NoEmbed";
218 AwSettingsPluginsTestHelper(AwTestContainerView containerView,
219 TestAwContentsClient contentViewClient) throws Throwable {
220 super(containerView, contentViewClient, true);
224 protected Boolean getAlteredValue() {
229 protected Boolean getInitialValue() {
234 protected Boolean getCurrentValue() {
235 return mAwSettings.getPluginsEnabled();
239 protected void setCurrentValue(Boolean value) {
240 mAwSettings.setPluginsEnabled(value);
244 protected void doEnsureSettingHasValue(Boolean value) throws Throwable {
245 loadDataSync(getData());
247 value == ENABLED ? PLUGINS_ENABLED_STRING : PLUGINS_DISABLED_STRING,
248 getTitleOnUiThread());
251 private String getData() {
252 return "<html><body onload=\"document.title = document.body.innerText;\">"
253 + "<noembed>No</noembed><span>Embed</span></body></html>";
257 class AwSettingsStandardFontFamilyTestHelper extends AwSettingsTestHelper<String> {
258 AwSettingsStandardFontFamilyTestHelper(
259 AwTestContainerView containerView,
260 TestAwContentsClient contentViewClient) throws Throwable {
261 super(containerView, contentViewClient, true);
265 protected String getAlteredValue() {
270 protected String getInitialValue() {
275 protected String getCurrentValue() {
276 return mAwSettings.getStandardFontFamily();
280 protected void setCurrentValue(String value) {
281 mAwSettings.setStandardFontFamily(value);
285 protected void doEnsureSettingHasValue(String value) throws Throwable {
286 loadDataSync(getData());
287 assertEquals(value, getTitleOnUiThread());
290 private String getData() {
291 return "<html><body onload=\"document.title = "
292 + "getComputedStyle(document.body).getPropertyValue('font-family');\">"
297 class AwSettingsDefaultFontSizeTestHelper extends AwSettingsTestHelper<Integer> {
298 AwSettingsDefaultFontSizeTestHelper(
299 AwTestContainerView containerView,
300 TestAwContentsClient contentViewClient) throws Throwable {
301 super(containerView, contentViewClient, true);
305 protected Integer getAlteredValue() {
310 protected Integer getInitialValue() {
315 protected Integer getCurrentValue() {
316 return mAwSettings.getDefaultFontSize();
320 protected void setCurrentValue(Integer value) {
321 mAwSettings.setDefaultFontSize(value);
325 protected void doEnsureSettingHasValue(Integer value) throws Throwable {
326 loadDataSync(getData());
327 assertEquals(value.toString() + "px", getTitleOnUiThread());
330 private String getData() {
331 return "<html><body onload=\"document.title = "
332 + "getComputedStyle(document.body).getPropertyValue('font-size');\">"
337 class AwSettingsLoadImagesAutomaticallyTestHelper extends AwSettingsTestHelper<Boolean> {
338 private ImagePageGenerator mGenerator;
340 AwSettingsLoadImagesAutomaticallyTestHelper(
341 AwTestContainerView containerView,
342 TestAwContentsClient contentViewClient,
343 ImagePageGenerator generator) throws Throwable {
344 super(containerView, contentViewClient, true);
345 mGenerator = generator;
349 protected Boolean getAlteredValue() {
354 protected Boolean getInitialValue() {
359 protected Boolean getCurrentValue() {
360 return mAwSettings.getLoadsImagesAutomatically();
364 protected void setCurrentValue(Boolean value) {
365 mAwSettings.setLoadsImagesAutomatically(value);
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());
379 class AwSettingsImagesEnabledHelper extends AwSettingsTestHelper<Boolean> {
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;
392 protected Boolean getAlteredValue() {
397 protected Boolean getInitialValue() {
402 protected Boolean getCurrentValue() {
403 return mAwSettings.getImagesEnabled();
407 protected void setCurrentValue(Boolean value) {
408 mAwSettings.setImagesEnabled(value);
412 protected void doEnsureSettingHasValue(Boolean value) throws Throwable {
413 final String httpImageUrl = mGenerator.getPageUrl(mWebServer);
414 AwSettingsTest.this.loadUrlSync(
416 mContentViewClient.getOnPageFinishedHelper(),
418 assertEquals(value == ENABLED
419 ? ImagePageGenerator.IMAGE_LOADED_STRING
420 : ImagePageGenerator.IMAGE_NOT_LOADED_STRING,
421 getTitleOnUiThread());
424 private TestWebServer mWebServer;
425 private ImagePageGenerator mGenerator;
428 class AwSettingsDefaultTextEncodingTestHelper extends AwSettingsTestHelper<String> {
429 AwSettingsDefaultTextEncodingTestHelper(
430 AwTestContainerView containerView,
431 TestAwContentsClient contentViewClient) throws Throwable {
432 super(containerView, contentViewClient, true);
436 protected String getAlteredValue() {
441 protected String getInitialValue() {
446 protected String getCurrentValue() {
447 return mAwSettings.getDefaultTextEncodingName();
451 protected void setCurrentValue(String value) {
452 mAwSettings.setDefaultTextEncodingName(value);
456 protected void doEnsureSettingHasValue(String value) throws Throwable {
457 loadDataSync(getData());
458 assertEquals(value, getTitleOnUiThread());
461 private String getData() {
462 return "<html><body onload='document.title=document.defaultCharset'></body></html>";
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";
471 AwSettingsUserAgentStringTestHelper(
472 AwTestContainerView containerView,
473 TestAwContentsClient contentViewClient) throws Throwable {
474 super(containerView, contentViewClient, true);
475 mDefaultUa = mAwSettings.getUserAgentString();
479 protected String getAlteredValue() {
484 protected String getInitialValue() {
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
495 String currentUa = mAwSettings.getUserAgentString();
496 return mDefaultUa.equals(currentUa) ? DEFAULT_UA : currentUa;
500 protected void setCurrentValue(String value) {
501 mAwSettings.setUserAgentString(value);
505 protected void doEnsureSettingHasValue(String value) throws Throwable {
506 loadDataSync(getData());
508 DEFAULT_UA.equals(value) ? mDefaultUa : value,
509 getTitleOnUiThread());
512 private String getData() {
513 return "<html><body onload='document.title=navigator.userAgent'></body></html>";
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";
522 AwSettingsDomStorageEnabledTestHelper(
523 AwTestContainerView containerView,
524 TestAwContentsClient contentViewClient) throws Throwable {
525 super(containerView, contentViewClient, true);
526 AwSettingsTest.assertFileIsReadable(UrlUtils.getTestFilePath(TEST_FILE));
530 protected Boolean getAlteredValue() {
535 protected Boolean getInitialValue() {
540 protected Boolean getCurrentValue() {
541 return mAwSettings.getDomStorageEnabled();
545 protected void setCurrentValue(Boolean value) {
546 mAwSettings.setDomStorageEnabled(value);
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));
555 value == ENABLED ? HAS_LOCAL_STORAGE : NO_LOCAL_STORAGE,
556 getTitleOnUiThread());
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";
565 AwSettingsDatabaseTestHelper(
566 AwTestContainerView containerView,
567 TestAwContentsClient contentViewClient) throws Throwable {
568 super(containerView, contentViewClient, true);
569 AwSettingsTest.assertFileIsReadable(UrlUtils.getTestFilePath(TEST_FILE));
573 protected Boolean getAlteredValue() {
578 protected Boolean getInitialValue() {
583 protected Boolean getCurrentValue() {
584 return mAwSettings.getDatabaseEnabled();
588 protected void setCurrentValue(Boolean value) {
589 mAwSettings.setDatabaseEnabled(value);
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
597 loadUrlSync(UrlUtils.getTestFileUrl(TEST_FILE));
599 value == ENABLED ? HAS_DATABASE : NO_DATABASE,
600 getTitleOnUiThread());
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";
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);
626 protected Boolean getAlteredValue() {
631 protected Boolean getInitialValue() {
636 protected Boolean getCurrentValue() {
637 return mAwSettings.getAllowUniversalAccessFromFileURLs();
641 protected void setCurrentValue(Boolean value) {
642 mAwSettings.setAllowUniversalAccessFromFileURLs(value);
646 protected void doEnsureSettingHasValue(Boolean value) throws Throwable {
647 loadUrlSync(mIframeContainerUrl);
649 value == ENABLED ? mIframeUrl : ACCESS_DENIED_TITLE,
650 getTitleOnUiThread());
653 private final String mIframeContainerUrl;
654 private final String mIframeUrl;
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";
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);
676 protected Boolean getAlteredValue() {
681 protected Boolean getInitialValue() {
686 protected Boolean getCurrentValue() {
687 return mAwSettings.getAllowFileAccessFromFileURLs();
691 protected void setCurrentValue(Boolean value) {
692 mAwSettings.setAllowFileAccessFromFileURLs(value);
696 protected void doEnsureSettingHasValue(Boolean value) throws Throwable {
697 loadUrlSync(mIframeContainerUrl);
699 value == ENABLED ? mIframeUrl : ACCESS_DENIED_TITLE,
700 getTitleOnUiThread());
703 private final String mIframeContainerUrl;
704 private final String mIframeUrl;
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";
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);
724 protected Boolean getAlteredValue() {
729 protected Boolean getInitialValue() {
734 protected Boolean getCurrentValue() {
735 return mAwSettings.getAllowFileAccessFromFileURLs();
739 protected void setCurrentValue(Boolean value) {
740 mAwSettings.setAllowFileAccessFromFileURLs(value);
744 protected void doEnsureSettingHasValue(Boolean value) throws Throwable {
745 loadUrlSync(mXhrContainerUrl);
747 value == ENABLED ? ACCESS_GRANTED_TITLE : ACCESS_DENIED_TITLE,
748 getTitleOnUiThread());
751 private final String mXhrContainerUrl;
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!";
758 AwSettingsFileUrlAccessTestHelper(
759 AwTestContainerView containerView,
760 TestAwContentsClient contentViewClient,
761 int startIndex) throws Throwable {
762 super(containerView, contentViewClient, true);
764 AwSettingsTest.assertFileIsReadable(UrlUtils.getTestFilePath(TEST_FILE));
768 protected Boolean getAlteredValue() {
773 protected Boolean getInitialValue() {
778 protected Boolean getCurrentValue() {
779 return mAwSettings.getAllowFileAccess();
783 protected void setCurrentValue(Boolean value) {
784 mAwSettings.setAllowFileAccess(value);
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);
792 if (value == ENABLED) {
793 loadUrlSync(fileUrl);
794 assertEquals(ACCESS_GRANTED_TITLE, getTitleOnUiThread());
796 loadUrlSyncAndExpectError(fileUrl);
803 class AwSettingsContentUrlAccessTestHelper extends AwSettingsTestHelper<Boolean> {
805 AwSettingsContentUrlAccessTestHelper(
806 AwTestContainerView containerView,
807 TestAwContentsClient contentViewClient,
808 int index) throws Throwable {
809 super(containerView, contentViewClient, true);
810 mTarget = "content_access_" + index;
814 protected Boolean getAlteredValue() {
819 protected Boolean getInitialValue() {
824 protected Boolean getCurrentValue() {
825 return mAwSettings.getAllowContentAccess();
829 protected void setCurrentValue(Boolean value) {
830 mAwSettings.setAllowContentAccess(value);
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);
844 loadUrlSyncAndExpectError(AwSettingsTest.this.createContentUrl(mTarget));
845 AwSettingsTest.this.ensureResourceRequestCountInContentProvider(mTarget, 0);
849 private final String mTarget;
852 class AwSettingsContentUrlAccessFromFileTestHelper extends AwSettingsTestHelper<Boolean> {
853 private static final String TARGET = "content_from_file";
855 AwSettingsContentUrlAccessFromFileTestHelper(
856 AwTestContainerView containerView,
857 TestAwContentsClient contentViewClient,
858 int index) throws Throwable {
859 super(containerView, contentViewClient, true);
861 mTempDir = getInstrumentation().getTargetContext().getCacheDir().getPath();
865 protected Boolean getAlteredValue() {
870 protected Boolean getInitialValue() {
875 protected Boolean getCurrentValue() {
876 return mAwSettings.getAllowContentAccess();
880 protected void setCurrentValue(Boolean value) {
881 mAwSettings.setAllowContentAccess(value);
885 protected void doEnsureSettingHasValue(Boolean value) throws Throwable {
886 AwSettingsTest.this.resetResourceRequestCountInContentProvider(TARGET);
887 final String fileName = mTempDir + "/" + TARGET + ".html";
889 TestFileUtil.createNewHtmlFile(fileName,
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) + "\">");
897 loadUrlSync("file://" + fileName);
898 if (value == ENABLED) {
899 AwSettingsTest.this.ensureResourceRequestCountInContentProvider(TARGET, 1);
901 AwSettingsTest.this.ensureResourceRequestCountInContentProvider(TARGET, 0);
904 TestFileUtil.deleteFile(fileName);
909 private String mTempDir;
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;
917 AwSettingsTextAutosizingTestHelper(
918 AwTestContainerView containerView,
919 TestAwContentsClient contentViewClient) throws Throwable {
920 super(containerView, contentViewClient, true);
921 mNeedToWaitForFontSizeChange = false;
922 loadDataSync(getData());
926 protected void setCurrentValue(T value) throws Throwable {
927 mNeedToWaitForFontSizeChange = false;
928 if (value != getCurrentValue()) {
929 mOldFontSize = getActualFontSize();
930 mNeedToWaitForFontSizeChange = true;
934 protected float getActualFontSize() throws Throwable {
935 if (!mNeedToWaitForFontSizeChange) {
936 executeJavaScriptAndWaitForResult("setTitleToActualFontSize()");
938 final float oldFontSize = mOldFontSize;
939 poll(new Callable<Boolean>() {
941 public Boolean call() throws Exception {
942 executeJavaScriptAndWaitForResult("setTitleToActualFontSize()");
943 float newFontSize = Float.parseFloat(getTitleOnUiThread());
944 return newFontSize != oldFontSize;
947 mNeedToWaitForFontSizeChange = false;
949 return Float.parseFloat(getTitleOnUiThread());
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();
959 + "<meta name=\"viewport\" content=\"width=" + layoutWidth + "\">"
961 + "body { width: " + layoutWidth + "px; margin: 0; overflow-y: hidden; }"
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>"
970 + "<p id=\"par\" style=\"font-size:");
971 sb.append(PARAGRAPH_FONT_SIZE);
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! ");
977 sb.append("</p></body></html>");
978 return sb.toString();
981 private boolean mNeedToWaitForFontSizeChange;
982 private float mOldFontSize;
985 class AwSettingsLayoutAlgorithmTestHelper extends
986 AwSettingsTextAutosizingTestHelper<LayoutAlgorithm> {
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);
997 protected LayoutAlgorithm getAlteredValue() {
998 return LayoutAlgorithm.TEXT_AUTOSIZING;
1002 protected LayoutAlgorithm getInitialValue() {
1003 return LayoutAlgorithm.NARROW_COLUMNS;
1007 protected LayoutAlgorithm getCurrentValue() {
1008 return mAwSettings.getLayoutAlgorithm();
1012 protected void setCurrentValue(LayoutAlgorithm value) throws Throwable {
1013 super.setCurrentValue(value);
1014 mAwSettings.setLayoutAlgorithm(value);
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);
1024 assertTrue("Actual font size: " + actualFontSize,
1025 actualFontSize == PARAGRAPH_FONT_SIZE);
1030 class AwSettingsTextZoomTestHelper extends AwSettingsTextAutosizingTestHelper<Integer> {
1031 private static final int INITIAL_TEXT_ZOOM = 100;
1032 private final float mInitialActualFontSize;
1034 AwSettingsTextZoomTestHelper(
1035 AwTestContainerView containerView,
1036 TestAwContentsClient contentViewClient) throws Throwable {
1037 super(containerView, contentViewClient);
1038 mInitialActualFontSize = getActualFontSize();
1042 protected Integer getAlteredValue() {
1043 return INITIAL_TEXT_ZOOM * 2;
1047 protected Integer getInitialValue() {
1048 return INITIAL_TEXT_ZOOM;
1052 protected Integer getCurrentValue() {
1053 return mAwSettings.getTextZoom();
1057 protected void setCurrentValue(Integer value) throws Throwable {
1058 super.setCurrentValue(value);
1059 mAwSettings.setTextZoom(value);
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));
1071 "|(" + actualFontSize + " / " + mInitialActualFontSize + ") - ("
1072 + value + " / " + INITIAL_TEXT_ZOOM + ")| = " + ratiosDelta,
1073 ratiosDelta <= 0.2f);
1077 class AwSettingsTextZoomAutosizingTestHelper
1078 extends AwSettingsTextAutosizingTestHelper<Integer> {
1079 private static final int INITIAL_TEXT_ZOOM = 100;
1080 private final float mInitialActualFontSize;
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
1089 mInitialActualFontSize = getActualFontSize();
1093 protected Integer getAlteredValue() {
1094 return INITIAL_TEXT_ZOOM * 2;
1098 protected Integer getInitialValue() {
1099 return INITIAL_TEXT_ZOOM;
1103 protected Integer getCurrentValue() {
1104 return mAwSettings.getTextZoom();
1108 protected void setCurrentValue(Integer value) throws Throwable {
1109 super.setCurrentValue(value);
1110 mAwSettings.setTextZoom(value);
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));
1122 "|(" + actualFontSize + " / " + mInitialActualFontSize + ") - ("
1123 + value + " / " + INITIAL_TEXT_ZOOM + ")| = " + ratiosDelta,
1124 ratiosDelta <= 0.2f);
1128 class AwSettingsJavaScriptPopupsTestHelper extends AwSettingsTestHelper<Boolean> {
1129 private static final String POPUP_ENABLED = "Popup enabled";
1130 private static final String POPUP_BLOCKED = "Popup blocked";
1132 AwSettingsJavaScriptPopupsTestHelper(
1133 AwTestContainerView containerView,
1134 TestAwContentsClient contentViewClient) throws Throwable {
1135 super(containerView, contentViewClient, true);
1139 protected Boolean getAlteredValue() {
1144 protected Boolean getInitialValue() {
1149 protected Boolean getCurrentValue() {
1150 return mAwSettings.getJavaScriptCanOpenWindowsAutomatically();
1154 protected void setCurrentValue(Boolean value) {
1155 mAwSettings.setJavaScriptCanOpenWindowsAutomatically(value);
1159 protected void doEnsureSettingHasValue(Boolean value) throws Throwable {
1160 loadDataSync(getData());
1161 final boolean expectPopupEnabled = value;
1162 poll(new Callable<Boolean>() {
1164 public Boolean call() throws Exception {
1165 String title = getTitleOnUiThread();
1166 return expectPopupEnabled ? POPUP_ENABLED.equals(title) :
1167 POPUP_BLOCKED.equals(title);
1170 assertEquals(value ? POPUP_ENABLED : POPUP_BLOCKED, getTitleOnUiThread());
1173 private String getData() {
1174 return "<html><head>"
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 + "';"
1182 + "</script></head>"
1183 + "<body onload='tryOpenWindow()'></body></html>";
1187 class AwSettingsCacheModeTestHelper extends AwSettingsTestHelper<Integer> {
1189 AwSettingsCacheModeTestHelper(
1190 AwTestContainerView containerView,
1191 TestAwContentsClient contentViewClient,
1193 TestWebServer webServer) throws Throwable {
1194 super(containerView, contentViewClient, true);
1196 mWebServer = webServer;
1200 protected Integer getAlteredValue() {
1201 // We use the value that results in a behaviour completely opposite to default.
1202 return WebSettings.LOAD_CACHE_ONLY;
1206 protected Integer getInitialValue() {
1207 return WebSettings.LOAD_DEFAULT;
1211 protected Integer getCurrentValue() {
1212 return mAwSettings.getCacheMode();
1216 protected void setCurrentValue(Integer value) {
1217 mAwSettings.setCacheMode(value);
1221 protected void doEnsureSettingHasValue(Integer value) throws Throwable {
1222 final String htmlPath = "/cache_mode_" + mIndex + ".html";
1224 final String url = mWebServer.setResponse(htmlPath, "response", null);
1225 assertEquals(0, mWebServer.getRequestCount(htmlPath));
1226 if (value == WebSettings.LOAD_DEFAULT) {
1228 assertEquals(1, mWebServer.getRequestCount(htmlPath));
1230 loadUrlSyncAndExpectError(url);
1231 assertEquals(0, mWebServer.getRequestCount(htmlPath));
1236 private TestWebServer mWebServer;
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";
1247 AwSettingsUseWideViewportTestHelper(
1248 AwTestContainerView containerView,
1249 TestAwContentsClient contentViewClient) throws Throwable {
1250 super(containerView, contentViewClient, true);
1254 protected Boolean getAlteredValue() {
1259 protected Boolean getInitialValue() {
1264 protected Boolean getCurrentValue() {
1265 return mAwSettings.getUseWideViewPort();
1269 protected void setCurrentValue(Boolean value) {
1270 mAwSettings.setUseWideViewPort(value);
1274 protected void doEnsureSettingHasValue(Boolean value) throws Throwable {
1275 loadDataSync(getData());
1276 final String bodyWidth = getTitleOnUiThread();
1278 assertTrue(bodyWidth, VIEWPORT_TAG_LAYOUT_WIDTH.equals(bodyWidth));
1280 assertFalse(bodyWidth, VIEWPORT_TAG_LAYOUT_WIDTH.equals(bodyWidth));
1284 private String getData() {
1285 return "<html><head>"
1286 + "<meta name='viewport' content='width=" + VIEWPORT_TAG_LAYOUT_WIDTH + "' />"
1288 + "<body onload='document.title=document.body.clientWidth'></body></html>";
1292 class AwSettingsLoadWithOverviewModeTestHelper extends AwSettingsTestHelper<Boolean> {
1293 private static final float DEFAULT_PAGE_SCALE = 1.0f;
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);
1305 protected Boolean getAlteredValue() {
1310 protected Boolean getInitialValue() {
1315 protected Boolean getCurrentValue() {
1316 return mAwSettings.getLoadWithOverviewMode();
1320 protected void setCurrentValue(Boolean value) {
1321 mExpectScaleChange = mAwSettings.getLoadWithOverviewMode() != value;
1322 if (mExpectScaleChange) {
1323 mOnScaleChangedCallCount =
1324 mContentViewClient.getOnScaleChangedHelper().getCallCount();
1326 mAwSettings.setLoadWithOverviewMode(value);
1330 protected void doEnsureSettingHasValue(Boolean value) throws Throwable {
1331 loadDataSync(getData());
1332 if (mExpectScaleChange) {
1333 mContentViewClient.getOnScaleChangedHelper()
1334 .waitForCallback(mOnScaleChangedCallCount);
1335 mExpectScaleChange = false;
1337 float currentScale = AwSettingsTest.this.getScaleOnUiThread(mAwContents);
1339 assertTrue("Expected: " + currentScale + " < " + DEFAULT_PAGE_SCALE,
1340 currentScale < DEFAULT_PAGE_SCALE);
1342 assertEquals(DEFAULT_PAGE_SCALE, currentScale);
1346 private String getData() {
1347 return "<html><head>"
1348 + (mWithViewPortTag ? "<meta name='viewport' content='width=3000' />" : "")
1350 + "<body></body></html>";
1353 private final boolean mWithViewPortTag;
1354 private boolean mExpectScaleChange;
1355 private int mOnScaleChangedCallCount;
1358 class AwSettingsForceZeroLayoutHeightTestHelper extends AwSettingsTestHelper<Boolean> {
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);
1370 protected Boolean getAlteredValue() {
1375 protected Boolean getInitialValue() {
1380 protected Boolean getCurrentValue() {
1381 return mAwSettings.getForceZeroLayoutHeight();
1385 protected void setCurrentValue(Boolean value) {
1386 mAwSettings.setForceZeroLayoutHeight(value);
1390 protected void doEnsureSettingHasValue(Boolean value) throws Throwable {
1391 loadDataSync(getData());
1392 int height = Integer.parseInt(getTitleOnUiThread());
1394 assertEquals(0, height);
1396 assertTrue("Div should be at least 50px high, was: " + height, height >= 50);
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; "
1410 + " <div style='height:50px;'>test</div> "
1411 + " <div id='testDiv' style='height:100%;'></div> "
1415 private final boolean mWithViewPortTag;
1418 class AwSettingsZeroLayoutHeightDisablesViewportQuirkTestHelper extends
1419 AwSettingsTestHelper<Boolean> {
1421 AwSettingsZeroLayoutHeightDisablesViewportQuirkTestHelper(
1422 AwTestContainerView containerView,
1423 TestAwContentsClient contentViewClient) throws Throwable {
1424 super(containerView, contentViewClient, true);
1425 mAwSettings.setUseWideViewPort(true);
1426 mAwSettings.setForceZeroLayoutHeight(true);
1430 protected Boolean getAlteredValue() {
1435 protected Boolean getInitialValue() {
1440 protected Boolean getCurrentValue() {
1441 return mAwSettings.getZeroLayoutHeightDisablesViewportQuirk();
1445 protected void setCurrentValue(Boolean value) {
1446 mAwSettings.setZeroLayoutHeightDisablesViewportQuirk(value);
1450 protected void doEnsureSettingHasValue(Boolean value) throws Throwable {
1451 DeviceDisplayInfo deviceInfo = DeviceDisplayInfo.create(mContext);
1452 int displayWidth = (int) (deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale());
1454 loadDataSync(getData());
1455 int width = Integer.parseInt(getTitleOnUiThread());
1457 assertEquals(displayWidth, width);
1459 assertEquals(3000, width);
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; "
1473 + " <div style='height:50px;'>test</div> "
1474 + " <div id='testDiv' style='height:100%;'></div> "
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
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();
1500 contentClient.getOnPageFinishedHelper(),
1504 assertEquals(jsDisabledString, getTitleOnUiThread(awContents));
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()));
1517 @Feature({"AndroidWebView", "Preferences"})
1518 public void testJavaScriptEnabledDynamicWithTwoViews() throws Throwable {
1519 ViewPair views = createViews();
1520 runPerViewSettingsTest(
1521 new AwSettingsJavaScriptDynamicTestHelper(
1522 views.getContainer0(), views.getClient0()),
1523 new AwSettingsJavaScriptDynamicTestHelper(
1524 views.getContainer1(), views.getClient1()));
1528 @Feature({"AndroidWebView", "Preferences"})
1529 public void testPluginsEnabledWithTwoViews() throws Throwable {
1530 ViewPair views = createViews();
1531 runPerViewSettingsTest(
1532 new AwSettingsPluginsTestHelper(views.getContainer0(), views.getClient0()),
1533 new AwSettingsPluginsTestHelper(views.getContainer1(), views.getClient1()));
1537 @Feature({"AndroidWebView", "Preferences"})
1538 public void testStandardFontFamilyWithTwoViews() throws Throwable {
1539 ViewPair views = createViews();
1540 runPerViewSettingsTest(
1541 new AwSettingsStandardFontFamilyTestHelper(
1542 views.getContainer0(), views.getClient0()),
1543 new AwSettingsStandardFontFamilyTestHelper(
1544 views.getContainer1(), views.getClient1()));
1548 @Feature({"AndroidWebView", "Preferences"})
1549 public void testDefaultFontSizeWithTwoViews() throws Throwable {
1550 ViewPair views = createViews();
1551 runPerViewSettingsTest(
1552 new AwSettingsDefaultFontSizeTestHelper(
1553 views.getContainer0(), views.getClient0()),
1554 new AwSettingsDefaultFontSizeTestHelper(
1555 views.getContainer1(), views.getClient1()));
1558 // The test verifies that after changing the LoadsImagesAutomatically
1559 // setting value from false to true previously skipped images are
1560 // automatically loaded.
1562 @Feature({"AndroidWebView", "Preferences"})
1563 public void testLoadsImagesAutomaticallyNoPageReload() throws Throwable {
1564 final TestAwContentsClient contentClient = new TestAwContentsClient();
1565 final AwTestContainerView testContainerView =
1566 createAwTestContainerViewOnMainSync(contentClient);
1567 final AwContents awContents = testContainerView.getAwContents();
1568 AwSettings settings = getAwSettingsOnUiThread(awContents);
1569 settings.setJavaScriptEnabled(true);
1570 ImagePageGenerator generator = new ImagePageGenerator(0, false);
1571 settings.setLoadsImagesAutomatically(false);
1572 loadDataSync(awContents,
1573 contentClient.getOnPageFinishedHelper(),
1574 generator.getPageSource(),
1575 "text/html", false);
1576 assertEquals(ImagePageGenerator.IMAGE_NOT_LOADED_STRING,
1577 getTitleOnUiThread(awContents));
1578 settings.setLoadsImagesAutomatically(true);
1579 poll(new Callable<Boolean>() {
1581 public Boolean call() throws Exception {
1582 return !ImagePageGenerator.IMAGE_NOT_LOADED_STRING.equals(
1583 getTitleOnUiThread(awContents));
1586 assertEquals(ImagePageGenerator.IMAGE_LOADED_STRING, getTitleOnUiThread(awContents));
1591 @Feature({"AndroidWebView", "Preferences"})
1592 public void testLoadsImagesAutomaticallyWithTwoViews() throws Throwable {
1593 ViewPair views = createViews();
1594 runPerViewSettingsTest(
1595 new AwSettingsLoadImagesAutomaticallyTestHelper(
1596 views.getContainer0(), views.getClient0(), new ImagePageGenerator(0, true)),
1597 new AwSettingsLoadImagesAutomaticallyTestHelper(
1598 views.getContainer1(), views.getClient1(), new ImagePageGenerator(1, true)));
1602 @Feature({"AndroidWebView", "Preferences"})
1603 public void testDefaultTextEncodingWithTwoViews() throws Throwable {
1604 ViewPair views = createViews();
1605 runPerViewSettingsTest(
1606 new AwSettingsDefaultTextEncodingTestHelper(
1607 views.getContainer0(), views.getClient0()),
1608 new AwSettingsDefaultTextEncodingTestHelper(
1609 views.getContainer1(), views.getClient1()));
1612 // The test verifies that the default user agent string follows the format
1613 // defined in Android CTS tests:
1615 // Mozilla/5.0 (Linux;[ U;] Android <version>;[ <language>-<country>;]
1616 // [<devicemodel>;] Build/<buildID>) AppleWebKit/<major>.<minor> (KHTML, like Gecko)
1617 // Version/<major>.<minor>[ Mobile] Safari/<major>.<minor>
1619 @Feature({"AndroidWebView", "Preferences"})
1620 public void testUserAgentStringDefault() throws Throwable {
1621 final TestAwContentsClient contentClient = new TestAwContentsClient();
1622 final AwTestContainerView testContainerView =
1623 createAwTestContainerViewOnMainSync(contentClient);
1624 final AwContents awContents = testContainerView.getAwContents();
1625 AwSettings settings = getAwSettingsOnUiThread(awContents);
1626 final String actualUserAgentString = settings.getUserAgentString();
1627 assertEquals(actualUserAgentString, AwSettings.getDefaultUserAgent());
1628 final String patternString =
1629 "Mozilla/5\\.0 \\(Linux;( U;)? Android ([^;]+);( (\\w+)-(\\w+);)?"
1630 + "\\s?(.*)\\sBuild/(.+)\\) AppleWebKit/(\\d+)\\.(\\d+) \\(KHTML, like Gecko\\) "
1631 + "Version/\\d+\\.\\d Chrome/\\d+\\.\\d+\\.\\d+\\.\\d+"
1632 + "( Mobile)? Safari/(\\d+)\\.(\\d+)";
1633 final Pattern userAgentExpr = Pattern.compile(patternString);
1634 Matcher patternMatcher = userAgentExpr.matcher(actualUserAgentString);
1635 assertTrue(String.format("User agent string did not match expected pattern. %nExpected "
1636 + "pattern:%n%s%nActual:%n%s", patternString, actualUserAgentString),
1637 patternMatcher.find());
1638 // No country-language code token.
1639 assertEquals(null, patternMatcher.group(3));
1640 if ("REL".equals(Build.VERSION.CODENAME)) {
1641 // Model is only added in release builds
1642 assertEquals(Build.MODEL, patternMatcher.group(6));
1643 // Release version is valid only in release builds
1644 assertEquals(Build.VERSION.RELEASE, patternMatcher.group(2));
1646 assertEquals(Build.ID, patternMatcher.group(7));
1650 @Feature({"AndroidWebView", "Preferences"})
1651 public void testUserAgentStringOverride() throws Throwable {
1652 final TestAwContentsClient contentClient = new TestAwContentsClient();
1653 final AwTestContainerView testContainerView =
1654 createAwTestContainerViewOnMainSync(contentClient);
1655 final AwContents awContents = testContainerView.getAwContents();
1656 AwSettings settings = getAwSettingsOnUiThread(awContents);
1657 final String defaultUserAgentString = settings.getUserAgentString();
1659 // Check that an attempt to reset the default UA string has no effect.
1660 settings.setUserAgentString(null);
1661 assertEquals(defaultUserAgentString, settings.getUserAgentString());
1662 settings.setUserAgentString("");
1663 assertEquals(defaultUserAgentString, settings.getUserAgentString());
1665 // Check that we can also set the default value.
1666 settings.setUserAgentString(defaultUserAgentString);
1667 assertEquals(defaultUserAgentString, settings.getUserAgentString());
1669 // Set a custom UA string, verify that it can be reset back to default.
1670 final String customUserAgentString = "AwSettingsTest";
1671 settings.setUserAgentString(customUserAgentString);
1672 assertEquals(customUserAgentString, settings.getUserAgentString());
1673 settings.setUserAgentString(null);
1674 assertEquals(defaultUserAgentString, settings.getUserAgentString());
1677 // Verify that the current UA override setting has a priority over UA
1678 // overrides in navigation history entries.
1680 @Feature({"AndroidWebView", "Preferences"})
1681 public void testUserAgentStringOverrideForHistory() throws Throwable {
1682 final TestAwContentsClient contentClient = new TestAwContentsClient();
1683 final AwTestContainerView testContainerView =
1684 createAwTestContainerViewOnMainSync(contentClient);
1685 final AwContents awContents = testContainerView.getAwContents();
1686 final WebContents webContents = awContents.getWebContents();
1687 CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper();
1688 AwSettings settings = getAwSettingsOnUiThread(awContents);
1689 settings.setJavaScriptEnabled(true);
1690 final String defaultUserAgentString = settings.getUserAgentString();
1691 final String customUserAgentString = "AwSettingsTest";
1692 // We are using different page titles to make sure that we are really
1693 // going back and forward between them.
1694 final String pageTemplate =
1695 "<html><head><title>%s</title></head>"
1696 + "<body onload='document.title+=navigator.userAgent'></body>"
1698 final String page1Title = "Page1";
1699 final String page2Title = "Page2";
1700 final String page1 = String.format(pageTemplate, page1Title);
1701 final String page2 = String.format(pageTemplate, page2Title);
1702 settings.setUserAgentString(customUserAgentString);
1704 awContents, onPageFinishedHelper, page1, "text/html", false);
1705 assertEquals(page1Title + customUserAgentString, getTitleOnUiThread(awContents));
1707 awContents, onPageFinishedHelper, page2, "text/html", false);
1708 assertEquals(page2Title + customUserAgentString, getTitleOnUiThread(awContents));
1709 settings.setUserAgentString(null);
1710 // Must not cause any changes until the next page loading.
1711 assertEquals(page2Title + customUserAgentString, getTitleOnUiThread(awContents));
1712 HistoryUtils.goBackSync(getInstrumentation(), webContents, onPageFinishedHelper);
1713 assertEquals(page1Title + defaultUserAgentString, getTitleOnUiThread(awContents));
1714 HistoryUtils.goForwardSync(getInstrumentation(), webContents,
1715 onPageFinishedHelper);
1716 assertEquals(page2Title + defaultUserAgentString, getTitleOnUiThread(awContents));
1720 @Feature({"AndroidWebView", "Preferences"})
1721 public void testUserAgentStringWithTwoViews() throws Throwable {
1722 ViewPair views = createViews();
1723 runPerViewSettingsTest(
1724 new AwSettingsUserAgentStringTestHelper(views.getContainer0(), views.getClient0()),
1725 new AwSettingsUserAgentStringTestHelper(views.getContainer1(), views.getClient1()));
1729 @Feature({"AndroidWebView", "Preferences"})
1730 public void testUserAgentWithTestServer() throws Throwable {
1731 final TestAwContentsClient contentClient = new TestAwContentsClient();
1732 final AwTestContainerView testContainerView =
1733 createAwTestContainerViewOnMainSync(contentClient);
1734 AwContents awContents = testContainerView.getAwContents();
1735 AwSettings settings = getAwSettingsOnUiThread(awContents);
1736 final String customUserAgentString =
1737 "testUserAgentWithTestServerUserAgent";
1739 String fileName = null;
1740 TestWebServer webServer = TestWebServer.start();
1742 final String httpPath = "/testUserAgentWithTestServer.html";
1743 final String url = webServer.setResponse(httpPath, "foo", null);
1745 settings.setUserAgentString(customUserAgentString);
1746 loadUrlSync(awContents,
1747 contentClient.getOnPageFinishedHelper(),
1750 assertEquals(1, webServer.getRequestCount(httpPath));
1751 HttpRequest request = webServer.getLastRequest(httpPath);
1752 Header[] matchingHeaders = request.getHeaders("User-Agent");
1753 assertEquals(1, matchingHeaders.length);
1755 Header header = matchingHeaders[0];
1756 assertEquals(customUserAgentString, header.getValue());
1758 webServer.shutdown();
1763 @Feature({"AndroidWebView", "Preferences"})
1764 public void testDomStorageEnabledWithTwoViews() throws Throwable {
1765 ViewPair views = createViews();
1766 runPerViewSettingsTest(
1767 new AwSettingsDomStorageEnabledTestHelper(
1768 views.getContainer0(), views.getClient0()),
1769 new AwSettingsDomStorageEnabledTestHelper(
1770 views.getContainer1(), views.getClient1()));
1773 // Ideally, these three tests below should be combined into one, or tested using
1774 // runPerViewSettingsTest. However, it seems the database setting cannot be toggled
1775 // once set. Filed b/8186497.
1777 @Feature({"AndroidWebView", "Preferences"})
1778 public void testDatabaseInitialValue() throws Throwable {
1779 TestAwContentsClient client = new TestAwContentsClient();
1780 final AwTestContainerView testContainerView =
1781 createAwTestContainerViewOnMainSync(client);
1782 AwSettingsDatabaseTestHelper helper =
1783 new AwSettingsDatabaseTestHelper(testContainerView, client);
1784 helper.ensureSettingHasInitialValue();
1788 @Feature({"AndroidWebView", "Preferences"})
1789 public void testDatabaseEnabled() throws Throwable {
1790 TestAwContentsClient client = new TestAwContentsClient();
1791 final AwTestContainerView testContainerView =
1792 createAwTestContainerViewOnMainSync(client);
1793 AwSettingsDatabaseTestHelper helper =
1794 new AwSettingsDatabaseTestHelper(testContainerView, client);
1795 helper.setAlteredSettingValue();
1796 helper.ensureSettingHasAlteredValue();
1800 @Feature({"AndroidWebView", "Preferences"})
1801 public void testDatabaseDisabled() throws Throwable {
1802 TestAwContentsClient client = new TestAwContentsClient();
1803 final AwTestContainerView testContainerView =
1804 createAwTestContainerViewOnMainSync(client);
1805 AwSettingsDatabaseTestHelper helper =
1806 new AwSettingsDatabaseTestHelper(testContainerView, client);
1807 helper.setInitialSettingValue();
1808 helper.ensureSettingHasInitialValue();
1812 @Feature({"AndroidWebView", "Preferences"})
1813 public void testUniversalAccessFromFilesWithTwoViews() throws Throwable {
1814 ViewPair views = createViews();
1815 runPerViewSettingsTest(
1816 new AwSettingsUniversalAccessFromFilesTestHelper(
1817 views.getContainer0(), views.getClient0()),
1818 new AwSettingsUniversalAccessFromFilesTestHelper(
1819 views.getContainer1(), views.getClient1()));
1822 // This test verifies that local image resources can be loaded from file:
1823 // URLs regardless of file access state.
1825 @Feature({"AndroidWebView", "Preferences"})
1826 public void testFileAccessFromFilesImage() throws Throwable {
1827 final String testFile = "webview/image_access.html";
1828 assertFileIsReadable(UrlUtils.getTestFilePath(testFile));
1829 final String imageContainerUrl = UrlUtils.getTestFileUrl(testFile);
1830 final String imageHeight = "16";
1831 final TestAwContentsClient contentClient = new TestAwContentsClient();
1832 final AwTestContainerView testContainerView =
1833 createAwTestContainerViewOnMainSync(contentClient);
1834 final AwContents awContents = testContainerView.getAwContents();
1835 AwSettings settings = getAwSettingsOnUiThread(awContents);
1836 settings.setJavaScriptEnabled(true);
1837 settings.setAllowUniversalAccessFromFileURLs(false);
1838 settings.setAllowFileAccessFromFileURLs(false);
1839 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), imageContainerUrl);
1840 assertEquals(imageHeight, getTitleOnUiThread(awContents));
1844 @Feature({"AndroidWebView", "Preferences"})
1845 public void testFileAccessFromFilesIframeWithTwoViews() throws Throwable {
1846 ViewPair views = createViews();
1847 runPerViewSettingsTest(
1848 new AwSettingsFileAccessFromFilesIframeTestHelper(
1849 views.getContainer0(), views.getClient0()),
1850 new AwSettingsFileAccessFromFilesIframeTestHelper(
1851 views.getContainer1(), views.getClient1()));
1855 @Feature({"AndroidWebView", "Preferences"})
1856 public void testFileAccessFromFilesXhrWithTwoViews() throws Throwable {
1857 ViewPair views = createViews();
1858 runPerViewSettingsTest(
1859 new AwSettingsFileAccessFromFilesXhrTestHelper(
1860 views.getContainer0(), views.getClient0()),
1861 new AwSettingsFileAccessFromFilesXhrTestHelper(
1862 views.getContainer1(), views.getClient1()));
1866 @Feature({"AndroidWebView", "Preferences"})
1867 public void testFileUrlAccessWithTwoViews() throws Throwable {
1868 ViewPair views = createViews();
1869 runPerViewSettingsTest(
1870 new AwSettingsFileUrlAccessTestHelper(
1871 views.getContainer0(), views.getClient0(), 0),
1872 new AwSettingsFileUrlAccessTestHelper(
1873 views.getContainer1(), views.getClient1(), 1));
1877 @Feature({"AndroidWebView", "Preferences"})
1878 public void testContentUrlAccessWithTwoViews() throws Throwable {
1879 ViewPair views = createViews();
1880 runPerViewSettingsTest(
1881 new AwSettingsContentUrlAccessTestHelper(
1882 views.getContainer0(), views.getClient0(), 0),
1883 new AwSettingsContentUrlAccessTestHelper(
1884 views.getContainer1(), views.getClient1(), 1));
1888 @Feature({"AndroidWebView", "Preferences", "Navigation"})
1889 public void testBlockingContentUrlsFromDataUrls() throws Throwable {
1890 final TestAwContentsClient contentClient = new TestAwContentsClient();
1891 final AwTestContainerView testContainerView =
1892 createAwTestContainerViewOnMainSync(contentClient);
1893 final AwContents awContents = testContainerView.getAwContents();
1894 final String target = "content_from_data";
1895 final String page = "<html><body>"
1897 + createContentUrl(target) + "\">"
1899 resetResourceRequestCountInContentProvider(target);
1902 contentClient.getOnPageFinishedHelper(),
1906 ensureResourceRequestCountInContentProvider(target, 0);
1910 @Feature({"AndroidWebView", "Preferences", "Navigation"})
1911 public void testContentUrlFromFileWithTwoViews() throws Throwable {
1912 ViewPair views = createViews();
1913 runPerViewSettingsTest(
1914 new AwSettingsContentUrlAccessFromFileTestHelper(
1915 views.getContainer0(), views.getClient0(), 0),
1916 new AwSettingsContentUrlAccessFromFileTestHelper(
1917 views.getContainer1(), views.getClient1(), 1));
1921 @Feature({"AndroidWebView", "Preferences"})
1922 public void testBlockNetworkImagesDoesNotBlockDataUrlImage() throws Throwable {
1923 final TestAwContentsClient contentClient = new TestAwContentsClient();
1924 final AwTestContainerView testContainerView =
1925 createAwTestContainerViewOnMainSync(contentClient);
1926 final AwContents awContents = testContainerView.getAwContents();
1927 final AwSettings settings = getAwSettingsOnUiThread(awContents);
1928 ImagePageGenerator generator = new ImagePageGenerator(0, false);
1930 settings.setJavaScriptEnabled(true);
1931 settings.setImagesEnabled(false);
1932 loadDataSync(awContents,
1933 contentClient.getOnPageFinishedHelper(),
1934 generator.getPageSource(),
1937 assertEquals(ImagePageGenerator.IMAGE_LOADED_STRING, getTitleOnUiThread(awContents));
1941 @Feature({"AndroidWebView", "Preferences"})
1942 public void testBlockNetworkImagesBlocksNetworkImageAndReloadInPlace() throws Throwable {
1943 final TestAwContentsClient contentClient = new TestAwContentsClient();
1944 final AwTestContainerView testContainerView =
1945 createAwTestContainerViewOnMainSync(contentClient);
1946 final AwContents awContents = testContainerView.getAwContents();
1947 final AwSettings settings = getAwSettingsOnUiThread(awContents);
1948 settings.setJavaScriptEnabled(true);
1949 ImagePageGenerator generator = new ImagePageGenerator(0, false);
1951 TestWebServer webServer = TestWebServer.start();
1953 final String httpImageUrl = generator.getPageUrl(webServer);
1955 settings.setImagesEnabled(false);
1956 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), httpImageUrl);
1957 assertEquals(ImagePageGenerator.IMAGE_NOT_LOADED_STRING,
1958 getTitleOnUiThread(awContents));
1960 settings.setImagesEnabled(true);
1961 poll(new Callable<Boolean>() {
1963 public Boolean call() throws Exception {
1964 return ImagePageGenerator.IMAGE_LOADED_STRING.equals(
1965 getTitleOnUiThread(awContents));
1969 webServer.shutdown();
1974 @Feature({"AndroidWebView", "Preferences"})
1975 public void testBlockNetworkImagesWithTwoViews() throws Throwable {
1976 ViewPair views = createViews();
1977 TestWebServer webServer = TestWebServer.start();
1979 runPerViewSettingsTest(
1980 new AwSettingsImagesEnabledHelper(
1981 views.getContainer0(),
1984 new ImagePageGenerator(0, true)),
1985 new AwSettingsImagesEnabledHelper(
1986 views.getContainer1(),
1989 new ImagePageGenerator(1, true)));
1991 webServer.shutdown();
1996 @Feature({"AndroidWebView", "Preferences"})
1997 public void testBlockNetworkLoadsWithHttpResources() throws Throwable {
1998 final TestAwContentsClient contentClient = new TestAwContentsClient();
1999 final AwTestContainerView testContainer =
2000 createAwTestContainerViewOnMainSync(contentClient);
2001 final AwContents awContents = testContainer.getAwContents();
2002 final AwSettings awSettings = getAwSettingsOnUiThread(awContents);
2003 awSettings.setJavaScriptEnabled(true);
2004 ImagePageGenerator generator = new ImagePageGenerator(0, false);
2006 String fileName = null;
2007 TestWebServer webServer = TestWebServer.start();
2009 // Set up http image.
2010 final String httpPath = "/image.png";
2011 final String imageUrl = webServer.setResponseBase64(
2012 httpPath, generator.getImageSourceNoAdvance(),
2013 CommonResources.getImagePngHeaders(true));
2015 // Set up file html that loads http iframe.
2016 String pageHtml = "<img src='" + imageUrl + "' "
2017 + "onload=\"document.title='img_onload_fired';\" "
2018 + "onerror=\"document.title='img_onerror_fired';\" />";
2019 Context context = getInstrumentation().getTargetContext();
2020 fileName = context.getCacheDir() + "/block_network_loads_test.html";
2021 TestFileUtil.deleteFile(fileName); // Remove leftover file if any.
2022 TestFileUtil.createNewHtmlFile(fileName, "unset", pageHtml);
2024 // Actual test. Blocking should trigger onerror handler.
2025 awSettings.setBlockNetworkLoads(true);
2028 contentClient.getOnPageFinishedHelper(),
2029 "file:///" + fileName);
2030 assertEquals(0, webServer.getRequestCount(httpPath));
2031 assertEquals("img_onerror_fired", getTitleOnUiThread(awContents));
2033 // Unblock should load normally.
2034 awSettings.setBlockNetworkLoads(false);
2037 contentClient.getOnPageFinishedHelper(),
2038 "file:///" + fileName);
2039 assertEquals(1, webServer.getRequestCount(httpPath));
2040 assertEquals("img_onload_fired", getTitleOnUiThread(awContents));
2042 webServer.shutdown();
2043 if (fileName != null) TestFileUtil.deleteFile(fileName);
2047 private static class AudioEvent {
2048 private CallbackHelper mCallback;
2049 public AudioEvent(CallbackHelper callback) {
2050 mCallback = callback;
2053 @JavascriptInterface
2054 public void onCanPlay() {
2055 mCallback.notifyCalled();
2058 @JavascriptInterface
2059 public void onError() {
2060 mCallback.notifyCalled();
2065 @Feature({"AndroidWebView", "Preferences"})
2066 public void testBlockNetworkLoadsWithAudio() throws Throwable {
2067 final TestAwContentsClient contentClient = new TestAwContentsClient();
2068 final AwTestContainerView testContainer =
2069 createAwTestContainerViewOnMainSync(contentClient);
2070 final AwContents awContents = testContainer.getAwContents();
2071 final AwSettings awSettings = getAwSettingsOnUiThread(awContents);
2072 final CallbackHelper callback = new CallbackHelper();
2073 awSettings.setJavaScriptEnabled(true);
2075 TestWebServer webServer = TestWebServer.start();
2077 final String httpPath = "/audio.mp3";
2078 // Don't care about the response is correct or not, just want
2079 // to know whether Url is accessed.
2080 final String audioUrl = webServer.setResponse(httpPath, "1", null);
2082 String pageHtml = "<html><body><audio controls src='" + audioUrl + "' "
2083 + "oncanplay=\"AudioEvent.onCanPlay();\" "
2084 + "onerror=\"AudioEvent.onError();\" /> </body></html>";
2085 // Actual test. Blocking should trigger onerror handler.
2086 awSettings.setBlockNetworkLoads(true);
2087 runTestOnUiThread(new Runnable() {
2090 awContents.addPossiblyUnsafeJavascriptInterface(
2091 new AudioEvent(callback), "AudioEvent", null);
2094 int count = callback.getCallCount();
2095 loadDataSync(awContents, contentClient.getOnPageFinishedHelper(), pageHtml,
2096 "text/html", false);
2097 callback.waitForCallback(count, 1);
2098 assertEquals(0, webServer.getRequestCount(httpPath));
2100 // The below test failed in Nexus Galaxy.
2101 // See https://code.google.com/p/chromium/issues/detail?id=313463
2102 // Unblock should load normally.
2104 awSettings.setBlockNetworkLoads(false);
2105 count = callback.getCallCount();
2106 loadDataSync(awContents, contentClient.getOnPageFinishedHelper(), pageHtml,
2107 "text/html", false);
2108 callback.waitForCallback(count, 1);
2109 assertTrue(0 != webServer.getRequestCount(httpPath));
2112 webServer.shutdown();
2116 // Test an assert URL (file:///android_asset/)
2118 @Feature({"AndroidWebView", "Navigation"})
2119 public void testAssetUrl() throws Throwable {
2120 // Note: this text needs to be kept in sync with the contents of the html file referenced
2122 final String expectedTitle = "Asset File";
2123 final TestAwContentsClient contentClient = new TestAwContentsClient();
2124 final AwTestContainerView testContainerView =
2125 createAwTestContainerViewOnMainSync(contentClient);
2126 final AwContents awContents = testContainerView.getAwContents();
2127 loadUrlSync(awContents,
2128 contentClient.getOnPageFinishedHelper(),
2129 "file:///android_asset/asset_file.html");
2130 assertEquals(expectedTitle, getTitleOnUiThread(awContents));
2133 // Test a resource URL (file:///android_res/).
2135 @Feature({"AndroidWebView", "Navigation"})
2136 public void testResourceUrl() throws Throwable {
2137 // Note: this text needs to be kept in sync with the contents of the html file referenced
2139 final String expectedTitle = "Resource File";
2140 final TestAwContentsClient contentClient = new TestAwContentsClient();
2141 final AwTestContainerView testContainerView =
2142 createAwTestContainerViewOnMainSync(contentClient);
2143 final AwContents awContents = testContainerView.getAwContents();
2144 loadUrlSync(awContents,
2145 contentClient.getOnPageFinishedHelper(),
2146 "file:///android_res/raw/resource_file.html");
2147 assertEquals(expectedTitle, getTitleOnUiThread(awContents));
2150 // Test that the file URL access toggle does not affect asset URLs.
2152 @Feature({"AndroidWebView", "Navigation"})
2153 public void testFileUrlAccessToggleDoesNotBlockAssetUrls() throws Throwable {
2154 // Note: this text needs to be kept in sync with the contents of the html file referenced
2156 final String expectedTitle = "Asset File";
2157 final TestAwContentsClient contentClient = new TestAwContentsClient();
2158 final AwTestContainerView testContainerView =
2159 createAwTestContainerViewOnMainSync(contentClient);
2160 final AwContents awContents = testContainerView.getAwContents();
2161 final AwSettings settings = getAwSettingsOnUiThread(awContents);
2162 settings.setAllowFileAccess(false);
2163 loadUrlSync(awContents,
2164 contentClient.getOnPageFinishedHelper(),
2165 "file:///android_asset/asset_file.html");
2166 assertEquals(expectedTitle, getTitleOnUiThread(awContents));
2169 // Test that the file URL access toggle does not affect resource URLs.
2171 @Feature({"AndroidWebView", "Navigation"})
2172 public void testFileUrlAccessToggleDoesNotBlockResourceUrls() throws Throwable {
2173 // Note: this text needs to be kept in sync with the contents of the html file referenced
2175 final String expectedTitle = "Resource File";
2176 final TestAwContentsClient contentClient = new TestAwContentsClient();
2177 final AwTestContainerView testContainerView =
2178 createAwTestContainerViewOnMainSync(contentClient);
2179 final AwContents awContents = testContainerView.getAwContents();
2180 final AwSettings settings = getAwSettingsOnUiThread(awContents);
2181 settings.setAllowFileAccess(false);
2182 loadUrlSync(awContents,
2183 contentClient.getOnPageFinishedHelper(),
2184 "file:///android_res/raw/resource_file.html");
2185 assertEquals(expectedTitle, getTitleOnUiThread(awContents));
2189 @Feature({"AndroidWebView", "Preferences"})
2190 public void testLayoutAlgorithmWithTwoViews() throws Throwable {
2191 ViewPair views = createViews();
2192 runPerViewSettingsTest(
2193 new AwSettingsLayoutAlgorithmTestHelper(views.getContainer0(), views.getClient0()),
2194 new AwSettingsLayoutAlgorithmTestHelper(views.getContainer1(), views.getClient1()));
2198 @Feature({"AndroidWebView", "Preferences"})
2199 public void testTextZoomWithTwoViews() throws Throwable {
2200 ViewPair views = createViews();
2201 runPerViewSettingsTest(
2202 new AwSettingsTextZoomTestHelper(views.getContainer0(), views.getClient0()),
2203 new AwSettingsTextZoomTestHelper(views.getContainer1(), views.getClient1()));
2207 @Feature({"AndroidWebView", "Preferences"})
2208 public void testTextZoomAutosizingWithTwoViews() throws Throwable {
2209 ViewPair views = createViews();
2210 runPerViewSettingsTest(
2211 new AwSettingsTextZoomAutosizingTestHelper(
2212 views.getContainer0(), views.getClient0()),
2213 new AwSettingsTextZoomAutosizingTestHelper(
2214 views.getContainer1(), views.getClient1()));
2218 @Feature({"AndroidWebView", "Preferences"})
2219 public void testJavaScriptPopupsWithTwoViews() throws Throwable {
2220 ViewPair views = createViews();
2221 runPerViewSettingsTest(
2222 new AwSettingsJavaScriptPopupsTestHelper(views.getContainer0(), views.getClient0()),
2223 new AwSettingsJavaScriptPopupsTestHelper(
2224 views.getContainer1(), views.getClient1()));
2228 @Feature({"AndroidWebView", "Preferences"})
2229 public void testCacheMode() throws Throwable {
2230 final TestAwContentsClient contentClient = new TestAwContentsClient();
2231 final AwTestContainerView testContainer =
2232 createAwTestContainerViewOnMainSync(contentClient);
2233 final AwContents awContents = testContainer.getAwContents();
2234 final AwSettings awSettings = getAwSettingsOnUiThread(testContainer.getAwContents());
2235 clearCacheOnUiThread(awContents, true);
2237 assertEquals(WebSettings.LOAD_DEFAULT, awSettings.getCacheMode());
2238 TestWebServer webServer = TestWebServer.start();
2240 final String htmlPath = "/testCacheMode.html";
2241 final String url = webServer.setResponse(htmlPath, "response", null);
2242 awSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
2243 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url);
2244 assertEquals(1, webServer.getRequestCount(htmlPath));
2245 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url);
2246 assertEquals(1, webServer.getRequestCount(htmlPath));
2248 awSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
2249 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url);
2250 assertEquals(2, webServer.getRequestCount(htmlPath));
2251 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url);
2252 assertEquals(3, webServer.getRequestCount(htmlPath));
2254 awSettings.setCacheMode(WebSettings.LOAD_CACHE_ONLY);
2255 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url);
2256 assertEquals(3, webServer.getRequestCount(htmlPath));
2257 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), url);
2258 assertEquals(3, webServer.getRequestCount(htmlPath));
2260 final String htmlNotInCachePath = "/testCacheMode-not-in-cache.html";
2261 final String urlNotInCache = webServer.setResponse(htmlNotInCachePath, "", null);
2262 loadUrlSyncAndExpectError(awContents,
2263 contentClient.getOnPageFinishedHelper(),
2264 contentClient.getOnReceivedErrorHelper(),
2266 assertEquals(0, webServer.getRequestCount(htmlNotInCachePath));
2268 webServer.shutdown();
2273 @Feature({"AndroidWebView", "Preferences"})
2274 // As our implementation of network loads blocking uses the same net::URLRequest settings, make
2275 // sure that setting cache mode doesn't accidentally enable network loads. The reference
2276 // behaviour is that when network loads are blocked, setting cache mode has no effect.
2277 public void testCacheModeWithBlockedNetworkLoads() throws Throwable {
2278 final TestAwContentsClient contentClient = new TestAwContentsClient();
2279 final AwTestContainerView testContainer =
2280 createAwTestContainerViewOnMainSync(contentClient);
2281 final AwContents awContents = testContainer.getAwContents();
2282 final AwSettings awSettings = getAwSettingsOnUiThread(testContainer.getAwContents());
2283 clearCacheOnUiThread(awContents, true);
2285 assertEquals(WebSettings.LOAD_DEFAULT, awSettings.getCacheMode());
2286 awSettings.setBlockNetworkLoads(true);
2287 TestWebServer webServer = TestWebServer.start();
2289 final String htmlPath = "/testCacheModeWithBlockedNetworkLoads.html";
2290 final String url = webServer.setResponse(htmlPath, "response", null);
2291 loadUrlSyncAndExpectError(awContents,
2292 contentClient.getOnPageFinishedHelper(),
2293 contentClient.getOnReceivedErrorHelper(),
2295 assertEquals(0, webServer.getRequestCount(htmlPath));
2297 awSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
2298 loadUrlSyncAndExpectError(awContents,
2299 contentClient.getOnPageFinishedHelper(),
2300 contentClient.getOnReceivedErrorHelper(),
2302 assertEquals(0, webServer.getRequestCount(htmlPath));
2304 awSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
2305 loadUrlSyncAndExpectError(awContents,
2306 contentClient.getOnPageFinishedHelper(),
2307 contentClient.getOnReceivedErrorHelper(),
2309 assertEquals(0, webServer.getRequestCount(htmlPath));
2311 awSettings.setCacheMode(WebSettings.LOAD_CACHE_ONLY);
2312 loadUrlSyncAndExpectError(awContents,
2313 contentClient.getOnPageFinishedHelper(),
2314 contentClient.getOnReceivedErrorHelper(),
2316 assertEquals(0, webServer.getRequestCount(htmlPath));
2318 webServer.shutdown();
2323 @Feature({"AndroidWebView", "Preferences"})
2324 public void testCacheModeWithTwoViews() throws Throwable {
2325 ViewPair views = createViews();
2326 TestWebServer webServer = TestWebServer.start();
2328 runPerViewSettingsTest(
2329 new AwSettingsCacheModeTestHelper(
2330 views.getContainer0(), views.getClient0(), 0, webServer),
2331 new AwSettingsCacheModeTestHelper(
2332 views.getContainer1(), views.getClient1(), 1, webServer));
2334 webServer.shutdown();
2338 static class ManifestTestHelper {
2339 private final TestWebServer mWebServer;
2340 private final String mHtmlPath;
2341 private final String mHtmlUrl;
2342 private final String mManifestPath;
2345 TestWebServer webServer, String htmlPageName, String manifestName) {
2346 mWebServer = webServer;
2347 mHtmlPath = "/" + htmlPageName;
2348 mHtmlUrl = webServer.setResponse(
2349 mHtmlPath, "<html manifest=\"" + manifestName + "\"></html>", null);
2350 mManifestPath = "/" + manifestName;
2351 webServer.setResponse(
2354 CommonResources.getContentTypeAndCacheHeaders("text/cache-manifest", false));
2357 String getHtmlPath() {
2361 String getHtmlUrl() {
2365 String getManifestPath() {
2366 return mManifestPath;
2369 int waitUntilHtmlIsRequested(final int initialRequestCount) throws Exception {
2370 return waitUntilResourceIsRequested(mHtmlPath, initialRequestCount);
2373 int waitUntilManifestIsRequested(final int initialRequestCount) throws Exception {
2374 return waitUntilResourceIsRequested(mManifestPath, initialRequestCount);
2377 private int waitUntilResourceIsRequested(
2378 final String path, final int initialRequestCount) throws Exception {
2379 poll(new Callable<Boolean>() {
2381 public Boolean call() throws Exception {
2382 return mWebServer.getRequestCount(path) > initialRequestCount;
2385 return mWebServer.getRequestCount(path);
2390 @Feature({"AndroidWebView", "Preferences", "AppCache"})
2391 public void testAppCache() throws Throwable {
2392 final TestAwContentsClient contentClient = new TestAwContentsClient();
2393 final AwTestContainerView testContainer =
2394 createAwTestContainerViewOnMainSync(contentClient);
2395 final AwContents awContents = testContainer.getAwContents();
2396 final AwSettings settings = getAwSettingsOnUiThread(awContents);
2397 settings.setJavaScriptEnabled(true);
2398 // Note that the cache isn't actually enabled until the call to setAppCachePath.
2399 settings.setAppCacheEnabled(true);
2401 TestWebServer webServer = TestWebServer.start();
2403 ManifestTestHelper helper = new ManifestTestHelper(
2404 webServer, "testAppCache.html", "appcache.manifest");
2407 contentClient.getOnPageFinishedHelper(),
2408 helper.getHtmlUrl());
2409 helper.waitUntilHtmlIsRequested(0);
2410 // Unfortunately, there is no other good way of verifying that AppCache is
2411 // disabled, other than checking that it didn't try to fetch the manifest.
2413 assertEquals(0, webServer.getRequestCount(helper.getManifestPath()));
2414 settings.setAppCachePath("whatever"); // Enables AppCache.
2417 contentClient.getOnPageFinishedHelper(),
2418 helper.getHtmlUrl());
2419 helper.waitUntilManifestIsRequested(0);
2421 webServer.shutdown();
2426 @Feature({"AndroidWebView", "Preferences", "AppCache"})
2427 public void testAppCacheWithTwoViews() throws Throwable {
2428 // We don't use the test helper here, because making sure that AppCache
2429 // is disabled takes a lot of time, so running through the usual drill
2430 // will take about 20 seconds.
2431 ViewPair views = createViews();
2433 AwSettings settings0 = getAwSettingsOnUiThread(views.getContents0());
2434 settings0.setJavaScriptEnabled(true);
2435 settings0.setAppCachePath("whatever");
2436 settings0.setAppCacheEnabled(true);
2437 AwSettings settings1 = getAwSettingsOnUiThread(views.getContents1());
2438 settings1.setJavaScriptEnabled(true);
2439 // AppCachePath setting is global, no need to set it for the second view.
2440 settings1.setAppCacheEnabled(true);
2442 TestWebServer webServer = TestWebServer.start();
2444 ManifestTestHelper helper0 = new ManifestTestHelper(
2445 webServer, "testAppCache_0.html", "appcache.manifest_0");
2447 views.getContents0(),
2448 views.getClient0().getOnPageFinishedHelper(),
2449 helper0.getHtmlUrl());
2450 int manifestRequests0 = helper0.waitUntilManifestIsRequested(0);
2451 ManifestTestHelper helper1 = new ManifestTestHelper(
2452 webServer, "testAppCache_1.html", "appcache.manifest_1");
2454 views.getContents1(),
2455 views.getClient1().getOnPageFinishedHelper(),
2456 helper1.getHtmlUrl());
2457 helper1.waitUntilManifestIsRequested(0);
2458 settings1.setAppCacheEnabled(false);
2460 views.getContents0(),
2461 views.getClient0().getOnPageFinishedHelper(),
2462 helper0.getHtmlUrl());
2463 helper0.waitUntilManifestIsRequested(manifestRequests0);
2464 final int prevManifestRequestCount =
2465 webServer.getRequestCount(helper1.getManifestPath());
2466 int htmlRequests1 = webServer.getRequestCount(helper1.getHtmlPath());
2468 views.getContents1(),
2469 views.getClient1().getOnPageFinishedHelper(),
2470 helper1.getHtmlUrl());
2471 helper1.waitUntilHtmlIsRequested(htmlRequests1);
2472 // Unfortunately, there is no other good way of verifying that AppCache is
2473 // disabled, other than checking that it didn't try to fetch the manifest.
2476 prevManifestRequestCount, webServer.getRequestCount(helper1.getManifestPath()));
2478 webServer.shutdown();
2483 @Feature({"AndroidWebView", "Preferences"})
2484 public void testUseWideViewportWithTwoViews() throws Throwable {
2485 ViewPair views = createViews(true);
2486 runPerViewSettingsTest(
2487 new AwSettingsUseWideViewportTestHelper(views.getContainer0(), views.getClient0()),
2488 new AwSettingsUseWideViewportTestHelper(views.getContainer1(), views.getClient1()));
2492 @Feature({"AndroidWebView", "Preferences"})
2493 public void testUseWideViewportWithTwoViewsNoQuirks() throws Throwable {
2494 ViewPair views = createViews();
2495 runPerViewSettingsTest(
2496 new AwSettingsUseWideViewportTestHelper(views.getContainer0(), views.getClient0()),
2497 new AwSettingsUseWideViewportTestHelper(views.getContainer1(), views.getClient1()));
2500 private void useWideViewportLayoutWidthTest(
2501 AwTestContainerView testContainer, CallbackHelper onPageFinishedHelper)
2503 final AwContents awContents = testContainer.getAwContents();
2504 AwSettings settings = getAwSettingsOnUiThread(awContents);
2506 final String pageTemplate = "<html><head>%s</head>"
2507 + "<body onload='document.title=document.body.clientWidth'></body></html>";
2508 final String pageNoViewport = String.format(pageTemplate, "");
2509 final String pageViewportDeviceWidth = String.format(
2511 "<meta name='viewport' content='width=device-width' />");
2512 final String viewportTagSpecifiedWidth = "3000";
2513 final String pageViewportSpecifiedWidth = String.format(
2515 "<meta name='viewport' content='width=" + viewportTagSpecifiedWidth + "' />");
2517 DeviceDisplayInfo deviceInfo = DeviceDisplayInfo.create(testContainer.getContext());
2518 int displayWidth = (int) (deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale());
2520 settings.setJavaScriptEnabled(true);
2521 assertFalse(settings.getUseWideViewPort());
2522 // When UseWideViewPort is off, "width" setting of "meta viewport"
2523 // tags is ignored, and the layout width is set to device width in CSS pixels.
2524 // Thus, all 3 pages will have the same body width.
2525 loadDataSync(awContents, onPageFinishedHelper, pageNoViewport, "text/html", false);
2526 int actualWidth = Integer.parseInt(getTitleOnUiThread(awContents));
2527 // Avoid rounding errors.
2528 assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth,
2529 Math.abs(displayWidth - actualWidth) <= 1);
2530 loadDataSync(awContents, onPageFinishedHelper, pageViewportDeviceWidth, "text/html", false);
2531 actualWidth = Integer.parseInt(getTitleOnUiThread(awContents));
2532 assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth,
2533 Math.abs(displayWidth - actualWidth) <= 1);
2535 awContents, onPageFinishedHelper, pageViewportSpecifiedWidth, "text/html", false);
2536 actualWidth = Integer.parseInt(getTitleOnUiThread(awContents));
2537 assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth,
2538 Math.abs(displayWidth - actualWidth) <= 1);
2540 settings.setUseWideViewPort(true);
2541 // When UseWideViewPort is on, "meta viewport" tag is used.
2542 // If there is no viewport tag, or width isn't specified,
2543 // then layout width is set to max(980, <device-width-in-DIP-pixels>)
2544 loadDataSync(awContents, onPageFinishedHelper, pageNoViewport, "text/html", false);
2545 actualWidth = Integer.parseInt(getTitleOnUiThread(awContents));
2546 assertTrue("Expected: >= 980 , Actual: " + actualWidth, actualWidth >= 980);
2547 loadDataSync(awContents, onPageFinishedHelper, pageViewportDeviceWidth, "text/html", false);
2548 actualWidth = Integer.parseInt(getTitleOnUiThread(awContents));
2549 assertTrue("Expected: " + displayWidth + ", Actual: " + actualWidth,
2550 Math.abs(displayWidth - actualWidth) <= 1);
2552 awContents, onPageFinishedHelper, pageViewportSpecifiedWidth, "text/html", false);
2553 assertEquals(viewportTagSpecifiedWidth, getTitleOnUiThread(awContents));
2557 @Feature({"AndroidWebView", "Preferences"})
2558 public void testUseWideViewportLayoutWidth() throws Throwable {
2559 TestAwContentsClient contentClient = new TestAwContentsClient();
2560 AwTestContainerView testContainerView =
2561 createAwTestContainerViewOnMainSync(contentClient);
2562 useWideViewportLayoutWidthTest(testContainerView, contentClient.getOnPageFinishedHelper());
2566 @Feature({"AndroidWebView", "Preferences"})
2567 public void testUseWideViewportLayoutWidthNoQuirks() throws Throwable {
2568 TestAwContentsClient contentClient = new TestAwContentsClient();
2569 AwTestContainerView testContainerView =
2570 createAwTestContainerViewOnMainSync(contentClient, false);
2571 useWideViewportLayoutWidthTest(testContainerView, contentClient.getOnPageFinishedHelper());
2575 @Feature({"AndroidWebView", "Preferences"})
2576 public void testUseWideViewportControlsDoubleTabToZoom() throws Throwable {
2577 final TestAwContentsClient contentClient = new TestAwContentsClient();
2578 final AwTestContainerView testContainerView =
2579 createAwTestContainerViewOnMainSync(contentClient);
2580 final AwContents awContents = testContainerView.getAwContents();
2581 CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper();
2582 AwSettings settings = getAwSettingsOnUiThread(awContents);
2583 settings.setBuiltInZoomControls(true);
2585 DeviceDisplayInfo deviceInfo =
2586 DeviceDisplayInfo.create(testContainerView.getContext());
2587 int displayWidth = (int) (deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale());
2588 int layoutWidth = displayWidth * 2;
2589 final String page = "<html>"
2590 + "<head><meta name='viewport' content='width=" + layoutWidth + "'>"
2591 + "<style> body { width: " + layoutWidth + "px; }</style></head>"
2592 + "<body>Page Text</body></html>";
2594 assertFalse(settings.getUseWideViewPort());
2595 // Without wide viewport the <meta viewport> tag will be ignored by WebView,
2596 // but it doesn't really matter as we don't expect double tap to change the scale.
2597 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false);
2598 final float initialScale = getScaleOnUiThread(awContents);
2599 simulateDoubleTapCenterOfWebViewOnUiThread(testContainerView);
2601 assertEquals(initialScale, getScaleOnUiThread(awContents));
2603 settings.setUseWideViewPort(true);
2604 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false);
2605 int onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount();
2606 simulateDoubleTapCenterOfWebViewOnUiThread(testContainerView);
2607 contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount);
2608 final float zoomedOutScale = getScaleOnUiThread(awContents);
2609 assertTrue("zoomedOut: " + zoomedOutScale + ", initial: " + initialScale,
2610 zoomedOutScale < initialScale);
2614 @Feature({"AndroidWebView", "Preferences"})
2615 public void testForceZeroLayoutHeightWithTwoViews() throws Throwable {
2616 ViewPair views = createViews();
2617 runPerViewSettingsTest(
2618 new AwSettingsForceZeroLayoutHeightTestHelper(
2619 views.getContainer0(), views.getClient0(), false),
2620 new AwSettingsForceZeroLayoutHeightTestHelper(
2621 views.getContainer1(), views.getClient1(), false));
2625 @Feature({"AndroidWebView", "Preferences"})
2626 public void testForceZeroLayoutHeightViewportTagWithTwoViews() throws Throwable {
2627 ViewPair views = createViews();
2628 runPerViewSettingsTest(
2629 new AwSettingsForceZeroLayoutHeightTestHelper(
2630 views.getContainer0(), views.getClient0(), true),
2631 new AwSettingsForceZeroLayoutHeightTestHelper(
2632 views.getContainer1(), views.getClient1(), true));
2636 @Feature({"AndroidWebView", "Preferences"})
2637 public void testZeroLayoutHeightDisablesViewportQuirkWithTwoViews() throws Throwable {
2638 ViewPair views = createViews();
2639 runPerViewSettingsTest(
2640 new AwSettingsZeroLayoutHeightDisablesViewportQuirkTestHelper(
2641 views.getContainer0(), views.getClient0()),
2642 new AwSettingsZeroLayoutHeightDisablesViewportQuirkTestHelper(
2643 views.getContainer1(), views.getClient1()));
2647 @Feature({"AndroidWebView", "Preferences"})
2648 public void testLoadWithOverviewModeWithTwoViews() throws Throwable {
2649 ViewPair views = createViews();
2650 runPerViewSettingsTest(
2651 new AwSettingsLoadWithOverviewModeTestHelper(
2652 views.getContainer0(), views.getClient0(), false),
2653 new AwSettingsLoadWithOverviewModeTestHelper(
2654 views.getContainer1(), views.getClient1(), false));
2658 @Feature({"AndroidWebView", "Preferences"})
2659 public void testLoadWithOverviewModeViewportTagWithTwoViews() throws Throwable {
2660 ViewPair views = createViews();
2661 runPerViewSettingsTest(
2662 new AwSettingsLoadWithOverviewModeTestHelper(
2663 views.getContainer0(), views.getClient0(), true),
2664 new AwSettingsLoadWithOverviewModeTestHelper(
2665 views.getContainer1(), views.getClient1(), true));
2669 @Feature({"AndroidWebView", "Preferences"})
2670 public void testSetInitialScale() throws Throwable {
2671 final TestAwContentsClient contentClient = new TestAwContentsClient();
2672 final AwTestContainerView testContainerView =
2673 createAwTestContainerViewOnMainSync(contentClient);
2674 final AwContents awContents = testContainerView.getAwContents();
2675 final AwSettings awSettings = getAwSettingsOnUiThread(awContents);
2676 CallbackHelper onPageFinishedHelper = contentClient.getOnPageFinishedHelper();
2678 WindowManager wm = (WindowManager) getInstrumentation().getTargetContext()
2679 .getSystemService(Context.WINDOW_SERVICE);
2680 Point screenSize = new Point();
2681 wm.getDefaultDisplay().getSize(screenSize);
2682 // Make sure after 50% scale, page width still larger than screen.
2683 int height = screenSize.y * 2 + 1;
2684 int width = screenSize.x * 2 + 1;
2685 final String page = "<html><body>"
2686 + "<p style='height:" + height + "px;width:" + width + "px'>"
2687 + "testSetInitialScale</p></body></html>";
2688 final float defaultScale =
2689 getInstrumentation().getTargetContext().getResources().getDisplayMetrics().density;
2691 assertEquals(defaultScale, getPixelScaleOnUiThread(awContents), .01f);
2692 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false);
2693 assertEquals(defaultScale, getPixelScaleOnUiThread(awContents), .01f);
2695 int onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount();
2696 awSettings.setInitialPageScale(50);
2697 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false);
2698 contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount);
2699 assertEquals(0.5f, getPixelScaleOnUiThread(awContents), .01f);
2701 onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount();
2702 awSettings.setInitialPageScale(500);
2703 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false);
2704 contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount);
2705 assertEquals(5.0f, getPixelScaleOnUiThread(awContents), .01f);
2707 onScaleChangedCallCount = contentClient.getOnScaleChangedHelper().getCallCount();
2708 awSettings.setInitialPageScale(0);
2709 loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false);
2710 contentClient.getOnScaleChangedHelper().waitForCallback(onScaleChangedCallCount);
2711 assertEquals(defaultScale, getPixelScaleOnUiThread(awContents), .01f);
2715 @DisableHardwareAccelerationForTest
2717 @Feature({"AndroidWebView", "Preferences"})
2718 http://crbug.com/304549
2721 public void testMediaPlaybackWithoutUserGesture() throws Throwable {
2722 assertTrue(VideoTestUtil.runVideoTest(this, false, WAIT_TIMEOUT_MS));
2725 @DisableHardwareAccelerationForTest
2727 @Feature({"AndroidWebView", "Preferences"})
2728 public void testMediaPlaybackWithUserGesture() throws Throwable {
2729 // Wait for 5 second to see if video played.
2730 assertFalse(VideoTestUtil.runVideoTest(this, true, scaleTimeout(5000)));
2734 @Feature({"AndroidWebView", "Preferences"})
2735 public void testDefaultVideoPosterURL() throws Throwable {
2736 final CallbackHelper videoPosterAccessedCallbackHelper = new CallbackHelper();
2737 final String defaultVideoPosterUrl = "http://default_video_poster/";
2738 TestAwContentsClient client = new TestAwContentsClient() {
2740 public AwWebResourceResponse shouldInterceptRequest(
2741 ShouldInterceptRequestParams params) {
2742 if (params.url.equals(defaultVideoPosterUrl)) {
2743 videoPosterAccessedCallbackHelper.notifyCalled();
2748 final AwContents awContents = createAwTestContainerViewOnMainSync(client).getAwContents();
2749 getInstrumentation().runOnMainSync(new Runnable() {
2752 AwSettings awSettings = awContents.getSettings();
2753 awSettings.setDefaultVideoPosterURL(defaultVideoPosterUrl);
2756 VideoTestWebServer webServer = new VideoTestWebServer();
2758 String data = "<html><head><body>"
2759 + "<video id='video' control src='"
2760 + webServer.getOnePixelOneFrameWebmURL() + "' /> </body></html>";
2761 loadDataAsync(awContents, data, "text/html", false);
2762 videoPosterAccessedCallbackHelper.waitForCallback(0, 1, 20, TimeUnit.SECONDS);
2764 if (webServer.getTestWebServer() != null) {
2765 webServer.getTestWebServer().shutdown();
2771 @Feature({"AndroidWebView", "Preferences"})
2772 public void testAllowMixedMode() throws Throwable {
2773 final TestAwContentsClient contentClient = new TestAwContentsClient() {
2775 public void onReceivedSslError(ValueCallback<Boolean> callback, SslError error) {
2776 callback.onReceiveValue(true);
2779 final AwTestContainerView testContainerView =
2780 createAwTestContainerViewOnMainSync(contentClient);
2781 final AwContents awContents = testContainerView.getAwContents();
2782 final AwSettings awSettings = getAwSettingsOnUiThread(awContents);
2784 awSettings.setJavaScriptEnabled(true);
2786 TestWebServer httpsServer = null;
2787 TestWebServer httpServer = null;
2789 httpsServer = TestWebServer.startSsl();
2790 httpServer = TestWebServer.start();
2792 final String jsUrl = "/insecure.js";
2793 final String imageUrl = "/insecure.png";
2794 final String secureUrl = "/secure.html";
2795 httpServer.setResponse(jsUrl, "window.loaded_js = 42;", null);
2796 httpServer.setResponseBase64(imageUrl, CommonResources.FAVICON_DATA_BASE64, null);
2798 final String jsHtml = "<script src=\"" + httpServer.getResponseUrl(jsUrl)
2800 final String imageHtml = "<img src=\"" + httpServer.getResponseUrl(imageUrl) + "\" />";
2801 final String secureHtml = "<body>" + imageHtml + " " + jsHtml + "</body>";
2803 String fullSecureUrl = httpsServer.setResponse(secureUrl, secureHtml, null);
2805 awSettings.setMixedContentMode(AwSettings.MIXED_CONTENT_NEVER_ALLOW);
2806 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), fullSecureUrl);
2807 assertEquals(1, httpsServer.getRequestCount(secureUrl));
2808 assertEquals(0, httpServer.getRequestCount(jsUrl));
2809 assertEquals(0, httpServer.getRequestCount(imageUrl));
2811 awSettings.setMixedContentMode(AwSettings.MIXED_CONTENT_ALWAYS_ALLOW);
2812 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), fullSecureUrl);
2813 assertEquals(2, httpsServer.getRequestCount(secureUrl));
2814 assertEquals(1, httpServer.getRequestCount(jsUrl));
2815 assertEquals(1, httpServer.getRequestCount(imageUrl));
2817 awSettings.setMixedContentMode(AwSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
2818 loadUrlSync(awContents, contentClient.getOnPageFinishedHelper(), fullSecureUrl);
2819 assertEquals(3, httpsServer.getRequestCount(secureUrl));
2820 assertEquals(1, httpServer.getRequestCount(jsUrl));
2821 assertEquals(2, httpServer.getRequestCount(imageUrl));
2823 if (httpServer != null) {
2824 httpServer.shutdown();
2826 if (httpsServer != null) {
2827 httpsServer.shutdown();
2833 static class ViewPair {
2834 private final AwTestContainerView mContainer0;
2835 private final TestAwContentsClient mClient0;
2836 private final AwTestContainerView mContainer1;
2837 private final TestAwContentsClient mClient1;
2839 ViewPair(AwTestContainerView container0, TestAwContentsClient client0,
2840 AwTestContainerView container1, TestAwContentsClient client1) {
2841 this.mContainer0 = container0;
2842 this.mClient0 = client0;
2843 this.mContainer1 = container1;
2844 this.mClient1 = client1;
2847 AwTestContainerView getContainer0() {
2851 AwContents getContents0() {
2852 return mContainer0.getAwContents();
2855 TestAwContentsClient getClient0() {
2859 AwTestContainerView getContainer1() {
2863 AwContents getContents1() {
2864 return mContainer1.getAwContents();
2867 TestAwContentsClient getClient1() {
2873 * Verifies the following statements about a setting:
2874 * - initially, the setting has a default value;
2875 * - the setting can be switched to an alternate value and back;
2876 * - switching a setting in the first WebView doesn't affect the setting
2877 * state in the second WebView and vice versa.
2879 * @param helper0 Test helper for the first ContentView
2880 * @param helper1 Test helper for the second ContentView
2883 private void runPerViewSettingsTest(AwSettingsTestHelper helper0,
2884 AwSettingsTestHelper helper1) throws Throwable {
2885 helper0.ensureSettingHasInitialValue();
2886 helper1.ensureSettingHasInitialValue();
2888 helper1.setAlteredSettingValue();
2889 helper0.ensureSettingHasInitialValue();
2890 helper1.ensureSettingHasAlteredValue();
2892 helper1.setInitialSettingValue();
2893 helper0.ensureSettingHasInitialValue();
2894 helper1.ensureSettingHasInitialValue();
2896 helper0.setAlteredSettingValue();
2897 helper0.ensureSettingHasAlteredValue();
2898 helper1.ensureSettingHasInitialValue();
2900 helper0.setInitialSettingValue();
2901 helper0.ensureSettingHasInitialValue();
2902 helper1.ensureSettingHasInitialValue();
2904 helper0.setAlteredSettingValue();
2905 helper0.ensureSettingHasAlteredValue();
2906 helper1.ensureSettingHasInitialValue();
2908 helper1.setAlteredSettingValue();
2909 helper0.ensureSettingHasAlteredValue();
2910 helper1.ensureSettingHasAlteredValue();
2912 helper0.setInitialSettingValue();
2913 helper0.ensureSettingHasInitialValue();
2914 helper1.ensureSettingHasAlteredValue();
2916 helper1.setInitialSettingValue();
2917 helper0.ensureSettingHasInitialValue();
2918 helper1.ensureSettingHasInitialValue();
2921 private ViewPair createViews() throws Throwable {
2922 return createViews(false);
2925 private ViewPair createViews(boolean supportsLegacyQuirks) throws Throwable {
2926 TestAwContentsClient client0 = new TestAwContentsClient();
2927 TestAwContentsClient client1 = new TestAwContentsClient();
2928 return new ViewPair(
2929 createAwTestContainerViewOnMainSync(client0, supportsLegacyQuirks),
2931 createAwTestContainerViewOnMainSync(client1, supportsLegacyQuirks),
2935 static void assertFileIsReadable(String filePath) {
2936 File file = new File(filePath);
2938 assertTrue("Test file \"" + filePath + "\" is not readable."
2939 + "Please make sure that files from android_webview/test/data/device_files/ "
2940 + "has been pushed to the device before testing",
2942 } catch (SecurityException e) {
2943 fail("Got a SecurityException for \"" + filePath + "\": " + e.toString());
2948 * Verifies the number of resource requests made to the content provider.
2949 * @param resource Resource name
2950 * @param expectedCount Expected resource requests count
2952 private void ensureResourceRequestCountInContentProvider(String resource, int expectedCount) {
2953 Context context = getInstrumentation().getTargetContext();
2954 int actualCount = TestContentProvider.getResourceRequestCount(context, resource);
2955 assertEquals(expectedCount, actualCount);
2958 private void resetResourceRequestCountInContentProvider(String resource) {
2959 Context context = getInstrumentation().getTargetContext();
2960 TestContentProvider.resetResourceRequestCount(context, resource);
2963 private String createContentUrl(final String target) {
2964 return TestContentProvider.createContentUrl(target);
2967 private void simulateDoubleTapCenterOfWebViewOnUiThread(final AwTestContainerView webView)
2969 final int x = (webView.getRight() - webView.getLeft()) / 2;
2970 final int y = (webView.getBottom() - webView.getTop()) / 2;
2971 final AwContents awContents = webView.getAwContents();
2972 runTestOnUiThread(new Runnable() {
2975 awContents.getContentViewCore().sendDoubleTapForTest(
2976 SystemClock.uptimeMillis(), x, y);