blob: dca09af7b3b727f167f62692529868a023306bd7 [file] [log] [blame]
Gustav Sennton53b78242016-04-07 15:56:10 +01001/*
2 * Copyright (C) 2016 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 com.android.server.webkit;
18
Gustav Sennton564c2fd2017-01-30 18:08:01 +000019import static org.junit.Assert.assertArrayEquals;
Gustav Sennton86f7bbe2016-10-24 16:49:32 +010020import static org.junit.Assert.assertEquals;
21import static org.junit.Assert.assertFalse;
Torne (Richard Coles)dc375072017-01-11 15:48:13 +000022import static org.junit.Assert.assertTrue;
Gustav Sennton86f7bbe2016-10-24 16:49:32 +010023
Gustav Sennton53b78242016-04-07 15:56:10 +010024import android.content.pm.ApplicationInfo;
25import android.content.pm.PackageInfo;
26import android.content.pm.Signature;
Gustav Sennton564c2fd2017-01-30 18:08:01 +000027import android.os.Build;
Gustav Sennton53b78242016-04-07 15:56:10 +010028import android.os.Bundle;
Gustav Sennton86f7bbe2016-10-24 16:49:32 +010029import android.support.test.InstrumentationRegistry;
30import android.support.test.runner.AndroidJUnit4;
Gustav Sennton148cb3e2016-09-02 15:58:38 +010031import android.test.suitebuilder.annotation.MediumTest;
Gustav Sennton53b78242016-04-07 15:56:10 +010032import android.util.Base64;
Gustav Senntone5468f72017-11-20 19:42:43 +000033import android.webkit.UserPackage;
Gustav Sennton53b78242016-04-07 15:56:10 +010034import android.webkit.WebViewFactory;
35import android.webkit.WebViewProviderInfo;
36import android.webkit.WebViewProviderResponse;
37
Gustav Sennton86f7bbe2016-10-24 16:49:32 +010038import org.junit.Test;
39import org.junit.runner.RunWith;
40
Philip P. Moltmann68366072017-11-27 12:29:20 -080041import org.mockito.ArgumentMatcher;
Gustav Sennton53b78242016-04-07 15:56:10 +010042import org.mockito.Mockito;
43import org.mockito.Matchers;
Gustav Sennton53b78242016-04-07 15:56:10 +010044
Gustav Senntonb2650162017-04-07 14:41:38 +010045import java.lang.Integer;
Gustav Sennton86f7bbe2016-10-24 16:49:32 +010046import java.util.concurrent.CountDownLatch;
47
Gustav Sennton53b78242016-04-07 15:56:10 +010048
49/**
50 * Tests for WebViewUpdateService
Gustav Sennton148cb3e2016-09-02 15:58:38 +010051 runtest --path frameworks/base/services/tests/servicestests/ \
52 -c com.android.server.webkit.WebViewUpdateServiceTest
Gustav Sennton53b78242016-04-07 15:56:10 +010053 */
Gustav Sennton148cb3e2016-09-02 15:58:38 +010054// Use MediumTest instead of SmallTest as the implementation of WebViewUpdateService
55// is intended to work on several threads and uses at least one sleep/wait-statement.
Gustav Sennton86f7bbe2016-10-24 16:49:32 +010056@RunWith(AndroidJUnit4.class)
Gustav Sennton148cb3e2016-09-02 15:58:38 +010057@MediumTest
Gustav Sennton86f7bbe2016-10-24 16:49:32 +010058public class WebViewUpdateServiceTest {
Gustav Sennton53b78242016-04-07 15:56:10 +010059 private final static String TAG = WebViewUpdateServiceTest.class.getSimpleName();
60
61 private WebViewUpdateServiceImpl mWebViewUpdateServiceImpl;
62 private TestSystemImpl mTestSystemImpl;
63
64 private static final String WEBVIEW_LIBRARY_FLAG = "com.android.webview.WebViewLibrary";
65
Gustav Sennton53b78242016-04-07 15:56:10 +010066 /**
67 * Creates a new instance.
68 */
69 public WebViewUpdateServiceTest() {
70 }
71
72 private void setupWithPackages(WebViewProviderInfo[] packages) {
73 setupWithPackages(packages, true);
74 }
75
76 private void setupWithPackages(WebViewProviderInfo[] packages,
77 boolean fallbackLogicEnabled) {
78 setupWithPackages(packages, fallbackLogicEnabled, 1);
79 }
80
81 private void setupWithPackages(WebViewProviderInfo[] packages,
82 boolean fallbackLogicEnabled, int numRelros) {
83 setupWithPackages(packages, fallbackLogicEnabled, numRelros,
84 true /* isDebuggable == true -> don't check package signatures */);
85 }
86
87 private void setupWithPackages(WebViewProviderInfo[] packages,
88 boolean fallbackLogicEnabled, int numRelros, boolean isDebuggable) {
Torne (Richard Coles)dc375072017-01-11 15:48:13 +000089 setupWithPackages(packages, fallbackLogicEnabled, numRelros, isDebuggable,
90 false /* multiProcessDefault */);
91 }
92
93 private void setupWithPackages(WebViewProviderInfo[] packages,
94 boolean fallbackLogicEnabled, int numRelros, boolean isDebuggable,
95 boolean multiProcessDefault) {
Gustav Sennton53b78242016-04-07 15:56:10 +010096 TestSystemImpl testing = new TestSystemImpl(packages, fallbackLogicEnabled, numRelros,
Torne (Richard Coles)dc375072017-01-11 15:48:13 +000097 isDebuggable, multiProcessDefault);
Gustav Sennton53b78242016-04-07 15:56:10 +010098 mTestSystemImpl = Mockito.spy(testing);
99 mWebViewUpdateServiceImpl =
100 new WebViewUpdateServiceImpl(null /*Context*/, mTestSystemImpl);
101 }
102
103 private void setEnabledAndValidPackageInfos(WebViewProviderInfo[] providers) {
Gustav Sennton364e1602016-12-14 09:10:50 +0000104 // Set package infos for the primary user (user 0).
105 setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, providers);
106 }
107
108 private void setEnabledAndValidPackageInfosForUser(int userId,
109 WebViewProviderInfo[] providers) {
Gustav Sennton53b78242016-04-07 15:56:10 +0100110 for(WebViewProviderInfo wpi : providers) {
Gustav Sennton364e1602016-12-14 09:10:50 +0000111 mTestSystemImpl.setPackageInfoForUser(userId, createPackageInfo(wpi.packageName,
112 true /* enabled */, true /* valid */, true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100113 }
114 }
115
Gustav Senntona9159042016-04-11 16:32:52 +0100116 private void checkCertainPackageUsedAfterWebViewBootPreparation(String expectedProviderName,
Gustav Sennton53b78242016-04-07 15:56:10 +0100117 WebViewProviderInfo[] webviewPackages) {
Gustav Senntona9159042016-04-11 16:32:52 +0100118 checkCertainPackageUsedAfterWebViewBootPreparation(
119 expectedProviderName, webviewPackages, 1);
Gustav Sennton53b78242016-04-07 15:56:10 +0100120 }
121
Gustav Senntona9159042016-04-11 16:32:52 +0100122 private void checkCertainPackageUsedAfterWebViewBootPreparation(String expectedProviderName,
Gustav Sennton53b78242016-04-07 15:56:10 +0100123 WebViewProviderInfo[] webviewPackages, int numRelros) {
124 setupWithPackages(webviewPackages, true, numRelros);
125 // Add (enabled and valid) package infos for each provider
126 setEnabledAndValidPackageInfos(webviewPackages);
127
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100128 runWebViewBootPreparationOnMainSync();
Gustav Sennton53b78242016-04-07 15:56:10 +0100129
130 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
131 Mockito.argThat(new IsPackageInfoWithName(expectedProviderName)));
132
133 for (int n = 0; n < numRelros; n++) {
134 mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
135 }
136
137 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
138 assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status);
139 assertEquals(expectedProviderName, response.packageInfo.packageName);
140 }
141
142 // For matching the package name of a PackageInfo
Philip P. Moltmann68366072017-11-27 12:29:20 -0800143 private class IsPackageInfoWithName implements ArgumentMatcher<PackageInfo> {
Gustav Sennton53b78242016-04-07 15:56:10 +0100144 private final String mPackageName;
145
146 IsPackageInfoWithName(String name) {
147 mPackageName = name;
148 }
149
150 @Override
Philip P. Moltmann68366072017-11-27 12:29:20 -0800151 public boolean matches(PackageInfo p) {
152 return p.packageName.equals(mPackageName);
Gustav Sennton53b78242016-04-07 15:56:10 +0100153 }
154
Gustav Sennton53b78242016-04-07 15:56:10 +0100155 @Override
Paul Duffin192bb0b2017-03-09 18:49:41 +0000156 public String toString() {
157 return String.format("PackageInfo with name '%s'", mPackageName);
Gustav Sennton53b78242016-04-07 15:56:10 +0100158 }
159 }
160
161 private static PackageInfo createPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100162 String packageName, boolean enabled, boolean valid, boolean installed) {
Gustav Sennton53b78242016-04-07 15:56:10 +0100163 PackageInfo p = new PackageInfo();
164 p.packageName = packageName;
165 p.applicationInfo = new ApplicationInfo();
166 p.applicationInfo.enabled = enabled;
167 p.applicationInfo.metaData = new Bundle();
Gustav Sennton0df2c552016-06-14 15:32:19 +0100168 if (installed) {
169 p.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
170 } else {
171 p.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED;
172 }
Gustav Sennton53b78242016-04-07 15:56:10 +0100173 if (valid) {
174 // no flag means invalid
175 p.applicationInfo.metaData.putString(WEBVIEW_LIBRARY_FLAG, "blah");
176 }
Gustav Sennton564c2fd2017-01-30 18:08:01 +0000177 // Default to this package being valid in terms of targetSdkVersion.
178 p.applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
Gustav Sennton53b78242016-04-07 15:56:10 +0100179 return p;
180 }
181
Gustav Sennton0df2c552016-06-14 15:32:19 +0100182 private static PackageInfo createPackageInfo(String packageName, boolean enabled, boolean valid,
183 boolean installed, Signature[] signatures, long updateTime) {
184 PackageInfo p = createPackageInfo(packageName, enabled, valid, installed);
Gustav Sennton53b78242016-04-07 15:56:10 +0100185 p.signatures = signatures;
Gustav Sennton0df2c552016-06-14 15:32:19 +0100186 p.lastUpdateTime = updateTime;
Gustav Sennton53b78242016-04-07 15:56:10 +0100187 return p;
188 }
189
Gustav Sennton18c9e152016-04-15 15:24:53 +0100190 private static PackageInfo createPackageInfo(String packageName, boolean enabled, boolean valid,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100191 boolean installed, Signature[] signatures, long updateTime, boolean hidden) {
192 PackageInfo p =
193 createPackageInfo(packageName, enabled, valid, installed, signatures, updateTime);
194 if (hidden) {
195 p.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
196 } else {
197 p.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
198 }
Gustav Sennton53b78242016-04-07 15:56:10 +0100199 return p;
200 }
201
Gustav Senntonfd222fc22016-06-16 20:24:23 +0100202 private static PackageInfo createPackageInfo(String packageName, boolean enabled, boolean valid,
203 boolean installed, Signature[] signatures, long updateTime, boolean hidden,
Dianne Hackborn891b74c2017-12-11 16:54:27 -0800204 long versionCode, boolean isSystemApp) {
Gustav Senntonfd222fc22016-06-16 20:24:23 +0100205 PackageInfo p = createPackageInfo(packageName, enabled, valid, installed, signatures,
206 updateTime, hidden);
Dianne Hackborn891b74c2017-12-11 16:54:27 -0800207 p.setLongVersionCode(versionCode);
Patrick Baumannc2def582018-04-04 12:14:15 -0700208 p.applicationInfo.setVersionCode(versionCode);
Gustav Sennton18c9e152016-04-15 15:24:53 +0100209 if (isSystemApp) p.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
210 return p;
211 }
212
Gustav Senntona9159042016-04-11 16:32:52 +0100213 private void checkPreparationPhasesForPackage(String expectedPackage, int numPreparation) {
214 // Verify that onWebViewProviderChanged was called for the numPreparation'th time for the
215 // expected package
216 Mockito.verify(mTestSystemImpl, Mockito.times(numPreparation)).onWebViewProviderChanged(
217 Mockito.argThat(new IsPackageInfoWithName(expectedPackage)));
218
219 mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
220
221 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
222 assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status);
223 assertEquals(expectedPackage, response.packageInfo.packageName);
224 }
225
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100226 /**
227 * The WebView preparation boot phase is run on the main thread (especially on a thread with a
228 * looper) so to avoid bugs where our tests fail because a looper hasn't been attached to the
229 * thread running prepareWebViewInSystemServer we run it on the main thread.
230 */
231 private void runWebViewBootPreparationOnMainSync() {
232 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
233 @Override
234 public void run() {
235 mWebViewUpdateServiceImpl.prepareWebViewInSystemServer();
236 }
237 });
238 }
239
Gustav Sennton53b78242016-04-07 15:56:10 +0100240
241 // ****************
242 // Tests
243 // ****************
244
245
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100246 @Test
Gustav Sennton53b78242016-04-07 15:56:10 +0100247 public void testWithSinglePackage() {
248 String testPackageName = "test.package.name";
Gustav Senntona9159042016-04-11 16:32:52 +0100249 checkCertainPackageUsedAfterWebViewBootPreparation(testPackageName,
Gustav Sennton53b78242016-04-07 15:56:10 +0100250 new WebViewProviderInfo[] {
251 new WebViewProviderInfo(testPackageName, "",
252 true /*default available*/, false /* fallback */, null)});
253 }
254
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100255 @Test
Gustav Sennton53b78242016-04-07 15:56:10 +0100256 public void testDefaultPackageUsedOverNonDefault() {
257 String defaultPackage = "defaultPackage";
258 String nonDefaultPackage = "nonDefaultPackage";
259 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
260 new WebViewProviderInfo(nonDefaultPackage, "", false, false, null),
261 new WebViewProviderInfo(defaultPackage, "", true, false, null)};
Gustav Senntona9159042016-04-11 16:32:52 +0100262 checkCertainPackageUsedAfterWebViewBootPreparation(defaultPackage, packages);
Gustav Sennton53b78242016-04-07 15:56:10 +0100263 }
264
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100265 @Test
Gustav Sennton53b78242016-04-07 15:56:10 +0100266 public void testSeveralRelros() {
267 String singlePackage = "singlePackage";
Gustav Senntona9159042016-04-11 16:32:52 +0100268 checkCertainPackageUsedAfterWebViewBootPreparation(
Gustav Sennton53b78242016-04-07 15:56:10 +0100269 singlePackage,
270 new WebViewProviderInfo[] {
271 new WebViewProviderInfo(singlePackage, "", true /*def av*/, false, null)},
272 2);
273 }
274
275 // Ensure that package with valid signatures is chosen rather than package with invalid
276 // signatures.
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100277 @Test
Gustav Sennton53b78242016-04-07 15:56:10 +0100278 public void testWithSignatures() {
279 String validPackage = "valid package";
280 String invalidPackage = "invalid package";
281
282 Signature validSignature = new Signature("11");
283 Signature invalidExpectedSignature = new Signature("22");
284 Signature invalidPackageSignature = new Signature("33");
285
286 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
287 new WebViewProviderInfo(invalidPackage, "", true, false, new String[]{
288 Base64.encodeToString(
289 invalidExpectedSignature.toByteArray(), Base64.DEFAULT)}),
290 new WebViewProviderInfo(validPackage, "", true, false, new String[]{
291 Base64.encodeToString(
292 validSignature.toByteArray(), Base64.DEFAULT)})
293 };
294 setupWithPackages(packages, true /* fallback logic enabled */, 1 /* numRelros */,
295 false /* isDebuggable */);
296 mTestSystemImpl.setPackageInfo(createPackageInfo(invalidPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100297 true /* valid */, true /* installed */, new Signature[]{invalidPackageSignature}
298 , 0 /* updateTime */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100299 mTestSystemImpl.setPackageInfo(createPackageInfo(validPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100300 true /* valid */, true /* installed */, new Signature[]{validSignature}
301 , 0 /* updateTime */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100302
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100303 runWebViewBootPreparationOnMainSync();
Gustav Sennton53b78242016-04-07 15:56:10 +0100304
Gustav Sennton53b78242016-04-07 15:56:10 +0100305
Gustav Senntona9159042016-04-11 16:32:52 +0100306 checkPreparationPhasesForPackage(validPackage, 1 /* first preparation for this package */);
Gustav Sennton53b78242016-04-07 15:56:10 +0100307
308 WebViewProviderInfo[] validPackages = mWebViewUpdateServiceImpl.getValidWebViewPackages();
309 assertEquals(1, validPackages.length);
310 assertEquals(validPackage, validPackages[0].packageName);
311 }
312
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100313 @Test
Gustav Sennton53b78242016-04-07 15:56:10 +0100314 public void testFailWaitingForRelro() {
315 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
316 new WebViewProviderInfo("packagename", "", true, true, null)};
317 setupWithPackages(packages);
318 setEnabledAndValidPackageInfos(packages);
319
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100320 runWebViewBootPreparationOnMainSync();
Gustav Sennton53b78242016-04-07 15:56:10 +0100321
322 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
323 Mockito.argThat(new IsPackageInfoWithName(packages[0].packageName)));
324
325 // Never call notifyRelroCreation()
326
327 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
328 assertEquals(WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO, response.status);
329 }
330
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100331 @Test
Gustav Sennton53b78242016-04-07 15:56:10 +0100332 public void testFailListingEmptyWebviewPackages() {
333 WebViewProviderInfo[] packages = new WebViewProviderInfo[0];
334 setupWithPackages(packages);
335 setEnabledAndValidPackageInfos(packages);
336
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100337 runWebViewBootPreparationOnMainSync();
Gustav Sennton53b78242016-04-07 15:56:10 +0100338
339 Mockito.verify(mTestSystemImpl, Mockito.never()).onWebViewProviderChanged(
340 Matchers.anyObject());
341
342 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
343 assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
Gustav Senntonbf683e02016-09-15 14:42:50 +0100344 assertEquals(null, mWebViewUpdateServiceImpl.getCurrentWebViewPackage());
345
346 // Now install a package
347 String singlePackage = "singlePackage";
348 packages = new WebViewProviderInfo[]{
349 new WebViewProviderInfo(singlePackage, "", true, false, null)};
350 setupWithPackages(packages);
351 setEnabledAndValidPackageInfos(packages);
352
353 mWebViewUpdateServiceImpl.packageStateChanged(singlePackage,
Gustav Sennton364e1602016-12-14 09:10:50 +0000354 WebViewUpdateService.PACKAGE_ADDED, TestSystemImpl.PRIMARY_USER_ID);
Gustav Senntonbf683e02016-09-15 14:42:50 +0100355
356 checkPreparationPhasesForPackage(singlePackage, 1 /* number of finished preparations */);
357 assertEquals(singlePackage,
358 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().packageName);
359
360 // Remove the package again
361 mTestSystemImpl.removePackageInfo(singlePackage);
362 mWebViewUpdateServiceImpl.packageStateChanged(singlePackage,
Gustav Sennton364e1602016-12-14 09:10:50 +0000363 WebViewUpdateService.PACKAGE_ADDED, TestSystemImpl.PRIMARY_USER_ID);
Gustav Senntonbf683e02016-09-15 14:42:50 +0100364
365 // Package removed - ensure our interface states that there is no package
366 response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
367 assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
368 assertEquals(null, mWebViewUpdateServiceImpl.getCurrentWebViewPackage());
Gustav Sennton53b78242016-04-07 15:56:10 +0100369 }
370
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100371 @Test
Gustav Sennton53b78242016-04-07 15:56:10 +0100372 public void testFailListingInvalidWebviewPackage() {
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100373 WebViewProviderInfo wpi = new WebViewProviderInfo("package", "", true, true, null);
Gustav Sennton53b78242016-04-07 15:56:10 +0100374 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {wpi};
375 setupWithPackages(packages);
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100376 mTestSystemImpl.setPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100377 createPackageInfo(wpi.packageName, true /* enabled */, false /* valid */,
378 true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100379
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100380 runWebViewBootPreparationOnMainSync();
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100381
382 Mockito.verify(mTestSystemImpl, Mockito.never()).onWebViewProviderChanged(
383 Matchers.anyObject());
384
Gustav Sennton53b78242016-04-07 15:56:10 +0100385 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
386 assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100387
388 // Verify that we can recover from failing to list webview packages.
389 mTestSystemImpl.setPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100390 createPackageInfo(wpi.packageName, true /* enabled */, true /* valid */,
391 true /* installed */));
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100392 mWebViewUpdateServiceImpl.packageStateChanged(wpi.packageName,
Gustav Sennton364e1602016-12-14 09:10:50 +0000393 WebViewUpdateService.PACKAGE_ADDED_REPLACED, TestSystemImpl.PRIMARY_USER_ID);
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100394
395 checkPreparationPhasesForPackage(wpi.packageName, 1);
Gustav Sennton53b78242016-04-07 15:56:10 +0100396 }
397
398 // Test that switching provider using changeProviderAndSetting works.
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100399 @Test
Gustav Sennton53b78242016-04-07 15:56:10 +0100400 public void testSwitchingProvider() {
401 String firstPackage = "first";
402 String secondPackage = "second";
403 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
404 new WebViewProviderInfo(firstPackage, "", true, false, null),
405 new WebViewProviderInfo(secondPackage, "", true, false, null)};
406 checkSwitchingProvider(packages, firstPackage, secondPackage);
407 }
408
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100409 @Test
Gustav Sennton53b78242016-04-07 15:56:10 +0100410 public void testSwitchingProviderToNonDefault() {
411 String defaultPackage = "defaultPackage";
412 String nonDefaultPackage = "nonDefaultPackage";
413 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
414 new WebViewProviderInfo(defaultPackage, "", true, false, null),
415 new WebViewProviderInfo(nonDefaultPackage, "", false, false, null)};
416 checkSwitchingProvider(packages, defaultPackage, nonDefaultPackage);
417 }
418
419 private void checkSwitchingProvider(WebViewProviderInfo[] packages, String initialPackage,
420 String finalPackage) {
Gustav Senntona9159042016-04-11 16:32:52 +0100421 checkCertainPackageUsedAfterWebViewBootPreparation(initialPackage, packages);
Gustav Sennton53b78242016-04-07 15:56:10 +0100422
423 mWebViewUpdateServiceImpl.changeProviderAndSetting(finalPackage);
Gustav Senntona9159042016-04-11 16:32:52 +0100424 checkPreparationPhasesForPackage(finalPackage, 1 /* first preparation for this package */);
Gustav Sennton53b78242016-04-07 15:56:10 +0100425
426 Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(initialPackage));
427 }
428
429 // Change provider during relro creation by using changeProviderAndSetting
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100430 @Test
Gustav Sennton53b78242016-04-07 15:56:10 +0100431 public void testSwitchingProviderDuringRelroCreation() {
432 checkChangingProviderDuringRelroCreation(true);
433 }
434
435 // Change provider during relro creation by enabling a provider
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100436 @Test
Gustav Sennton53b78242016-04-07 15:56:10 +0100437 public void testChangingProviderThroughEnablingDuringRelroCreation() {
438 checkChangingProviderDuringRelroCreation(false);
439 }
440
441 private void checkChangingProviderDuringRelroCreation(boolean settingsChange) {
442 String firstPackage = "first";
443 String secondPackage = "second";
444 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
445 new WebViewProviderInfo(firstPackage, "", true, false, null),
446 new WebViewProviderInfo(secondPackage, "", true, false, null)};
447 setupWithPackages(packages);
Gustav Sennton364e1602016-12-14 09:10:50 +0000448 // Have all packages be enabled, so that we can change provider however we want to
449 setEnabledAndValidPackageInfos(packages);
Gustav Sennton53b78242016-04-07 15:56:10 +0100450
451 CountDownLatch countdown = new CountDownLatch(1);
452
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100453 runWebViewBootPreparationOnMainSync();
Gustav Sennton53b78242016-04-07 15:56:10 +0100454
455 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
456 Mockito.argThat(new IsPackageInfoWithName(firstPackage)));
457
Gustav Senntonbf683e02016-09-15 14:42:50 +0100458 assertEquals(firstPackage,
459 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().packageName);
Gustav Sennton53b78242016-04-07 15:56:10 +0100460
461 new Thread(new Runnable() {
462 @Override
463 public void run() {
464 WebViewProviderResponse threadResponse =
465 mWebViewUpdateServiceImpl.waitForAndGetProvider();
466 assertEquals(WebViewFactory.LIBLOAD_SUCCESS, threadResponse.status);
467 assertEquals(secondPackage, threadResponse.packageInfo.packageName);
Gustav Sennton364e1602016-12-14 09:10:50 +0000468 // Verify that we killed the first package if we performed a settings change -
469 // otherwise we had to disable the first package, in which case its dependents
470 // should have been killed by the framework.
471 if (settingsChange) {
472 Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(firstPackage));
473 }
Gustav Sennton53b78242016-04-07 15:56:10 +0100474 countdown.countDown();
475 }
476 }).start();
477 try {
Gustav Sennton0df2c552016-06-14 15:32:19 +0100478 Thread.sleep(500); // Let the new thread run / be blocked
Gustav Sennton53b78242016-04-07 15:56:10 +0100479 } catch (InterruptedException e) {
480 }
481
482 if (settingsChange) {
483 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage);
484 } else {
Gustav Sennton364e1602016-12-14 09:10:50 +0000485 // Enable the second provider
Gustav Sennton53b78242016-04-07 15:56:10 +0100486 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100487 true /* valid */, true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100488 mWebViewUpdateServiceImpl.packageStateChanged(
Gustav Sennton364e1602016-12-14 09:10:50 +0000489 secondPackage, WebViewUpdateService.PACKAGE_CHANGED, TestSystemImpl.PRIMARY_USER_ID);
490
491 // Ensure we haven't changed package yet.
492 assertEquals(firstPackage,
493 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().packageName);
494
495 // Switch provider by disabling the first one
496 mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, false /* enabled */,
497 true /* valid */, true /* installed */));
498 mWebViewUpdateServiceImpl.packageStateChanged(
499 firstPackage, WebViewUpdateService.PACKAGE_CHANGED, TestSystemImpl.PRIMARY_USER_ID);
Gustav Sennton53b78242016-04-07 15:56:10 +0100500 }
501 mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
502 // first package done, should start on second
503
504 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
505 Mockito.argThat(new IsPackageInfoWithName(secondPackage)));
506
507 mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
508 // second package done, the other thread should now be unblocked
509 try {
510 countdown.await();
511 } catch (InterruptedException e) {
512 }
513 }
514
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100515 @Test
Gustav Sennton53b78242016-04-07 15:56:10 +0100516 public void testRunFallbackLogicIfEnabled() {
517 checkFallbackLogicBeingRun(true);
518 }
519
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100520 @Test
Gustav Sennton53b78242016-04-07 15:56:10 +0100521 public void testDontRunFallbackLogicIfDisabled() {
522 checkFallbackLogicBeingRun(false);
523 }
524
525 private void checkFallbackLogicBeingRun(boolean fallbackLogicEnabled) {
526 String primaryPackage = "primary";
527 String fallbackPackage = "fallback";
528 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
529 new WebViewProviderInfo(
530 primaryPackage, "", true /* default available */, false /* fallback */, null),
531 new WebViewProviderInfo(
532 fallbackPackage, "", true /* default available */, true /* fallback */, null)};
533 setupWithPackages(packages, fallbackLogicEnabled);
534 setEnabledAndValidPackageInfos(packages);
535
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100536 runWebViewBootPreparationOnMainSync();
Gustav Sennton53b78242016-04-07 15:56:10 +0100537 // Verify that we disable the fallback package if fallback logic enabled, and don't disable
538 // the fallback package if that logic is disabled
539 if (fallbackLogicEnabled) {
540 Mockito.verify(mTestSystemImpl).uninstallAndDisablePackageForAllUsers(
541 Matchers.anyObject(), Mockito.eq(fallbackPackage));
542 } else {
543 Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers(
544 Matchers.anyObject(), Matchers.anyObject());
545 }
546 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
547 Mockito.argThat(new IsPackageInfoWithName(primaryPackage)));
548
549 // Enable fallback package
550 mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100551 true /* valid */, true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100552 mWebViewUpdateServiceImpl.packageStateChanged(
Gustav Sennton364e1602016-12-14 09:10:50 +0000553 fallbackPackage, WebViewUpdateService.PACKAGE_CHANGED, TestSystemImpl.PRIMARY_USER_ID);
Gustav Sennton53b78242016-04-07 15:56:10 +0100554
555 if (fallbackLogicEnabled) {
556 // Check that we have now disabled the fallback package twice
557 Mockito.verify(mTestSystemImpl, Mockito.times(2)).uninstallAndDisablePackageForAllUsers(
558 Matchers.anyObject(), Mockito.eq(fallbackPackage));
559 } else {
560 // Check that we still haven't disabled any package
561 Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers(
562 Matchers.anyObject(), Matchers.anyObject());
563 }
564 }
565
566 /**
567 * Scenario for installing primary package when fallback enabled.
568 * 1. Start with only fallback installed
569 * 2. Install non-fallback
570 * 3. Fallback should be disabled
571 */
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100572 @Test
Gustav Sennton53b78242016-04-07 15:56:10 +0100573 public void testInstallingNonFallbackPackage() {
574 String primaryPackage = "primary";
575 String fallbackPackage = "fallback";
576 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
577 new WebViewProviderInfo(
578 primaryPackage, "", true /* default available */, false /* fallback */, null),
579 new WebViewProviderInfo(
580 fallbackPackage, "", true /* default available */, true /* fallback */, null)};
581 setupWithPackages(packages, true /* isFallbackLogicEnabled */);
582 mTestSystemImpl.setPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100583 createPackageInfo(fallbackPackage, true /* enabled */ , true /* valid */,
584 true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100585
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100586 runWebViewBootPreparationOnMainSync();
Gustav Sennton53b78242016-04-07 15:56:10 +0100587 Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers(
588 Matchers.anyObject(), Matchers.anyObject());
Gustav Sennton53b78242016-04-07 15:56:10 +0100589
Gustav Senntona9159042016-04-11 16:32:52 +0100590 checkPreparationPhasesForPackage(fallbackPackage,
591 1 /* first preparation for this package*/);
Gustav Sennton53b78242016-04-07 15:56:10 +0100592
593 // Install primary package
594 mTestSystemImpl.setPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100595 createPackageInfo(primaryPackage, true /* enabled */ , true /* valid */,
596 true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100597 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
Gustav Sennton364e1602016-12-14 09:10:50 +0000598 WebViewUpdateService.PACKAGE_ADDED_REPLACED, TestSystemImpl.PRIMARY_USER_ID);
Gustav Sennton53b78242016-04-07 15:56:10 +0100599
Gustav Senntona9159042016-04-11 16:32:52 +0100600 // Verify fallback disabled, primary package used as provider, and fallback package killed
Gustav Sennton53b78242016-04-07 15:56:10 +0100601 Mockito.verify(mTestSystemImpl).uninstallAndDisablePackageForAllUsers(
602 Matchers.anyObject(), Mockito.eq(fallbackPackage));
Gustav Senntona9159042016-04-11 16:32:52 +0100603 checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation for this package*/);
Gustav Sennton53b78242016-04-07 15:56:10 +0100604 Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(fallbackPackage));
605 }
606
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100607 @Test
Gustav Sennton364e1602016-12-14 09:10:50 +0000608 public void testFallbackChangesEnabledStateSingleUser() {
609 for (PackageRemovalType removalType : REMOVAL_TYPES) {
610 checkFallbackChangesEnabledState(false /* multiUser */, removalType);
611 }
612 }
613
614 @Test
615 public void testFallbackChangesEnabledStateMultiUser() {
616 for (PackageRemovalType removalType : REMOVAL_TYPES) {
617 checkFallbackChangesEnabledState(true /* multiUser */, removalType);
618 }
619 }
620
621 /**
622 * Represents how to remove a package during a tests (disabling it / uninstalling it / hiding
623 * it).
624 */
625 private enum PackageRemovalType {
626 UNINSTALL, DISABLE, HIDE
627 }
628
629 private PackageRemovalType[] REMOVAL_TYPES = PackageRemovalType.class.getEnumConstants();
630
631 public void checkFallbackChangesEnabledState(boolean multiUser,
632 PackageRemovalType removalType) {
Gustav Sennton53b78242016-04-07 15:56:10 +0100633 String primaryPackage = "primary";
634 String fallbackPackage = "fallback";
635 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
636 new WebViewProviderInfo(
637 primaryPackage, "", true /* default available */, false /* fallback */, null),
638 new WebViewProviderInfo(
639 fallbackPackage, "", true /* default available */, true /* fallback */, null)};
640 setupWithPackages(packages, true /* fallbackLogicEnabled */);
Gustav Sennton364e1602016-12-14 09:10:50 +0000641 int secondaryUserId = 10;
642 int userIdToChangePackageFor = multiUser ? secondaryUserId : TestSystemImpl.PRIMARY_USER_ID;
643 if (multiUser) {
644 mTestSystemImpl.addUser(secondaryUserId);
645 setEnabledAndValidPackageInfosForUser(secondaryUserId, packages);
646 }
647 setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, packages);
Gustav Sennton53b78242016-04-07 15:56:10 +0100648
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100649 runWebViewBootPreparationOnMainSync();
Gustav Sennton53b78242016-04-07 15:56:10 +0100650
651 // Verify fallback disabled at boot when primary package enabled
Gustav Sennton364e1602016-12-14 09:10:50 +0000652 checkEnablePackageForUserCalled(fallbackPackage, false, multiUser
653 ? new int[] {TestSystemImpl.PRIMARY_USER_ID, secondaryUserId}
654 : new int[] {TestSystemImpl.PRIMARY_USER_ID}, 1 /* numUsages */);
Gustav Sennton53b78242016-04-07 15:56:10 +0100655
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100656 checkPreparationPhasesForPackage(primaryPackage, 1);
657
Gustav Sennton364e1602016-12-14 09:10:50 +0000658 boolean enabled = !(removalType == PackageRemovalType.DISABLE);
659 boolean installed = !(removalType == PackageRemovalType.UNINSTALL);
660 boolean hidden = (removalType == PackageRemovalType.HIDE);
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100661 // Disable primary package and ensure fallback becomes enabled and used
Gustav Sennton364e1602016-12-14 09:10:50 +0000662 mTestSystemImpl.setPackageInfoForUser(userIdToChangePackageFor,
663 createPackageInfo(primaryPackage, enabled /* enabled */, true /* valid */,
664 installed /* installed */, null /* signature */, 0 /* updateTime */,
665 hidden /* hidden */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100666 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
Gustav Sennton364e1602016-12-14 09:10:50 +0000667 removalType == PackageRemovalType.DISABLE
668 ? WebViewUpdateService.PACKAGE_CHANGED : WebViewUpdateService.PACKAGE_REMOVED,
669 userIdToChangePackageFor); // USER ID
Gustav Sennton53b78242016-04-07 15:56:10 +0100670
Gustav Sennton364e1602016-12-14 09:10:50 +0000671 checkEnablePackageForUserCalled(fallbackPackage, true, multiUser
672 ? new int[] {TestSystemImpl.PRIMARY_USER_ID, secondaryUserId}
673 : new int[] {TestSystemImpl.PRIMARY_USER_ID}, 1 /* numUsages */);
Gustav Sennton53b78242016-04-07 15:56:10 +0100674
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100675 checkPreparationPhasesForPackage(fallbackPackage, 1);
676
677
678 // Again enable primary package and verify primary is used and fallback becomes disabled
Gustav Sennton364e1602016-12-14 09:10:50 +0000679 mTestSystemImpl.setPackageInfoForUser(userIdToChangePackageFor,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100680 createPackageInfo(primaryPackage, true /* enabled */, true /* valid */,
681 true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100682 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
Gustav Sennton364e1602016-12-14 09:10:50 +0000683 removalType == PackageRemovalType.DISABLE
684 ? WebViewUpdateService.PACKAGE_CHANGED : WebViewUpdateService.PACKAGE_ADDED,
685 userIdToChangePackageFor);
Gustav Sennton53b78242016-04-07 15:56:10 +0100686
687 // Verify fallback is disabled a second time when primary package becomes enabled
Gustav Sennton364e1602016-12-14 09:10:50 +0000688 checkEnablePackageForUserCalled(fallbackPackage, false, multiUser
689 ? new int[] {TestSystemImpl.PRIMARY_USER_ID, secondaryUserId}
690 : new int[] {TestSystemImpl.PRIMARY_USER_ID}, 2 /* numUsages */);
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100691
692 checkPreparationPhasesForPackage(primaryPackage, 2);
Gustav Sennton53b78242016-04-07 15:56:10 +0100693 }
694
Gustav Sennton364e1602016-12-14 09:10:50 +0000695 private void checkEnablePackageForUserCalled(String packageName, boolean expectEnabled,
696 int[] userIds, int numUsages) {
697 for (int userId : userIds) {
698 Mockito.verify(mTestSystemImpl, Mockito.times(numUsages)).enablePackageForUser(
699 Mockito.eq(packageName), Mockito.eq(expectEnabled), Mockito.eq(userId));
700 }
701 }
702
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100703 @Test
Gustav Sennton53b78242016-04-07 15:56:10 +0100704 public void testAddUserWhenFallbackLogicEnabled() {
705 checkAddingNewUser(true);
706 }
707
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100708 @Test
Gustav Sennton53b78242016-04-07 15:56:10 +0100709 public void testAddUserWhenFallbackLogicDisabled() {
710 checkAddingNewUser(false);
711 }
712
713 public void checkAddingNewUser(boolean fallbackLogicEnabled) {
714 String primaryPackage = "primary";
715 String fallbackPackage = "fallback";
716 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
717 new WebViewProviderInfo(
718 primaryPackage, "", true /* default available */, false /* fallback */, null),
719 new WebViewProviderInfo(
720 fallbackPackage, "", true /* default available */, true /* fallback */, null)};
721 setupWithPackages(packages, fallbackLogicEnabled);
Gustav Sennton364e1602016-12-14 09:10:50 +0000722 setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, packages);
Gustav Sennton53b78242016-04-07 15:56:10 +0100723 int newUser = 100;
Gustav Sennton364e1602016-12-14 09:10:50 +0000724 mTestSystemImpl.addUser(newUser);
725 setEnabledAndValidPackageInfosForUser(newUser, packages);
Gustav Sennton53b78242016-04-07 15:56:10 +0100726 mWebViewUpdateServiceImpl.handleNewUser(newUser);
727 if (fallbackLogicEnabled) {
728 // Verify fallback package becomes disabled for new user
729 Mockito.verify(mTestSystemImpl).enablePackageForUser(
730 Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */,
731 Mockito.eq(newUser));
732 } else {
733 // Verify that we don't disable fallback for new user
734 Mockito.verify(mTestSystemImpl, Mockito.never()).enablePackageForUser(
735 Mockito.anyObject(), Matchers.anyBoolean() /* enable */,
736 Matchers.anyInt() /* user */);
737 }
738 }
739
740 /**
Gustav Sennton364e1602016-12-14 09:10:50 +0000741 * Ensures that adding a new user for which the current WebView package is uninstalled causes a
742 * change of WebView provider.
743 */
744 @Test
745 public void testAddingNewUserWithUninstalledPackage() {
746 String primaryPackage = "primary";
747 String fallbackPackage = "fallback";
748 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
749 new WebViewProviderInfo(
750 primaryPackage, "", true /* default available */, false /* fallback */, null),
751 new WebViewProviderInfo(
752 fallbackPackage, "", true /* default available */, true /* fallback */, null)};
753 setupWithPackages(packages, true /* fallbackLogicEnabled */);
754 setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, packages);
755 int newUser = 100;
756 mTestSystemImpl.addUser(newUser);
757 // Let the primary package be uninstalled for the new user
758 mTestSystemImpl.setPackageInfoForUser(newUser,
759 createPackageInfo(primaryPackage, true /* enabled */, true /* valid */,
760 false /* installed */));
761 mTestSystemImpl.setPackageInfoForUser(newUser,
762 createPackageInfo(fallbackPackage, false /* enabled */, true /* valid */,
763 true /* installed */));
764 mWebViewUpdateServiceImpl.handleNewUser(newUser);
765 // Verify fallback package doesn't become disabled for the primary user.
766 Mockito.verify(mTestSystemImpl, Mockito.never()).enablePackageForUser(
767 Mockito.anyObject(), Mockito.eq(false) /* enable */,
768 Mockito.eq(TestSystemImpl.PRIMARY_USER_ID) /* user */);
769 // Verify that we enable the fallback package for the secondary user.
770 Mockito.verify(mTestSystemImpl, Mockito.times(1)).enablePackageForUser(
771 Mockito.eq(fallbackPackage), Mockito.eq(true) /* enable */,
772 Mockito.eq(newUser) /* user */);
773 checkPreparationPhasesForPackage(fallbackPackage, 1 /* numRelros */);
774 }
775
776 /**
Gustav Sennton53b78242016-04-07 15:56:10 +0100777 * Timing dependent test where we verify that the list of valid webview packages becoming empty
778 * at a certain point doesn't crash us or break our state.
779 */
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100780 @Test
Gustav Sennton53b78242016-04-07 15:56:10 +0100781 public void testNotifyRelroDoesntCrashIfNoPackages() {
782 String firstPackage = "first";
783 String secondPackage = "second";
784 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
785 new WebViewProviderInfo(firstPackage, "", true /* default available */,
786 false /* fallback */, null),
787 new WebViewProviderInfo(secondPackage, "", true /* default available */,
788 false /* fallback */, null)};
789 setupWithPackages(packages);
790 // Add (enabled and valid) package infos for each provider
791 setEnabledAndValidPackageInfos(packages);
792
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100793 runWebViewBootPreparationOnMainSync();
Gustav Sennton53b78242016-04-07 15:56:10 +0100794
795 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
796 Mockito.argThat(new IsPackageInfoWithName(firstPackage)));
797
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100798 // Change provider during relro creation to enter a state where we are
799 // waiting for relro creation to complete just to re-run relro creation.
800 // (so that in next notifyRelroCreationCompleted() call we have to list webview packages)
Gustav Sennton53b78242016-04-07 15:56:10 +0100801 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage);
802
803 // Make packages invalid to cause exception to be thrown
804 mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100805 false /* valid */, true /* installed */, null /* signatures */,
806 0 /* updateTime */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100807 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100808 false /* valid */, true /* installed */));
Gustav Sennton53b78242016-04-07 15:56:10 +0100809
810 // This shouldn't throw an exception!
811 mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
812
813 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
814 assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
815
816 // Now make a package valid again and verify that we can switch back to that
817 mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100818 true /* valid */, true /* installed */, null /* signatures */,
819 1 /* updateTime */ ));
Gustav Sennton53b78242016-04-07 15:56:10 +0100820
821 mWebViewUpdateServiceImpl.packageStateChanged(firstPackage,
Gustav Sennton364e1602016-12-14 09:10:50 +0000822 WebViewUpdateService.PACKAGE_ADDED_REPLACED, TestSystemImpl.PRIMARY_USER_ID);
Gustav Sennton53b78242016-04-07 15:56:10 +0100823
Gustav Senntona9159042016-04-11 16:32:52 +0100824 // Ensure we use firstPackage
825 checkPreparationPhasesForPackage(firstPackage, 2 /* second preparation for this package */);
826 }
Gustav Sennton53b78242016-04-07 15:56:10 +0100827
Gustav Senntona9159042016-04-11 16:32:52 +0100828 /**
829 * Verify that even if a user-chosen package is removed temporarily we start using it again when
830 * it is added back.
831 */
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100832 @Test
Gustav Senntona9159042016-04-11 16:32:52 +0100833 public void testTempRemovePackageDoesntSwitchProviderPermanently() {
834 String firstPackage = "first";
835 String secondPackage = "second";
836 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
837 new WebViewProviderInfo(firstPackage, "", true /* default available */,
838 false /* fallback */, null),
839 new WebViewProviderInfo(secondPackage, "", true /* default available */,
840 false /* fallback */, null)};
841 checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages);
Gustav Sennton53b78242016-04-07 15:56:10 +0100842
Gustav Senntona9159042016-04-11 16:32:52 +0100843 // Explicitly use the second package
844 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage);
845 checkPreparationPhasesForPackage(secondPackage, 1 /* first time for this package */);
846
847 // Remove second package (invalidate it) and verify that first package is used
848 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100849 false /* valid */, true /* installed */));
Gustav Senntona9159042016-04-11 16:32:52 +0100850 mWebViewUpdateServiceImpl.packageStateChanged(secondPackage,
Gustav Sennton364e1602016-12-14 09:10:50 +0000851 WebViewUpdateService.PACKAGE_ADDED, TestSystemImpl.PRIMARY_USER_ID);
Gustav Senntona9159042016-04-11 16:32:52 +0100852 checkPreparationPhasesForPackage(firstPackage, 2 /* second time for this package */);
853
854 // Now make the second package valid again and verify that it is used again
855 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100856 true /* valid */, true /* installed */));
Gustav Senntona9159042016-04-11 16:32:52 +0100857 mWebViewUpdateServiceImpl.packageStateChanged(secondPackage,
Gustav Sennton364e1602016-12-14 09:10:50 +0000858 WebViewUpdateService.PACKAGE_ADDED, TestSystemImpl.PRIMARY_USER_ID);
Gustav Senntona9159042016-04-11 16:32:52 +0100859 checkPreparationPhasesForPackage(secondPackage, 2 /* second time for this package */);
860 }
861
862 /**
863 * Ensure that we update the user-chosen setting across boots if the chosen package is no
864 * longer installed and valid.
865 */
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100866 @Test
Gustav Senntona9159042016-04-11 16:32:52 +0100867 public void testProviderSettingChangedDuringBootIfProviderNotAvailable() {
868 String chosenPackage = "chosenPackage";
869 String nonChosenPackage = "non-chosenPackage";
870 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
871 new WebViewProviderInfo(chosenPackage, "", true /* default available */,
872 false /* fallback */, null),
873 new WebViewProviderInfo(nonChosenPackage, "", true /* default available */,
874 false /* fallback */, null)};
875
876 setupWithPackages(packages);
877 // Only 'install' nonChosenPackage
878 mTestSystemImpl.setPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100879 createPackageInfo(nonChosenPackage, true /* enabled */, true /* valid */, true /* installed */));
Gustav Senntona9159042016-04-11 16:32:52 +0100880
881 // Set user-chosen package
882 mTestSystemImpl.updateUserSetting(null, chosenPackage);
883
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100884 runWebViewBootPreparationOnMainSync();
Gustav Senntona9159042016-04-11 16:32:52 +0100885
886 // Verify that we switch the setting to point to the current package
887 Mockito.verify(mTestSystemImpl).updateUserSetting(
888 Mockito.anyObject(), Mockito.eq(nonChosenPackage));
889 assertEquals(nonChosenPackage, mTestSystemImpl.getUserChosenWebViewProvider(null));
890
891 checkPreparationPhasesForPackage(nonChosenPackage, 1);
Gustav Sennton53b78242016-04-07 15:56:10 +0100892 }
893
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100894 @Test
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100895 public void testRecoverFailedListingWebViewPackagesSettingsChange() {
896 checkRecoverAfterFailListingWebviewPackages(true);
897 }
898
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100899 @Test
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100900 public void testRecoverFailedListingWebViewPackagesAddedPackage() {
901 checkRecoverAfterFailListingWebviewPackages(false);
902 }
903
904 /**
905 * Test that we can recover correctly from failing to list WebView packages.
906 * settingsChange: whether to fail during changeProviderAndSetting or packageStateChanged
907 */
908 public void checkRecoverAfterFailListingWebviewPackages(boolean settingsChange) {
909 String firstPackage = "first";
910 String secondPackage = "second";
911 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
912 new WebViewProviderInfo(firstPackage, "", true /* default available */,
913 false /* fallback */, null),
914 new WebViewProviderInfo(secondPackage, "", true /* default available */,
915 false /* fallback */, null)};
916 checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages);
917
918 // Make both packages invalid so that we fail listing WebView packages
919 mTestSystemImpl.setPackageInfo(createPackageInfo(firstPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100920 false /* valid */, true /* installed */));
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100921 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100922 false /* valid */, true /* installed */));
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100923
924 // Change package to hit the webview packages listing problem.
925 if (settingsChange) {
926 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage);
927 } else {
928 mWebViewUpdateServiceImpl.packageStateChanged(secondPackage,
Gustav Sennton364e1602016-12-14 09:10:50 +0000929 WebViewUpdateService.PACKAGE_ADDED_REPLACED, TestSystemImpl.PRIMARY_USER_ID);
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100930 }
931
932 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
933 assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
934
935 // Make second package valid and verify that we can load it again
936 mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +0100937 true /* valid */, true /* installed */));
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100938
939 mWebViewUpdateServiceImpl.packageStateChanged(secondPackage,
Gustav Sennton364e1602016-12-14 09:10:50 +0000940 WebViewUpdateService.PACKAGE_ADDED_REPLACED, TestSystemImpl.PRIMARY_USER_ID);
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100941
942
943 checkPreparationPhasesForPackage(secondPackage, 1);
944 }
945
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100946 @Test
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100947 public void testDontKillIfPackageReplaced() {
948 checkDontKillIfPackageRemoved(true);
949 }
950
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100951 @Test
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100952 public void testDontKillIfPackageRemoved() {
953 checkDontKillIfPackageRemoved(false);
954 }
955
956 public void checkDontKillIfPackageRemoved(boolean replaced) {
957 String firstPackage = "first";
958 String secondPackage = "second";
959 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
960 new WebViewProviderInfo(firstPackage, "", true /* default available */,
961 false /* fallback */, null),
962 new WebViewProviderInfo(secondPackage, "", true /* default available */,
963 false /* fallback */, null)};
964 checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages);
965
966 // Replace or remove the current webview package
967 if (replaced) {
968 mTestSystemImpl.setPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +0100969 createPackageInfo(firstPackage, true /* enabled */, false /* valid */,
970 true /* installed */));
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100971 mWebViewUpdateServiceImpl.packageStateChanged(firstPackage,
Gustav Sennton364e1602016-12-14 09:10:50 +0000972 WebViewUpdateService.PACKAGE_ADDED_REPLACED, TestSystemImpl.PRIMARY_USER_ID);
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100973 } else {
974 mTestSystemImpl.removePackageInfo(firstPackage);
975 mWebViewUpdateServiceImpl.packageStateChanged(firstPackage,
Gustav Sennton364e1602016-12-14 09:10:50 +0000976 WebViewUpdateService.PACKAGE_REMOVED, TestSystemImpl.PRIMARY_USER_ID);
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100977 }
978
979 checkPreparationPhasesForPackage(secondPackage, 1);
980
981 Mockito.verify(mTestSystemImpl, Mockito.never()).killPackageDependents(
982 Mockito.anyObject());
983 }
984
Gustav Sennton86f7bbe2016-10-24 16:49:32 +0100985 @Test
Gustav Sennton95f7e8e2016-04-14 15:07:09 +0100986 public void testKillIfSettingChanged() {
987 String firstPackage = "first";
988 String secondPackage = "second";
989 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
990 new WebViewProviderInfo(firstPackage, "", true /* default available */,
991 false /* fallback */, null),
992 new WebViewProviderInfo(secondPackage, "", true /* default available */,
993 false /* fallback */, null)};
994 checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages);
995
996 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage);
997
998 checkPreparationPhasesForPackage(secondPackage, 1);
999
1000 Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(firstPackage));
1001 }
1002
1003 /**
1004 * Test that we kill apps using an old provider when we change the provider setting, even if the
1005 * new provider is not the one we intended to change to.
1006 */
Gustav Sennton86f7bbe2016-10-24 16:49:32 +01001007 @Test
Gustav Sennton95f7e8e2016-04-14 15:07:09 +01001008 public void testKillIfChangeProviderIncorrectly() {
1009 String firstPackage = "first";
1010 String secondPackage = "second";
1011 String thirdPackage = "third";
1012 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
1013 new WebViewProviderInfo(firstPackage, "", true /* default available */,
1014 false /* fallback */, null),
1015 new WebViewProviderInfo(secondPackage, "", true /* default available */,
1016 false /* fallback */, null),
1017 new WebViewProviderInfo(thirdPackage, "", true /* default available */,
1018 false /* fallback */, null)};
1019 setupWithPackages(packages);
1020 setEnabledAndValidPackageInfos(packages);
1021
1022 // Start with the setting pointing to the third package
1023 mTestSystemImpl.updateUserSetting(null, thirdPackage);
1024
Gustav Sennton86f7bbe2016-10-24 16:49:32 +01001025 runWebViewBootPreparationOnMainSync();
Gustav Sennton95f7e8e2016-04-14 15:07:09 +01001026 checkPreparationPhasesForPackage(thirdPackage, 1);
1027
1028 mTestSystemImpl.setPackageInfo(
Gustav Sennton0df2c552016-06-14 15:32:19 +01001029 createPackageInfo(secondPackage, true /* enabled */, false /* valid */, true /* installed */));
Gustav Sennton95f7e8e2016-04-14 15:07:09 +01001030
1031 // Try to switch to the invalid second package, this should result in switching to the first
1032 // package, since that is more preferred than the third one.
1033 assertEquals(firstPackage,
1034 mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage));
1035
1036 checkPreparationPhasesForPackage(firstPackage, 1);
1037
1038 Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(thirdPackage));
1039 }
Gustav Sennton18c9e152016-04-15 15:24:53 +01001040
Torne (Richard Coles)ab5d0ba2016-11-03 15:09:34 +00001041 @Test
Gustav Sennton18c9e152016-04-15 15:24:53 +01001042 public void testLowerPackageVersionNotValid() {
Hui Shu826a24b2016-04-26 14:53:40 -07001043 checkPackageVersions(new int[]{200000} /* system version */, 100000/* candidate version */,
1044 false /* expected validity */);
Gustav Sennton18c9e152016-04-15 15:24:53 +01001045 }
1046
Torne (Richard Coles)ab5d0ba2016-11-03 15:09:34 +00001047 @Test
Gustav Sennton18c9e152016-04-15 15:24:53 +01001048 public void testEqualPackageVersionValid() {
Hui Shu826a24b2016-04-26 14:53:40 -07001049 checkPackageVersions(new int[]{100000} /* system version */, 100000 /* candidate version */,
1050 true /* expected validity */);
Gustav Sennton18c9e152016-04-15 15:24:53 +01001051 }
1052
Torne (Richard Coles)ab5d0ba2016-11-03 15:09:34 +00001053 @Test
Gustav Sennton18c9e152016-04-15 15:24:53 +01001054 public void testGreaterPackageVersionValid() {
Hui Shu826a24b2016-04-26 14:53:40 -07001055 checkPackageVersions(new int[]{100000} /* system versions */, 200000 /* candidate version */,
1056 true /* expected validity */);
Gustav Sennton18c9e152016-04-15 15:24:53 +01001057 }
1058
Torne (Richard Coles)ab5d0ba2016-11-03 15:09:34 +00001059 @Test
Hui Shu826a24b2016-04-26 14:53:40 -07001060 public void testLastFiveDigitsIgnored() {
1061 checkPackageVersions(new int[]{654321} /* system version */, 612345 /* candidate version */,
1062 true /* expected validity */);
Gustav Sennton18c9e152016-04-15 15:24:53 +01001063 }
1064
Torne (Richard Coles)ab5d0ba2016-11-03 15:09:34 +00001065 @Test
Hui Shu826a24b2016-04-26 14:53:40 -07001066 public void testMinimumSystemVersionUsedTwoDefaultsCandidateValid() {
1067 checkPackageVersions(new int[]{300000, 100000} /* system versions */,
1068 200000 /* candidate version */, true /* expected validity */);
Gustav Sennton18c9e152016-04-15 15:24:53 +01001069 }
1070
Torne (Richard Coles)ab5d0ba2016-11-03 15:09:34 +00001071 @Test
Hui Shu826a24b2016-04-26 14:53:40 -07001072 public void testMinimumSystemVersionUsedTwoDefaultsCandidateInvalid() {
1073 checkPackageVersions(new int[]{300000, 200000} /* system versions */,
1074 100000 /* candidate version */, false /* expected validity */);
Gustav Sennton18c9e152016-04-15 15:24:53 +01001075 }
1076
Torne (Richard Coles)ab5d0ba2016-11-03 15:09:34 +00001077 @Test
Hui Shu826a24b2016-04-26 14:53:40 -07001078 public void testMinimumSystemVersionUsedSeveralDefaultsCandidateValid() {
1079 checkPackageVersions(new int[]{100000, 200000, 300000, 400000, 500000} /* system versions */,
1080 100000 /* candidate version */, true /* expected validity */);
1081 }
1082
Torne (Richard Coles)ab5d0ba2016-11-03 15:09:34 +00001083 @Test
Hui Shu826a24b2016-04-26 14:53:40 -07001084 public void testMinimumSystemVersionUsedSeveralDefaultsCandidateInvalid() {
1085 checkPackageVersions(new int[]{200000, 300000, 400000, 500000, 600000} /* system versions */,
1086 100000 /* candidate version */, false /* expected validity */);
Gustav Sennton18c9e152016-04-15 15:24:53 +01001087 }
1088
Torne (Richard Coles)ab5d0ba2016-11-03 15:09:34 +00001089 @Test
Gustav Sennton18c9e152016-04-15 15:24:53 +01001090 public void testMinimumSystemVersionUsedFallbackIgnored() {
Hui Shu826a24b2016-04-26 14:53:40 -07001091 checkPackageVersions(new int[]{300000, 400000, 500000, 600000, 700000} /* system versions */,
1092 200000 /* candidate version */, false /* expected validity */, true /* add fallback */,
1093 100000 /* fallback version */, false /* expected validity of fallback */);
Gustav Sennton18c9e152016-04-15 15:24:53 +01001094 }
1095
Torne (Richard Coles)ab5d0ba2016-11-03 15:09:34 +00001096 @Test
Hui Shu826a24b2016-04-26 14:53:40 -07001097 public void testFallbackValid() {
1098 checkPackageVersions(new int[]{300000, 400000, 500000, 600000, 700000} /* system versions */,
1099 200000/* candidate version */, false /* expected validity */, true /* add fallback */,
1100 300000 /* fallback version */, true /* expected validity of fallback */);
1101 }
1102
1103 private void checkPackageVersions(int[] systemVersions, int candidateVersion,
1104 boolean candidateShouldBeValid) {
1105 checkPackageVersions(systemVersions, candidateVersion, candidateShouldBeValid,
1106 false, 0, false);
Gustav Sennton18c9e152016-04-15 15:24:53 +01001107 }
1108
1109 /**
1110 * Utility method for checking that package version restriction works as it should.
1111 * I.e. that a package with lower version than the system-default is not valid and that a
1112 * package with greater than or equal version code is considered valid.
1113 */
Hui Shu826a24b2016-04-26 14:53:40 -07001114 private void checkPackageVersions(int[] systemVersions, int candidateVersion,
1115 boolean candidateShouldBeValid, boolean addFallback, int fallbackVersion,
1116 boolean fallbackShouldBeValid) {
Gustav Sennton18c9e152016-04-15 15:24:53 +01001117 int numSystemPackages = systemVersions.length;
1118 int numFallbackPackages = (addFallback ? 1 : 0);
1119 int numPackages = systemVersions.length + 1 + numFallbackPackages;
Hui Shu826a24b2016-04-26 14:53:40 -07001120 String candidatePackage = "candidatePackage";
Gustav Sennton18c9e152016-04-15 15:24:53 +01001121 String systemPackage = "systemPackage";
1122 String fallbackPackage = "fallbackPackage";
1123
1124 // Each package needs a valid signature since we set isDebuggable to false
1125 Signature signature = new Signature("11");
1126 String encodedSignatureString =
1127 Base64.encodeToString(signature.toByteArray(), Base64.DEFAULT);
1128
1129 // Set up config
Hui Shu826a24b2016-04-26 14:53:40 -07001130 // 1. candidatePackage
Gustav Sennton18c9e152016-04-15 15:24:53 +01001131 // 2-N. default available non-fallback packages
1132 // N+1. default available fallback package
1133 WebViewProviderInfo[] packages = new WebViewProviderInfo[numPackages];
Hui Shu826a24b2016-04-26 14:53:40 -07001134 packages[0] = new WebViewProviderInfo(candidatePackage, "",
Gustav Sennton18c9e152016-04-15 15:24:53 +01001135 false /* available by default */, false /* fallback */,
1136 new String[]{encodedSignatureString});
1137 for(int n = 1; n < numSystemPackages + 1; n++) {
1138 packages[n] = new WebViewProviderInfo(systemPackage + n, "",
1139 true /* available by default */, false /* fallback */,
1140 new String[]{encodedSignatureString});
1141 }
1142 if (addFallback) {
1143 packages[packages.length-1] = new WebViewProviderInfo(fallbackPackage, "",
1144 true /* available by default */, true /* fallback */,
1145 new String[]{encodedSignatureString});
1146 }
1147
1148 setupWithPackages(packages, true /* fallback logic enabled */, 1 /* numRelros */,
1149 false /* isDebuggable */);
1150
1151 // Set package infos
1152 mTestSystemImpl.setPackageInfo(
Hui Shu826a24b2016-04-26 14:53:40 -07001153 createPackageInfo(candidatePackage, true /* enabled */, true /* valid */,
Gustav Senntonfd222fc22016-06-16 20:24:23 +01001154 true /* installed */, new Signature[]{signature}, 0 /* updateTime */,
1155 false /* hidden */, candidateVersion, false /* isSystemApp */));
Gustav Sennton18c9e152016-04-15 15:24:53 +01001156 for(int n = 1; n < numSystemPackages + 1; n++) {
1157 mTestSystemImpl.setPackageInfo(
1158 createPackageInfo(systemPackage + n, true /* enabled */, true /* valid */,
Gustav Senntonfd222fc22016-06-16 20:24:23 +01001159 true /* installed */, new Signature[]{signature}, 0 /* updateTime */,
1160 false /* hidden */, systemVersions[n-1], true /* isSystemApp */));
Gustav Sennton18c9e152016-04-15 15:24:53 +01001161 }
1162 if (addFallback) {
1163 mTestSystemImpl.setPackageInfo(
1164 createPackageInfo(fallbackPackage, true /* enabled */, true /* valid */,
Gustav Senntonfd222fc22016-06-16 20:24:23 +01001165 true /* installed */, new Signature[]{signature}, 0 /* updateTime */,
1166 false /* hidden */, fallbackVersion, true /* isSystemApp */));
Gustav Sennton18c9e152016-04-15 15:24:53 +01001167 }
1168
1169 WebViewProviderInfo[] validPackages = mWebViewUpdateServiceImpl.getValidWebViewPackages();
Hui Shu826a24b2016-04-26 14:53:40 -07001170 int expectedNumValidPackages = numSystemPackages;
1171 if (candidateShouldBeValid) {
1172 expectedNumValidPackages++;
Gustav Sennton18c9e152016-04-15 15:24:53 +01001173 } else {
Hui Shu826a24b2016-04-26 14:53:40 -07001174 // Ensure the candidate package is not one of the valid packages
Gustav Sennton18c9e152016-04-15 15:24:53 +01001175 for(int n = 0; n < validPackages.length; n++) {
Hui Shu826a24b2016-04-26 14:53:40 -07001176 assertFalse(candidatePackage.equals(validPackages[n].packageName));
Gustav Sennton18c9e152016-04-15 15:24:53 +01001177 }
1178 }
1179
Hui Shu826a24b2016-04-26 14:53:40 -07001180 if (fallbackShouldBeValid) {
1181 expectedNumValidPackages += numFallbackPackages;
1182 } else {
1183 // Ensure the fallback package is not one of the valid packages
1184 for(int n = 0; n < validPackages.length; n++) {
1185 assertFalse(fallbackPackage.equals(validPackages[n].packageName));
1186 }
1187 }
1188
1189 assertEquals(expectedNumValidPackages, validPackages.length);
1190
Torne (Richard Coles)ab5d0ba2016-11-03 15:09:34 +00001191 runWebViewBootPreparationOnMainSync();
Gustav Sennton18c9e152016-04-15 15:24:53 +01001192
1193 // The non-system package is not available by default so it shouldn't be used here
1194 checkPreparationPhasesForPackage(systemPackage + "1", 1);
1195
Hui Shu826a24b2016-04-26 14:53:40 -07001196 // Try explicitly switching to the candidate package
1197 String packageChange = mWebViewUpdateServiceImpl.changeProviderAndSetting(candidatePackage);
1198 if (candidateShouldBeValid) {
1199 assertEquals(candidatePackage, packageChange);
1200 checkPreparationPhasesForPackage(candidatePackage, 1);
Gustav Sennton18c9e152016-04-15 15:24:53 +01001201 } else {
1202 assertEquals(systemPackage + "1", packageChange);
1203 // We didn't change package so the webview preparation won't run here
1204 }
1205 }
Gustav Senntonfd222fc22016-06-16 20:24:23 +01001206
Gustav Sennton364e1602016-12-14 09:10:50 +00001207 /**
1208 * Ensure that the update service does use an uninstalled package when that is the only
1209 * package available.
1210 */
Gustav Sennton86f7bbe2016-10-24 16:49:32 +01001211 @Test
Gustav Sennton0df2c552016-06-14 15:32:19 +01001212 public void testWithSingleUninstalledPackage() {
1213 String testPackageName = "test.package.name";
1214 WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] {
1215 new WebViewProviderInfo(testPackageName, "",
1216 true /*default available*/, false /* fallback */, null)};
1217 setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */);
1218 mTestSystemImpl.setPackageInfo(createPackageInfo(testPackageName, true /* enabled */,
1219 true /* valid */, false /* installed */));
1220
Gustav Sennton86f7bbe2016-10-24 16:49:32 +01001221 runWebViewBootPreparationOnMainSync();
Gustav Sennton0df2c552016-06-14 15:32:19 +01001222
Gustav Sennton963dbbb2017-04-06 16:18:02 +01001223 Mockito.verify(mTestSystemImpl, Mockito.never()).onWebViewProviderChanged(
1224 Matchers.anyObject());
1225 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
1226 assertEquals(WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES, response.status);
1227 assertEquals(null, mWebViewUpdateServiceImpl.getCurrentWebViewPackage());
Gustav Sennton0df2c552016-06-14 15:32:19 +01001228 }
1229
Gustav Sennton86f7bbe2016-10-24 16:49:32 +01001230 @Test
Gustav Sennton0df2c552016-06-14 15:32:19 +01001231 public void testNonhiddenPackageUserOverHidden() {
Gustav Sennton364e1602016-12-14 09:10:50 +00001232 checkVisiblePackageUserOverNonVisible(false /* multiUser*/, PackageRemovalType.HIDE);
1233 checkVisiblePackageUserOverNonVisible(true /* multiUser*/, PackageRemovalType.HIDE);
Gustav Sennton0df2c552016-06-14 15:32:19 +01001234 }
1235
Gustav Sennton86f7bbe2016-10-24 16:49:32 +01001236 @Test
Gustav Sennton0df2c552016-06-14 15:32:19 +01001237 public void testInstalledPackageUsedOverUninstalled() {
Gustav Sennton364e1602016-12-14 09:10:50 +00001238 checkVisiblePackageUserOverNonVisible(false /* multiUser*/, PackageRemovalType.UNINSTALL);
1239 checkVisiblePackageUserOverNonVisible(true /* multiUser*/, PackageRemovalType.UNINSTALL);
Gustav Sennton0df2c552016-06-14 15:32:19 +01001240 }
1241
Gustav Sennton364e1602016-12-14 09:10:50 +00001242 private void checkVisiblePackageUserOverNonVisible(boolean multiUser,
1243 PackageRemovalType removalType) {
1244 assert removalType != PackageRemovalType.DISABLE;
1245 boolean testUninstalled = removalType == PackageRemovalType.UNINSTALL;
1246 boolean testHidden = removalType == PackageRemovalType.HIDE;
Gustav Sennton0df2c552016-06-14 15:32:19 +01001247 String installedPackage = "installedPackage";
1248 String uninstalledPackage = "uninstalledPackage";
1249 WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] {
1250 new WebViewProviderInfo(uninstalledPackage, "", true /* available by default */,
1251 false /* fallback */, null),
1252 new WebViewProviderInfo(installedPackage, "", true /* available by default */,
1253 false /* fallback */, null)};
1254
1255 setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */);
Gustav Sennton364e1602016-12-14 09:10:50 +00001256 int secondaryUserId = 5;
1257 if (multiUser) {
1258 mTestSystemImpl.addUser(secondaryUserId);
1259 // Install all packages for the primary user.
1260 setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, webviewPackages);
1261 mTestSystemImpl.setPackageInfoForUser(secondaryUserId, createPackageInfo(
1262 installedPackage, true /* enabled */, true /* valid */, true /* installed */));
1263 // Hide or uninstall the primary package for the second user
1264 mTestSystemImpl.setPackageInfo(createPackageInfo(uninstalledPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +01001265 true /* valid */, (testUninstalled ? false : true) /* installed */,
1266 null /* signatures */, 0 /* updateTime */, (testHidden ? true : false)));
Gustav Sennton364e1602016-12-14 09:10:50 +00001267 } else {
1268 mTestSystemImpl.setPackageInfo(createPackageInfo(installedPackage, true /* enabled */,
1269 true /* valid */, true /* installed */));
1270 // Hide or uninstall the primary package
1271 mTestSystemImpl.setPackageInfo(createPackageInfo(uninstalledPackage, true /* enabled */,
1272 true /* valid */, (testUninstalled ? false : true) /* installed */,
1273 null /* signatures */, 0 /* updateTime */, (testHidden ? true : false)));
1274 }
Gustav Sennton0df2c552016-06-14 15:32:19 +01001275
Gustav Sennton86f7bbe2016-10-24 16:49:32 +01001276 runWebViewBootPreparationOnMainSync();
Gustav Sennton0df2c552016-06-14 15:32:19 +01001277
1278 checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */);
1279 }
1280
Gustav Sennton86f7bbe2016-10-24 16:49:32 +01001281 @Test
Gustav Sennton0df2c552016-06-14 15:32:19 +01001282 public void testCantSwitchToHiddenPackage () {
1283 checkCantSwitchToNonVisiblePackage(false /* true == uninstalled, false == hidden */);
1284 }
1285
1286
Gustav Sennton86f7bbe2016-10-24 16:49:32 +01001287 @Test
Gustav Sennton0df2c552016-06-14 15:32:19 +01001288 public void testCantSwitchToUninstalledPackage () {
1289 checkCantSwitchToNonVisiblePackage(true /* true == uninstalled, false == hidden */);
1290 }
1291
1292 /**
Gustav Sennton364e1602016-12-14 09:10:50 +00001293 * Ensure that we won't prioritize an uninstalled (or hidden) package even if it is user-chosen.
Gustav Sennton0df2c552016-06-14 15:32:19 +01001294 */
1295 private void checkCantSwitchToNonVisiblePackage(boolean uninstalledNotHidden) {
1296 boolean testUninstalled = uninstalledNotHidden;
1297 boolean testHidden = !uninstalledNotHidden;
1298 String installedPackage = "installedPackage";
1299 String uninstalledPackage = "uninstalledPackage";
1300 WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] {
1301 new WebViewProviderInfo(uninstalledPackage, "", true /* available by default */,
1302 false /* fallback */, null),
1303 new WebViewProviderInfo(installedPackage, "", true /* available by default */,
1304 false /* fallback */, null)};
1305
1306 setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */);
Gustav Sennton364e1602016-12-14 09:10:50 +00001307 int secondaryUserId = 412;
1308 mTestSystemImpl.addUser(secondaryUserId);
1309
1310 // Let all packages be installed and enabled for the primary user.
1311 setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, webviewPackages);
1312 // Only uninstall the 'uninstalled package' for the secondary user.
1313 mTestSystemImpl.setPackageInfoForUser(secondaryUserId, createPackageInfo(installedPackage,
1314 true /* enabled */, true /* valid */, true /* installed */));
1315 mTestSystemImpl.setPackageInfoForUser(secondaryUserId, createPackageInfo(uninstalledPackage,
1316 true /* enabled */, true /* valid */, !testUninstalled /* installed */,
1317 null /* signatures */, 0 /* updateTime */, testHidden /* hidden */));
Gustav Sennton0df2c552016-06-14 15:32:19 +01001318
Gustav Sennton86f7bbe2016-10-24 16:49:32 +01001319 runWebViewBootPreparationOnMainSync();
Gustav Sennton0df2c552016-06-14 15:32:19 +01001320
1321 checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */);
1322
Gustav Sennton0df2c552016-06-14 15:32:19 +01001323 // ensure that we don't switch to the uninstalled package (it will be used if it becomes
1324 // installed later)
1325 assertEquals(installedPackage,
1326 mWebViewUpdateServiceImpl.changeProviderAndSetting(uninstalledPackage));
1327
Gustav Sennton364e1602016-12-14 09:10:50 +00001328 // Ensure both packages are considered valid.
1329 assertEquals(2, mWebViewUpdateServiceImpl.getValidWebViewPackages().length);
1330
1331
Gustav Sennton0df2c552016-06-14 15:32:19 +01001332 // We should only have called onWebViewProviderChanged once (before calling
1333 // changeProviderAndSetting
1334 Mockito.verify(mTestSystemImpl, Mockito.times(1)).onWebViewProviderChanged(
1335 Mockito.argThat(new IsPackageInfoWithName(installedPackage)));
1336 }
1337
Gustav Sennton86f7bbe2016-10-24 16:49:32 +01001338 @Test
Gustav Sennton0df2c552016-06-14 15:32:19 +01001339 public void testHiddenPackageNotPrioritizedEvenIfChosen() {
1340 checkNonvisiblePackageNotPrioritizedEvenIfChosen(
1341 false /* true == uninstalled, false == hidden */);
1342 }
1343
Gustav Sennton86f7bbe2016-10-24 16:49:32 +01001344 @Test
Gustav Sennton0df2c552016-06-14 15:32:19 +01001345 public void testUninstalledPackageNotPrioritizedEvenIfChosen() {
1346 checkNonvisiblePackageNotPrioritizedEvenIfChosen(
1347 true /* true == uninstalled, false == hidden */);
1348 }
1349
1350 public void checkNonvisiblePackageNotPrioritizedEvenIfChosen(boolean uninstalledNotHidden) {
1351 boolean testUninstalled = uninstalledNotHidden;
1352 boolean testHidden = !uninstalledNotHidden;
1353 String installedPackage = "installedPackage";
1354 String uninstalledPackage = "uninstalledPackage";
1355 WebViewProviderInfo[] webviewPackages = new WebViewProviderInfo[] {
1356 new WebViewProviderInfo(uninstalledPackage, "", true /* available by default */,
1357 false /* fallback */, null),
1358 new WebViewProviderInfo(installedPackage, "", true /* available by default */,
1359 false /* fallback */, null)};
1360
1361 setupWithPackages(webviewPackages, true /* fallback logic enabled */, 1 /* numRelros */);
Gustav Sennton364e1602016-12-14 09:10:50 +00001362 int secondaryUserId = 4;
1363 mTestSystemImpl.addUser(secondaryUserId);
1364
1365 setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, webviewPackages);
1366 mTestSystemImpl.setPackageInfoForUser(secondaryUserId, createPackageInfo(installedPackage,
1367 true /* enabled */, true /* valid */, true /* installed */));
1368 mTestSystemImpl.setPackageInfoForUser(secondaryUserId, createPackageInfo(uninstalledPackage,
1369 true /* enabled */, true /* valid */,
1370 (testUninstalled ? false : true) /* installed */, null /* signatures */,
1371 0 /* updateTime */, (testHidden ? true : false) /* hidden */));
Gustav Sennton0df2c552016-06-14 15:32:19 +01001372
1373 // Start with the setting pointing to the uninstalled package
1374 mTestSystemImpl.updateUserSetting(null, uninstalledPackage);
1375
Gustav Sennton86f7bbe2016-10-24 16:49:32 +01001376 runWebViewBootPreparationOnMainSync();
Gustav Sennton0df2c552016-06-14 15:32:19 +01001377
1378 checkPreparationPhasesForPackage(installedPackage, 1 /* first preparation phase */);
1379 }
1380
Gustav Sennton364e1602016-12-14 09:10:50 +00001381 @Test
1382 public void testFallbackEnabledIfPrimaryUninstalledSingleUser() {
1383 checkFallbackEnabledIfPrimaryUninstalled(false /* multiUser */);
1384 }
1385
1386 @Test
1387 public void testFallbackEnabledIfPrimaryUninstalledMultiUser() {
1388 checkFallbackEnabledIfPrimaryUninstalled(true /* multiUser */);
1389 }
1390
Gustav Sennton0df2c552016-06-14 15:32:19 +01001391 /**
Gustav Sennton364e1602016-12-14 09:10:50 +00001392 * Ensures that fallback becomes enabled at boot if the primary package is uninstalled for some
Gustav Sennton0df2c552016-06-14 15:32:19 +01001393 * user.
1394 */
Gustav Sennton364e1602016-12-14 09:10:50 +00001395 private void checkFallbackEnabledIfPrimaryUninstalled(boolean multiUser) {
Gustav Sennton0df2c552016-06-14 15:32:19 +01001396 String primaryPackage = "primary";
1397 String fallbackPackage = "fallback";
1398 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
1399 new WebViewProviderInfo(
1400 primaryPackage, "", true /* default available */, false /* fallback */, null),
1401 new WebViewProviderInfo(
1402 fallbackPackage, "", true /* default available */, true /* fallback */, null)};
1403 setupWithPackages(packages, true /* fallback logic enabled */);
Gustav Sennton364e1602016-12-14 09:10:50 +00001404 int secondaryUserId = 5;
1405 if (multiUser) {
1406 mTestSystemImpl.addUser(secondaryUserId);
1407 // Install all packages for the primary user.
1408 setEnabledAndValidPackageInfosForUser(TestSystemImpl.PRIMARY_USER_ID, packages);
1409 // Only install fallback package for secondary user.
1410 mTestSystemImpl.setPackageInfoForUser(secondaryUserId,
1411 createPackageInfo(primaryPackage, true /* enabled */,
1412 true /* valid */, false /* installed */));
1413 mTestSystemImpl.setPackageInfoForUser(secondaryUserId,
1414 createPackageInfo(fallbackPackage, false /* enabled */,
1415 true /* valid */, true /* installed */));
1416 } else {
1417 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +01001418 true /* valid */, false /* installed */));
Gustav Sennton364e1602016-12-14 09:10:50 +00001419 mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, false /* enabled */,
Gustav Sennton0df2c552016-06-14 15:32:19 +01001420 true /* valid */, true /* installed */));
Gustav Sennton364e1602016-12-14 09:10:50 +00001421 }
Gustav Sennton0df2c552016-06-14 15:32:19 +01001422
Gustav Sennton86f7bbe2016-10-24 16:49:32 +01001423 runWebViewBootPreparationOnMainSync();
Gustav Sennton0df2c552016-06-14 15:32:19 +01001424 // Verify that we enable the fallback package
1425 Mockito.verify(mTestSystemImpl).enablePackageForAllUsers(
1426 Mockito.anyObject(), Mockito.eq(fallbackPackage), Mockito.eq(true) /* enable */);
1427
1428 checkPreparationPhasesForPackage(fallbackPackage, 1 /* first preparation phase */);
1429 }
1430
Gustav Sennton86f7bbe2016-10-24 16:49:32 +01001431 @Test
Gustav Sennton0df2c552016-06-14 15:32:19 +01001432 public void testPreparationRunsIffNewPackage() {
1433 String primaryPackage = "primary";
1434 String fallbackPackage = "fallback";
1435 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
1436 new WebViewProviderInfo(
1437 primaryPackage, "", true /* default available */, false /* fallback */, null),
1438 new WebViewProviderInfo(
1439 fallbackPackage, "", true /* default available */, true /* fallback */, null)};
1440 setupWithPackages(packages, true /* fallback logic enabled */);
1441 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
1442 true /* valid */, true /* installed */, null /* signatures */,
1443 10 /* lastUpdateTime*/ ));
1444 mTestSystemImpl.setPackageInfo(createPackageInfo(fallbackPackage, true /* enabled */,
1445 true /* valid */, true /* installed */));
1446
Gustav Sennton86f7bbe2016-10-24 16:49:32 +01001447 runWebViewBootPreparationOnMainSync();
Gustav Sennton0df2c552016-06-14 15:32:19 +01001448
1449 checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation phase */);
1450 Mockito.verify(mTestSystemImpl, Mockito.times(1)).enablePackageForUser(
1451 Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */,
1452 Matchers.anyInt() /* user */);
1453
1454
1455 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
1456 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0 /* userId */);
1457 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
1458 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 1 /* userId */);
1459 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
1460 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 2 /* userId */);
1461 // package still has the same update-time so we shouldn't run preparation here
1462 Mockito.verify(mTestSystemImpl, Mockito.times(1)).onWebViewProviderChanged(
1463 Mockito.argThat(new IsPackageInfoWithName(primaryPackage)));
1464 Mockito.verify(mTestSystemImpl, Mockito.times(1)).enablePackageForUser(
1465 Mockito.eq(fallbackPackage), Mockito.eq(false) /* enable */,
1466 Matchers.anyInt() /* user */);
1467
1468 // Ensure we can still load the package
1469 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
1470 assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status);
1471 assertEquals(primaryPackage, response.packageInfo.packageName);
1472
1473
1474 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
1475 true /* valid */, true /* installed */, null /* signatures */,
1476 20 /* lastUpdateTime*/ ));
1477 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
1478 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 0);
1479 // The package has now changed - ensure that we have run the preparation phase a second time
1480 checkPreparationPhasesForPackage(primaryPackage, 2 /* second preparation phase */);
1481
1482
1483 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
1484 true /* valid */, true /* installed */, null /* signatures */,
1485 50 /* lastUpdateTime*/ ));
1486 // Receive intent for different user
1487 mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage,
1488 WebViewUpdateService.PACKAGE_ADDED_REPLACED, 2);
1489
1490 checkPreparationPhasesForPackage(primaryPackage, 3 /* third preparation phase */);
1491 }
Gustav Senntonbf683e02016-09-15 14:42:50 +01001492
Torne (Richard Coles)ab5d0ba2016-11-03 15:09:34 +00001493 @Test
Gustav Senntonbf683e02016-09-15 14:42:50 +01001494 public void testGetCurrentWebViewPackage() {
1495 PackageInfo firstPackage = createPackageInfo("first", true /* enabled */,
1496 true /* valid */, true /* installed */);
Dianne Hackborn891b74c2017-12-11 16:54:27 -08001497 firstPackage.setLongVersionCode(100);
Gustav Senntonbf683e02016-09-15 14:42:50 +01001498 firstPackage.versionName = "first package version";
1499 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
1500 new WebViewProviderInfo(firstPackage.packageName, "", true, false, null)};
1501 setupWithPackages(packages, true);
1502 mTestSystemImpl.setPackageInfo(firstPackage);
1503
Torne (Richard Coles)ab5d0ba2016-11-03 15:09:34 +00001504 runWebViewBootPreparationOnMainSync();
Gustav Senntonbf683e02016-09-15 14:42:50 +01001505
1506 Mockito.verify(mTestSystemImpl).onWebViewProviderChanged(
1507 Mockito.argThat(new IsPackageInfoWithName(firstPackage.packageName)));
1508
1509 mWebViewUpdateServiceImpl.notifyRelroCreationCompleted();
1510
1511 // Ensure the API is correct before running waitForAndGetProvider
1512 assertEquals(firstPackage.packageName,
1513 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().packageName);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001514 assertEquals(firstPackage.getLongVersionCode(),
1515 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().getLongVersionCode());
Gustav Senntonbf683e02016-09-15 14:42:50 +01001516 assertEquals(firstPackage.versionName,
1517 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().versionName);
1518
1519 WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider();
1520 assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status);
1521 assertEquals(firstPackage.packageName, response.packageInfo.packageName);
1522
1523 // Ensure the API is still correct after running waitForAndGetProvider
1524 assertEquals(firstPackage.packageName,
1525 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().packageName);
Dianne Hackborn3accca02013-09-20 09:32:11 -07001526 assertEquals(firstPackage.getLongVersionCode(),
1527 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().getLongVersionCode());
Gustav Senntonbf683e02016-09-15 14:42:50 +01001528 assertEquals(firstPackage.versionName,
1529 mWebViewUpdateServiceImpl.getCurrentWebViewPackage().versionName);
1530 }
Torne (Richard Coles)dc375072017-01-11 15:48:13 +00001531
1532 @Test
1533 public void testMultiProcessEnabledByDefault() {
Gustav Senntonb2650162017-04-07 14:41:38 +01001534 testMultiProcessByDefault(true /* enabledByDefault */);
Torne (Richard Coles)dc375072017-01-11 15:48:13 +00001535 }
1536
1537 @Test
1538 public void testMultiProcessDisabledByDefault() {
Gustav Senntonb2650162017-04-07 14:41:38 +01001539 testMultiProcessByDefault(false /* enabledByDefault */);
1540 }
1541
1542 private void testMultiProcessByDefault(boolean enabledByDefault) {
Torne (Richard Coles)dc375072017-01-11 15:48:13 +00001543 String primaryPackage = "primary";
1544 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
1545 new WebViewProviderInfo(
1546 primaryPackage, "", true /* default available */, false /* fallback */, null)};
1547 setupWithPackages(packages, true /* fallback logic enabled */, 1 /* numRelros */,
Gustav Senntonb2650162017-04-07 14:41:38 +01001548 true /* debuggable */,
1549 enabledByDefault /* not multiprocess by default */);
Torne (Richard Coles)dc375072017-01-11 15:48:13 +00001550 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
1551 true /* valid */, true /* installed */, null /* signatures */,
1552 10 /* lastUpdateTime*/, false /* not hidden */, 1000 /* versionCode */,
1553 false /* isSystemApp */));
1554
1555 runWebViewBootPreparationOnMainSync();
1556 checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation phase */);
1557
1558 // Check it's off by default
Gustav Senntonb2650162017-04-07 14:41:38 +01001559 assertEquals(enabledByDefault, mWebViewUpdateServiceImpl.isMultiProcessEnabled());
Torne (Richard Coles)dc375072017-01-11 15:48:13 +00001560
1561 // Test toggling it
Gustav Senntonb2650162017-04-07 14:41:38 +01001562 mWebViewUpdateServiceImpl.enableMultiProcess(!enabledByDefault);
1563 assertEquals(!enabledByDefault, mWebViewUpdateServiceImpl.isMultiProcessEnabled());
1564 mWebViewUpdateServiceImpl.enableMultiProcess(enabledByDefault);
1565 assertEquals(enabledByDefault, mWebViewUpdateServiceImpl.isMultiProcessEnabled());
Torne (Richard Coles)dc375072017-01-11 15:48:13 +00001566 }
Gustav Sennton564c2fd2017-01-30 18:08:01 +00001567
Gustav Senntonb2650162017-04-07 14:41:38 +01001568 @Test
1569 public void testMultiProcessEnabledByDefaultWithSettingsValue() {
1570 testMultiProcessByDefaultWithSettingsValue(
1571 true /* enabledByDefault */, Integer.MIN_VALUE, false /* expectEnabled */);
1572 testMultiProcessByDefaultWithSettingsValue(
1573 true /* enabledByDefault */, -999999, true /* expectEnabled */);
1574 testMultiProcessByDefaultWithSettingsValue(
1575 true /* enabledByDefault */, 0, true /* expectEnabled */);
1576 testMultiProcessByDefaultWithSettingsValue(
1577 true /* enabledByDefault */, 999999, true /* expectEnabled */);
1578 }
1579
1580 @Test
1581 public void testMultiProcessDisabledByDefaultWithSettingsValue() {
1582 testMultiProcessByDefaultWithSettingsValue(
1583 false /* enabledByDefault */, Integer.MIN_VALUE, false /* expectEnabled */);
1584 testMultiProcessByDefaultWithSettingsValue(
1585 false /* enabledByDefault */, 0, false /* expectEnabled */);
1586 testMultiProcessByDefaultWithSettingsValue(
1587 false /* enabledByDefault */, 999999, false /* expectEnabled */);
1588 testMultiProcessByDefaultWithSettingsValue(
1589 false /* enabledByDefault */, Integer.MAX_VALUE, true /* expectEnabled */);
1590 }
1591
1592 /**
1593 * Test the logic of the multiprocess setting depending on whether multiprocess is enabled by
1594 * default, and what the setting is set to.
1595 * @param enabledByDefault whether multiprocess is enabled by default.
1596 * @param settingValue value of the multiprocess setting.
1597 */
1598 private void testMultiProcessByDefaultWithSettingsValue(
1599 boolean enabledByDefault, int settingValue, boolean expectEnabled) {
1600 String primaryPackage = "primary";
1601 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
1602 new WebViewProviderInfo(
1603 primaryPackage, "", true /* default available */, false /* fallback */, null)};
1604 setupWithPackages(packages, true /* fallback logic enabled */, 1 /* numRelros */,
1605 true /* debuggable */, enabledByDefault /* multiprocess by default */);
1606 mTestSystemImpl.setPackageInfo(createPackageInfo(primaryPackage, true /* enabled */,
1607 true /* valid */, true /* installed */, null /* signatures */,
1608 10 /* lastUpdateTime*/, false /* not hidden */, 1000 /* versionCode */,
1609 false /* isSystemApp */));
1610
1611 runWebViewBootPreparationOnMainSync();
1612 checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation phase */);
1613
1614 mTestSystemImpl.setMultiProcessSetting(null /* context */, settingValue);
1615
1616 assertEquals(expectEnabled, mWebViewUpdateServiceImpl.isMultiProcessEnabled());
1617 }
1618
1619
Gustav Sennton564c2fd2017-01-30 18:08:01 +00001620 /**
1621 * Ensure that packages with a targetSdkVersion targeting the current platform are valid, and
1622 * that packages targeting an older version are not valid.
1623 */
1624 @Test
1625 public void testTargetSdkVersionValidity() {
1626 PackageInfo newSdkPackage = createPackageInfo("newTargetSdkPackage",
1627 true /* enabled */, true /* valid */, true /* installed */);
1628 newSdkPackage.applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
1629 PackageInfo currentSdkPackage = createPackageInfo("currentTargetSdkPackage",
1630 true /* enabled */, true /* valid */, true /* installed */);
Gustav Senntone5468f72017-11-20 19:42:43 +00001631 currentSdkPackage.applicationInfo.targetSdkVersion = UserPackage.MINIMUM_SUPPORTED_SDK;
Gustav Sennton564c2fd2017-01-30 18:08:01 +00001632 PackageInfo oldSdkPackage = createPackageInfo("oldTargetSdkPackage",
1633 true /* enabled */, true /* valid */, true /* installed */);
Gustav Senntone5468f72017-11-20 19:42:43 +00001634 oldSdkPackage.applicationInfo.targetSdkVersion = UserPackage.MINIMUM_SUPPORTED_SDK - 1;
Gustav Sennton564c2fd2017-01-30 18:08:01 +00001635
1636 WebViewProviderInfo newSdkProviderInfo =
1637 new WebViewProviderInfo(newSdkPackage.packageName, "", true, false, null);
1638 WebViewProviderInfo currentSdkProviderInfo =
1639 new WebViewProviderInfo(currentSdkPackage.packageName, "", true, false, null);
1640 WebViewProviderInfo[] packages = new WebViewProviderInfo[] {
1641 new WebViewProviderInfo(oldSdkPackage.packageName, "", true, false, null),
1642 currentSdkProviderInfo, newSdkProviderInfo};
1643 setupWithPackages(packages, true);
1644;
1645 mTestSystemImpl.setPackageInfo(newSdkPackage);
1646 mTestSystemImpl.setPackageInfo(currentSdkPackage);
1647 mTestSystemImpl.setPackageInfo(oldSdkPackage);
1648
1649 assertArrayEquals(new WebViewProviderInfo[]{currentSdkProviderInfo, newSdkProviderInfo},
1650 mWebViewUpdateServiceImpl.getValidWebViewPackages());
1651
1652 runWebViewBootPreparationOnMainSync();
1653
1654 checkPreparationPhasesForPackage(currentSdkPackage.packageName,
1655 1 /* first preparation phase */);
1656 }
Gustav Sennton53b78242016-04-07 15:56:10 +01001657}