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