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

webview: Move context wrapper to embedder_support.

Move ResourcesContextWrapperFactory to the embedder_support component so
that weblayer can share it. In the process, rename it to
ClassLoaderContextWrapperFactory, which better reflects what it actually
does: it has little to do with resources (which are always just
delegated directly to the context it is wrapping), and the primary thing
it overrides is getClassLoader().

Downstream code still refers to the old class, so leave a forwarding
version in place for now.

Change-Id: I3c22c390012289d7c91aeb6986f1bf44fd34dda1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1867230
Auto-Submit: Richard Coles <torne@chromium.org>
Reviewed-by: default avatarTobias Sargeant <tobiasjs@chromium.org>
Reviewed-by: default avatarBo <boliu@chromium.org>
Commit-Queue: Bo <boliu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#707807}
parent f2c5d73c
...@@ -623,6 +623,7 @@ android_library("browser_java") { ...@@ -623,6 +623,7 @@ android_library("browser_java") {
"//components/content_capture/android:java", "//components/content_capture/android:java",
"//components/crash/android:handler_java", "//components/crash/android:handler_java",
"//components/crash/android:java", "//components/crash/android:java",
"//components/embedder_support/android:application_java",
"//components/embedder_support/android:web_contents_delegate_java", "//components/embedder_support/android:web_contents_delegate_java",
"//components/minidump_uploader:minidump_uploader_java", "//components/minidump_uploader:minidump_uploader_java",
"//components/navigation_interception/android:navigation_interception_java", "//components/navigation_interception/android:navigation_interception_java",
......
...@@ -20,6 +20,7 @@ android_library("glue") { ...@@ -20,6 +20,7 @@ android_library("glue") {
"//base:jni_java", "//base:jni_java",
"//components/autofill/android:autofill_java", "//components/autofill/android:autofill_java",
"//components/autofill/android:provider_java", "//components/autofill/android:provider_java",
"//components/embedder_support/android:application_java",
"//content/public/android:content_java", "//content/public/android:content_java",
"//net/android:net_java", "//net/android:net_java",
"//ui/android:ui_java", "//ui/android:ui_java",
......
...@@ -60,7 +60,6 @@ import org.chromium.android_webview.AwContents; ...@@ -60,7 +60,6 @@ import org.chromium.android_webview.AwContents;
import org.chromium.android_webview.AwContentsStatics; import org.chromium.android_webview.AwContentsStatics;
import org.chromium.android_webview.AwPrintDocumentAdapter; import org.chromium.android_webview.AwPrintDocumentAdapter;
import org.chromium.android_webview.AwSettings; import org.chromium.android_webview.AwSettings;
import org.chromium.android_webview.ResourcesContextWrapperFactory;
import org.chromium.android_webview.gfx.AwDrawFnImpl; import org.chromium.android_webview.gfx.AwDrawFnImpl;
import org.chromium.android_webview.renderer_priority.RendererPriority; import org.chromium.android_webview.renderer_priority.RendererPriority;
import org.chromium.base.BuildInfo; import org.chromium.base.BuildInfo;
...@@ -70,6 +69,7 @@ import org.chromium.base.metrics.CachedMetrics.TimesHistogramSample; ...@@ -70,6 +69,7 @@ import org.chromium.base.metrics.CachedMetrics.TimesHistogramSample;
import org.chromium.base.metrics.ScopedSysTraceEvent; import org.chromium.base.metrics.ScopedSysTraceEvent;
import org.chromium.base.task.PostTask; import org.chromium.base.task.PostTask;
import org.chromium.components.autofill.AutofillProvider; import org.chromium.components.autofill.AutofillProvider;
import org.chromium.components.embedder_support.application.ClassLoaderContextWrapperFactory;
import org.chromium.content_public.browser.NavigationHistory; import org.chromium.content_public.browser.NavigationHistory;
import org.chromium.content_public.browser.SmartClipProvider; import org.chromium.content_public.browser.SmartClipProvider;
import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.UiThreadTaskTraits;
...@@ -249,7 +249,7 @@ class WebViewChromium implements WebViewProvider, WebViewProvider.ScrollDelegate ...@@ -249,7 +249,7 @@ class WebViewChromium implements WebViewProvider, WebViewProvider.ScrollDelegate
mWebView = webView; mWebView = webView;
mWebViewPrivate = webViewPrivate; mWebViewPrivate = webViewPrivate;
mHitTestResult = new WebView.HitTestResult(); mHitTestResult = new WebView.HitTestResult();
mContext = ResourcesContextWrapperFactory.get(mWebView.getContext()); mContext = ClassLoaderContextWrapperFactory.get(mWebView.getContext());
mAppTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion; mAppTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
mFactory = factory; mFactory = factory;
mShouldDisableThreadChecking = shouldDisableThreadChecking; mShouldDisableThreadChecking = shouldDisableThreadChecking;
......
...@@ -35,7 +35,6 @@ import org.chromium.android_webview.AwBrowserContext; ...@@ -35,7 +35,6 @@ import org.chromium.android_webview.AwBrowserContext;
import org.chromium.android_webview.AwBrowserProcess; import org.chromium.android_webview.AwBrowserProcess;
import org.chromium.android_webview.AwSettings; import org.chromium.android_webview.AwSettings;
import org.chromium.android_webview.AwSwitches; import org.chromium.android_webview.AwSwitches;
import org.chromium.android_webview.ResourcesContextWrapperFactory;
import org.chromium.android_webview.WebViewChromiumRunQueue; import org.chromium.android_webview.WebViewChromiumRunQueue;
import org.chromium.android_webview.common.CommandLineUtil; import org.chromium.android_webview.common.CommandLineUtil;
import org.chromium.base.BuildInfo; import org.chromium.base.BuildInfo;
...@@ -53,6 +52,7 @@ import org.chromium.base.library_loader.NativeLibraries; ...@@ -53,6 +52,7 @@ import org.chromium.base.library_loader.NativeLibraries;
import org.chromium.base.metrics.CachedMetrics.TimesHistogramSample; import org.chromium.base.metrics.CachedMetrics.TimesHistogramSample;
import org.chromium.base.metrics.ScopedSysTraceEvent; import org.chromium.base.metrics.ScopedSysTraceEvent;
import org.chromium.components.autofill.AutofillProvider; import org.chromium.components.autofill.AutofillProvider;
import org.chromium.components.embedder_support.application.ClassLoaderContextWrapperFactory;
import org.chromium.content_public.browser.LGEmailActionModeWorkaround; import org.chromium.content_public.browser.LGEmailActionModeWorkaround;
import java.io.File; import java.io.File;
...@@ -264,7 +264,7 @@ public class WebViewChromiumFactoryProvider implements WebViewFactoryProvider { ...@@ -264,7 +264,7 @@ public class WebViewChromiumFactoryProvider implements WebViewFactoryProvider {
} }
// WebView needs to make sure to always use the wrapped application context. // WebView needs to make sure to always use the wrapped application context.
ContextUtils.initApplicationContext(ResourcesContextWrapperFactory.get(ctx)); ContextUtils.initApplicationContext(ClassLoaderContextWrapperFactory.get(ctx));
// Find the package ID for the package that WebView's resources come from. // Find the package ID for the package that WebView's resources come from.
// This will be the donor package if there is one, not our main package. // This will be the donor package if there is one, not our main package.
......
...@@ -4,121 +4,18 @@ ...@@ -4,121 +4,18 @@
package org.chromium.android_webview; package org.chromium.android_webview;
import android.content.ComponentCallbacks;
import android.content.Context; import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.view.LayoutInflater;
import org.chromium.base.ContextUtils; import org.chromium.components.embedder_support.application.ClassLoaderContextWrapperFactory;
import java.lang.ref.WeakReference;
import java.util.WeakHashMap;
/** /**
* This class allows us to wrap the application context so that the WebView implementation can * This class was migrated to embedder_support; this forwarding wrapper exists to avoid breaking
* correctly reference both org.chromium.* and application classes which is necessary to properly * downstream code until it's updated.
* inflate UI.
*/ */
public class ResourcesContextWrapperFactory { public class ResourcesContextWrapperFactory {
private ResourcesContextWrapperFactory() {} private ResourcesContextWrapperFactory() {}
// Note WeakHashMap only guarantees that keys are weakly held, and ContextWrapper holds a strong
// reference to the wrapped context. So need a WeakReference here to ensure the Context does not
// leak.
private static final WeakHashMap<Context, WeakReference<WebViewContextWrapper>> sCtxToWrapper =
new WeakHashMap<>();
private static final Object sLock = new Object();
public static Context get(Context ctx) { public static Context get(Context ctx) {
// Avoid double-wrapping a context. return ClassLoaderContextWrapperFactory.get(ctx);
if (ctx instanceof WebViewContextWrapper) {
return ctx;
}
WebViewContextWrapper wrapper = null;
synchronized (sLock) {
WeakReference<WebViewContextWrapper> ref = sCtxToWrapper.get(ctx);
wrapper = (ref == null) ? null : ref.get();
if (wrapper == null) {
wrapper = new WebViewContextWrapper(ctx);
sCtxToWrapper.put(ctx, new WeakReference<>(wrapper));
}
}
return wrapper;
}
private static class WebViewContextWrapper extends ContextWrapper {
private Context mApplicationContext;
public WebViewContextWrapper(Context base) {
super(base);
}
@Override
public ClassLoader getClassLoader() {
final ClassLoader appCl = getBaseContext().getClassLoader();
final ClassLoader webViewCl = this.getClass().getClassLoader();
return new ClassLoader() {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// First look in the WebViewProvider class loader.
try {
return webViewCl.loadClass(name);
} catch (ClassNotFoundException e) {
// Look in the app class loader; allowing it to throw
// ClassNotFoundException.
return appCl.loadClass(name);
}
}
};
}
@Override
public Object getSystemService(String name) {
if (Context.LAYOUT_INFLATER_SERVICE.equals(name)) {
LayoutInflater i = (LayoutInflater) getBaseContext().getSystemService(name);
return i.cloneInContext(this);
} else {
return getBaseContext().getSystemService(name);
}
}
@Override
@SuppressWarnings("NoContextGetApplicationContext")
public Context getApplicationContext() {
if (mApplicationContext == null) {
Context appCtx = getBaseContext().getApplicationContext();
if (appCtx == getBaseContext()) {
mApplicationContext = this;
} else {
mApplicationContext = get(appCtx);
}
}
return mApplicationContext;
}
@Override
public void registerComponentCallbacks(ComponentCallbacks callback) {
// We have to override registerComponentCallbacks and unregisterComponentCallbacks
// since they call getApplicationContext().[un]registerComponentCallbacks()
// which causes us to go into a loop.
getBaseContext().registerComponentCallbacks(callback);
}
@Override
public void unregisterComponentCallbacks(ComponentCallbacks callback) {
getBaseContext().unregisterComponentCallbacks(callback);
}
@Override
public void startActivity(Intent intent) {
if (ContextUtils.activityFromContext(this) == null) {
// FLAG_ACTIVITY_NEW_TASK is needed to start activities from a non-activity
// context.
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
super.startActivity(intent);
}
} }
} }
...@@ -8,7 +8,10 @@ android_library("application_java") { ...@@ -8,7 +8,10 @@ android_library("application_java") {
deps = [ deps = [
"//base:base_java", "//base:base_java",
] ]
java_files = [ "java/src/org/chromium/components/embedder_support/application/FontPreloadingWorkaround.java" ] java_files = [
"java/src/org/chromium/components/embedder_support/application/ClassLoaderContextWrapperFactory.java",
"java/src/org/chromium/components/embedder_support/application/FontPreloadingWorkaround.java",
]
} }
static_library("view") { static_library("view") {
......
// Copyright 2014 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.components.embedder_support.application;
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.view.LayoutInflater;
import org.chromium.base.ContextUtils;
import java.lang.ref.WeakReference;
import java.util.WeakHashMap;
/**
* This class allows us to wrap the application context so that a Chromium implementation loaded
* from a separate APK can correctly reference both org.chromium.* and application classes which is
* necessary to properly inflate UI.
*/
public class ClassLoaderContextWrapperFactory {
private ClassLoaderContextWrapperFactory() {}
// Note WeakHashMap only guarantees that keys are weakly held, and ContextWrapper holds a strong
// reference to the wrapped context. So need a WeakReference here to ensure the Context does not
// leak.
private static final WeakHashMap<Context, WeakReference<ClassLoaderContextWrapper>>
sCtxToWrapper = new WeakHashMap<>();
private static final Object sLock = new Object();
public static Context get(Context ctx) {
// Avoid double-wrapping a context.
if (ctx instanceof ClassLoaderContextWrapper) {
return ctx;
}
ClassLoaderContextWrapper wrapper = null;
synchronized (sLock) {
WeakReference<ClassLoaderContextWrapper> ref = sCtxToWrapper.get(ctx);
wrapper = (ref == null) ? null : ref.get();
if (wrapper == null) {
wrapper = new ClassLoaderContextWrapper(ctx);
sCtxToWrapper.put(ctx, new WeakReference<>(wrapper));
}
}
return wrapper;
}
private static class ClassLoaderContextWrapper extends ContextWrapper {
private Context mApplicationContext;
public ClassLoaderContextWrapper(Context base) {
super(base);
}
@Override
public ClassLoader getClassLoader() {
final ClassLoader appCl = getBaseContext().getClassLoader();
final ClassLoader chromiumCl = ClassLoaderContextWrapper.class.getClassLoader();
return new ClassLoader() {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// First look in the Chromium class loader.
try {
return chromiumCl.loadClass(name);
} catch (ClassNotFoundException e) {
// Look in the app class loader; allowing it to throw
// ClassNotFoundException.
return appCl.loadClass(name);
}
}
};
}
@Override
public Object getSystemService(String name) {
if (Context.LAYOUT_INFLATER_SERVICE.equals(name)) {
LayoutInflater i = (LayoutInflater) getBaseContext().getSystemService(name);
return i.cloneInContext(this);
} else {
return getBaseContext().getSystemService(name);
}
}
@Override
@SuppressWarnings("NoContextGetApplicationContext")
public Context getApplicationContext() {
if (mApplicationContext == null) {
Context appCtx = getBaseContext().getApplicationContext();
if (appCtx == getBaseContext()) {
mApplicationContext = this;
} else {
mApplicationContext = get(appCtx);
}
}
return mApplicationContext;
}
@Override
public void registerComponentCallbacks(ComponentCallbacks callback) {
// We have to override registerComponentCallbacks and unregisterComponentCallbacks
// since they call getApplicationContext().[un]registerComponentCallbacks()
// which causes us to go into a loop.
getBaseContext().registerComponentCallbacks(callback);
}
@Override
public void unregisterComponentCallbacks(ComponentCallbacks callback) {
getBaseContext().unregisterComponentCallbacks(callback);
}
@Override
public void startActivity(Intent intent) {
if (ContextUtils.activityFromContext(this) == null) {
// FLAG_ACTIVITY_NEW_TASK is needed to start activities from a non-activity
// context.
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
super.startActivity(intent);
}
}
}
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