WebViewCompatTest.java revision eab2c96c81d8081fa56f8ca44a271633a0836ea3
1/*
2 * Copyright 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package androidx.webkit;
18
19import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertFalse;
21import static org.junit.Assert.assertNotNull;
22import static org.junit.Assert.assertNull;
23import static org.junit.Assert.assertTrue;
24import static org.junit.Assert.fail;
25import static org.junit.Assume.assumeTrue;
26
27import android.content.Context;
28import android.content.ContextWrapper;
29import android.os.Build;
30import android.os.Looper;
31import android.support.test.InstrumentationRegistry;
32import android.support.test.filters.MediumTest;
33import android.support.test.runner.AndroidJUnit4;
34import android.webkit.ValueCallback;
35import android.webkit.WebResourceRequest;
36import android.webkit.WebView;
37
38import androidx.core.os.BuildCompat;
39
40import org.junit.Assert;
41import org.junit.Before;
42import org.junit.Test;
43import org.junit.runner.RunWith;
44
45import java.net.MalformedURLException;
46import java.net.URL;
47import java.util.ArrayList;
48import java.util.List;
49import java.util.concurrent.CountDownLatch;
50import java.util.concurrent.TimeUnit;
51
52@MediumTest
53@RunWith(AndroidJUnit4.class)
54public class WebViewCompatTest {
55    WebViewOnUiThread mWebViewOnUiThread;
56
57    private static final long TEST_TIMEOUT = 20000L;
58
59    @Before
60    public void setUp() {
61        mWebViewOnUiThread = new androidx.webkit.WebViewOnUiThread();
62    }
63
64    @Test
65    public void testVisualStateCallbackCalled() throws Exception {
66        // TODO(gsennton) activate this test for pre-P devices when we can pre-install a WebView APK
67        // containing support for the WebView Support Library, see b/73454652.
68        if (!BuildCompat.isAtLeastP()) return;
69
70        final CountDownLatch callbackLatch = new CountDownLatch(1);
71        final long kRequest = 100;
72
73        mWebViewOnUiThread.loadUrl("about:blank");
74
75        mWebViewOnUiThread.postVisualStateCallbackCompat(kRequest,
76                new WebViewCompat.VisualStateCallback() {
77                        public void onComplete(long requestId) {
78                            assertEquals(kRequest, requestId);
79                            callbackLatch.countDown();
80                        }
81                });
82
83        assertTrue(callbackLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
84    }
85
86    @Test
87    public void testCheckThread() {
88        if (!WebViewFeature.isFeatureSupported(WebViewFeature.VISUAL_STATE_CALLBACK)) {
89            // Skip this test if VisualStateCallback is not supported.
90            return;
91        }
92        try {
93            WebViewCompat.postVisualStateCallback(mWebViewOnUiThread.getWebViewOnCurrentThread(), 5,
94                    new WebViewCompat.VisualStateCallback() {
95                        @Override
96                        public void onComplete(long requestId) {
97                        }
98                    });
99        } catch (RuntimeException e) {
100            return;
101        }
102        fail("Calling a WebViewCompat method on the wrong thread must cause a run-time exception");
103    }
104
105    private static class MockContext extends ContextWrapper {
106        private boolean mGetApplicationContextWasCalled;
107
108        MockContext(Context context) {
109            super(context);
110        }
111
112        public Context getApplicationContext() {
113            mGetApplicationContextWasCalled = true;
114            return super.getApplicationContext();
115        }
116
117        public boolean wasGetApplicationContextCalled() {
118            return mGetApplicationContextWasCalled;
119        }
120    }
121
122    @Test
123    public void testStartSafeBrowsingUseApplicationContext() throws Exception {
124        // TODO(gsennton) activate this test for pre-P devices when we can pre-install a WebView APK
125        // containing support for the WebView Support Library, see b/73454652.
126        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) return;
127
128        final MockContext ctx =
129                new MockContext(InstrumentationRegistry.getTargetContext().getApplicationContext());
130        final CountDownLatch resultLatch = new CountDownLatch(1);
131        WebViewCompat.startSafeBrowsing(ctx, new ValueCallback<Boolean>() {
132            @Override
133            public void onReceiveValue(Boolean value) {
134                assertTrue(ctx.wasGetApplicationContextCalled());
135                resultLatch.countDown();
136                return;
137            }
138        });
139        assertTrue(resultLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
140    }
141
142    @Test
143    public void testStartSafeBrowsingWithNullCallbackDoesntCrash() throws Exception {
144        // TODO(gsennton) activate this test for pre-P devices when we can pre-install a WebView APK
145        // containing support for the WebView Support Library, see b/73454652.
146        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) return;
147
148        WebViewCompat.startSafeBrowsing(InstrumentationRegistry.getTargetContext(), null);
149    }
150
151    @Test
152    public void testStartSafeBrowsingInvokesCallback() throws Exception {
153        // TODO(gsennton) activate this test for pre-P devices when we can pre-install a WebView APK
154        // containing support for the WebView Support Library, see b/73454652.
155        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) return;
156
157        final CountDownLatch resultLatch = new CountDownLatch(1);
158        WebViewCompat.startSafeBrowsing(
159                InstrumentationRegistry.getTargetContext().getApplicationContext(),
160                new ValueCallback<Boolean>() {
161                    @Override
162                    public void onReceiveValue(Boolean value) {
163                        assertTrue(Looper.getMainLooper().isCurrentThread());
164                        resultLatch.countDown();
165                        return;
166                    }
167                });
168        assertTrue(resultLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
169    }
170
171    @Test
172    public void testSetSafeBrowsingWhitelistWithMalformedList() throws Exception {
173        // TODO(gsennton) activate this test for pre-P devices when we can pre-install a WebView APK
174        // containing support for the WebView Support Library, see b/73454652.
175        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) return;
176
177        List whitelist = new ArrayList<String>();
178        // Protocols are not supported in the whitelist
179        whitelist.add("http://google.com");
180        final CountDownLatch resultLatch = new CountDownLatch(1);
181        WebViewCompat.setSafeBrowsingWhitelist(whitelist, new ValueCallback<Boolean>() {
182            @Override
183            public void onReceiveValue(Boolean success) {
184                assertFalse(success);
185                resultLatch.countDown();
186            }
187        });
188        assertTrue(resultLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
189    }
190
191    @Test
192    public void testSetSafeBrowsingWhitelistWithValidList() throws Exception {
193        // TODO(gsennton) activate this test for pre-P devices when we can pre-install a WebView APK
194        // containing support for the WebView Support Library, see b/73454652.
195        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) return;
196        // This test relies on the onSafeBrowsingHit callback to verify correctness.
197        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_HIT));
198
199        List whitelist = new ArrayList<String>();
200        whitelist.add("safe-browsing");
201        final CountDownLatch resultLatch = new CountDownLatch(1);
202        WebViewCompat.setSafeBrowsingWhitelist(whitelist, new ValueCallback<Boolean>() {
203            @Override
204            public void onReceiveValue(Boolean success) {
205                assertTrue(success);
206                resultLatch.countDown();
207            }
208        });
209        assertTrue(resultLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
210
211        final CountDownLatch resultLatch2 = new CountDownLatch(1);
212        mWebViewOnUiThread.setWebViewClient(new WebViewClientCompat() {
213            @Override
214            public void onPageFinished(WebView view, String url) {
215                resultLatch2.countDown();
216            }
217
218            @Override
219            public void onSafeBrowsingHit(WebView view, WebResourceRequest request, int threatType,
220                    SafeBrowsingResponseCompat callback) {
221                Assert.fail("Should not invoke onSafeBrowsingHit");
222            }
223        });
224
225        mWebViewOnUiThread.loadUrl("chrome://safe-browsing/match?type=malware");
226
227        // Wait until page load has completed
228        assertTrue(resultLatch2.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
229    }
230
231    @Test
232    public void testGetSafeBrowsingPrivacyPolicyUrl() throws Exception {
233        // TODO(gsennton) activate this test for pre-P devices when we can pre-install a WebView APK
234        // containing support for the WebView Support Library, see b/73454652.
235        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) return;
236
237        assertNotNull(WebViewCompat.getSafeBrowsingPrivacyPolicyUrl());
238        try {
239            new URL(WebViewCompat.getSafeBrowsingPrivacyPolicyUrl().toString());
240        } catch (MalformedURLException e) {
241            Assert.fail("The privacy policy URL should be a well-formed URL");
242        }
243    }
244
245    /**
246     * WebViewCompat.getCurrentWebViewPackage should be null on pre-L devices.
247     * On L+ devices WebViewCompat.getCurrentWebViewPackage should be null only in exceptional
248     * circumstances - like when the WebView APK is being updated, or for Wear devices. The L+
249     * devices used in support library testing should have a non-null WebView package.
250     */
251    @Test
252    public void testGetCurrentWebViewPackage() {
253        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
254            assertNull(WebViewCompat.getCurrentWebViewPackage(
255                    InstrumentationRegistry.getTargetContext()));
256        } else {
257            assertNotNull(
258                    WebViewCompat.getCurrentWebViewPackage(
259                            InstrumentationRegistry.getTargetContext()));
260        }
261    }
262}
263