Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(406)

Side by Side Diff: components/cronet/android/api/src/org/chromium/net/CronetProvider.java

Issue 2660963002: Cronet: a framework to provide alternative Cronet implementations (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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.
4
5 package org.chromium.net;
6
7 import android.content.Context;
8 import android.util.Log;
9
10 import java.lang.reflect.Constructor;
11 import java.lang.reflect.InvocationTargetException;
12 import java.util.ArrayList;
13 import java.util.List;
14
15 /**
16 * Provides a factory method to create {@link CronetEngine.Builder} instances.
17 * A {@code CronetEngine.Builder} instance can be used to create a specific {@li nk CronetEngine}
18 * implementation. To get the list of available {@link CronetProvider}s call
19 * {@link #getAllProviders(Context)}.
20 * <p/>
21 * <b>NOTE:</b> This class is for advanced users that want to select a particula r
22 * Cronet implementation. Most users should simply use {@code new} {@link
23 * CronetEngine.Builder#CronetEngine.Builder(android.content.Context)}.
24 *
25 * {@hide}
26 */
27 public abstract class CronetProvider {
28 /**
29 * String returned by {@link CronetProvider#getName} for {@link CronetProvid er}
30 * that provides native Cronet implementation packaged inside an application .
31 * This implementation offers significantly higher performance relative to t he
32 * fallback Cronet implementations (see {@link #PROVIDER_NAME_FALLBACK}).
33 */
34 public static final String PROVIDER_NAME_APP_PACKAGED = "App-Packaged-Cronet -Provider";
35
36 /**
37 * String returned by {@link CronetProvider#getName} for {@link CronetProvid er}
38 * that provides Cronet implementation based on the system's
39 * {@link java.net.HttpURLConnection} implementation. This implementation
40 * offers significantly degraded performance relative to native Cronet
41 * implementations (see {@link #PROVIDER_NAME_APP_PACKAGED}).
42 */
43 public static final String PROVIDER_NAME_FALLBACK = "Fallback-Cronet-Provide r";
44
45 /**
46 * The name of an optional key in the app string resource file that contains the class name of
47 * an alternative {@code CronetProvider} implementation.
48 */
49 private static final String RES_KEY_CRONET_IMPL_CLASS = "CronetProviderClass Name";
50
51 private static final String TAG = CronetProvider.class.getSimpleName();
52
53 protected final Context mContext;
54
55 protected CronetProvider(Context context) {
56 mContext = context;
57 }
58
59 /**
60 * Creates and returns an instance of {@link CronetEngine.Builder}.
61 * <p/>
62 * <b>NOTE:</b> This class is for advanced users that want to select a parti cular
63 * Cronet implementation. Most users should simply use {@code new} {@link
64 * CronetEngine.Builder#CronetEngine.Builder(android.content.Context)}.
65 *
66 * @return {@code CronetEngine.Builder}.
67 * @throws IllegalStateException if the provider is not enabled (see {@link #isEnabled}.
68 */
69 public abstract CronetEngine.Builder createBuilder();
70
71 /**
72 * Returns the provider name. The well-know provider names include:
73 * <ul>
74 * <li>{@link #PROVIDER_NAME_APP_PACKAGED}</li>
75 * <li>{@link #PROVIDER_NAME_FALLBACK}</li>
76 * </ul>
77 *
78 * @return provider name.
79 */
80 public abstract String getName();
81
82 /**
83 * Returns the provider version. The version can be used to select the newes t
84 * available provider if multiple providers are available.
85 *
86 * @return provider version.
87 */
88 public abstract String getVersion();
89
90 /**
91 * Returns whether the provider is enabled and can be used to instantiate th e Cronet engine.
92 * A provider being out-of-date (older than the API) and needing updating is one potential
93 * reason it could be disabled. Please read the provider documentation for
94 * enablement procedure.
95 *
96 * @return {@code true} if the provider is enabled.
97 */
98 public abstract boolean isEnabled();
99
100 @Override
101 public String toString() {
102 return "["
103 + "class=" + getClass().getName() + ", "
104 + "name=" + getName() + ", "
105 + "version=" + getVersion() + ", "
106 + "enabled=" + isEnabled() + "]";
107 }
108
109 /**
110 * Name of the Java {@link CronetProvider} class.
111 */
112 private static final String JAVA_CRONET_PROVIDER_CLASS =
113 "org.chromium.net.impl.JavaCronetProvider";
114
115 /**
116 * Name of the native {@link CronetProvider} class.
117 */
118 private static final String NATIVE_CRONET_PROVIDER_CLASS =
119 "org.chromium.net.impl.NativeCronetProvider";
120
121 /**
122 * Returns an unmodifiable list of all available {@link CronetProvider}s.
123 * The providers are returned in no particular order. Some of the returned
124 * providers may be in a disabled state and should be enabled by the invoker .
125 * See {@link CronetProvider#isEnabled()}.
126 *
127 * @return the list of available providers.
128 */
129 public static List<CronetProvider> getAllProviders(Context context) {
130 List<CronetProvider> providers = new ArrayList<>();
131 addCronetProviderFromResourceFile(context, providers);
132 addCronetProviderImplByClassName(context, NATIVE_CRONET_PROVIDER_CLASS, providers, false);
133 addCronetProviderImplByClassName(context, JAVA_CRONET_PROVIDER_CLASS, pr oviders, false);
134 return providers;
135 }
136
137 /**
138 * Attempts to add a new provider referenced by the class name to the end of the list.
139 *
140 * @param className the class name of the provider that should be instantiat ed.
141 * @param providers the list of providers to add the new provider to.
142 * @return {@code true} if the provider was added to the list; {@code false}
143 * if the provider couldn't be instantiated.
144 */
145 private static boolean addCronetProviderImplByClassName(
146 Context context, String className, List<CronetProvider> providers, b oolean logError) {
147 ClassLoader loader = context.getClassLoader();
148 try {
149 Class<? extends CronetProvider> providerClass =
150 loader.loadClass(className).asSubclass(CronetProvider.class) ;
151 Constructor<? extends CronetProvider> ctor =
152 providerClass.getConstructor(Context.class);
153 providers.add(ctor.newInstance(context));
154 return true;
155 } catch (InstantiationException e) {
156 logReflectiveOperationException(className, logError, e);
157 } catch (InvocationTargetException e) {
158 logReflectiveOperationException(className, logError, e);
159 } catch (NoSuchMethodException e) {
160 logReflectiveOperationException(className, logError, e);
161 } catch (IllegalAccessException e) {
162 logReflectiveOperationException(className, logError, e);
163 } catch (ClassNotFoundException e) {
164 logReflectiveOperationException(className, logError, e);
165 }
166 return false;
167 }
168
169 /**
170 * De-duplicates exception handling logic in {@link #addCronetProviderImplBy ClassName}.
171 * It should be removed when support of API Levels lower than 19 is deprecat ed.
172 */
173 private static void logReflectiveOperationException(
174 String className, boolean logError, Exception e) {
175 if (logError) {
176 Log.e(TAG, "Unable to load provider class: " + className, e);
177 } else {
178 Log.d(TAG, "Tried to load " + className + " provider class but it wa sn't"
179 + " included in the app classpath");
180 }
181 }
182
183 /**
184 * Attempts to add a provider specified in the app resource file to the end
185 * of the provider list.
186 *
187 * @param providers the list of providers to add the new provider to.
188 * @return {@code true} if the provider was added to the list; {@code false}
189 * if the app resources do not include the string with
190 * {@link #RES_KEY_CRONET_IMPL_CLASS} key.
191 * @throws RuntimeException if the provider cannot be found or instantiated.
192 */
193 private static boolean addCronetProviderFromResourceFile(
194 Context context, List<CronetProvider> providers) {
195 int resId = context.getResources().getIdentifier(
196 RES_KEY_CRONET_IMPL_CLASS, "string", context.getPackageName());
197 // Resource not found
198 if (resId == 0) {
199 // The resource wasn't included in the app; therefore, there is noth ing to add.
200 return false;
201 }
202 String className = context.getResources().getString(resId);
203
204 if (!addCronetProviderImplByClassName(context, className, providers, tru e)) {
205 throw new RuntimeException("Unable to instantiate Cronet implementat ion class "
206 + className + " that is listed as in the app string resource file under "
207 + RES_KEY_CRONET_IMPL_CLASS + " key");
208 }
209 return true;
210 }
211 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698