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

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

Issue 1363723002: [Cronet] Create Builders, rename UrlRequestContext to CronetEngine (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 3 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 2014 The Chromium Authors. All rights reserved.
mef 2015/09/25 21:32:19 2015?
pauljensen 2015/09/28 14:18:12 Done.
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 import android.util.Pair;
10
11 import org.json.JSONArray;
12 import org.json.JSONException;
13 import org.json.JSONObject;
14
15 import java.io.File;
16 import java.lang.reflect.Constructor;
17 import java.util.concurrent.Executor;
18
19 /**
20 * An engine to process {@link UrlRequest}s, which uses the best HTTP stack
21 * available on the current platform.
22 */
23 public abstract class CronetEngine {
24 /**
25 * A builder for {@link CronetEngine}s, which allows runtime configuration o f
26 * {@code CronetEngine}. Configuration options are set on the builder and
27 * then {@link #build} is called to create the {@code CronetEngine}.
28 */
29 public static class Builder {
30 private final JSONObject mConfig;
31 private Context mContext;
32
33 /**
34 * Default config enables SPDY, disables QUIC, SDCH and http cache.
35 */
36 public Builder() {
37 mConfig = new JSONObject();
38 enableLegacyMode(false);
39 enableQUIC(false);
40 enableHTTP2(true);
41 enableSDCH(false);
42 enableHttpCache(HTTP_CACHE_DISABLED, 0);
43 }
44
45 /**
46 * Creates a config from a JSON string, which was serialized using
47 * {@link #toString}.
48 */
49 public Builder(String json) throws JSONException {
50 mConfig = new JSONObject(json);
51 }
52
53 /**
54 * Overrides the user-agent header for all requests.
55 * @return the config to facilitate chaining.
56 */
57 public Builder setUserAgent(String userAgent) {
58 return putString(CronetEngineBuilderList.USER_AGENT, userAgent);
59 }
60
61 String userAgent() {
62 return mConfig.optString(CronetEngineBuilderList.USER_AGENT);
63 }
64
65 /**
66 * Sets directory for HTTP Cache and Cookie Storage. The directory must
67 * exist.
68 * @param value path to existing directory.
69 * @return the config to facilitate chaining.
70 */
71 public Builder setStoragePath(String value) {
72 if (!new File(value).isDirectory()) {
73 throw new IllegalArgumentException(
74 "Storage path must be set to existing directory");
75 }
76
77 return putString(CronetEngineBuilderList.STORAGE_PATH, value);
78 }
79
80 String storagePath() {
81 return mConfig.optString(CronetEngineBuilderList.STORAGE_PATH);
82 }
83
84 /**
85 * Sets whether falling back to implementation based on system's
86 * {@link java.net.HttpURLConnection} implementation is enabled.
87 * Defaults to disabled.
88 * @return the config to facilitate chaining.
89 * @deprecated Not supported by the new API.
90 */
91 @Deprecated
92 public Builder enableLegacyMode(boolean value) {
93 return putBoolean(CronetEngineBuilderList.ENABLE_LEGACY_MODE, value) ;
94 }
95
96 boolean legacyMode() {
97 return mConfig.optBoolean(CronetEngineBuilderList.ENABLE_LEGACY_MODE );
98 }
99
100 /**
101 * Overrides the name of the native library backing Cronet.
102 * @return the config to facilitate chaining.
103 */
104 Builder setLibraryName(String libName) {
105 return putString(CronetEngineBuilderList.NATIVE_LIBRARY_NAME, libNam e);
106 }
107
108 String libraryName() {
109 return mConfig.optString(CronetEngineBuilderList.NATIVE_LIBRARY_NAME , "cronet");
110 }
111
112 /**
113 * Sets whether <a href="https://www.chromium.org/quic">QUIC</a> protoco l
114 * is enabled. Defaults to disabled.
115 * @return the config to facilitate chaining.
116 */
117 public Builder enableQUIC(boolean value) {
118 return putBoolean(CronetEngineBuilderList.ENABLE_QUIC, value);
119 }
120
121 /**
122 * Sets whether <a href="https://tools.ietf.org/html/rfc7540">HTTP/2</a>
123 * protocol is enabled. Defaults to enabled.
124 * @return the config to facilitate chaining.
mef 2015/09/25 21:32:19 Here and elsewhere: @return the builder to facili
pauljensen 2015/09/28 14:18:12 Done.
125 */
126 public Builder enableHTTP2(boolean value) {
127 return putBoolean(CronetEngineBuilderList.ENABLE_SPDY, value);
128 }
129
130 /**
131 * Sets whether
132 * <a
133 * href="https://lists.w3.org/Archives/Public/ietf-http-wg/2008JulSep/at t-0441/Shared_Dictionary_Compression_over_HTTP.pdf">
134 * SDCH</a> compression is enabled. Defaults to disabled.
135 * @return the config to facilitate chaining.
136 */
137 public Builder enableSDCH(boolean value) {
138 return putBoolean(CronetEngineBuilderList.ENABLE_SDCH, value);
139 }
140
141 /**
142 * Enables
143 * <a href="https://developer.chrome.com/multidevice/data-compression">D ata
144 * Reduction Proxy</a>. Defaults to disabled.
145 * @param key key to use when authenticating with the proxy.
146 * @return the config to facilitate chaining.
147 */
148 public Builder enableDataReductionProxy(String key) {
149 return (putString(CronetEngineBuilderList.DATA_REDUCTION_PROXY_KEY, key));
150 }
151
152 /**
153 * Overrides
154 * <a href="https://developer.chrome.com/multidevice/data-compression">
155 * Data Reduction Proxy</a> configuration parameters with a primary
156 * proxy name, fallback proxy name, and a secure proxy check URL. Proxie s
157 * are specified as [scheme://]host[:port]. Used for testing.
158 * @param primaryProxy the primary data reduction proxy to use.
159 * @param fallbackProxy a fallback data reduction proxy to use.
160 * @param secureProxyCheckUrl a URL to fetch to determine if using a sec ure
161 * proxy is allowed.
162 * @return the config to facilitate chaining.
163 * @hide
164 */
165 public Builder setDataReductionProxyOptions(
166 String primaryProxy, String fallbackProxy, String secureProxyChe ckUrl) {
167 if (primaryProxy.isEmpty() || fallbackProxy.isEmpty()
168 || secureProxyCheckUrl.isEmpty()) {
169 throw new IllegalArgumentException(
170 "Primary and fallback proxies and check url must be set" );
171 }
172 putString(CronetEngineBuilderList.DATA_REDUCTION_PRIMARY_PROXY, prim aryProxy);
173 putString(CronetEngineBuilderList.DATA_REDUCTION_FALLBACK_PROXY, fal lbackProxy);
174 putString(CronetEngineBuilderList.DATA_REDUCTION_SECURE_PROXY_CHECK_ URL,
175 secureProxyCheckUrl);
176 return this;
177 }
178
179 /**
180 * Setting to disable HTTP cache. Some data may still be temporarily sto red in memory.
181 * Passed to {@link #enableHttpCache}.
182 */
183 public static final int HTTP_CACHE_DISABLED = 0;
184
185 /**
186 * Setting to enable in-memory HTTP cache, including HTTP data.
187 * Passed to {@link #enableHttpCache}.
188 */
189 public static final int HTTP_CACHE_IN_MEMORY = 1;
190
191 /**
192 * Setting to enable on-disk cache, excluding HTTP data.
193 * {@link #setStoragePath} must be called prior to passing this constant to
194 * {@link #enableHttpCache}.
195 */
196 public static final int HTTP_CACHE_DISK_NO_HTTP = 2;
197
198 /**
199 * Setting to enable on-disk cache, including HTTP data.
200 * {@link #setStoragePath} must be called prior to passing this constant to
201 * {@link #enableHttpCache}.
202 */
203 public static final int HTTP_CACHE_DISK = 3;
204
205 /**
206 * Enables or disables caching of HTTP data and other information like Q UIC
207 * server information.
208 * @param cacheMode control location and type of cached data.
209 * @param maxSize maximum size used to cache data (advisory and maybe
210 * exceeded at times).
211 * @return the config to facilitate chaining.
212 */
213 public Builder enableHttpCache(int cacheMode, long maxSize) {
214 if (cacheMode == HTTP_CACHE_DISK || cacheMode == HTTP_CACHE_DISK_NO_ HTTP) {
215 if (storagePath().isEmpty()) {
216 throw new IllegalArgumentException("Storage path must be set ");
217 }
218 } else {
219 if (!storagePath().isEmpty()) {
220 throw new IllegalArgumentException("Storage path must be emp ty");
221 }
222 }
223 putBoolean(CronetEngineBuilderList.LOAD_DISABLE_CACHE,
224 cacheMode == HTTP_CACHE_DISABLED || cacheMode == HTTP_CACHE_ DISK_NO_HTTP);
225 putLong(CronetEngineBuilderList.HTTP_CACHE_MAX_SIZE, maxSize);
226
227 switch (cacheMode) {
228 case HTTP_CACHE_DISABLED:
229 return putString(CronetEngineBuilderList.HTTP_CACHE,
230 CronetEngineBuilderList.HTTP_CACHE_DISABLED);
231 case HTTP_CACHE_DISK_NO_HTTP:
232 case HTTP_CACHE_DISK:
233 return putString(CronetEngineBuilderList.HTTP_CACHE,
234 CronetEngineBuilderList.HTTP_CACHE_DISK);
235
236 case HTTP_CACHE_IN_MEMORY:
237 return putString(CronetEngineBuilderList.HTTP_CACHE,
238 CronetEngineBuilderList.HTTP_CACHE_MEMORY);
239 }
240 return this;
241 }
242
243 /**
244 * Adds hint that {@code host} supports QUIC.
245 * Note that {@link #enableHttpCache enableHttpCache}
246 * ({@link HttpCache#DISK DISK}) is needed to take advantage of 0-RTT
247 * connection establishment between sessions.
248 *
249 * @param host hostname of the server that supports QUIC.
250 * @param port host of the server that supports QUIC.
251 * @param alternatePort alternate port to use for QUIC.
252 * @return the config to facilitate chaining.
253 */
254 public Builder addQuicHint(String host, int port, int alternatePort) {
255 if (host.contains("/")) {
256 throw new IllegalArgumentException("Illegal QUIC Hint Host: " + host);
257 }
258 try {
259 JSONArray quicHints = mConfig.optJSONArray(CronetEngineBuilderLi st.QUIC_HINTS);
260 if (quicHints == null) {
261 quicHints = new JSONArray();
262 mConfig.put(CronetEngineBuilderList.QUIC_HINTS, quicHints);
263 }
264
265 JSONObject hint = new JSONObject();
266 hint.put(CronetEngineBuilderList.QUIC_HINT_HOST, host);
267 hint.put(CronetEngineBuilderList.QUIC_HINT_PORT, port);
268 hint.put(CronetEngineBuilderList.QUIC_HINT_ALT_PORT, alternatePo rt);
269 quicHints.put(hint);
270 } catch (JSONException e) {
271 // Intentionally do nothing.
272 }
273 return this;
274 }
275
276 /**
277 * Sets experimental QUIC connection options, overwriting any pre-existi ng
278 * options. List of options is subject to change.
279 *
280 * @param quicConnectionOptions comma-separated QUIC options (for exampl e
281 * "PACE,IW10") to use if QUIC is enabled.
282 * @return the config to facilitate chaining.
283 */
284 public Builder setExperimentalQuicConnectionOptions(String quicConnectio nOptions) {
285 return putString(CronetEngineBuilderList.QUIC_OPTIONS, quicConnectio nOptions);
286 }
287
288 /**
289 * Get JSON string representation of the config.
mef 2015/09/25 21:32:18 builder
pauljensen 2015/09/28 14:18:12 Done.
290 */
291 @Override
292 public String toString() {
293 return mConfig.toString();
294 }
295
296 /**
297 * Sets a boolean value in the config. Returns a reference to the same
298 * config object, so you can chain put calls together.
299 * @return the config to facilitate chaining.
300 */
301 private Builder putBoolean(String key, boolean value) {
302 try {
303 mConfig.put(key, value);
304 } catch (JSONException e) {
305 // Intentionally do nothing.
306 }
307 return this;
308 }
309
310 /**
311 * Sets a long value in the config. Returns a reference to the same
312 * config object, so you can chain put calls together.
313 * @return the config to facilitate chaining.
314 */
315 private Builder putLong(String key, long value) {
316 try {
317 mConfig.put(key, value);
318 } catch (JSONException e) {
319 // Intentionally do nothing.
320 }
321 return this;
322 }
323
324 /**
325 * Sets a string value in the config. Returns a reference to the same
326 * config object, so you can chain put calls together.
327 * @return the config to facilitate chaining.
328 */
329 private Builder putString(String key, String value) {
330 try {
331 mConfig.put(key, value);
332 } catch (JSONException e) {
333 // Intentionally do nothing.
334 }
335 return this;
336 }
337
338 /**
339 * Build a {@link CronetEngine} using this builder's configuration.
340 */
341 public CronetEngine build(Context context) {
342 return createContext(context, this);
343 }
344 }
345
346 private static final String TAG = "UrlRequestFactory";
347 private static final String CRONET_URL_REQUEST_CONTEXT =
348 "org.chromium.net.CronetUrlRequestContext";
349
350 /**
351 * Creates a {@link UrlRequest} given a {@link Builder}, and starts
mef 2015/09/25 21:32:19 I think this should link to UrlRequest.Builder.
pauljensen 2015/09/28 14:18:12 It seems to link properly as "Builder"; the link a
352 * the request, all callbacks go to the {@link UrlRequestListener}.
353 */
354 public UrlRequest executeRequest(UrlRequest.Builder builder) {
355 final UrlRequest request = createRequest(
356 builder.mUrl, builder.mListener, builder.mExecutor, builder.mPri ority);
357 if (builder.mMethod != null) {
358 request.setHttpMethod(builder.mMethod);
359 }
360 if (builder.mDisableCache) {
361 request.disableCache();
362 }
363 for (Pair<String, String> header : builder.mRequestHeaders) {
mef 2015/09/25 21:32:19 should we switch from Pair<String, String> to Map.
pauljensen 2015/09/28 14:18:12 CronetUrlRequest uses an ArrayList<Pair<String, St
mef 2015/09/28 17:13:37 Ack. That will change once https://codereview.chro
364 request.addHeader(header.first, header.second);
365 }
366 if (builder.mUploadDataProvider != null) {
367 request.setUploadDataProvider(
368 builder.mUploadDataProvider, builder.mUploadDataProviderExec utor);
369 }
370 request.start();
371 return request;
372 }
373
374 /**
375 * Creates a {@link UrlRequest} object. All callbacks will
376 * be called on {@code executor}'s thread. {@code executor} must not run
377 * tasks on the current thread to prevent blocking networking operations
378 * and causing exceptions during shutdown. Request is given medium priority,
379 * see {@link UrlRequest#REQUEST_PRIORITY_MEDIUM}. To specify other
380 * priorities see {@link #createRequest(String, UrlRequestListener,
381 * Executor, int priority)}.
382 *
383 * @param url {@link java.net.URL} for the request.
384 * @param listener callback class that gets called on different events.
385 * @param executor {@link Executor} on which all callbacks will be called.
386 * @return new request.
387 * @deprecated Use {@link #executeRequest}.
388 */
389 @Deprecated
390 public abstract UrlRequest createRequest(
391 String url, UrlRequestListener listener, Executor executor);
392
393 /**
394 * Creates a {@link UrlRequest} object. All callbacks will
395 * be called on {@code executor}'s thread. {@code executor} must not run
396 * tasks on the current thread to prevent blocking networking operations
397 * and causing exceptions during shutdown.
398 *
399 * @param url {@link java.net.URL} for the request.
400 * @param listener callback class that gets called on different events.
401 * @param executor {@link Executor} on which all callbacks will be called.
402 * @param priority priority of the request which should be one of the
403 * {@link UrlRequest#REQUEST_PRIORITY_IDLE REQUEST_PRIORITY_*}
404 * values.
405 * @return new request.
406 * @deprecated Use {@link #executeRequest}.
407 */
408 @Deprecated
409 public abstract UrlRequest createRequest(
410 String url, UrlRequestListener listener, Executor executor, int prio rity);
411
412 /**
413 * @return {@code true} if the engine is enabled.
414 */
415 abstract boolean isEnabled();
416
417 /**
418 * @return a human-readable version string of the engine.
419 */
420 public abstract String getVersionString();
421
422 /**
423 * Shuts down the {@link CronetEngine} if there are no active requests,
424 * otherwise throws an exception.
425 *
426 * Cannot be called on network thread - the thread Cronet calls into
427 * Executor on (which is different from the thread the Executor invokes
428 * callbacks on). May block until all the {@code CronetEngine}'s
429 * resources have been cleaned up.
430 */
431 public abstract void shutdown();
432
433 /**
434 * Starts NetLog logging to a file. The NetLog is useful for debugging.
435 * The file can be viewed using a Chrome browser navigated to
436 * chrome://net-internals/#import
437 * @param fileName the complete file path. It must not be empty. If the file
438 * exists, it is truncated before starting. If actively logging,
439 * this method is ignored.
440 * @param logAll {@code true} to include basic events, user cookies,
441 * credentials and all transferred bytes in the log.
442 * {@code false} to just include basic events.
443 */
444 public abstract void startNetLogToFile(String fileName, boolean logAll);
445
446 /**
447 * Stops NetLog logging and flushes file to disk. If a logging session is
448 * not in progress, this call is ignored.
449 */
450 public abstract void stopNetLog();
451
452 /**
453 * Creates a {@link CronetEngine} with the given {@link Builder}.
454 * @param context Android {@link Context}.
455 * @param config engine configuration.
456 * @deprecated Use {@link CronetEngine.Builder}.
457 */
458 @Deprecated
459 public static CronetEngine createContext(Context context, Builder config) {
460 CronetEngine cronetEngine = null;
461 if (config.userAgent().isEmpty()) {
462 config.setUserAgent(UserAgent.from(context));
463 }
464 if (!config.legacyMode()) {
465 cronetEngine = createCronetEngine(context, config);
466 }
467 if (cronetEngine == null) {
468 // TODO(mef): Fallback to stub implementation. Once stub
469 // implementation is available merge with createCronetFactory.
470 cronetEngine = createCronetEngine(context, config);
471 }
472 Log.i(TAG, "Using network stack: " + cronetEngine.getVersionString());
473 return cronetEngine;
474 }
475
476 private static CronetEngine createCronetEngine(Context context, Builder conf ig) {
477 CronetEngine cronetEngine = null;
478 try {
479 Class<? extends CronetEngine> engineClass =
480 CronetEngine.class.getClassLoader()
481 .loadClass(CRONET_URL_REQUEST_CONTEXT)
482 .asSubclass(CronetEngine.class);
483 Constructor<? extends CronetEngine> constructor =
484 engineClass.getConstructor(Context.class, Builder.class);
485 CronetEngine possibleEngine = constructor.newInstance(context, confi g);
486 if (possibleEngine.isEnabled()) {
487 cronetEngine = possibleEngine;
488 }
489 } catch (ClassNotFoundException e) {
490 // Leave as null.
491 } catch (Exception e) {
492 throw new IllegalStateException("Cannot instantiate: " + CRONET_URL_ REQUEST_CONTEXT, e);
493 }
494 return cronetEngine;
495 }
496 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698