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 {
final boolean isExternalService = true;
final boolean bindToCaller = true;
final boolean ignoreVisibilityForImportance = true;
ChildProcessCreationParams.set(getWebViewPackageName(), isExternalService,
ChildProcessCreationParams.set(getWebViewPackageName(), null /* privilegedServicesName */,
getWebViewPackageName(), null /* sandboxedServicesName */, isExternalService,
LibraryProcessType.PROCESS_WEBVIEW_CHILD, bindToCaller,
ignoreVisibilityForImportance, null /* privilegedServicesName */,
null /* sandboxedServicesName */);
ignoreVisibilityForImportance);
}
/**
......
......@@ -39,9 +39,9 @@ public class MonochromeApplication extends ChromeApplication {
// and are external, and will fail to bind otherwise.
boolean bindToCaller = false;
boolean ignoreVisibilityForImportance = false;
ChildProcessCreationParams.set(getPackageName(), true /* isExternalService */,
LibraryProcessType.PROCESS_CHILD, bindToCaller, ignoreVisibilityForImportance,
null /* privilegedServicesName */, null /* sandboxedServicesName */);
ChildProcessCreationParams.set(getPackageName(), null /* privilegedServicesName */,
getPackageName(), null /* sandboxedServicesName */, true /* isExternalService */,
LibraryProcessType.PROCESS_CHILD, bindToCaller, ignoreVisibilityForImportance);
}
@Override
......
......@@ -21,7 +21,8 @@ public class ChildProcessCreationParamsImpl {
"org.chromium.content.app.SandboxedProcessService";
// 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 int sLibraryProcessType;
private static boolean sBindToCallerCheck;
......@@ -36,20 +37,21 @@ public class ChildProcessCreationParamsImpl {
private ChildProcessCreationParamsImpl() {}
/** Set params. This should be called once on start up. */
public static void set(String packageNameForService, boolean isExternalSandboxedService,
int libraryProcessType, boolean bindToCallerCheck,
boolean ignoreVisibilityForImportance, String privilegedServicesName,
String sandboxedServicesName) {
public static void set(String privilegedPackageName, String privilegedServicesName,
String sandboxedPackageName, String sandboxedServicesName,
boolean isExternalSandboxedService, int libraryProcessType, boolean bindToCallerCheck,
boolean ignoreVisibilityForImportance) {
assert !sInitialized;
sPackageNameForService = packageNameForService;
sIsSandboxedServiceExternal = isExternalSandboxedService;
sLibraryProcessType = libraryProcessType;
sBindToCallerCheck = bindToCallerCheck;
sIgnoreVisibilityForImportance = ignoreVisibilityForImportance;
sPackageNameForPrivilegedService = privilegedPackageName;
sPrivilegedServicesName =
privilegedServicesName == null ? PRIVILEGED_SERVICES_NAME : privilegedServicesName;
sPackageNameForSandboxedService = sandboxedPackageName;
sSandboxedServicesName =
sandboxedServicesName == null ? SANDBOXED_SERVICES_NAME : sandboxedServicesName;
sIsSandboxedServiceExternal = isExternalSandboxedService;
sLibraryProcessType = libraryProcessType;
sBindToCallerCheck = bindToCallerCheck;
sIgnoreVisibilityForImportance = ignoreVisibilityForImportance;
sInitialized = true;
}
......@@ -57,8 +59,13 @@ public class ChildProcessCreationParamsImpl {
if (sInitialized) extras.putInt(EXTRA_LIBRARY_PROCESS_TYPE, sLibraryProcessType);
}
public static String getPackageNameForService() {
return sInitialized ? sPackageNameForService
public static String getPackageNameForPrivilegedService() {
return sInitialized ? sPackageNameForPrivilegedService
: ContextUtils.getApplicationContext().getPackageName();
}
public static String getPackageNameForSandboxedService() {
return sInitialized ? sPackageNameForSandboxedService
: ContextUtils.getApplicationContext().getPackageName();
}
......
......@@ -350,23 +350,25 @@ public final class ChildProcessLauncherHelperImpl {
@VisibleForTesting
static ChildConnectionAllocator getConnectionAllocator(Context context, boolean sandboxed) {
assert LauncherThread.runningOnLauncherThread();
final String packageName = ChildProcessCreationParamsImpl.getPackageNameForService();
boolean bindToCaller = ChildProcessCreationParamsImpl.getBindToCallerCheck();
boolean bindAsExternalService =
sandboxed && ChildProcessCreationParamsImpl.getIsSandboxedServiceExternal();
if (!sandboxed) {
if (sPrivilegedChildConnectionAllocator == null) {
sPrivilegedChildConnectionAllocator = ChildConnectionAllocator.create(context,
LauncherThread.getHandler(), null, packageName,
ChildProcessCreationParamsImpl.getPrivilegedServicesName(),
NUM_PRIVILEGED_SERVICES_KEY, bindToCaller, bindAsExternalService,
true /* useStrongBinding */);
sPrivilegedChildConnectionAllocator =
ChildConnectionAllocator.create(context, LauncherThread.getHandler(), null,
ChildProcessCreationParamsImpl.getPackageNameForPrivilegedService(),
ChildProcessCreationParamsImpl.getPrivilegedServicesName(),
NUM_PRIVILEGED_SERVICES_KEY, bindToCaller, bindAsExternalService,
true /* useStrongBinding */);
}
return sPrivilegedChildConnectionAllocator;
}
if (sSandboxedChildConnectionAllocator == null) {
final String packageName =
ChildProcessCreationParamsImpl.getPackageNameForSandboxedService();
Log.d(TAG,
"Create a new ChildConnectionAllocator with package name = %s,"
+ " sandboxed = true",
......
......@@ -10,19 +10,19 @@ import org.chromium.content.browser.ChildProcessCreationParamsImpl;
* Allows specifying the package name for looking up child services
* configuration and classes into (if it differs from the application package
* name, like in the case of Android WebView). Also allows specifying additional
* child service binging flags.
* child service binding flags.
*/
public final class ChildProcessCreationParams {
/**
* 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.
*/
public static void set(String packageNameForService, boolean isExternalSandboxedService,
int libraryProcessType, boolean bindToCallerCheck,
boolean ignoreVisibilityForImportance, String privilegedServicesName,
String sandboxedServicesName) {
ChildProcessCreationParamsImpl.set(packageNameForService, isExternalSandboxedService,
libraryProcessType, bindToCallerCheck, ignoreVisibilityForImportance,
privilegedServicesName, sandboxedServicesName);
public static void set(String privilegedPackageName, String privilegedServicesName,
String sandboxedPackageName, String sandboxedServicesName,
boolean isExternalSandboxedService, int libraryProcessType, boolean bindToCallerCheck,
boolean ignoreVisibilityForImportance) {
ChildProcessCreationParamsImpl.set(privilegedPackageName, privilegedServicesName,
sandboxedPackageName, sandboxedServicesName, isExternalSandboxedService,
libraryProcessType, bindToCallerCheck, ignoreVisibilityForImportance);
}
}
......@@ -149,10 +149,11 @@ public class ChildProcessLauncherHelperTest {
// 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.
ChildProcessCreationParamsImpl.set(context.getPackageName(), false /* isExternalService */,
ChildProcessCreationParamsImpl.set(context.getPackageName(),
null /* privilegedServicesName */, context.getPackageName(),
null /* sandboxedServicesName */, false /* isExternalService */,
LibraryProcessType.PROCESS_CHILD, true /* bindToCallerCheck */,
false /* ignoreVisibilityForImportance */, null /* privilegedServicesName */,
null /* sandboxedServicesName */);
false /* ignoreVisibilityForImportance */);
ChildProcessLauncherHelperImpl launcher =
startSandboxedChildProcess(BLOCK_UNTIL_SETUP, true /* doSetupConnection */);
......@@ -256,10 +257,11 @@ public class ChildProcessLauncherHelperTest {
@Feature({"ProcessManagement"})
public void testWarmUpWithBindToCaller() {
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 */,
false /* ignoreVisibilityForImportance */, null /* privilegedServicesName */,
null /* sandboxedServicesName */);
false /* ignoreVisibilityForImportance */);
testWarmUpImpl();
}
......
......@@ -72,9 +72,10 @@ public class ChildProcessLauncherTestHelperService extends Service {
private void doBindService(final Message msg) {
String[] commandLine = { "_", "--" + BaseSwitches.RENDERER_WAIT_FOR_JAVA_DEBUGGER };
final boolean bindToCaller = true;
ChildProcessCreationParams.set(getPackageName(), false, LibraryProcessType.PROCESS_CHILD,
bindToCaller, false /* ignoreVisibilityForImportance */,
null /* privilegedServicesName */, null /* sandboxedServicesName */);
ChildProcessCreationParams.set(getPackageName(), null /* privilegedServicesName */,
getPackageName(), null /* sandboxedServicesName */, false,
LibraryProcessType.PROCESS_CHILD, bindToCaller,
false /* ignoreVisibilityForImportance */);
mProcessLauncher = ChildProcessLauncherTestUtils.startForTesting(true /* sandboxed */,
commandLine, new FileDescriptorInfo[0], true /* doSetupConnection */);
......
......@@ -62,6 +62,11 @@ public final class WebLayerImpl extends IWebLayer.Stub {
// "//chrome/test/chromedriver/chrome/device_manager.cc"). If you change this variable, update
// "device_manager.cc" too.
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();
......@@ -155,11 +160,7 @@ public final class WebLayerImpl extends IWebLayer.Stub {
ResourceBundle.setAvailablePakLocales(new String[] {}, ProductConfig.UNCOMPRESSED_LOCALES);
ChildProcessCreationParams.set(appContext.getPackageName(), false /* isExternalService */,
LibraryProcessType.PROCESS_WEBLAYER_CHILD, true /* bindToCaller */,
false /* ignoreVisibilityForImportance */,
"org.chromium.weblayer.ChildProcessService$Privileged",
"org.chromium.weblayer.ChildProcessService$Sandboxed");
setChildProcessCreationParams(appContext, packageInfo.packageName);
if (!CommandLine.isInitialized()) {
if (BuildInfo.isDebugAndroid()) {
......@@ -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
interface Natives {
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