summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustav Sennton <gsennton@google.com>2018-04-27 11:13:24 +0000
committerCommit Bot <commit-bot@chromium.org>2018-04-27 11:13:24 +0000
commit2c18fa68c27280f1ba7659fd6a74c1c3d1e317e1 (patch)
tree58b6dac08a47c89130ce36445b57610b53bd43eb
parent54c8c4fac0e1e1df7db4cac6ab918583a9575db2 (diff)
downloadwebview_support_interfaces-2c18fa68c27280f1ba7659fd6a74c1c3d1e317e1.tar.gz
[android webview] properly support per-method feature detection.
To properly support per-method feature detection we need to allow converting back and forth between support library and frameworks classes. This CL adds support for converting between webkit and support library objects for already implemented post-L classes: 1. ServiceWorkerController 2. ServiceWorkerWebSettings 3. WebResourceError Bug: 836339 Change-Id: I334d17153eb8d71834e1fafc43676bc2c706b4e2 Reviewed-on: https://chromium-review.googlesource.com/1027815 Commit-Queue: Gustav Sennton <gsennton@chromium.org> Reviewed-by: Richard Coles <torne@chromium.org> Reviewed-by: Nate Fischer <ntfschr@chromium.org> Cr-Original-Commit-Position: refs/heads/master@{#554356} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: db9520ce98b750e578caf7270eee0c5130a0e1fb
-rw-r--r--src/org/chromium/support_lib_boundary/WebkitToCompatConverterBoundaryInterface.java36
-rw-r--r--src/org/chromium/support_lib_boundary/util/BoundaryInterfaceReflectionUtil.java55
2 files changed, 76 insertions, 15 deletions
diff --git a/src/org/chromium/support_lib_boundary/WebkitToCompatConverterBoundaryInterface.java b/src/org/chromium/support_lib_boundary/WebkitToCompatConverterBoundaryInterface.java
index 12690f2..b79797d 100644
--- a/src/org/chromium/support_lib_boundary/WebkitToCompatConverterBoundaryInterface.java
+++ b/src/org/chromium/support_lib_boundary/WebkitToCompatConverterBoundaryInterface.java
@@ -14,9 +14,41 @@ import java.lang.reflect.InvocationHandler;
* objects.
*/
public interface WebkitToCompatConverterBoundaryInterface {
+ // ====================================================
+ // Pre-L classes, these only need conversion methods from webkit -> support library since their
+ // support library implementations are all static methods.
+ // Webkit -> support library conversions.
+ // ====================================================
+
/* SupportLibraryWebSettings */ InvocationHandler convertSettings(WebSettings webSettings);
- /* SupportLibServiceWorkerSettings */ InvocationHandler convertServiceWorkerSettings(
- /* ServiceWorkerWebSettings */ Object serviceWorkerWebSettings);
/* SupportLibraryWebResourceRequest */ InvocationHandler convertWebResourceRequest(
WebResourceRequest request);
+
+ // ====================================================
+ // Post-L classes, these classes need conversion methods both from webkit -> support library and
+ // back because they have full functional implementations in the support library (so some APIs
+ // will return the support library version of the class).
+ //
+ // None of the following methods can be called before the API level in which the related webkit
+ // class was introduced (e.g. API level 24 for convertServiceWorkerSettings since
+ // android.webkit.ServiceWorkerWebSettings was introduced at API level 24).
+ //
+ // Note that these methods use the 'Object' class to represent webkit classes because these are
+ // post-L webkit classes. Whenever we would create a Proxy for the version of
+ // WebkitToCompatConverterBoundaryInterface using actual webkit classes on an L device the Proxy
+ // class would fail to look up post-L webkit classes and thus cause a crash, see
+ // http://crbug.com/831554.
+ // ====================================================
+
+ // ServiceWorkerWebSettings
+ /* SupportLibServiceWorkerSettings */ InvocationHandler convertServiceWorkerSettings(
+ /* ServiceWorkerWebSettings */ Object serviceWorkerWebSettings);
+ /* ServiceWorkerWebSettings */ Object convertServiceWorkerSettings(
+ /* SupportLibServiceWorkerSettings */ InvocationHandler serviceWorkerSettings);
+
+ // WebResourceError
+ /* SupportLibWebResourceError */ InvocationHandler convertWebResourceError(
+ /* WebResourceError */ Object webResourceError);
+ /* WebResourceError */ Object convertWebResourceError(
+ /* SupportLibWebResourceError */ InvocationHandler webResourceError);
}
diff --git a/src/org/chromium/support_lib_boundary/util/BoundaryInterfaceReflectionUtil.java b/src/org/chromium/support_lib_boundary/util/BoundaryInterfaceReflectionUtil.java
index 1e741bb..bbf6b5b 100644
--- a/src/org/chromium/support_lib_boundary/util/BoundaryInterfaceReflectionUtil.java
+++ b/src/org/chromium/support_lib_boundary/util/BoundaryInterfaceReflectionUtil.java
@@ -56,20 +56,49 @@ public class BoundaryInterfaceReflectionUtil {
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
public static InvocationHandler createInvocationHandlerFor(final Object delegate) {
- final ClassLoader delegateLoader = delegate.getClass().getClassLoader();
- return new InvocationHandler() {
- @Override
- public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
- try {
- return dupeMethod(method, delegateLoader).invoke(delegate, objects);
- } catch (InvocationTargetException e) {
- // If something went wrong, ensure we throw the original exception.
- throw e.getTargetException();
- } catch (ReflectiveOperationException e) {
- throw new RuntimeException("Reflection failed for method " + method, e);
- }
+ return new InvocationHandlerWithDelegateGetter(delegate);
+ }
+
+ /**
+ * Assuming that the given InvocationHandler was created in the current classloader and is an
+ * InvocationHandlerWithDelegateGetter, return the object the InvocationHandler delegates its
+ * method calls to.
+ */
+ public static Object getDelegateFromInvocationHandler(InvocationHandler invocationHandler) {
+ InvocationHandlerWithDelegateGetter objectHolder =
+ (InvocationHandlerWithDelegateGetter) invocationHandler;
+ return objectHolder.getDelegate();
+ }
+
+ /**
+ * An InvocationHandler storing the original object that method calls are delegated to.
+ * This allows us to pass InvocationHandlers across the support library boundary and later
+ * unwrap the objects used as delegates within those InvocationHandlers.
+ */
+ @TargetApi(Build.VERSION_CODES.KITKAT)
+ private static class InvocationHandlerWithDelegateGetter implements InvocationHandler {
+ private final Object mDelegate;
+
+ public InvocationHandlerWithDelegateGetter(final Object delegate) {
+ mDelegate = delegate;
+ }
+
+ @Override
+ public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
+ final ClassLoader delegateLoader = mDelegate.getClass().getClassLoader();
+ try {
+ return dupeMethod(method, delegateLoader).invoke(mDelegate, objects);
+ } catch (InvocationTargetException e) {
+ // If something went wrong, ensure we throw the original exception.
+ throw e.getTargetException();
+ } catch (ReflectiveOperationException e) {
+ throw new RuntimeException("Reflection failed for method " + method, e);
}
- };
+ }
+
+ public Object getDelegate() {
+ return mDelegate;
+ }
}
/**