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