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