Commit b560a714 authored by Torne (Richard Coles)'s avatar Torne (Richard Coles) Committed by Commit Bot

weblayer: use the WebView zygote where possible.

When we're on O+ and loading from the WebView implementation, we can use
the WebView's declared sandboxed service processes instead of the
client's, which will cause them to be forked from the WebView zygote,
saving some startup time and memory.

Fixed: 1025602
Change-Id: I902cc7bd5685ebddfa4681d7d87bb45fc8330dbd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1974840
Commit-Queue: Richard Coles <torne@chromium.org>
Commit-Queue: Bo <boliu@chromium.org>
Reviewed-by: default avatarBo <boliu@chromium.org>
Reviewed-by: default avatarAndrew Grieve <agrieve@chromium.org>
Reviewed-by: default avatarClark DuVall <cduvall@chromium.org>
Auto-Submit: Richard Coles <torne@chromium.org>
Cr-Commit-Position: refs/heads/master@{#726563}
parent 0292ac42
...@@ -104,10 +104,10 @@ public final class AwBrowserProcess { ...@@ -104,10 +104,10 @@ public final class AwBrowserProcess {
final boolean isExternalService = true; final boolean isExternalService = true;
final boolean bindToCaller = true; final boolean bindToCaller = true;
final boolean ignoreVisibilityForImportance = true; final boolean ignoreVisibilityForImportance = true;
ChildProcessCreationParams.set(getWebViewPackageName(), isExternalService, ChildProcessCreationParams.set(getWebViewPackageName(), null /* privilegedServicesName */,
getWebViewPackageName(), null /* sandboxedServicesName */, isExternalService,
LibraryProcessType.PROCESS_WEBVIEW_CHILD, bindToCaller, LibraryProcessType.PROCESS_WEBVIEW_CHILD, bindToCaller,
ignoreVisibilityForImportance, null /* privilegedServicesName */, ignoreVisibilityForImportance);
null /* sandboxedServicesName */);
} }
/** /**
......
...@@ -39,9 +39,9 @@ public class MonochromeApplication extends ChromeApplication { ...@@ -39,9 +39,9 @@ public class MonochromeApplication extends ChromeApplication {
// and are external, and will fail to bind otherwise. // and are external, and will fail to bind otherwise.
boolean bindToCaller = false; boolean bindToCaller = false;
boolean ignoreVisibilityForImportance = false; boolean ignoreVisibilityForImportance = false;
ChildProcessCreationParams.set(getPackageName(), true /* isExternalService */, ChildProcessCreationParams.set(getPackageName(), null /* privilegedServicesName */,
LibraryProcessType.PROCESS_CHILD, bindToCaller, ignoreVisibilityForImportance, getPackageName(), null /* sandboxedServicesName */, true /* isExternalService */,
null /* privilegedServicesName */, null /* sandboxedServicesName */); LibraryProcessType.PROCESS_CHILD, bindToCaller, ignoreVisibilityForImportance);
} }
@Override @Override
......
...@@ -21,7 +21,8 @@ public class ChildProcessCreationParamsImpl { ...@@ -21,7 +21,8 @@ public class ChildProcessCreationParamsImpl {
"org.chromium.content.app.SandboxedProcessService"; "org.chromium.content.app.SandboxedProcessService";
// Members should all be immutable to avoid worrying about thread safety. // Members should all be immutable to avoid worrying about thread safety.
private static String sPackageNameForService; private static String sPackageNameForPrivilegedService;
private static String sPackageNameForSandboxedService;
private static boolean sIsSandboxedServiceExternal; private static boolean sIsSandboxedServiceExternal;
private static int sLibraryProcessType; private static int sLibraryProcessType;
private static boolean sBindToCallerCheck; private static boolean sBindToCallerCheck;
...@@ -36,20 +37,21 @@ public class ChildProcessCreationParamsImpl { ...@@ -36,20 +37,21 @@ public class ChildProcessCreationParamsImpl {
private ChildProcessCreationParamsImpl() {} private ChildProcessCreationParamsImpl() {}
/** Set params. This should be called once on start up. */ /** Set params. This should be called once on start up. */
public static void set(String packageNameForService, boolean isExternalSandboxedService, public static void set(String privilegedPackageName, String privilegedServicesName,
int libraryProcessType, boolean bindToCallerCheck, String sandboxedPackageName, String sandboxedServicesName,
boolean ignoreVisibilityForImportance, String privilegedServicesName, boolean isExternalSandboxedService, int libraryProcessType, boolean bindToCallerCheck,
String sandboxedServicesName) { boolean ignoreVisibilityForImportance) {
assert !sInitialized; assert !sInitialized;
sPackageNameForService = packageNameForService; sPackageNameForPrivilegedService = privilegedPackageName;
sIsSandboxedServiceExternal = isExternalSandboxedService;
sLibraryProcessType = libraryProcessType;
sBindToCallerCheck = bindToCallerCheck;
sIgnoreVisibilityForImportance = ignoreVisibilityForImportance;
sPrivilegedServicesName = sPrivilegedServicesName =
privilegedServicesName == null ? PRIVILEGED_SERVICES_NAME : privilegedServicesName; privilegedServicesName == null ? PRIVILEGED_SERVICES_NAME : privilegedServicesName;
sPackageNameForSandboxedService = sandboxedPackageName;
sSandboxedServicesName = sSandboxedServicesName =
sandboxedServicesName == null ? SANDBOXED_SERVICES_NAME : sandboxedServicesName; sandboxedServicesName == null ? SANDBOXED_SERVICES_NAME : sandboxedServicesName;
sIsSandboxedServiceExternal = isExternalSandboxedService;
sLibraryProcessType = libraryProcessType;
sBindToCallerCheck = bindToCallerCheck;
sIgnoreVisibilityForImportance = ignoreVisibilityForImportance;
sInitialized = true; sInitialized = true;
} }
...@@ -57,8 +59,13 @@ public class ChildProcessCreationParamsImpl { ...@@ -57,8 +59,13 @@ public class ChildProcessCreationParamsImpl {
if (sInitialized) extras.putInt(EXTRA_LIBRARY_PROCESS_TYPE, sLibraryProcessType); if (sInitialized) extras.putInt(EXTRA_LIBRARY_PROCESS_TYPE, sLibraryProcessType);
} }
public static String getPackageNameForService() { public static String getPackageNameForPrivilegedService() {
return sInitialized ? sPackageNameForService return sInitialized ? sPackageNameForPrivilegedService
: ContextUtils.getApplicationContext().getPackageName();
}
public static String getPackageNameForSandboxedService() {
return sInitialized ? sPackageNameForSandboxedService
: ContextUtils.getApplicationContext().getPackageName(); : ContextUtils.getApplicationContext().getPackageName();
} }
......
...@@ -350,23 +350,25 @@ public final class ChildProcessLauncherHelperImpl { ...@@ -350,23 +350,25 @@ public final class ChildProcessLauncherHelperImpl {
@VisibleForTesting @VisibleForTesting
static ChildConnectionAllocator getConnectionAllocator(Context context, boolean sandboxed) { static ChildConnectionAllocator getConnectionAllocator(Context context, boolean sandboxed) {
assert LauncherThread.runningOnLauncherThread(); assert LauncherThread.runningOnLauncherThread();
final String packageName = ChildProcessCreationParamsImpl.getPackageNameForService();
boolean bindToCaller = ChildProcessCreationParamsImpl.getBindToCallerCheck(); boolean bindToCaller = ChildProcessCreationParamsImpl.getBindToCallerCheck();
boolean bindAsExternalService = boolean bindAsExternalService =
sandboxed && ChildProcessCreationParamsImpl.getIsSandboxedServiceExternal(); sandboxed && ChildProcessCreationParamsImpl.getIsSandboxedServiceExternal();
if (!sandboxed) { if (!sandboxed) {
if (sPrivilegedChildConnectionAllocator == null) { if (sPrivilegedChildConnectionAllocator == null) {
sPrivilegedChildConnectionAllocator = ChildConnectionAllocator.create(context, sPrivilegedChildConnectionAllocator =
LauncherThread.getHandler(), null, packageName, ChildConnectionAllocator.create(context, LauncherThread.getHandler(), null,
ChildProcessCreationParamsImpl.getPrivilegedServicesName(), ChildProcessCreationParamsImpl.getPackageNameForPrivilegedService(),
NUM_PRIVILEGED_SERVICES_KEY, bindToCaller, bindAsExternalService, ChildProcessCreationParamsImpl.getPrivilegedServicesName(),
true /* useStrongBinding */); NUM_PRIVILEGED_SERVICES_KEY, bindToCaller, bindAsExternalService,
true /* useStrongBinding */);
} }
return sPrivilegedChildConnectionAllocator; return sPrivilegedChildConnectionAllocator;
} }
if (sSandboxedChildConnectionAllocator == null) { if (sSandboxedChildConnectionAllocator == null) {
final String packageName =
ChildProcessCreationParamsImpl.getPackageNameForSandboxedService();
Log.d(TAG, Log.d(TAG,
"Create a new ChildConnectionAllocator with package name = %s," "Create a new ChildConnectionAllocator with package name = %s,"
+ " sandboxed = true", + " sandboxed = true",
......
...@@ -10,19 +10,19 @@ import org.chromium.content.browser.ChildProcessCreationParamsImpl; ...@@ -10,19 +10,19 @@ import org.chromium.content.browser.ChildProcessCreationParamsImpl;
* Allows specifying the package name for looking up child services * Allows specifying the package name for looking up child services
* configuration and classes into (if it differs from the application package * configuration and classes into (if it differs from the application package
* name, like in the case of Android WebView). Also allows specifying additional * name, like in the case of Android WebView). Also allows specifying additional
* child service binging flags. * child service binding flags.
*/ */
public final class ChildProcessCreationParams { public final class ChildProcessCreationParams {
/** /**
* Set params. This should be called once on start up. If null is passed for * Set params. This should be called once on start up. If null is passed for
* privilegedServicesName or sandboxedServicesName, the default service names will be used. * privilegedServicesName or sandboxedServicesName, the default service names will be used.
*/ */
public static void set(String packageNameForService, boolean isExternalSandboxedService, public static void set(String privilegedPackageName, String privilegedServicesName,
int libraryProcessType, boolean bindToCallerCheck, String sandboxedPackageName, String sandboxedServicesName,
boolean ignoreVisibilityForImportance, String privilegedServicesName, boolean isExternalSandboxedService, int libraryProcessType, boolean bindToCallerCheck,
String sandboxedServicesName) { boolean ignoreVisibilityForImportance) {
ChildProcessCreationParamsImpl.set(packageNameForService, isExternalSandboxedService, ChildProcessCreationParamsImpl.set(privilegedPackageName, privilegedServicesName,
libraryProcessType, bindToCallerCheck, ignoreVisibilityForImportance, sandboxedPackageName, sandboxedServicesName, isExternalSandboxedService,
privilegedServicesName, sandboxedServicesName); libraryProcessType, bindToCallerCheck, ignoreVisibilityForImportance);
} }
} }
...@@ -149,10 +149,11 @@ public class ChildProcessLauncherHelperTest { ...@@ -149,10 +149,11 @@ public class ChildProcessLauncherHelperTest {
// Launch a service from this process. Since slot 0 is already bound by the Helper, it // Launch a service from this process. Since slot 0 is already bound by the Helper, it
// will fail to start and the ChildProcessLauncher will retry and use the slot 1. // will fail to start and the ChildProcessLauncher will retry and use the slot 1.
ChildProcessCreationParamsImpl.set(context.getPackageName(), false /* isExternalService */, ChildProcessCreationParamsImpl.set(context.getPackageName(),
null /* privilegedServicesName */, context.getPackageName(),
null /* sandboxedServicesName */, false /* isExternalService */,
LibraryProcessType.PROCESS_CHILD, true /* bindToCallerCheck */, LibraryProcessType.PROCESS_CHILD, true /* bindToCallerCheck */,
false /* ignoreVisibilityForImportance */, null /* privilegedServicesName */, false /* ignoreVisibilityForImportance */);
null /* sandboxedServicesName */);
ChildProcessLauncherHelperImpl launcher = ChildProcessLauncherHelperImpl launcher =
startSandboxedChildProcess(BLOCK_UNTIL_SETUP, true /* doSetupConnection */); startSandboxedChildProcess(BLOCK_UNTIL_SETUP, true /* doSetupConnection */);
...@@ -256,10 +257,11 @@ public class ChildProcessLauncherHelperTest { ...@@ -256,10 +257,11 @@ public class ChildProcessLauncherHelperTest {
@Feature({"ProcessManagement"}) @Feature({"ProcessManagement"})
public void testWarmUpWithBindToCaller() { public void testWarmUpWithBindToCaller() {
Context context = InstrumentationRegistry.getTargetContext(); Context context = InstrumentationRegistry.getTargetContext();
ChildProcessCreationParamsImpl.set(context.getPackageName(), false /* isExternalService */, ChildProcessCreationParamsImpl.set(context.getPackageName(),
null /* privilegedServicesName */, context.getPackageName(),
null /* sandboxedServicesName */, false /* isExternalService */,
LibraryProcessType.PROCESS_CHILD, true /* bindToCallerCheck */, LibraryProcessType.PROCESS_CHILD, true /* bindToCallerCheck */,
false /* ignoreVisibilityForImportance */, null /* privilegedServicesName */, false /* ignoreVisibilityForImportance */);
null /* sandboxedServicesName */);
testWarmUpImpl(); testWarmUpImpl();
} }
......
...@@ -72,9 +72,10 @@ public class ChildProcessLauncherTestHelperService extends Service { ...@@ -72,9 +72,10 @@ public class ChildProcessLauncherTestHelperService extends Service {
private void doBindService(final Message msg) { private void doBindService(final Message msg) {
String[] commandLine = { "_", "--" + BaseSwitches.RENDERER_WAIT_FOR_JAVA_DEBUGGER }; String[] commandLine = { "_", "--" + BaseSwitches.RENDERER_WAIT_FOR_JAVA_DEBUGGER };
final boolean bindToCaller = true; final boolean bindToCaller = true;
ChildProcessCreationParams.set(getPackageName(), false, LibraryProcessType.PROCESS_CHILD, ChildProcessCreationParams.set(getPackageName(), null /* privilegedServicesName */,
bindToCaller, false /* ignoreVisibilityForImportance */, getPackageName(), null /* sandboxedServicesName */, false,
null /* privilegedServicesName */, null /* sandboxedServicesName */); LibraryProcessType.PROCESS_CHILD, bindToCaller,
false /* ignoreVisibilityForImportance */);
mProcessLauncher = ChildProcessLauncherTestUtils.startForTesting(true /* sandboxed */, mProcessLauncher = ChildProcessLauncherTestUtils.startForTesting(true /* sandboxed */,
commandLine, new FileDescriptorInfo[0], true /* doSetupConnection */); commandLine, new FileDescriptorInfo[0], true /* doSetupConnection */);
......
...@@ -62,6 +62,11 @@ public final class WebLayerImpl extends IWebLayer.Stub { ...@@ -62,6 +62,11 @@ public final class WebLayerImpl extends IWebLayer.Stub {
// "//chrome/test/chromedriver/chrome/device_manager.cc"). If you change this variable, update // "//chrome/test/chromedriver/chrome/device_manager.cc"). If you change this variable, update
// "device_manager.cc" too. // "device_manager.cc" too.
private static final String COMMAND_LINE_FILE = "/data/local/tmp/weblayer-command-line"; private static final String COMMAND_LINE_FILE = "/data/local/tmp/weblayer-command-line";
// This metadata key, if defined, overrides the default behaviour of loading WebLayer from the
// current WebView implementation. This is only intended for testing, and does not enforce any
// signature requirements on the implementation, nor does it use the production code path to
// load the code. Do not set this in production APKs!
private static final String PACKAGE_MANIFEST_KEY = "org.chromium.weblayer.WebLayerPackage";
private final ProfileManager mProfileManager = new ProfileManager(); private final ProfileManager mProfileManager = new ProfileManager();
...@@ -155,11 +160,7 @@ public final class WebLayerImpl extends IWebLayer.Stub { ...@@ -155,11 +160,7 @@ public final class WebLayerImpl extends IWebLayer.Stub {
ResourceBundle.setAvailablePakLocales(new String[] {}, ProductConfig.UNCOMPRESSED_LOCALES); ResourceBundle.setAvailablePakLocales(new String[] {}, ProductConfig.UNCOMPRESSED_LOCALES);
ChildProcessCreationParams.set(appContext.getPackageName(), false /* isExternalService */, setChildProcessCreationParams(appContext, packageInfo.packageName);
LibraryProcessType.PROCESS_WEBLAYER_CHILD, true /* bindToCaller */,
false /* ignoreVisibilityForImportance */,
"org.chromium.weblayer.ChildProcessService$Privileged",
"org.chromium.weblayer.ChildProcessService$Sandboxed");
if (!CommandLine.isInitialized()) { if (!CommandLine.isInitialized()) {
if (BuildInfo.isDebugAndroid()) { if (BuildInfo.isDebugAndroid()) {
...@@ -320,6 +321,50 @@ public final class WebLayerImpl extends IWebLayer.Stub { ...@@ -320,6 +321,50 @@ public final class WebLayerImpl extends IWebLayer.Stub {
} }
} }
private void setChildProcessCreationParams(Context appContext, String implPackageName) {
final boolean bindToCaller = true;
final boolean ignoreVisibilityForImportance = false;
final String privilegedServicesPackageName = appContext.getPackageName();
final String privilegedServicesName =
"org.chromium.weblayer.ChildProcessService$Privileged";
String sandboxedServicesPackageName = appContext.getPackageName();
String sandboxedServicesName = "org.chromium.weblayer.ChildProcessService$Sandboxed";
boolean isExternalService = false;
boolean loadedFromWebView = wasLoadedFromWebView(appContext);
if (loadedFromWebView && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// On O+ when loading from a WebView implementation, we can just use WebView's declared
// external services as our renderers, which means we benefit from the webview zygote
// process. We still need to use the client's privileged services, as only isolated
// services can be external.
isExternalService = true;
sandboxedServicesPackageName = implPackageName;
sandboxedServicesName = null;
}
ChildProcessCreationParams.set(privilegedServicesPackageName, privilegedServicesName,
sandboxedServicesPackageName, sandboxedServicesName, isExternalService,
LibraryProcessType.PROCESS_WEBLAYER_CHILD, bindToCaller,
ignoreVisibilityForImportance);
}
private static boolean wasLoadedFromWebView(Context appContext) {
try {
Bundle metaData = appContext.getPackageManager()
.getApplicationInfo(appContext.getPackageName(),
PackageManager.GET_META_DATA)
.metaData;
if (metaData != null && metaData.getString(PACKAGE_MANIFEST_KEY) != null) {
return false;
}
return true;
} catch (PackageManager.NameNotFoundException e) {
// This would indicate the client app doesn't exist;
// just return true as there's nothing sensible to do here.
return true;
}
}
@NativeMethods @NativeMethods
interface Natives { interface Natives {
void setRemoteDebuggingEnabled(boolean enabled); void setRemoteDebuggingEnabled(boolean enabled);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment