Commit c5f986b9 authored by Clark DuVall's avatar Clark DuVall Committed by Commit Bot

[WebLayer] Support building WebLayer as an isolated split in WebView

This adds basic support for building WebLayer as an isolated split in
WebView. A new gn arg "weblayer_in_split" is added which will move
WebLayer Java code to it's own DFM if true.

Supporting isolated splits required some client changes in WebLayer, so
I added a check in WebLayerFactoryImpl.isClientSupported() to make sure
isolated splits aren't used with an unsupported client.

This also adds the ability to write the version_name and version_code of
a bundle module to the build_config, which allows DFMs to match the base
module version info (an error is thrown if these don't match). This
makes it easy to share version info, since computing WebView
version_code is pretty complicated.

The bundle with isolated splits won't install correctly with the current
version of bundletool we have in Chromium, but I'm working in parallel
on fixing bundletool.

Bug: 1105096
Change-Id: Id5522b42e283dc813fa84aaedc806f7519b586ad
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2353378
Commit-Queue: Clark DuVall <cduvall@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarRichard Coles <torne@chromium.org>
Reviewed-by: default avatarAndrew Grieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/master@{#798815}
parent 6a4c1eaa
...@@ -173,17 +173,19 @@ android_resources("monochrome_devui_launcher_icon_resources") { ...@@ -173,17 +173,19 @@ android_resources("monochrome_devui_launcher_icon_resources") {
custom_package = "org.chromium.android_webview.devui.icon" custom_package = "org.chromium.android_webview.devui.icon"
} }
_webview_jinja_variables = [ "manifest_package=$system_webview_package_name" ] +
webview_jinja_variables
jinja_template("system_webview_manifest") { jinja_template("system_webview_manifest") {
input = "java/AndroidManifest.xml" input = "java/AndroidManifest.xml"
output = system_webview_android_manifest output = system_webview_android_manifest
variables = [ "manifest_package=$system_webview_package_name" ] variables = _webview_jinja_variables
} }
jinja_template("trichrome_webview_manifest") { jinja_template("trichrome_webview_manifest") {
input = "java/AndroidManifest.xml" input = "java/AndroidManifest.xml"
output = trichrome_webview_android_manifest output = trichrome_webview_android_manifest
variables = trichrome_jinja_variables + variables = trichrome_jinja_variables + _webview_jinja_variables
[ "manifest_package=$system_webview_package_name" ]
if (android_64bit_target_cpu) { if (android_64bit_target_cpu) {
variables += [ variables += [
"use32bitAbi=", "use32bitAbi=",
...@@ -202,10 +204,9 @@ if (android_64bit_target_cpu) { ...@@ -202,10 +204,9 @@ if (android_64bit_target_cpu) {
jinja_template("trichrome_webview_64_32_manifest") { jinja_template("trichrome_webview_64_32_manifest") {
input = "java/AndroidManifest.xml" input = "java/AndroidManifest.xml"
output = trichrome_webview_64_32_android_manifest output = trichrome_webview_64_32_android_manifest
variables = trichrome_jinja_variables + [ variables = trichrome_jinja_variables + _webview_jinja_variables + [
"use32bitAbi=", "use32bitAbi=",
"trichrome_version=$trichrome_64_32_version_code", "trichrome_version=$trichrome_64_32_version_code",
"manifest_package=$system_webview_package_name",
"library=libmonochrome_64.so", "library=libmonochrome_64.so",
] ]
} }
...@@ -213,9 +214,8 @@ if (android_64bit_target_cpu) { ...@@ -213,9 +214,8 @@ if (android_64bit_target_cpu) {
jinja_template("trichrome_webview_32_64_manifest") { jinja_template("trichrome_webview_32_64_manifest") {
input = "java/AndroidManifest.xml" input = "java/AndroidManifest.xml"
output = trichrome_webview_32_64_android_manifest output = trichrome_webview_32_64_android_manifest
variables = trichrome_jinja_variables + [ variables = trichrome_jinja_variables + _webview_jinja_variables + [
"trichrome_version=$trichrome_32_64_version_code", "trichrome_version=$trichrome_32_64_version_code",
"manifest_package=$system_webview_package_name",
"library=libmonochrome.so", "library=libmonochrome.so",
] ]
} }
...@@ -223,9 +223,8 @@ if (android_64bit_target_cpu) { ...@@ -223,9 +223,8 @@ if (android_64bit_target_cpu) {
jinja_template("trichrome_webview_32_manifest") { jinja_template("trichrome_webview_32_manifest") {
input = "java/AndroidManifest.xml" input = "java/AndroidManifest.xml"
output = trichrome_webview_32_android_manifest output = trichrome_webview_32_android_manifest
variables = trichrome_jinja_variables + [ variables = trichrome_jinja_variables + _webview_jinja_variables + [
"trichrome_version=$trichrome_32_version_code", "trichrome_version=$trichrome_32_version_code",
"manifest_package=$system_webview_package_name",
"library=libmonochrome.so", "library=libmonochrome.so",
] ]
} }
......
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
package="{{manifest_package|default('com.android.webview')}}" package="{{manifest_package|default('com.android.webview')}}"
{% if use_isolated_splits is defined and use_isolated_splits == 'true' %}
android:isolatedSplits="true"
{% endif %}
tools:ignore="MissingLeanbackLauncher"> tools:ignore="MissingLeanbackLauncher">
<uses-feature android:name="android.hardware.touchscreen" <uses-feature android:name="android.hardware.touchscreen"
......
...@@ -51,7 +51,14 @@ template("system_webview_apk_or_module_tmpl") { ...@@ -51,7 +51,14 @@ template("system_webview_apk_or_module_tmpl") {
if (_exclude_weblayer_java) { if (_exclude_weblayer_java) {
deps += [ "//android_webview:android_webview_no_weblayer_java" ] deps += [ "//android_webview:android_webview_no_weblayer_java" ]
} else { } else {
deps += [ "//android_webview:android_webview_java" ] if (_is_bundle_module && weblayer_in_split) {
deps += [
"//android_webview:android_webview_no_weblayer_java",
"//weblayer/browser/java:base_module_java",
]
} else {
deps += [ "//android_webview:android_webview_java" ]
}
# Resources from this target will be kept in the base bundle module # Resources from this target will be kept in the base bundle module
# instead of in language splits. # instead of in language splits.
......
...@@ -4,12 +4,62 @@ ...@@ -4,12 +4,62 @@
import("//build/config/android/rules.gni") import("//build/config/android/rules.gni")
import("//build/config/locales.gni") import("//build/config/locales.gni")
import("//weblayer/variables.gni")
template("system_webview_bundle") { template("system_webview_bundle") {
if (webview_includes_weblayer && weblayer_in_split) {
# TODO(crbug.com/1105096): If WebView starts using
# //components/module_installer, it will probably make sense to refactor
# chrome_feature_module() to be used here.
_base_target_name = get_label_info(invoker.base_module_target, "name")
_base_target_gen_dir =
get_label_info(invoker.base_module_target, "target_gen_dir")
_base_module_build_config_target =
"${invoker.base_module_target}$build_config_target_suffix"
_base_module_build_config =
"$_base_target_gen_dir/${_base_target_name}.build_config"
_rebased_base_module_build_config =
rebase_path(_base_module_build_config, root_build_dir)
_weblayer_module_target = "${target_name}__weblayer_bundle_module"
_weblayer_module_desc = {
name = "weblayer"
module_target = ":${_weblayer_module_target}"
}
android_app_bundle_module(_weblayer_module_target) {
forward_variables_from(invoker,
[
"base_module_target",
"min_sdk_version",
"uncompress_shared_libraries",
])
android_manifest = "//weblayer/browser/java/AndroidManifest.xml"
deps = [
"//weblayer/browser/java",
_base_module_build_config_target,
]
if (defined(invoker.weblayer_deps)) {
deps += invoker.weblayer_deps
}
aapt_locale_allowlist = locales
proguard_enabled = !is_java_debug
package_name = "weblayer"
package_id = 126
version_name =
"@FileArg($_rebased_base_module_build_config:deps_info:version_name)"
version_code =
"@FileArg($_rebased_base_module_build_config:deps_info:version_code)"
manifest_package =
"@FileArg($_rebased_base_module_build_config:deps_info:package_name)"
}
}
android_app_bundle(target_name) { android_app_bundle(target_name) {
command_line_flags_file = "webview-command-line" command_line_flags_file = "webview-command-line"
proguard_enabled = !is_java_debug proguard_enabled = !is_java_debug
enable_language_splits = true enable_language_splits = true
if (webview_includes_weblayer && weblayer_in_split) {
extra_modules = [ _weblayer_module_desc ]
}
system_image_locale_allowlist = locales system_image_locale_allowlist = locales
is_multi_abi = is_multi_abi =
android_64bit_target_cpu && (!defined(invoker.include_64_bit_webview) || android_64bit_target_cpu && (!defined(invoker.include_64_bit_webview) ||
......
...@@ -33,4 +33,6 @@ if (webview_includes_weblayer) { ...@@ -33,4 +33,6 @@ if (webview_includes_weblayer) {
[ "//weblayer/browser/java:gms_bridge_upstream_impl_java" ] [ "//weblayer/browser/java:gms_bridge_upstream_impl_java" ]
} }
webview_jinja_variables = [ "use_isolated_splits=$weblayer_in_split" ]
webview_product_config_java_package = "org.chromium.android_webview" webview_product_config_java_package = "org.chromium.android_webview"
...@@ -6,6 +6,8 @@ package org.chromium.base.compat; ...@@ -6,6 +6,8 @@ package org.chromium.base.compat;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.content.ClipDescription; import android.content.ClipDescription;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Build; import android.os.Build;
...@@ -54,4 +56,15 @@ public final class ApiHelperForO { ...@@ -54,4 +56,15 @@ public final class ApiHelperForO {
public static long getTimestamp(ClipDescription clipDescription) { public static long getTimestamp(ClipDescription clipDescription) {
return clipDescription.getTimestamp(); return clipDescription.getTimestamp();
} }
/** See {@link ApplicationInfo#splitNames}. */
public static String[] getSplitNames(ApplicationInfo info) {
return info.splitNames;
}
/** See {@link Context.createContextForSplit(String) }. */
public static Context createContextForSplit(Context context, String name)
throws PackageManager.NameNotFoundException {
return context.createContextForSplit(name);
}
} }
...@@ -1062,6 +1062,9 @@ def main(argv): ...@@ -1062,6 +1062,9 @@ def main(argv):
help='For bundles, the paths of all non-async module .build_configs ' help='For bundles, the paths of all non-async module .build_configs '
'for modules that are part of the bundle.') 'for modules that are part of the bundle.')
parser.add_option('--version-name', help='Version name for this APK.')
parser.add_option('--version-code', help='Version code for this APK.')
options, args = parser.parse_args(argv) options, args = parser.parse_args(argv)
if args: if args:
...@@ -1265,6 +1268,8 @@ def main(argv): ...@@ -1265,6 +1268,8 @@ def main(argv):
if options.apk_proto_resources: if options.apk_proto_resources:
deps_info['proto_resources_path'] = options.apk_proto_resources deps_info['proto_resources_path'] = options.apk_proto_resources
deps_info['version_name'] = options.version_name
deps_info['version_code'] = options.version_code
if options.module_pathmap_path: if options.module_pathmap_path:
deps_info['module_pathmap_path'] = options.module_pathmap_path deps_info['module_pathmap_path'] = options.module_pathmap_path
else: else:
......
...@@ -554,6 +554,18 @@ template("write_build_config") { ...@@ -554,6 +554,18 @@ template("write_build_config") {
rebase_path(invoker.module_build_configs, root_build_dir) rebase_path(invoker.module_build_configs, root_build_dir)
args += [ "--module-build-configs=$_rebased_configs" ] args += [ "--module-build-configs=$_rebased_configs" ]
} }
if (defined(invoker.version_name)) {
args += [
"--version-name",
invoker.version_name,
]
}
if (defined(invoker.version_code)) {
args += [
"--version-code",
invoker.version_code,
]
}
if (current_toolchain != default_toolchain) { if (current_toolchain != default_toolchain) {
# This has to be a built-time error rather than a GN assert because many # This has to be a built-time error rather than a GN assert because many
# packages have a mix of java and non-java targets. For example, the # packages have a mix of java and non-java targets. For example, the
...@@ -3646,6 +3658,8 @@ if (enable_java_templates) { ...@@ -3646,6 +3658,8 @@ if (enable_java_templates) {
"is_base_module", "is_base_module",
"module_pathmap_path", "module_pathmap_path",
"proto_resources_path", "proto_resources_path",
"version_name",
"version_code",
]) ])
} }
chromium_code = _chromium_code chromium_code = _chromium_code
......
...@@ -2777,6 +2777,11 @@ if (enable_java_templates) { ...@@ -2777,6 +2777,11 @@ if (enable_java_templates) {
type = "android_app_bundle_module" type = "android_app_bundle_module"
res_size_info_path = _res_size_info_path res_size_info_path = _res_size_info_path
is_base_module = _is_base_module is_base_module = _is_base_module
forward_variables_from(invoker,
[
"version_code",
"version_name",
])
} else { } else {
type = "android_apk" type = "android_apk"
} }
......
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2020 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:dist="http://schemas.android.com/apk/distribution"
featureSplit="weblayer">
<!-- Due to b/164116603 fusing is false for now. Once that bug is fixed,
the WebLayer module should be fused. -->
<dist:module
dist:onDemand="false">
<dist:fusing dist:include="false" />
</dist:module>
<application />
</manifest>
...@@ -7,6 +7,15 @@ import("//build/config/android/rules.gni") ...@@ -7,6 +7,15 @@ import("//build/config/android/rules.gni")
import("//build/config/locales.gni") import("//build/config/locales.gni")
import("//weblayer/variables.gni") import("//weblayer/variables.gni")
_bundle_utils_output =
"$target_gen_dir/org/chromium/weblayer_private/WebLayerBundleUtils.java"
jinja_template("weblayer_bundle_utils") {
input = "WebLayerBundleUtils.java.jinja2"
output = _bundle_utils_output
variables = "weblayer_in_split=$weblayer_in_split"
}
android_resources("weblayer_resources") { android_resources("weblayer_resources") {
sources = [ sources = [
"res/drawable/weblayer_tab_indicator.xml", "res/drawable/weblayer_tab_indicator.xml",
...@@ -36,6 +45,13 @@ android_resources("weblayer_resources") { ...@@ -36,6 +45,13 @@ android_resources("weblayer_resources") {
] ]
} }
# This resource target is kept in the base module when WebLayer is in a split,
# and allows WebLayer to call onResourcesLoaded() on resources shared with
# WebView.
android_resources("weblayer_base_module_resources") {
custom_package = "org.chromium.weblayer_private.base"
}
generate_product_config_srcjar("weblayer_product_config") { generate_product_config_srcjar("weblayer_product_config") {
java_package = weblayer_product_config_java_package java_package = weblayer_product_config_java_package
} }
...@@ -69,6 +85,16 @@ java_cpp_enum("generated_enums") { ...@@ -69,6 +85,16 @@ java_cpp_enum("generated_enums") {
] ]
} }
android_library("base_module_java") {
sources =
[ "org/chromium/weblayer_private/WebViewCompatibilityHelperImpl.java" ]
deps = [
":weblayer_base_module_resources",
"//base:base_java",
]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
}
android_library("java") { android_library("java") {
sources = [ sources = [
"org/chromium/weblayer_private/ActionModeCallback.java", "org/chromium/weblayer_private/ActionModeCallback.java",
...@@ -122,16 +148,18 @@ android_library("java") { ...@@ -122,16 +148,18 @@ android_library("java") {
"org/chromium/weblayer_private/WebLayerTabModalPresenter.java", "org/chromium/weblayer_private/WebLayerTabModalPresenter.java",
"org/chromium/weblayer_private/WebMessageReplyProxyImpl.java", "org/chromium/weblayer_private/WebMessageReplyProxyImpl.java",
"org/chromium/weblayer_private/WebShareServiceFactory.java", "org/chromium/weblayer_private/WebShareServiceFactory.java",
"org/chromium/weblayer_private/WebViewCompatibilityHelperImpl.java",
"org/chromium/weblayer_private/metrics/MetricsServiceClient.java", "org/chromium/weblayer_private/metrics/MetricsServiceClient.java",
"org/chromium/weblayer_private/metrics/UmaUtils.java", "org/chromium/weblayer_private/metrics/UmaUtils.java",
"org/chromium/weblayer_private/permissions/PermissionRequestUtils.java", "org/chromium/weblayer_private/permissions/PermissionRequestUtils.java",
"org/chromium/weblayer_private/resources/ResourceMapper.java", "org/chromium/weblayer_private/resources/ResourceMapper.java",
_bundle_utils_output,
] ]
deps = [ deps = [
":base_module_java",
":gms_bridge_java", ":gms_bridge_java",
":interfaces_java", ":interfaces_java",
":weblayer_bundle_utils",
":weblayer_resources", ":weblayer_resources",
"//base:base_java", "//base:base_java",
"//base:jni_java", "//base:jni_java",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.weblayer_private;
public final class WebLayerBundleUtils {
public static final boolean IS_WEBLAYER_IN_SPLIT = {{ weblayer_in_split }};
}
...@@ -50,6 +50,11 @@ public final class WebLayerFactoryImpl extends IWebLayerFactory.Stub { ...@@ -50,6 +50,11 @@ public final class WebLayerFactoryImpl extends IWebLayerFactory.Stub {
@Override @Override
public boolean isClientSupported() { public boolean isClientSupported() {
StrictModeWorkaround.apply(); StrictModeWorkaround.apply();
// Client changes were required to support WebLayer in a split.
if (ProductConfig.IS_BUNDLE && WebLayerBundleUtils.IS_WEBLAYER_IN_SPLIT
&& sClientMajorVersion < 86) {
return false;
}
int implMajorVersion = getImplementationMajorVersion(); int implMajorVersion = getImplementationMajorVersion();
// While the client always calls this method, the most recently shipped product gets to // While the client always calls this method, the most recently shipped product gets to
// decide compatibility. If we instead let the implementation always decide, then we would // decide compatibility. If we instead let the implementation always decide, then we would
......
...@@ -38,6 +38,7 @@ import org.chromium.base.StrictModeContext; ...@@ -38,6 +38,7 @@ import org.chromium.base.StrictModeContext;
import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods; import org.chromium.base.annotations.NativeMethods;
import org.chromium.base.compat.ApiHelperForO;
import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.components.embedder_support.application.ClassLoaderContextWrapperFactory; import org.chromium.components.embedder_support.application.ClassLoaderContextWrapperFactory;
...@@ -197,7 +198,9 @@ public final class WebLayerImpl extends IWebLayer.Stub { ...@@ -197,7 +198,9 @@ public final class WebLayerImpl extends IWebLayer.Stub {
notifyWebViewRunningInProcess(remoteContext.getClassLoader()); notifyWebViewRunningInProcess(remoteContext.getClassLoader());
} }
Context appContext = minimalInitForContext(appContextWrapper, remoteContextWrapper); remoteContext = processRemoteContext(remoteContext);
Context appContext = minimalInitForContext(
ObjectWrapper.unwrap(appContextWrapper, Context.class), remoteContext);
PackageInfo packageInfo = WebViewFactory.getLoadedPackageInfo(); PackageInfo packageInfo = WebViewFactory.getLoadedPackageInfo();
// If a remote context is not provided, the client is an older version that loads the native // If a remote context is not provided, the client is an older version that loads the native
...@@ -211,7 +214,8 @@ public final class WebLayerImpl extends IWebLayer.Stub { ...@@ -211,7 +214,8 @@ public final class WebLayerImpl extends IWebLayer.Stub {
FirebaseConfig.getFirebaseAppIdForPackage(packageInfo.packageName)); FirebaseConfig.getFirebaseAppIdForPackage(packageInfo.packageName));
// TODO: The call to onResourcesLoaded() can be slow, we may need to parallelize this with // TODO: The call to onResourcesLoaded() can be slow, we may need to parallelize this with
// other expensive startup tasks. // other expensive startup tasks.
R.onResourcesLoaded(forceCorrectPackageId(remoteContext)); org.chromium.weblayer_private.base.R.onResourcesLoaded(
forceCorrectPackageId(remoteContext));
SelectionPopupController.setMustUseWebContentsContext(); SelectionPopupController.setMustUseWebContentsContext();
ResourceBundle.setAvailablePakLocales(new String[] {}, ProductConfig.UNCOMPRESSED_LOCALES); ResourceBundle.setAvailablePakLocales(new String[] {}, ProductConfig.UNCOMPRESSED_LOCALES);
...@@ -298,7 +302,8 @@ public final class WebLayerImpl extends IWebLayer.Stub { ...@@ -298,7 +302,8 @@ public final class WebLayerImpl extends IWebLayer.Stub {
IObjectWrapper appContext, IObjectWrapper remoteContext) { IObjectWrapper appContext, IObjectWrapper remoteContext) {
StrictModeWorkaround.apply(); StrictModeWorkaround.apply();
// This is a no-op if init has already happened. // This is a no-op if init has already happened.
WebLayerImpl.minimalInitForContext(appContext, remoteContext); WebLayerImpl.minimalInitForContext(ObjectWrapper.unwrap(appContext, Context.class),
processRemoteContext(ObjectWrapper.unwrap(remoteContext, Context.class)));
return CrashReporterControllerImpl.getInstance(); return CrashReporterControllerImpl.getInstance();
} }
...@@ -444,13 +449,10 @@ public final class WebLayerImpl extends IWebLayer.Stub { ...@@ -444,13 +449,10 @@ public final class WebLayerImpl extends IWebLayer.Stub {
* Performs the minimal initialization needed for a context. This is used for example in * Performs the minimal initialization needed for a context. This is used for example in
* CrashReporterControllerImpl, so it can be used before full WebLayer initialization. * CrashReporterControllerImpl, so it can be used before full WebLayer initialization.
*/ */
private static Context minimalInitForContext( private static Context minimalInitForContext(Context appContext, Context remoteContext) {
IObjectWrapper appContextWrapper, IObjectWrapper remoteContextWrapper) {
if (ContextUtils.getApplicationContext() != null) { if (ContextUtils.getApplicationContext() != null) {
return ContextUtils.getApplicationContext(); return ContextUtils.getApplicationContext();
} }
Context appContext = ObjectWrapper.unwrap(appContextWrapper, Context.class);
Context remoteContext = ObjectWrapper.unwrap(remoteContextWrapper, Context.class);
assert remoteContext != null; assert remoteContext != null;
ClassLoaderContextWrapperFactory.setResourceOverrideContext(remoteContext); ClassLoaderContextWrapperFactory.setResourceOverrideContext(remoteContext);
// Wrap the app context so that it can be used to load WebLayer implementation classes. // Wrap the app context so that it can be used to load WebLayer implementation classes.
...@@ -674,6 +676,18 @@ public final class WebLayerImpl extends IWebLayer.Stub { ...@@ -674,6 +676,18 @@ public final class WebLayerImpl extends IWebLayer.Stub {
} }
} }
private static Context processRemoteContext(Context remoteContext) {
// If WebLayer is in a DFM, make sure the correct resources are used.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
try {
return ApiHelperForO.createContextForSplit(remoteContext, "weblayer");
} catch (PackageManager.NameNotFoundException e) {
// WebLayer is not in a split, the original context will have the resources.
}
}
return remoteContext;
}
@CalledByNative @CalledByNative
@Nullable @Nullable
private static String getEmbedderName() { private static String getEmbedderName() {
......
...@@ -88,6 +88,7 @@ android_library("java") { ...@@ -88,6 +88,7 @@ android_library("java") {
"org/chromium/weblayer/UnsupportedVersionException.java", "org/chromium/weblayer/UnsupportedVersionException.java",
"org/chromium/weblayer/UrlBarController.java", "org/chromium/weblayer/UrlBarController.java",
"org/chromium/weblayer/UrlBarOptions.java", "org/chromium/weblayer/UrlBarOptions.java",
"org/chromium/weblayer/VerifiesOnO.java",
"org/chromium/weblayer/WebLayer.java", "org/chromium/weblayer/WebLayer.java",
"org/chromium/weblayer/WebLayerFileProvider.java", "org/chromium/weblayer/WebLayerFileProvider.java",
"org/chromium/weblayer/WebMessage.java", "org/chromium/weblayer/WebMessage.java",
...@@ -109,6 +110,8 @@ android_library("java") { ...@@ -109,6 +110,8 @@ android_library("java") {
"//third_party/android_deps:androidx_lifecycle_lifecycle_viewmodel_java", "//third_party/android_deps:androidx_lifecycle_lifecycle_viewmodel_java",
"//weblayer/browser/java:interfaces_java", "//weblayer/browser/java:interfaces_java",
] ]
proguard_configs = [ "proguard.flags" ]
} }
dist_aar("client_aar") { dist_aar("client_aar") {
......
...@@ -31,7 +31,7 @@ public abstract class ChildProcessService extends Service { ...@@ -31,7 +31,7 @@ public abstract class ChildProcessService extends Service {
Context appContext = getApplicationContext(); Context appContext = getApplicationContext();
Context remoteContext = WebLayer.getOrCreateRemoteContext(appContext); Context remoteContext = WebLayer.getOrCreateRemoteContext(appContext);
mImpl = IChildProcessService.Stub.asInterface( mImpl = IChildProcessService.Stub.asInterface(
(IBinder) remoteContext.getClassLoader() (IBinder) WebLayer.getOrCreateRemoteClassLoader(appContext)
.loadClass("org.chromium.weblayer_private.ChildProcessServiceImpl") .loadClass("org.chromium.weblayer_private.ChildProcessServiceImpl")
.getMethod("create", Service.class, Context.class, Context.class) .getMethod("create", Service.class, Context.class, Context.class)
.invoke(null, this, appContext, remoteContext)); .invoke(null, this, appContext, remoteContext));
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.weblayer;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* The annotated method or class verifies on O, but not below.
*
* The annotated method (or methods on the annotated class) are guaranteed to not be inlined by R8
* on builds targeted below O. This prevents class verification errors (which results in a very slow
* retry-verification-at-runtime) from spreading into other classes on these lower versions.
*
* Note: this is the WebLayer client library version of the annotation from
* org.chromium.base.annotations.
*/
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
/* package */ @interface VerifiesOnO {}
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.weblayer; package org.chromium.weblayer;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
...@@ -575,7 +576,19 @@ public class WebLayer { ...@@ -575,7 +576,19 @@ public class WebLayer {
// Child processes do not need WebView compatibility since there is no chance // Child processes do not need WebView compatibility since there is no chance
// WebView will run in the same process. // WebView will run in the same process.
if (sDisableWebViewCompatibilityMode) { if (sDisableWebViewCompatibilityMode) {
sRemoteClassLoader = getOrCreateRemoteContext(appContext).getClassLoader(); Context context = getOrCreateRemoteContext(appContext);
// Android versions before O do not support isolated splits, so WebLayer will be loaded
// as a normal split which is already available from the base class loader.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
try {
// If the implementation APK does not support isolated splits, this will just
// return the original context.
context = ApiHelperForO.createContextForSplit(context, "weblayer");
} catch (PackageManager.NameNotFoundException e) {
// WebLayer not in split, proceed with the base context.
}
}
sRemoteClassLoader = context.getClassLoader();
} else { } else {
sRemoteClassLoader = WebViewCompatibilityHelper.initialize(appContext); sRemoteClassLoader = WebViewCompatibilityHelper.initialize(appContext);
} }
...@@ -678,4 +691,14 @@ public class WebLayer { ...@@ -678,4 +691,14 @@ public class WebLayer {
return R.id.weblayer_media_session_notification; return R.id.weblayer_media_session_notification;
} }
} }
@VerifiesOnO
@TargetApi(Build.VERSION_CODES.O)
private static final class ApiHelperForO {
/** See {@link Context.createContextForSplit(String) }. */
public static Context createContextForSplit(Context context, String name)
throws PackageManager.NameNotFoundException {
return context.createContextForSplit(name);
}
}
} }
# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-keep @interface org.chromium.weblayer.VerifiesOnO
-if @org.chromium.weblayer.VerifiesOnO class * {
*** *(...);
}
-keep,allowobfuscation class <1> {
*** <2>(...);
}
-keepclassmembers,allowobfuscation class ** {
@org.chromium.weblayer.VerifiesOnO <methods>;
}
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
declare_args() { declare_args() {
# Include the //weblayer code in WebView implementation APKs. # Include the //weblayer code in WebView implementation APKs.
webview_includes_weblayer = true webview_includes_weblayer = true
# Whether WebLayer will be included as a DFM.
weblayer_in_split = false
} }
weblayer_product_config_java_package = "org.chromium.weblayer_private" weblayer_product_config_java_package = "org.chromium.weblayer_private"
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