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

Commit 1a4c4e35 authored by Torne (Richard Coles)'s avatar Torne (Richard Coles)
Browse files

Handle multiprocess flag in WebView update service.

Instead of letting DevelopmentSettings manage the setting directly and
observing the changes from WebViewUpdateService, have the update service
manage the setting and just expose IPCs for the settings app to use to
get/set the setting. This means we can set a more flexible policy for
whether multiprocess is enabled by default and change it without
touching the settings code, though for now this CL does not change the
behaviour and is just a refactoring.

Bug: 21643067
Test: Toggle multiprocess WebView in developer settings
Change-Id: I3057c09d99f5f6f472a5195a8e14e9164ea5733a
parent 82e955fc
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -78,4 +78,14 @@ interface IWebViewUpdateService {
     * Enable or disable the WebView package fallback mechanism.
     */
    void enableFallbackLogic(boolean enable);

    /**
     * Used by Settings to determine whether multiprocess is enabled.
     */
    boolean isMultiProcessEnabled();

    /**
     * Used by Settings to enable/disable multiprocess.
     */
    void enableMultiProcess(boolean enable);
}
+11 −12
Original line number Diff line number Diff line
@@ -271,21 +271,20 @@ public class SystemImpl implements SystemInterface {
    }

    @Override
    public void setMultiProcessEnabledFromContext(Context context) {
        boolean enableMultiProcess = false;
        try {
            enableMultiProcess = Settings.Global.getInt(context.getContentResolver(),
                    Settings.Global.WEBVIEW_MULTIPROCESS) == 1;
        } catch (Settings.SettingNotFoundException ex) {
    public int getMultiProcessSetting(Context context) {
        return Settings.Global.getInt(context.getContentResolver(),
                                      Settings.Global.WEBVIEW_MULTIPROCESS, 0);
    }
        WebViewZygote.setMultiprocessEnabled(enableMultiProcess);

    @Override
    public void setMultiProcessSetting(Context context, int value) {
        Settings.Global.putInt(context.getContentResolver(),
                               Settings.Global.WEBVIEW_MULTIPROCESS, value);
    }

    @Override
    public void registerContentObserver(Context context, ContentObserver contentObserver) {
        context.getContentResolver().registerContentObserver(
                Settings.Global.getUriFor(Settings.Global.WEBVIEW_MULTIPROCESS),
                false, contentObserver);
    public void notifyZygote(boolean enableMultiProcess) {
        WebViewZygote.setMultiprocessEnabled(enableMultiProcess);
    }

    // flags declaring we want extra info from the package manager for webview providers
+3 −2
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ public interface SystemInterface {
    public PackageInfo getPackageInfoForProvider(WebViewProviderInfo configInfo)
            throws NameNotFoundException;

    public void setMultiProcessEnabledFromContext(Context context);
    public void registerContentObserver(Context context, ContentObserver contentObserver);
    public int getMultiProcessSetting(Context context);
    public void setMultiProcessSetting(Context context, int value);
    public void notifyZygote(boolean enableMultiProcess);
}
+26 −0
Original line number Diff line number Diff line
@@ -261,6 +261,32 @@ public class WebViewUpdateService extends SystemService {
            }
        }

        @Override // Binder call
        public boolean isMultiProcessEnabled() {
            return WebViewUpdateService.this.mImpl.isMultiProcessEnabled();
        }

        @Override // Binder call
        public void enableMultiProcess(boolean enable) {
            if (getContext().checkCallingPermission(
                        android.Manifest.permission.WRITE_SECURE_SETTINGS)
                    != PackageManager.PERMISSION_GRANTED) {
                String msg = "Permission Denial: enableMultiProcess() from pid="
                        + Binder.getCallingPid()
                        + ", uid=" + Binder.getCallingUid()
                        + " requires " + android.Manifest.permission.WRITE_SECURE_SETTINGS;
                Slog.w(TAG, msg);
                throw new SecurityException(msg);
            }

            long callingId = Binder.clearCallingIdentity();
            try {
                WebViewUpdateService.this.mImpl.enableMultiProcess(enable);
            } finally {
                Binder.restoreCallingIdentity(callingId);
            }
        }

        @Override
        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+14 −32
Original line number Diff line number Diff line
@@ -20,8 +20,6 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
import android.util.Base64;
@@ -77,7 +75,6 @@ public class WebViewUpdateServiceImpl {

    private SystemInterface mSystemInterface;
    private WebViewUpdater mWebViewUpdater;
    private SettingsObserver mSettingsObserver;
    final private Context mContext;

    public WebViewUpdateServiceImpl(Context context, SystemInterface systemInterface) {
@@ -97,10 +94,7 @@ public class WebViewUpdateServiceImpl {
    void prepareWebViewInSystemServer() {
        updateFallbackStateOnBoot();
        mWebViewUpdater.prepareWebViewInSystemServer();

        // Register for changes in the multiprocess developer option. This has to be done
        // here, since the update service gets created before the ContentResolver service.
        mSettingsObserver = new SettingsObserver();
        mSystemInterface.notifyZygote(isMultiProcessEnabled());
    }

    private boolean existsValidNonFallbackProvider(WebViewProviderInfo[] providers) {
@@ -247,6 +241,19 @@ public class WebViewUpdateServiceImpl {
                && packageName.equals(fallbackProvider.packageName));
    }

    boolean isMultiProcessEnabled() {
        return mSystemInterface.getMultiProcessSetting(mContext) != 0;
    }

    void enableMultiProcess(boolean enable) {
        PackageInfo current = getCurrentWebViewPackage();
        mSystemInterface.setMultiProcessSetting(mContext, enable ? 1 : 0);
        mSystemInterface.notifyZygote(enable);
        if (current != null) {
            mSystemInterface.killPackageDependents(current.packageName);
        }
    }

    /**
     * Class that decides what WebView implementation to use and prepares that implementation for
     * use.
@@ -739,31 +746,6 @@ public class WebViewUpdateServiceImpl {
                        & ApplicationInfo.PRIVATE_FLAG_HIDDEN) == 0));
    }

    /**
     * Watches for changes in the WEBVIEW_MULTIPROCESS setting and lets
     * the WebViewZygote know, so it can start or stop the zygote process
     * appropriately.
     */
    private class SettingsObserver extends ContentObserver {
        SettingsObserver() {
            super(new Handler());

            mSystemInterface.registerContentObserver(mContext, this);

            // Push the current value of the setting immediately.
            notifyZygote();
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            notifyZygote();
        }

        private void notifyZygote() {
            mSystemInterface.setMultiProcessEnabledFromContext(mContext);
        }
    }

    /**
     * Dump the state of this Service.
     */
Loading