Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4b0a3dc7 authored by Gustav Sennton's avatar Gustav Sennton Committed by The Android Automerger
Browse files

Support using uninstalled WebView packages as WebView implementation.

A package can be uninstalled for the system user but still be installed
on the device. Currently, we do not use such a package as WebView
implementation which means we fall back to using the fallback WebView
package.
However, if the fallback package is not valid (because it needs to be
updated first) loading WebView will fail.

With this change we fetch allow the fetching of information from
packages that are uninstalled for the system user so that we can still
load WebView when the only valid WebView provider is uninstalled for the
system user.

Also listen to package additions/changes/removals for all users -
otherwise we won't notice when a package becomes replaced if it was
already uninstalled for the system user.

Bug: 29321185
Change-Id: Ia23c4493844877aea1b4eab7e666fd37540c4f97
parent 1b226c85
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -270,5 +270,6 @@ public class SystemImpl implements SystemInterface {

    // flags declaring we want extra info from the package manager for webview providers
    private final static int PACKAGE_FLAGS = PackageManager.GET_META_DATA
            | PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
            | PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING
            | PackageManager.MATCH_UNINSTALLED_PACKAGES;
}
+9 −7
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ public class WebViewUpdateService extends SystemService {
        mWebViewUpdatedReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
                    switch (intent.getAction()) {
                        case Intent.ACTION_PACKAGE_REMOVED:
                            // When a package is replaced we will receive two intents, one
@@ -73,24 +74,22 @@ public class WebViewUpdateService extends SystemService {
                            // run the update-logic twice.
                            if (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) return;
                            mImpl.packageStateChanged(packageNameFromIntent(intent),
                                    PACKAGE_REMOVED);
                                    PACKAGE_REMOVED, userId);
                            break;
                        case Intent.ACTION_PACKAGE_CHANGED:
                            // Ensure that we only heed PACKAGE_CHANGED intents if they change an
                            // entire package, not just a component
                            if (entirePackageChanged(intent)) {
                                mImpl.packageStateChanged(packageNameFromIntent(intent),
                                        PACKAGE_CHANGED);
                                        PACKAGE_CHANGED, userId);
                            }
                            break;
                        case Intent.ACTION_PACKAGE_ADDED:
                            mImpl.packageStateChanged(packageNameFromIntent(intent),
                                    (intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)
                                     ? PACKAGE_ADDED_REPLACED : PACKAGE_ADDED));
                                     ? PACKAGE_ADDED_REPLACED : PACKAGE_ADDED), userId);
                            break;
                        case Intent.ACTION_USER_ADDED:
                            int userId =
                                intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
                            mImpl.handleNewUser(userId);
                            break;
                    }
@@ -105,11 +104,14 @@ public class WebViewUpdateService extends SystemService {
        for (WebViewProviderInfo provider : mImpl.getWebViewPackages()) {
            filter.addDataSchemeSpecificPart(provider.packageName, PatternMatcher.PATTERN_LITERAL);
        }
        getContext().registerReceiver(mWebViewUpdatedReceiver, filter);

        getContext().registerReceiverAsUser(mWebViewUpdatedReceiver, UserHandle.ALL, filter,
                null /* broadcast permission */, null /* handler */);

        IntentFilter userAddedFilter = new IntentFilter();
        userAddedFilter.addAction(Intent.ACTION_USER_ADDED);
        getContext().registerReceiver(mWebViewUpdatedReceiver, userAddedFilter);
        getContext().registerReceiverAsUser(mWebViewUpdatedReceiver, UserHandle.ALL,
                userAddedFilter, null /* broadcast permission */, null /* handler */);

        publishBinderService("webviewupdate", new BinderService(), true /*allowIsolated*/);
    }
+36 −11
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.os.UserHandle;
import android.util.Base64;
import android.util.Slog;
import android.webkit.WebViewFactory;
@@ -49,7 +50,10 @@ public class WebViewUpdateServiceImpl {
        mWebViewUpdater = new WebViewUpdater(mContext, mSystemInterface);
    }

    void packageStateChanged(String packageName, int changedState) {
    void packageStateChanged(String packageName, int changedState, int userId) {
        // We don't early out here in different cases where we could potentially early-out (e.g. if
        // we receive PACKAGE_CHANGED for another user than the system user) since that would
        // complicate this logic further and open up for more edge cases.
        updateFallbackStateOnPackageChange(packageName, changedState);
        mWebViewUpdater.packageStateChanged(packageName, changedState);
    }
@@ -64,7 +68,7 @@ public class WebViewUpdateServiceImpl {
            if (provider.availableByDefault && !provider.isFallback) {
                try {
                    PackageInfo packageInfo = mSystemInterface.getPackageInfoForProvider(provider);
                    if (isEnabledPackage(packageInfo)
                    if (isInstalledPackage(packageInfo) && isEnabledPackage(packageInfo)
                            && mWebViewUpdater.isValidProvider(provider, packageInfo)) {
                        return true;
                    }
@@ -103,7 +107,7 @@ public class WebViewUpdateServiceImpl {
    }

    WebViewProviderInfo[] getValidWebViewPackages() {
        return mWebViewUpdater.getValidWebViewPackages();
        return mWebViewUpdater.getValidAndInstalledWebViewPackages();
    }

    WebViewProviderInfo[] getWebViewPackages() {
@@ -254,6 +258,12 @@ public class WebViewUpdateServiceImpl {
                                    // (not if it has been enabled/disabled).
                                    return;
                                }
                                if (newPackage.packageName.equals(oldProviderName)
                                        && (newPackage.lastUpdateTime
                                            == mCurrentWebViewPackage.lastUpdateTime)) {
                                    // If the chosen package hasn't been updated, then early-out
                                    return;
                                }
                            }
                            // Only trigger update actions if the updated package is the one
                            // that will be used, or the one that was in use before the
@@ -373,14 +383,15 @@ public class WebViewUpdateServiceImpl {
            }
        }

        private ProviderAndPackageInfo[] getValidWebViewPackagesAndInfos() {
        private ProviderAndPackageInfo[] getValidWebViewPackagesAndInfos(boolean onlyInstalled) {
            WebViewProviderInfo[] allProviders = mSystemInterface.getWebViewPackages();
            List<ProviderAndPackageInfo> providers = new ArrayList<>();
            for(int n = 0; n < allProviders.length; n++) {
                try {
                    PackageInfo packageInfo =
                        mSystemInterface.getPackageInfoForProvider(allProviders[n]);
                    if (isValidProvider(allProviders[n], packageInfo)) {
                    if ((!onlyInstalled || isInstalledPackage(packageInfo))
                            && isValidProvider(allProviders[n], packageInfo)) {
                        providers.add(new ProviderAndPackageInfo(allProviders[n], packageInfo));
                    }
                } catch (NameNotFoundException e) {
@@ -393,8 +404,9 @@ public class WebViewUpdateServiceImpl {
        /**
         * Fetch only the currently valid WebView packages.
         **/
        public WebViewProviderInfo[] getValidWebViewPackages() {
            ProviderAndPackageInfo[] providersAndPackageInfos = getValidWebViewPackagesAndInfos();
        public WebViewProviderInfo[] getValidAndInstalledWebViewPackages() {
            ProviderAndPackageInfo[] providersAndPackageInfos =
                getValidWebViewPackagesAndInfos(true /* only fetch installed packages */);
            WebViewProviderInfo[] providers =
                new WebViewProviderInfo[providersAndPackageInfos.length];
            for(int n = 0; n < providersAndPackageInfos.length; n++) {
@@ -421,29 +433,33 @@ public class WebViewUpdateServiceImpl {
         *
         */
        private PackageInfo findPreferredWebViewPackage() {
            ProviderAndPackageInfo[] providers = getValidWebViewPackagesAndInfos();
            ProviderAndPackageInfo[] providers =
                getValidWebViewPackagesAndInfos(false /* onlyInstalled */);

            String userChosenProvider = mSystemInterface.getUserChosenWebViewProvider(mContext);

            // If the user has chosen provider, use that
            for (ProviderAndPackageInfo providerAndPackage : providers) {
                if (providerAndPackage.provider.packageName.equals(userChosenProvider)
                        && isInstalledPackage(providerAndPackage.packageInfo)
                        && isEnabledPackage(providerAndPackage.packageInfo)) {
                    return providerAndPackage.packageInfo;
                }
            }

            // User did not choose, or the choice failed; use the most stable provider that is
            // enabled and available by default (not through user choice).
            // installed and enabled for the device owner, and available by default (not through
            // user choice).
            for (ProviderAndPackageInfo providerAndPackage : providers) {
                if (providerAndPackage.provider.availableByDefault
                        && isInstalledPackage(providerAndPackage.packageInfo)
                        && isEnabledPackage(providerAndPackage.packageInfo)) {
                    return providerAndPackage.packageInfo;
                }
            }

            // Could not find any enabled package either, use the most stable and default-available
            // provider.
            // Could not find any installed and enabled package either, use the most stable and
            // default-available provider.
            for (ProviderAndPackageInfo providerAndPackage : providers) {
                if (providerAndPackage.provider.availableByDefault) {
                    return providerAndPackage.packageInfo;
@@ -642,4 +658,13 @@ public class WebViewUpdateServiceImpl {
        return packageInfo.applicationInfo.enabled;
    }

    /**
     * Return true if the package is installed and not hidden
     */
    private static boolean isInstalledPackage(PackageInfo packageInfo) {
        return (((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0)
            && ((packageInfo.applicationInfo.privateFlags
                        & ApplicationInfo.PRIVATE_FLAG_HIDDEN) == 0));
    }

}
+295 −41

File changed.

Preview size limit exceeded, changes collapsed.