Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / android_webview / glue / java / src / com / android / webview / chromium / WebViewDelegateFactory.java
blob27155fa94e2fc070285fddd672d0a173c1b35160
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package com.android.webview.chromium;
7 import android.app.Application;
8 import android.content.Context;
9 import android.content.pm.PackageInfo;
10 import android.content.res.AssetManager;
11 import android.content.res.Resources;
12 import android.graphics.Canvas;
13 import android.os.Trace;
14 import android.util.SparseArray;
15 import android.view.View;
17 import java.lang.reflect.Method;
19 /**
20 * Factory class for {@link WebViewDelegate com.android.webview.chromium.WebViewDelegate}s.
22 * <p>{@link WebViewDelegate com.android.webview.chromium.WebViewDelegate}s provide the same
23 * interface as {@link android.webkit.WebViewDelegate android.webkit.WebViewDelegate} but without
24 * a dependency on the webkit class. Defining our own
25 * {@link WebViewDelegate com.android.webview.chromium.WebViewDelegate} in frameworks/webview
26 * allows the WebView apk to be binary compatible with the API 21 version of the framework, in
27 * which {@link android.webkit.WebViewDelegate android.webkit.WebViewDelegate} had not yet been
28 * introduced.
30 * <p>The {@link WebViewDelegate com.android.webview.chromium.WebViewDelegate} interface and this
31 * factory class can be removed once we don't longer need to support WebView apk updates to devices
32 * running the API 21 version of the framework. At that point, we should use
33 * {@link android.webkit.WebViewDelegate android.webkit.WebViewDelegate} directly instead.
35 class WebViewDelegateFactory {
36 /**
37 * Copy of {@link android.webkit.WebViewDelegate android.webkit.WebViewDelegate}'s interface.
38 * See {@link WebViewDelegateFactory} for the reasons why this copy is needed.
40 interface WebViewDelegate {
41 /** @see android.webkit.WebViewDelegate.OnTraceEnabledChangeListener */
42 interface OnTraceEnabledChangeListener {
43 void onTraceEnabledChange(boolean enabled);
46 /** @see android.webkit.WebViewDelegate#setOnTraceEnabledChangeListener */
47 void setOnTraceEnabledChangeListener(final OnTraceEnabledChangeListener listener);
49 /** @see android.webkit.WebViewDelegate#isTraceTagEnabled */
50 boolean isTraceTagEnabled();
52 /** @see android.webkit.WebViewDelegate#canInvokeDrawGlFunctor */
53 boolean canInvokeDrawGlFunctor(View containerView);
55 /** @see android.webkit.WebViewDelegate#invokeDrawGlFunctor */
56 void invokeDrawGlFunctor(
57 View containerView, long nativeDrawGLFunctor, boolean waitForCompletion);
59 /** @see android.webkit.WebViewDelegate#callDrawGlFunction */
60 void callDrawGlFunction(Canvas canvas, long nativeDrawGLFunctor);
62 /** @see android.webkit.WebViewDelegate#detachDrawGlFunctor */
63 void detachDrawGlFunctor(View containerView, long nativeDrawGLFunctor);
65 /** @see android.webkit.WebViewDelegate#getPackageId */
66 int getPackageId(Resources resources, String packageName);
68 /** @see android.webkit.WebViewDelegate#getApplication */
69 Application getApplication();
71 /** @see android.webkit.WebViewDelegate#getErrorString */
72 String getErrorString(Context context, int errorCode);
74 /** @see android.webkit.WebViewDelegate#addWebViewAssetPath */
75 void addWebViewAssetPath(Context context);
78 /**
79 * Creates a {@link WebViewDelegate com.android.webview.chromium.WebViewDelegate} that proxies
80 * requests to the given {@link android.webkit.WebViewDelegate android.webkit.WebViewDelegate}.
82 * @return the created delegate
84 static WebViewDelegate createProxyDelegate(android.webkit.WebViewDelegate delegate) {
85 return new ProxyDelegate(delegate);
88 /**
89 * Creates a {@link WebViewDelegate com.android.webview.chromium.WebViewDelegate} compatible
90 * with the API 21 version of the framework in which
91 * {@link android.webkit.WebViewDelegate android.webkit.WebViewDelegate} had not yet been
92 * introduced.
94 * @return the created delegate
96 static WebViewDelegate createApi21CompatibilityDelegate() {
97 return new Api21CompatibilityDelegate();
101 * A {@link WebViewDelegate com.android.webview.chromium.WebViewDelegate} that proxies requests
102 * to a {@link android.webkit.WebViewDelegate android.webkit.WebViewDelegate}.
104 private static class ProxyDelegate implements WebViewDelegate {
105 android.webkit.WebViewDelegate mDelegate;
107 ProxyDelegate(android.webkit.WebViewDelegate delegate) {
108 mDelegate = delegate;
111 @Override
112 public void setOnTraceEnabledChangeListener(final OnTraceEnabledChangeListener listener) {
113 mDelegate.setOnTraceEnabledChangeListener(
114 new android.webkit.WebViewDelegate.OnTraceEnabledChangeListener() {
115 @Override
116 public void onTraceEnabledChange(boolean enabled) {
117 listener.onTraceEnabledChange(enabled);
122 @Override
123 public boolean isTraceTagEnabled() {
124 return mDelegate.isTraceTagEnabled();
127 @Override
128 public boolean canInvokeDrawGlFunctor(View containerView) {
129 return mDelegate.canInvokeDrawGlFunctor(containerView);
132 @Override
133 public void invokeDrawGlFunctor(
134 View containerView, long nativeDrawGLFunctor, boolean waitForCompletion) {
135 mDelegate.invokeDrawGlFunctor(containerView, nativeDrawGLFunctor, waitForCompletion);
138 @Override
139 public void callDrawGlFunction(Canvas canvas, long nativeDrawGLFunctor) {
140 mDelegate.callDrawGlFunction(canvas, nativeDrawGLFunctor);
143 @Override
144 public void detachDrawGlFunctor(View containerView, long nativeDrawGLFunctor) {
145 mDelegate.detachDrawGlFunctor(containerView, nativeDrawGLFunctor);
148 @Override
149 public int getPackageId(Resources resources, String packageName) {
150 return mDelegate.getPackageId(resources, packageName);
153 @Override
154 public Application getApplication() {
155 return mDelegate.getApplication();
158 @Override
159 public String getErrorString(Context context, int errorCode) {
160 return mDelegate.getErrorString(context, errorCode);
163 @Override
164 public void addWebViewAssetPath(Context context) {
165 mDelegate.addWebViewAssetPath(context);
170 * A {@link WebViewDelegate com.android.webview.chromium.WebViewDelegate} compatible with the
171 * API 21 version of the framework in which
172 * {@link android.webkit.WebViewDelegate android.webkit.WebViewDelegate} had not yet been
173 * introduced.
175 * <p>This class implements the
176 * {@link WebViewDelegate com.android.webview.chromium.WebViewDelegate} functionality by using
177 * reflection to call into hidden frameworks APIs released in the API-21 version of the
178 * framework.
180 private static class Api21CompatibilityDelegate implements WebViewDelegate {
181 /** Copy of Trace.TRACE_TAG_WEBVIEW */
182 private static final long TRACE_TAG_WEBVIEW = 1L << 4;
184 /** Hidden APIs released in the API 21 version of the framework */
185 private final Method mIsTagEnabledMethod;
186 private final Method mAddChangeCallbackMethod;
187 private final Method mGetViewRootImplMethod;
188 private final Method mInvokeFunctorMethod;
189 private final Method mCallDrawGLFunctionMethod;
190 private final Method mDetachFunctorMethod;
191 private final Method mGetAssignedPackageIdentifiersMethod;
192 private final Method mAddAssetPathMethod;
193 private final Method mCurrentApplicationMethod;
194 private final Method mGetStringMethod;
195 private final Method mGetLoadedPackageInfoMethod;
197 Api21CompatibilityDelegate() {
198 try {
199 // Important: This reflection essentially defines a snapshot of some hidden APIs
200 // at version 21 of the framework for compatibility reasons, and the reflection
201 // should not be changed even if those hidden APIs change in future releases.
202 mIsTagEnabledMethod = Trace.class.getMethod("isTagEnabled", long.class);
203 mAddChangeCallbackMethod = Class.forName("android.os.SystemProperties")
204 .getMethod("addChangeCallback", Runnable.class);
205 mGetViewRootImplMethod = View.class.getMethod("getViewRootImpl");
206 mInvokeFunctorMethod =
207 Class.forName("android.view.ViewRootImpl")
208 .getMethod("invokeFunctor", long.class, boolean.class);
209 mDetachFunctorMethod = Class.forName("android.view.ViewRootImpl")
210 .getMethod("detachFunctor", long.class);
211 mCallDrawGLFunctionMethod = Class.forName("android.view.HardwareCanvas")
212 .getMethod("callDrawGLFunction", long.class);
213 mGetAssignedPackageIdentifiersMethod =
214 AssetManager.class.getMethod("getAssignedPackageIdentifiers");
215 mAddAssetPathMethod = AssetManager.class.getMethod("addAssetPath", String.class);
216 mCurrentApplicationMethod =
217 Class.forName("android.app.ActivityThread").getMethod("currentApplication");
218 mGetStringMethod = Class.forName("android.net.http.ErrorStrings")
219 .getMethod("getString", int.class, Context.class);
220 mGetLoadedPackageInfoMethod = Class.forName("android.webkit.WebViewFactory")
221 .getMethod("getLoadedPackageInfo");
222 } catch (Exception e) {
223 throw new RuntimeException("Invalid reflection", e);
227 @Override
228 public void setOnTraceEnabledChangeListener(final OnTraceEnabledChangeListener listener) {
229 try {
230 mAddChangeCallbackMethod.invoke(null, new Runnable() {
231 @Override
232 public void run() {
233 listener.onTraceEnabledChange(isTraceTagEnabled());
236 } catch (Exception e) {
237 throw new RuntimeException("Invalid reflection", e);
241 @Override
242 public boolean isTraceTagEnabled() {
243 try {
244 return ((Boolean) mIsTagEnabledMethod.invoke(null, TRACE_TAG_WEBVIEW));
245 } catch (Exception e) {
246 throw new RuntimeException("Invalid reflection", e);
250 @Override
251 public boolean canInvokeDrawGlFunctor(View containerView) {
252 try {
253 Object viewRootImpl = mGetViewRootImplMethod.invoke(containerView);
254 // viewRootImpl can be null during teardown when window is leaked.
255 return viewRootImpl != null;
256 } catch (Exception e) {
257 throw new RuntimeException("Invalid reflection", e);
261 @Override
262 public void invokeDrawGlFunctor(
263 View containerView, long nativeDrawGLFunctor, boolean waitForCompletion) {
264 try {
265 Object viewRootImpl = mGetViewRootImplMethod.invoke(containerView);
266 if (viewRootImpl != null) {
267 mInvokeFunctorMethod.invoke(
268 viewRootImpl, nativeDrawGLFunctor, waitForCompletion);
270 } catch (Exception e) {
271 throw new RuntimeException("Invalid reflection", e);
275 @Override
276 public void callDrawGlFunction(Canvas canvas, long nativeDrawGLFunctor) {
277 try {
278 mCallDrawGLFunctionMethod.invoke(canvas, nativeDrawGLFunctor);
279 } catch (Exception e) {
280 throw new RuntimeException("Invalid reflection", e);
284 @Override
285 public void detachDrawGlFunctor(View containerView, long nativeDrawGLFunctor) {
286 try {
287 Object viewRootImpl = mGetViewRootImplMethod.invoke(containerView);
288 if (viewRootImpl != null) {
289 mDetachFunctorMethod.invoke(viewRootImpl, nativeDrawGLFunctor);
291 } catch (Exception e) {
292 throw new RuntimeException("Invalid reflection", e);
296 @Override
297 public int getPackageId(Resources resources, String packageName) {
298 try {
299 SparseArray packageIdentifiers =
300 (SparseArray) mGetAssignedPackageIdentifiersMethod.invoke(
301 resources.getAssets());
302 for (int i = 0; i < packageIdentifiers.size(); i++) {
303 final String name = (String) packageIdentifiers.valueAt(i);
305 if (packageName.equals(name)) {
306 return packageIdentifiers.keyAt(i);
309 } catch (Exception e) {
310 throw new RuntimeException("Invalid reflection", e);
312 throw new RuntimeException("Package not found: " + packageName);
315 @Override
316 public Application getApplication() {
317 try {
318 return (Application) mCurrentApplicationMethod.invoke(null);
319 } catch (Exception e) {
320 throw new RuntimeException("Invalid reflection", e);
324 @Override
325 public String getErrorString(Context context, int errorCode) {
326 try {
327 return (String) mGetStringMethod.invoke(null, errorCode, context);
328 } catch (Exception e) {
329 throw new RuntimeException("Invalid reflection", e);
333 @Override
334 public void addWebViewAssetPath(Context context) {
335 try {
336 PackageInfo info = (PackageInfo) mGetLoadedPackageInfoMethod.invoke(null);
337 mAddAssetPathMethod.invoke(context.getAssets(), info.applicationInfo.sourceDir);
338 } catch (Exception e) {
339 throw new RuntimeException("Invalid reflection", e);