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