diff options
| -rw-r--r-- | services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java | 15 | ||||
| -rw-r--r-- | services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java | 137 |
2 files changed, 103 insertions, 49 deletions
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java index e17ea49bc3a3..8c01c4cf76a1 100644 --- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java +++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java @@ -291,6 +291,13 @@ public class WebViewUpdateServiceImpl { try { synchronized(mLock) { mCurrentWebViewPackage = findPreferredWebViewPackage(); + // Don't persist the user-chosen setting across boots if the package being + // chosen is not used (could be disabled or uninstalled) so that the user won't + // be surprised by the device switching to using a certain webview package, + // that was uninstalled/disabled a long time ago, if it is installed/enabled + // again. + mSystemInterface.updateUserSetting(mContext, + mCurrentWebViewPackage.packageName); onWebViewProviderChanged(mCurrentWebViewPackage); } } catch (Throwable t) { @@ -345,7 +352,6 @@ public class WebViewUpdateServiceImpl { mAnyWebViewInstalled = true; if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) { mCurrentWebViewPackage = newPackage; - mSystemInterface.updateUserSetting(mContext, newPackage.packageName); // The relro creations might 'finish' (not start at all) before // WebViewFactory.onWebViewProviderChanged which means we might not know the @@ -432,9 +438,12 @@ public class WebViewUpdateServiceImpl { } } - // Could not find any enabled package either, use the most stable provider. + // Could not find any enabled package either, use the most stable and default-available + // provider. for (ProviderAndPackageInfo providerAndPackage : providers) { - return providerAndPackage.packageInfo; + if (providerAndPackage.provider.availableByDefault) { + return providerAndPackage.packageInfo; + } } mAnyWebViewInstalled = false; diff --git a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java index c00520dc3552..7d404c9d09ed 100644 --- a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java @@ -90,12 +90,13 @@ public class WebViewUpdateServiceTest extends AndroidTestCase { } } - private void checkCertainPackageUsedAfterWebViewPreparation(String expectedProviderName, + private void checkCertainPackageUsedAfterWebViewBootPreparation(String expectedProviderName, WebViewProviderInfo[] webviewPackages) { - checkCertainPackageUsedAfterWebViewPreparation(expectedProviderName, webviewPackages, 1); + checkCertainPackageUsedAfterWebViewBootPreparation( + expectedProviderName, webviewPackages, 1); } - private void checkCertainPackageUsedAfterWebViewPreparation(String expectedProviderName, + private void checkCertainPackageUsedAfterWebViewBootPreparation(String expectedProviderName, WebViewProviderInfo[] webviewPackages, int numRelros) { setupWithPackages(webviewPackages, true, numRelros); // Add (enabled and valid) package infos for each provider @@ -156,6 +157,19 @@ public class WebViewUpdateServiceTest extends AndroidTestCase { return p; } + private void checkPreparationPhasesForPackage(String expectedPackage, int numPreparation) { + // Verify that onWebViewProviderChanged was called for the numPreparation'th time for the + // expected package + Mockito.verify(mTestSystemImpl, Mockito.times(numPreparation)).onWebViewProviderChanged( + Mockito.argThat(new IsPackageInfoWithName(expectedPackage))); + + mWebViewUpdateServiceImpl.notifyRelroCreationCompleted(); + + WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); + assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status); + assertEquals(expectedPackage, response.packageInfo.packageName); + } + // **************** // Tests @@ -164,7 +178,7 @@ public class WebViewUpdateServiceTest extends AndroidTestCase { public void testWithSinglePackage() { String testPackageName = "test.package.name"; - checkCertainPackageUsedAfterWebViewPreparation(testPackageName, + checkCertainPackageUsedAfterWebViewBootPreparation(testPackageName, new WebViewProviderInfo[] { new WebViewProviderInfo(testPackageName, "", true /*default available*/, false /* fallback */, null)}); @@ -176,12 +190,12 @@ public class WebViewUpdateServiceTest extends AndroidTestCase { WebViewProviderInfo[] packages = new WebViewProviderInfo[] { new WebViewProviderInfo(nonDefaultPackage, "", false, false, null), new WebViewProviderInfo(defaultPackage, "", true, false, null)}; - checkCertainPackageUsedAfterWebViewPreparation(defaultPackage, packages); + checkCertainPackageUsedAfterWebViewBootPreparation(defaultPackage, packages); } public void testSeveralRelros() { String singlePackage = "singlePackage"; - checkCertainPackageUsedAfterWebViewPreparation( + checkCertainPackageUsedAfterWebViewBootPreparation( singlePackage, new WebViewProviderInfo[] { new WebViewProviderInfo(singlePackage, "", true /*def av*/, false, null)}, @@ -215,14 +229,8 @@ public class WebViewUpdateServiceTest extends AndroidTestCase { mWebViewUpdateServiceImpl.prepareWebViewInSystemServer(); - Mockito.verify(mTestSystemImpl).onWebViewProviderChanged( - Mockito.argThat(new IsPackageInfoWithName(validPackage))); - - mWebViewUpdateServiceImpl.notifyRelroCreationCompleted(); - WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); - assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status); - assertEquals(validPackage, response.packageInfo.packageName); + checkPreparationPhasesForPackage(validPackage, 1 /* first preparation for this package */); WebViewProviderInfo[] validPackages = mWebViewUpdateServiceImpl.getValidWebViewPackages(); assertEquals(1, validPackages.length); @@ -292,18 +300,10 @@ public class WebViewUpdateServiceTest extends AndroidTestCase { private void checkSwitchingProvider(WebViewProviderInfo[] packages, String initialPackage, String finalPackage) { - checkCertainPackageUsedAfterWebViewPreparation(initialPackage, packages); + checkCertainPackageUsedAfterWebViewBootPreparation(initialPackage, packages); mWebViewUpdateServiceImpl.changeProviderAndSetting(finalPackage); - - Mockito.verify(mTestSystemImpl).onWebViewProviderChanged( - Mockito.argThat(new IsPackageInfoWithName(finalPackage))); - - mWebViewUpdateServiceImpl.notifyRelroCreationCompleted(); - - WebViewProviderResponse secondResponse = mWebViewUpdateServiceImpl.waitForAndGetProvider(); - assertEquals(WebViewFactory.LIBLOAD_SUCCESS, secondResponse.status); - assertEquals(finalPackage, secondResponse.packageInfo.packageName); + checkPreparationPhasesForPackage(finalPackage, 1 /* first preparation for this package */); Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(initialPackage)); } @@ -455,14 +455,9 @@ public class WebViewUpdateServiceTest extends AndroidTestCase { mWebViewUpdateServiceImpl.prepareWebViewInSystemServer(); Mockito.verify(mTestSystemImpl, Mockito.never()).uninstallAndDisablePackageForAllUsers( Matchers.anyObject(), Matchers.anyObject()); - Mockito.verify(mTestSystemImpl).onWebViewProviderChanged( - Mockito.argThat(new IsPackageInfoWithName(fallbackPackage))); - - mWebViewUpdateServiceImpl.notifyRelroCreationCompleted(); - WebViewProviderResponse response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); - assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status); - assertEquals(fallbackPackage, response.packageInfo.packageName); + checkPreparationPhasesForPackage(fallbackPackage, + 1 /* first preparation for this package*/); // Install primary package mTestSystemImpl.setPackageInfo( @@ -470,17 +465,10 @@ public class WebViewUpdateServiceTest extends AndroidTestCase { mWebViewUpdateServiceImpl.packageStateChanged(primaryPackage, WebViewUpdateService.PACKAGE_ADDED); - // Verify fallback disabled and primary package used as provider + // Verify fallback disabled, primary package used as provider, and fallback package killed Mockito.verify(mTestSystemImpl).uninstallAndDisablePackageForAllUsers( Matchers.anyObject(), Mockito.eq(fallbackPackage)); - Mockito.verify(mTestSystemImpl).onWebViewProviderChanged( - Mockito.argThat(new IsPackageInfoWithName(primaryPackage))); - - // Finish the webview preparation and ensure primary package used and fallback killed - mWebViewUpdateServiceImpl.notifyRelroCreationCompleted(); - response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); - assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status); - assertEquals(primaryPackage, response.packageInfo.packageName); + checkPreparationPhasesForPackage(primaryPackage, 1 /* first preparation for this package*/); Mockito.verify(mTestSystemImpl).killPackageDependents(Mockito.eq(fallbackPackage)); } @@ -598,15 +586,72 @@ public class WebViewUpdateServiceTest extends AndroidTestCase { mWebViewUpdateServiceImpl.packageStateChanged(firstPackage, WebViewUpdateService.PACKAGE_ADDED); - // Second time we call onWebViewProviderChanged for firstPackage - Mockito.verify(mTestSystemImpl, Mockito.times(2)).onWebViewProviderChanged( - Mockito.argThat(new IsPackageInfoWithName(firstPackage))); + // Ensure we use firstPackage + checkPreparationPhasesForPackage(firstPackage, 2 /* second preparation for this package */); + } - mWebViewUpdateServiceImpl.notifyRelroCreationCompleted(); + /** + * Verify that even if a user-chosen package is removed temporarily we start using it again when + * it is added back. + */ + public void testTempRemovePackageDoesntSwitchProviderPermanently() { + String firstPackage = "first"; + String secondPackage = "second"; + WebViewProviderInfo[] packages = new WebViewProviderInfo[] { + new WebViewProviderInfo(firstPackage, "", true /* default available */, + false /* fallback */, null), + new WebViewProviderInfo(secondPackage, "", true /* default available */, + false /* fallback */, null)}; + checkCertainPackageUsedAfterWebViewBootPreparation(firstPackage, packages); - response = mWebViewUpdateServiceImpl.waitForAndGetProvider(); - assertEquals(WebViewFactory.LIBLOAD_SUCCESS, response.status); - assertEquals(firstPackage, response.packageInfo.packageName); + // Explicitly use the second package + mWebViewUpdateServiceImpl.changeProviderAndSetting(secondPackage); + checkPreparationPhasesForPackage(secondPackage, 1 /* first time for this package */); + + // Remove second package (invalidate it) and verify that first package is used + mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */, + false /* valid */)); + mWebViewUpdateServiceImpl.packageStateChanged(secondPackage, + WebViewUpdateService.PACKAGE_ADDED); + checkPreparationPhasesForPackage(firstPackage, 2 /* second time for this package */); + + // Now make the second package valid again and verify that it is used again + mTestSystemImpl.setPackageInfo(createPackageInfo(secondPackage, true /* enabled */, + true /* valid */)); + mWebViewUpdateServiceImpl.packageStateChanged(secondPackage, + WebViewUpdateService.PACKAGE_ADDED); + checkPreparationPhasesForPackage(secondPackage, 2 /* second time for this package */); + } + + /** + * Ensure that we update the user-chosen setting across boots if the chosen package is no + * longer installed and valid. + */ + public void testProviderSettingChangedDuringBootIfProviderNotAvailable() { + String chosenPackage = "chosenPackage"; + String nonChosenPackage = "non-chosenPackage"; + WebViewProviderInfo[] packages = new WebViewProviderInfo[] { + new WebViewProviderInfo(chosenPackage, "", true /* default available */, + false /* fallback */, null), + new WebViewProviderInfo(nonChosenPackage, "", true /* default available */, + false /* fallback */, null)}; + + setupWithPackages(packages); + // Only 'install' nonChosenPackage + mTestSystemImpl.setPackageInfo( + createPackageInfo(nonChosenPackage, true /* enabled */, true /* valid */)); + + // Set user-chosen package + mTestSystemImpl.updateUserSetting(null, chosenPackage); + + mWebViewUpdateServiceImpl.prepareWebViewInSystemServer(); + + // Verify that we switch the setting to point to the current package + Mockito.verify(mTestSystemImpl).updateUserSetting( + Mockito.anyObject(), Mockito.eq(nonChosenPackage)); + assertEquals(nonChosenPackage, mTestSystemImpl.getUserChosenWebViewProvider(null)); + + checkPreparationPhasesForPackage(nonChosenPackage, 1); } // TODO (gsennton) add more tests for ensuring killPackageDependents is called / not called |