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 17 package androidx.webkit; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertNull; 23 import static org.junit.Assert.assertTrue; 24 import static org.junit.Assert.fail; 25 import static org.junit.Assume.assumeTrue; 26 27 import android.content.Context; 28 import android.content.ContextWrapper; 29 import android.os.Build; 30 import android.os.Looper; 31 import android.support.test.InstrumentationRegistry; 32 import android.support.test.filters.MediumTest; 33 import android.support.test.runner.AndroidJUnit4; 34 import android.webkit.ValueCallback; 35 import android.webkit.WebResourceRequest; 36 import android.webkit.WebView; 37 38 import org.junit.Assert; 39 import org.junit.Before; 40 import org.junit.Test; 41 import org.junit.runner.RunWith; 42 43 import java.net.MalformedURLException; 44 import java.net.URL; 45 import java.util.ArrayList; 46 import java.util.List; 47 import java.util.concurrent.CountDownLatch; 48 import java.util.concurrent.TimeUnit; 49 50 @MediumTest 51 @RunWith(AndroidJUnit4.class) 52 public 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