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