WebViewCompatTest.java revision 610473e5bb1295c992f8be92311bbfad96f03311
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 org.junit.Assert;
39import org.junit.Before;
40import org.junit.Test;
41import org.junit.runner.RunWith;
42
43import java.net.MalformedURLException;
44import java.net.URL;
45import java.util.ArrayList;
46import java.util.List;
47import java.util.concurrent.CountDownLatch;
48import java.util.concurrent.TimeUnit;
49
50@MediumTest
51@RunWith(AndroidJUnit4.class)
52public class WebViewCompatTest {
53    WebViewOnUiThread mWebViewOnUiThread;
54
55    private static final long TEST_TIMEOUT = 20000L;
56
57    @Before
58    public void setUp() {
59        mWebViewOnUiThread = new androidx.webkit.WebViewOnUiThread();
60    }
61
62    @Test
63    public void testVisualStateCallbackCalled() throws Exception {
64        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.VISUAL_STATE_CALLBACK));
65
66        final CountDownLatch callbackLatch = new CountDownLatch(1);
67        final long kRequest = 100;
68
69        mWebViewOnUiThread.loadUrl("about:blank");
70
71        mWebViewOnUiThread.postVisualStateCallbackCompat(kRequest,
72                new WebViewCompat.VisualStateCallback() {
73                        public void onComplete(long requestId) {
74                            assertEquals(kRequest, requestId);
75                            callbackLatch.countDown();
76                        }
77                });
78
79        assertTrue(callbackLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
80    }
81
82    @Test
83    public void testCheckThread() {
84        // Skip this test if VisualStateCallback is not supported.
85        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.VISUAL_STATE_CALLBACK));
86        try {
87            WebViewCompat.postVisualStateCallback(mWebViewOnUiThread.getWebViewOnCurrentThread(), 5,
88                    new WebViewCompat.VisualStateCallback() {
89                        @Override
90                        public void onComplete(long requestId) {
91                        }
92                    });
93        } catch (RuntimeException e) {
94            return;
95        }
96        fail("Calling a WebViewCompat method on the wrong thread must cause a run-time exception");
97    }
98
99    private static class MockContext extends ContextWrapper {
100        private boolean mGetApplicationContextWasCalled;
101
102        MockContext(Context context) {
103            super(context);
104        }
105
106        public Context getApplicationContext() {
107            mGetApplicationContextWasCalled = true;
108            return super.getApplicationContext();
109        }
110
111        public boolean wasGetApplicationContextCalled() {
112            return mGetApplicationContextWasCalled;
113        }
114    }
115
116    @Test
117    public void testStartSafeBrowsingUseApplicationContext() throws Exception {
118        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.START_SAFE_BROWSING));
119
120        final MockContext ctx =
121                new MockContext(InstrumentationRegistry.getTargetContext().getApplicationContext());
122        final CountDownLatch resultLatch = new CountDownLatch(1);
123        WebViewCompat.startSafeBrowsing(ctx, new ValueCallback<Boolean>() {
124            @Override
125            public void onReceiveValue(Boolean value) {
126                assertTrue(ctx.wasGetApplicationContextCalled());
127                resultLatch.countDown();
128                return;
129            }
130        });
131        assertTrue(resultLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
132    }
133
134    @Test
135    public void testStartSafeBrowsingWithNullCallbackDoesntCrash() throws Exception {
136        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.START_SAFE_BROWSING));
137
138        WebViewCompat.startSafeBrowsing(InstrumentationRegistry.getTargetContext(), null);
139    }
140
141    @Test
142    public void testStartSafeBrowsingInvokesCallback() throws Exception {
143        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.START_SAFE_BROWSING));
144
145        final CountDownLatch resultLatch = new CountDownLatch(1);
146        WebViewCompat.startSafeBrowsing(
147                InstrumentationRegistry.getTargetContext().getApplicationContext(),
148                new ValueCallback<Boolean>() {
149                    @Override
150                    public void onReceiveValue(Boolean value) {
151                        assertTrue(Looper.getMainLooper().isCurrentThread());
152                        resultLatch.countDown();
153                        return;
154                    }
155                });
156        assertTrue(resultLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
157    }
158
159    @Test
160    public void testSetSafeBrowsingWhitelistWithMalformedList() throws Exception {
161        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_WHITELIST));
162
163        List whitelist = new ArrayList<String>();
164        // Protocols are not supported in the whitelist
165        whitelist.add("http://google.com");
166        final CountDownLatch resultLatch = new CountDownLatch(1);
167        WebViewCompat.setSafeBrowsingWhitelist(whitelist, new ValueCallback<Boolean>() {
168            @Override
169            public void onReceiveValue(Boolean success) {
170                assertFalse(success);
171                resultLatch.countDown();
172            }
173        });
174        assertTrue(resultLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
175    }
176
177    @Test
178    public void testSetSafeBrowsingWhitelistWithValidList() throws Exception {
179        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_WHITELIST));
180        // This test relies on the onSafeBrowsingHit callback to verify correctness.
181        assumeTrue(WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_HIT));
182
183        List whitelist = new ArrayList<String>();
184        whitelist.add("safe-browsing");
185        final CountDownLatch resultLatch = new CountDownLatch(1);
186        WebViewCompat.setSafeBrowsingWhitelist(whitelist, new ValueCallback<Boolean>() {
187            @Override
188            public void onReceiveValue(Boolean success) {
189                assertTrue(success);
190                resultLatch.countDown();
191            }
192        });
193        assertTrue(resultLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
194
195        final CountDownLatch resultLatch2 = new CountDownLatch(1);
196        mWebViewOnUiThread.setWebViewClient(new WebViewClientCompat() {
197            @Override
198            public void onPageFinished(WebView view, String url) {
199                resultLatch2.countDown();
200            }
201
202            @Override
203            public void onSafeBrowsingHit(WebView view, WebResourceRequest request, int threatType,
204                    SafeBrowsingResponseCompat callback) {
205                Assert.fail("Should not invoke onSafeBrowsingHit");
206            }
207        });
208
209        mWebViewOnUiThread.loadUrl("chrome://safe-browsing/match?type=malware");
210
211        // Wait until page load has completed
212        assertTrue(resultLatch2.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
213    }
214
215    @Test
216    public void testGetSafeBrowsingPrivacyPolicyUrl() throws Exception {
217        assumeTrue(
218                WebViewFeature.isFeatureSupported(WebViewFeature.SAFE_BROWSING_PRIVACY_POLICY_URL));
219
220        assertNotNull(WebViewCompat.getSafeBrowsingPrivacyPolicyUrl());
221        try {
222            new URL(WebViewCompat.getSafeBrowsingPrivacyPolicyUrl().toString());
223        } catch (MalformedURLException e) {
224            Assert.fail("The privacy policy URL should be a well-formed URL");
225        }
226    }
227
228    /**
229     * WebViewCompat.getCurrentWebViewPackage should be null on pre-L devices.
230     * On L+ devices WebViewCompat.getCurrentWebViewPackage should be null only in exceptional
231     * circumstances - like when the WebView APK is being updated, or for Wear devices. The L+
232     * devices used in support library testing should have a non-null WebView package.
233     */
234    @Test
235    public void testGetCurrentWebViewPackage() {
236        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
237            assertNull(WebViewCompat.getCurrentWebViewPackage(
238                    InstrumentationRegistry.getTargetContext()));
239        } else {
240            assertNotNull(
241                    WebViewCompat.getCurrentWebViewPackage(
242                            InstrumentationRegistry.getTargetContext()));
243        }
244    }
245}
246