| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package com.android.webview.chromium; | 5 package com.android.webview.chromium; |
| 6 | 6 |
| 7 import android.content.ComponentCallbacks; | 7 import android.content.ComponentCallbacks; |
| 8 import android.content.Context; | 8 import android.content.Context; |
| 9 import android.content.ContextWrapper; | 9 import android.content.ContextWrapper; |
| 10 import android.view.LayoutInflater; | 10 import android.view.LayoutInflater; |
| 11 | 11 |
| 12 import org.chromium.base.annotations.SuppressFBWarnings; | 12 import org.chromium.base.annotations.SuppressFBWarnings; |
| 13 | 13 |
| 14 import java.util.WeakHashMap; | |
| 15 | |
| 16 /** | 14 /** |
| 17 * This class allows us to wrap the application context so that the WebView impl
ementation can | 15 * This class allows us to wrap the application context so that the WebView impl
ementation can |
| 18 * correctly reference both org.chromium.* and application classes which is nece
ssary to properly | 16 * correctly reference both org.chromium.* and application classes which is nece
ssary to properly |
| 19 * inflate UI. We keep a weak map from contexts to wrapped contexts to avoid co
nstantly re-wrapping | 17 * inflate UI. |
| 20 * or doubly wrapping contexts. | |
| 21 */ | 18 */ |
| 22 public class ResourcesContextWrapperFactory { | 19 public class ResourcesContextWrapperFactory { |
| 23 private static WeakHashMap<Context, ContextWrapper> sCtxToWrapper = | |
| 24 new WeakHashMap<Context, ContextWrapper>(); | |
| 25 private static final Object sLock = new Object(); | |
| 26 | |
| 27 private ResourcesContextWrapperFactory() {} | 20 private ResourcesContextWrapperFactory() {} |
| 28 | 21 |
| 29 public static Context get(Context ctx) { | 22 public static Context get(Context ctx) { |
| 30 ContextWrapper wrappedCtx; | 23 // Avoid double-wrapping a context. |
| 31 synchronized (sLock) { | 24 if (ctx instanceof WebViewContextWrapper) { |
| 32 wrappedCtx = sCtxToWrapper.get(ctx); | 25 return ctx; |
| 33 if (wrappedCtx == null) { | 26 } |
| 34 wrappedCtx = createWrapper(ctx); | 27 return new WebViewContextWrapper(ctx); |
| 35 sCtxToWrapper.put(ctx, wrappedCtx); | 28 } |
| 29 |
| 30 private static class WebViewContextWrapper extends ContextWrapper { |
| 31 private Context mApplicationContext; |
| 32 |
| 33 public WebViewContextWrapper(Context base) { |
| 34 super(base); |
| 35 } |
| 36 |
| 37 @SuppressFBWarnings("DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED") |
| 38 @Override |
| 39 public ClassLoader getClassLoader() { |
| 40 final ClassLoader appCl = getBaseContext().getClassLoader(); |
| 41 final ClassLoader webViewCl = this.getClass().getClassLoader(); |
| 42 return new ClassLoader() { |
| 43 @Override |
| 44 protected Class<?> findClass(String name) throws ClassNotFoundEx
ception { |
| 45 // First look in the WebViewProvider class loader. |
| 46 try { |
| 47 return webViewCl.loadClass(name); |
| 48 } catch (ClassNotFoundException e) { |
| 49 // Look in the app class loader; allowing it to throw |
| 50 // ClassNotFoundException. |
| 51 return appCl.loadClass(name); |
| 52 } |
| 53 } |
| 54 }; |
| 55 } |
| 56 |
| 57 @Override |
| 58 public Object getSystemService(String name) { |
| 59 if (Context.LAYOUT_INFLATER_SERVICE.equals(name)) { |
| 60 LayoutInflater i = (LayoutInflater) getBaseContext().getSystemSe
rvice(name); |
| 61 return i.cloneInContext(this); |
| 62 } else { |
| 63 return getBaseContext().getSystemService(name); |
| 36 } | 64 } |
| 37 } | 65 } |
| 38 return wrappedCtx; | |
| 39 } | |
| 40 | 66 |
| 41 private static ContextWrapper createWrapper(final Context ctx) { | 67 @Override |
| 42 return new ContextWrapper(ctx) { | 68 public Context getApplicationContext() { |
| 43 private Context mApplicationContext; | 69 if (mApplicationContext == null) { |
| 44 | 70 Context appCtx = getBaseContext().getApplicationContext(); |
| 45 @SuppressFBWarnings("DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED") | 71 if (appCtx == getBaseContext()) { |
| 46 @Override | 72 mApplicationContext = this; |
| 47 public ClassLoader getClassLoader() { | |
| 48 final ClassLoader appCl = getBaseContext().getClassLoader(); | |
| 49 final ClassLoader webViewCl = this.getClass().getClassLoader(); | |
| 50 return new ClassLoader() { | |
| 51 @Override | |
| 52 protected Class<?> findClass(String name) throws ClassNotFou
ndException { | |
| 53 // First look in the WebViewProvider class loader. | |
| 54 try { | |
| 55 return webViewCl.loadClass(name); | |
| 56 } catch (ClassNotFoundException e) { | |
| 57 // Look in the app class loader; allowing it to thro
w | |
| 58 // ClassNotFoundException. | |
| 59 return appCl.loadClass(name); | |
| 60 } | |
| 61 } | |
| 62 }; | |
| 63 } | |
| 64 | |
| 65 @Override | |
| 66 public Object getSystemService(String name) { | |
| 67 if (Context.LAYOUT_INFLATER_SERVICE.equals(name)) { | |
| 68 LayoutInflater i = (LayoutInflater) getBaseContext().getSyst
emService(name); | |
| 69 return i.cloneInContext(this); | |
| 70 } else { | 73 } else { |
| 71 return getBaseContext().getSystemService(name); | 74 mApplicationContext = get(appCtx); |
| 72 } | 75 } |
| 73 } | 76 } |
| 77 return mApplicationContext; |
| 78 } |
| 74 | 79 |
| 75 @Override | 80 @Override |
| 76 public Context getApplicationContext() { | 81 public void registerComponentCallbacks(ComponentCallbacks callback) { |
| 77 if (mApplicationContext == null) { | 82 // We have to override registerComponentCallbacks and unregisterComp
onentCallbacks |
| 78 mApplicationContext = get(ctx.getApplicationContext()); | 83 // since they call getApplicationContext().[un]registerComponentCall
backs() |
| 79 } | 84 // which causes us to go into a loop. |
| 80 return mApplicationContext; | 85 getBaseContext().registerComponentCallbacks(callback); |
| 81 } | 86 } |
| 82 | 87 |
| 83 @Override | 88 @Override |
| 84 public void registerComponentCallbacks(ComponentCallbacks callback)
{ | 89 public void unregisterComponentCallbacks(ComponentCallbacks callback) { |
| 85 // We have to override registerComponentCallbacks and unregister
ComponentCallbacks | 90 getBaseContext().unregisterComponentCallbacks(callback); |
| 86 // since they call getApplicationContext().[un]registerComponent
Callbacks() | 91 } |
| 87 // which causes us to go into a loop. | |
| 88 ctx.registerComponentCallbacks(callback); | |
| 89 } | |
| 90 | |
| 91 @Override | |
| 92 public void unregisterComponentCallbacks(ComponentCallbacks callback
) { | |
| 93 ctx.unregisterComponentCallbacks(callback); | |
| 94 } | |
| 95 }; | |
| 96 } | 92 } |
| 97 } | 93 } |
| OLD | NEW |