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