| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package org.chromium.net; |
| |
| import android.content.Context; |
| import android.support.annotation.IntDef; |
| import android.util.Log; |
| |
| import org.json.JSONArray; |
| import org.json.JSONException; |
| import org.json.JSONObject; |
| |
| import java.io.File; |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.lang.reflect.Constructor; |
| import java.net.Proxy; |
| import java.net.URL; |
| import java.net.URLConnection; |
| import java.net.URLStreamHandlerFactory; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.Executor; |
| |
| /** |
| * An engine to process {@link UrlRequest}s, which uses the best HTTP stack |
| * available on the current platform. |
| */ |
| public abstract class CronetEngine { |
| /** |
| * A builder for {@link CronetEngine}s, which allows runtime configuration of |
| * {@code CronetEngine}. Configuration options are set on the builder and |
| * then {@link #build} is called to create the {@code CronetEngine}. |
| */ |
| public static class Builder { |
| private final JSONObject mConfig; |
| private final Context mContext; |
| |
| /** |
| * Default config enables SPDY, disables QUIC, SDCH and HTTP cache. |
| * @param context Android {@link Context} for engine to use. |
| */ |
| public Builder(Context context) { |
| mConfig = new JSONObject(); |
| mContext = context; |
| enableLegacyMode(false); |
| enableQUIC(false); |
| enableHTTP2(true); |
| enableSDCH(false); |
| enableHttpCache(HTTP_CACHE_DISABLED, 0); |
| } |
| |
| /** |
| * Constructs a User-Agent string including Cronet version, and |
| * application name and version. |
| * |
| * @return User-Agent string. |
| */ |
| public String getDefaultUserAgent() { |
| return UserAgent.from(mContext); |
| } |
| |
| /** |
| * Overrides the User-Agent header for all requests. |
| * @return the builder to facilitate chaining. |
| */ |
| public Builder setUserAgent(String userAgent) { |
| return putString(CronetEngineBuilderList.USER_AGENT, userAgent); |
| } |
| |
| String getUserAgent() { |
| return mConfig.optString(CronetEngineBuilderList.USER_AGENT); |
| } |
| |
| /** |
| * Sets directory for HTTP Cache and Cookie Storage. The directory must |
| * exist. |
| * <p> |
| * <b>NOTE:</b> Do not use the same storage directory with more than one |
| * {@code CronetEngine} at a time. Access to the storage directory does |
| * not support concurrent access by multiple {@code CronetEngine}s. |
| * |
| * @param value path to existing directory. |
| * @return the builder to facilitate chaining. |
| */ |
| public Builder setStoragePath(String value) { |
| if (!new File(value).isDirectory()) { |
| throw new IllegalArgumentException( |
| "Storage path must be set to existing directory"); |
| } |
| |
| return putString(CronetEngineBuilderList.STORAGE_PATH, value); |
| } |
| |
| String storagePath() { |
| return mConfig.optString(CronetEngineBuilderList.STORAGE_PATH); |
| } |
| |
| /** |
| * Sets whether falling back to implementation based on system's |
| * {@link java.net.HttpURLConnection} implementation is enabled. |
| * Defaults to disabled. |
| * @return the builder to facilitate chaining. |
| * @deprecated Not supported by the new API. |
| */ |
| @Deprecated |
| public Builder enableLegacyMode(boolean value) { |
| return putBoolean(CronetEngineBuilderList.ENABLE_LEGACY_MODE, value); |
| } |
| |
| boolean legacyMode() { |
| return mConfig.optBoolean(CronetEngineBuilderList.ENABLE_LEGACY_MODE); |
| } |
| |
| /** |
| * Overrides the name of the native library backing Cronet. |
| * @return the builder to facilitate chaining. |
| */ |
| Builder setLibraryName(String libName) { |
| return putString(CronetEngineBuilderList.NATIVE_LIBRARY_NAME, libName); |
| } |
| |
| String libraryName() { |
| return mConfig.optString(CronetEngineBuilderList.NATIVE_LIBRARY_NAME, "cronet"); |
| } |
| |
| /** |
| * Sets whether <a href="https://www.chromium.org/quic">QUIC</a> protocol |
| * is enabled. Defaults to disabled. |
| * @return the builder to facilitate chaining. |
| */ |
| public Builder enableQUIC(boolean value) { |
| return putBoolean(CronetEngineBuilderList.ENABLE_QUIC, value); |
| } |
| |
| /** |
| * Sets whether <a href="https://tools.ietf.org/html/rfc7540">HTTP/2</a> |
| * protocol is enabled. Defaults to enabled. |
| * @return the builder to facilitate chaining. |
| */ |
| public Builder enableHTTP2(boolean value) { |
| return putBoolean(CronetEngineBuilderList.ENABLE_SPDY, value); |
| } |
| |
| /** |
| * Sets whether |
| * <a |
| * href="https://lists.w3.org/Archives/Public/ietf-http-wg/2008JulSep/att-0441/Shared_Dictionary_Compression_over_HTTP.pdf"> |
| * SDCH</a> compression is enabled. Defaults to disabled. |
| * @return the builder to facilitate chaining. |
| */ |
| public Builder enableSDCH(boolean value) { |
| return putBoolean(CronetEngineBuilderList.ENABLE_SDCH, value); |
| } |
| |
| /** |
| * Enables |
| * <a href="https://developer.chrome.com/multidevice/data-compression">Data |
| * Reduction Proxy</a>. Defaults to disabled. |
| * @param key key to use when authenticating with the proxy. |
| * @return the builder to facilitate chaining. |
| */ |
| public Builder enableDataReductionProxy(String key) { |
| return (putString(CronetEngineBuilderList.DATA_REDUCTION_PROXY_KEY, key)); |
| } |
| |
| /** |
| * Overrides |
| * <a href="https://developer.chrome.com/multidevice/data-compression"> |
| * Data Reduction Proxy</a> configuration parameters with a primary |
| * proxy name, fallback proxy name, and a secure proxy check URL. Proxies |
| * are specified as [scheme://]host[:port]. Used for testing. |
| * @param primaryProxy the primary data reduction proxy to use. |
| * @param fallbackProxy a fallback data reduction proxy to use. |
| * @param secureProxyCheckUrl a URL to fetch to determine if using a secure |
| * proxy is allowed. |
| * @return the builder to facilitate chaining. |
| * @hide |
| * @deprecated Marked as deprecated because @hide doesn't properly hide but |
| * javadocs are built with nodeprecated="yes". |
| */ |
| @SuppressWarnings("DepAnn") |
| public Builder setDataReductionProxyOptions( |
| String primaryProxy, String fallbackProxy, String secureProxyCheckUrl) { |
| if (primaryProxy.isEmpty() || fallbackProxy.isEmpty() |
| || secureProxyCheckUrl.isEmpty()) { |
| throw new IllegalArgumentException( |
| "Primary and fallback proxies and check url must be set"); |
| } |
| putString(CronetEngineBuilderList.DATA_REDUCTION_PRIMARY_PROXY, primaryProxy); |
| putString(CronetEngineBuilderList.DATA_REDUCTION_FALLBACK_PROXY, fallbackProxy); |
| putString(CronetEngineBuilderList.DATA_REDUCTION_SECURE_PROXY_CHECK_URL, |
| secureProxyCheckUrl); |
| return this; |
| } |
| |
| /** @deprecated not really deprecated but hidden. */ |
| @IntDef({ |
| HTTP_CACHE_DISABLED, HTTP_CACHE_IN_MEMORY, HTTP_CACHE_DISK_NO_HTTP, HTTP_CACHE_DISK, |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| @SuppressWarnings("DepAnn") |
| public @interface HttpCacheSetting {} |
| |
| /** |
| * Setting to disable HTTP cache. Some data may still be temporarily stored in memory. |
| * Passed to {@link #enableHttpCache}. |
| */ |
| public static final int HTTP_CACHE_DISABLED = 0; |
| |
| /** |
| * Setting to enable in-memory HTTP cache, including HTTP data. |
| * Passed to {@link #enableHttpCache}. |
| */ |
| public static final int HTTP_CACHE_IN_MEMORY = 1; |
| |
| /** |
| * Setting to enable on-disk cache, excluding HTTP data. |
| * {@link #setStoragePath} must be called prior to passing this constant to |
| * {@link #enableHttpCache}. |
| */ |
| public static final int HTTP_CACHE_DISK_NO_HTTP = 2; |
| |
| /** |
| * Setting to enable on-disk cache, including HTTP data. |
| * {@link #setStoragePath} must be called prior to passing this constant to |
| * {@link #enableHttpCache}. |
| */ |
| public static final int HTTP_CACHE_DISK = 3; |
| |
| /** |
| * Enables or disables caching of HTTP data and other information like QUIC |
| * server information. |
| * @param cacheMode control location and type of cached data. Must be one of |
| * {@link #HTTP_CACHE_DISABLED HTTP_CACHE_*}. |
| * @param maxSize maximum size in bytes used to cache data (advisory and maybe |
| * exceeded at times). |
| * @return the builder to facilitate chaining. |
| */ |
| public Builder enableHttpCache(@HttpCacheSetting int cacheMode, long maxSize) { |
| if (cacheMode == HTTP_CACHE_DISK || cacheMode == HTTP_CACHE_DISK_NO_HTTP) { |
| if (storagePath().isEmpty()) { |
| throw new IllegalArgumentException("Storage path must be set"); |
| } |
| } else { |
| if (!storagePath().isEmpty()) { |
| throw new IllegalArgumentException("Storage path must be empty"); |
| } |
| } |
| putBoolean(CronetEngineBuilderList.LOAD_DISABLE_CACHE, |
| cacheMode == HTTP_CACHE_DISABLED || cacheMode == HTTP_CACHE_DISK_NO_HTTP); |
| putLong(CronetEngineBuilderList.HTTP_CACHE_MAX_SIZE, maxSize); |
| |
| switch (cacheMode) { |
| case HTTP_CACHE_DISABLED: |
| return putString(CronetEngineBuilderList.HTTP_CACHE, |
| CronetEngineBuilderList.HTTP_CACHE_DISABLED); |
| case HTTP_CACHE_DISK_NO_HTTP: |
| case HTTP_CACHE_DISK: |
| return putString(CronetEngineBuilderList.HTTP_CACHE, |
| CronetEngineBuilderList.HTTP_CACHE_DISK); |
| |
| case HTTP_CACHE_IN_MEMORY: |
| return putString(CronetEngineBuilderList.HTTP_CACHE, |
| CronetEngineBuilderList.HTTP_CACHE_MEMORY); |
| } |
| return this; |
| } |
| |
| /** |
| * Adds hint that {@code host} supports QUIC. |
| * Note that {@link #enableHttpCache enableHttpCache} |
| * ({@link #HTTP_CACHE_DISK}) is needed to take advantage of 0-RTT |
| * connection establishment between sessions. |
| * |
| * @param host hostname of the server that supports QUIC. |
| * @param port host of the server that supports QUIC. |
| * @param alternatePort alternate port to use for QUIC. |
| * @return the builder to facilitate chaining. |
| */ |
| public Builder addQuicHint(String host, int port, int alternatePort) { |
| if (host.contains("/")) { |
| throw new IllegalArgumentException("Illegal QUIC Hint Host: " + host); |
| } |
| try { |
| JSONArray quicHints = mConfig.optJSONArray(CronetEngineBuilderList.QUIC_HINTS); |
| if (quicHints == null) { |
| quicHints = new JSONArray(); |
| mConfig.put(CronetEngineBuilderList.QUIC_HINTS, quicHints); |
| } |
| |
| JSONObject hint = new JSONObject(); |
| hint.put(CronetEngineBuilderList.QUIC_HINT_HOST, host); |
| hint.put(CronetEngineBuilderList.QUIC_HINT_PORT, port); |
| hint.put(CronetEngineBuilderList.QUIC_HINT_ALT_PORT, alternatePort); |
| quicHints.put(hint); |
| } catch (JSONException e) { |
| // Intentionally do nothing. |
| } |
| return this; |
| } |
| |
| /** |
| * Sets experimental options to be used in Cronet. |
| * |
| * @param options JSON formatted experimental options. |
| * @return the builder to facilitate chaining. |
| */ |
| public Builder setExperimentalOptions(String options) { |
| return putString(CronetEngineBuilderList.EXPERIMENTAL_OPTIONS, options); |
| } |
| |
| /** |
| * Sets a native MockCertVerifier for testing. |
| */ |
| Builder setMockCertVerifierForTesting(long mockCertVerifier) { |
| return putString( |
| CronetEngineBuilderList.MOCK_CERT_VERIFIER, String.valueOf(mockCertVerifier)); |
| } |
| |
| /** |
| * Gets a JSON string representation of the builder. |
| */ |
| String toJSONString() { |
| return mConfig.toString(); |
| } |
| |
| /** |
| * Returns {@link Context} for builder. |
| * |
| * @return {@link Context} for builder. |
| */ |
| Context getContext() { |
| return mContext; |
| } |
| |
| /** |
| * Sets a boolean value in the config. Returns a reference to the same |
| * config object, so you can chain put calls together. |
| * @return the builder to facilitate chaining. |
| */ |
| private Builder putBoolean(String key, boolean value) { |
| try { |
| mConfig.put(key, value); |
| } catch (JSONException e) { |
| // Intentionally do nothing. |
| } |
| return this; |
| } |
| |
| /** |
| * Sets a long value in the config. Returns a reference to the same |
| * config object, so you can chain put calls together. |
| * @return the builder to facilitate chaining. |
| */ |
| private Builder putLong(String key, long value) { |
| try { |
| mConfig.put(key, value); |
| } catch (JSONException e) { |
| // Intentionally do nothing. |
| } |
| return this; |
| } |
| |
| /** |
| * Sets a string value in the config. Returns a reference to the same |
| * config object, so you can chain put calls together. |
| * @return the builder to facilitate chaining. |
| */ |
| private Builder putString(String key, String value) { |
| try { |
| mConfig.put(key, value); |
| } catch (JSONException e) { |
| // Intentionally do nothing. |
| } |
| return this; |
| } |
| |
| /** |
| * Build a {@link CronetEngine} using this builder's configuration. |
| */ |
| public CronetEngine build() { |
| return createContext(this); |
| } |
| } |
| |
| private static final String TAG = "UrlRequestFactory"; |
| private static final String CRONET_URL_REQUEST_CONTEXT = |
| "org.chromium.net.CronetUrlRequestContext"; |
| |
| /** |
| * Creates a {@link UrlRequest} object. All callbacks will |
| * be called on {@code executor}'s thread. {@code executor} must not run |
| * tasks on the current thread to prevent blocking networking operations |
| * and causing exceptions during shutdown. Request is given medium priority, |
| * see {@link UrlRequest.Builder#REQUEST_PRIORITY_MEDIUM}. To specify other |
| * priorities see {@link #createRequest(String, UrlRequest.Callback, |
| * Executor, int priority)}. |
| * |
| * @param url {@link URL} for the request. |
| * @param callback callback object that gets invoked on different events. |
| * @param executor {@link Executor} on which all callbacks will be invoked. |
| * @return new request. |
| * @deprecated Use {@link UrlRequest.Builder#build}. |
| */ |
| @Deprecated |
| public abstract UrlRequest createRequest( |
| String url, UrlRequest.Callback callback, Executor executor); |
| |
| /** |
| * Creates a {@link UrlRequest} object. All callbacks will |
| * be called on {@code executor}'s thread. {@code executor} must not run |
| * tasks on the current thread to prevent blocking networking operations |
| * and causing exceptions during shutdown. |
| * |
| * @param url {@link URL} for the request. |
| * @param callback callback object that gets invoked on different events. |
| * @param executor {@link Executor} on which all callbacks will be invoked. |
| * @param priority priority of the request which should be one of the |
| * {@link UrlRequest.Builder#REQUEST_PRIORITY_IDLE REQUEST_PRIORITY_*} |
| * values. |
| * @return new request. |
| * @deprecated Use {@link UrlRequest.Builder#build}. |
| */ |
| @Deprecated |
| public abstract UrlRequest createRequest( |
| String url, UrlRequest.Callback callback, Executor executor, int priority); |
| |
| /** |
| * Creates a {@link BidirectionalStream} object. {@code callback} methods will |
| * be invoked on {@code executor}. {@code executor} must not run |
| * tasks on the current thread to prevent blocking networking operations |
| * and causing exceptions during shutdown. |
| * |
| * @param url the URL for the stream |
| * @param callback the object whose methods get invoked upon different events |
| * @param executor the {@link Executor} on which all callbacks will be called |
| * @param httpMethod the HTTP method to use for the stream |
| * @param requestHeaders the list of request headers |
| * @return a new stream. |
| */ |
| abstract BidirectionalStream createBidirectionalStream(String url, |
| BidirectionalStream.Callback callback, Executor executor, String httpMethod, |
| List<Map.Entry<String, String>> requestHeaders); |
| |
| /** |
| * @return {@code true} if the engine is enabled. |
| */ |
| abstract boolean isEnabled(); |
| |
| /** |
| * @return a human-readable version string of the engine. |
| */ |
| public abstract String getVersionString(); |
| |
| /** |
| * Shuts down the {@link CronetEngine} if there are no active requests, |
| * otherwise throws an exception. |
| * |
| * Cannot be called on network thread - the thread Cronet calls into |
| * Executor on (which is different from the thread the Executor invokes |
| * callbacks on). May block until all the {@code CronetEngine}'s |
| * resources have been cleaned up. |
| */ |
| public abstract void shutdown(); |
| |
| /** |
| * Starts NetLog logging to a file. The NetLog is useful for debugging. |
| * The file can be viewed using a Chrome browser navigated to |
| * chrome://net-internals/#import |
| * @param fileName the complete file path. It must not be empty. If the file |
| * exists, it is truncated before starting. If actively logging, |
| * this method is ignored. |
| * @param logAll {@code true} to include basic events, user cookies, |
| * credentials and all transferred bytes in the log. |
| * {@code false} to just include basic events. |
| */ |
| public abstract void startNetLogToFile(String fileName, boolean logAll); |
| |
| /** |
| * Stops NetLog logging and flushes file to disk. If a logging session is |
| * not in progress, this call is ignored. |
| */ |
| public abstract void stopNetLog(); |
| |
| /** |
| * Returns differences in metrics collected by Cronet since the last call to |
| * {@link #getGlobalMetricsDeltas}. |
| * <p> |
| * Cronet collects these metrics globally. This means deltas returned by |
| * {@code getGlobalMetricsDeltas()} will include measurements of requests |
| * processed by other {@link CronetEngine} instances. Since this function |
| * returns differences in metrics collected since the last call, and these |
| * metrics are collected globally, a call to any {@code CronetEngine} |
| * instance's {@code getGlobalMetricsDeltas()} method will affect the deltas |
| * returned by any other {@code CronetEngine} instance's |
| * {@code getGlobalMetricsDeltas()}. |
| * <p> |
| * Cronet starts collecting these metrics after the first call to |
| * {@code getGlobalMetricsDeltras()}, so the first call returns no |
| * useful data as no metrics have yet been collected. |
| * |
| * @return differences in metrics collected by Cronet, since the last call |
| * to {@code getGlobalMetricsDeltas()}, serialized as a |
| * <a href=https://developers.google.com/protocol-buffers>protobuf |
| * </a>. |
| */ |
| public abstract byte[] getGlobalMetricsDeltas(); |
| |
| /** |
| * Enables the network quality estimator, which collects and reports |
| * measurements of round trip time (RTT) and downstream throughput at |
| * various layers of the network stack. After enabling the estimator, |
| * listeners of RTT and throughput can be added with |
| * {@link #addRttListener} and {@link #addThroughputListener} and |
| * removed with {@link #removeRttListener} and |
| * {@link #removeThroughputListener}. The estimator uses memory and CPU |
| * only when enabled. |
| * @param executor an executor that will be used to notified all |
| * added RTT and throughput listeners. |
| * @deprecated not really deprecated but hidden for now as it's a prototype. |
| */ |
| @Deprecated public abstract void enableNetworkQualityEstimator(Executor executor); |
| |
| /** |
| * Enables the network quality estimator for testing. This must be called |
| * before round trip time and throughput listeners are added. Set both |
| * boolean parameters to false for default behavior. |
| * @param useLocalHostRequests include requests to localhost in estimates. |
| * @param useSmallerResponses include small responses in throughput estimates. |
| * @param executor an {@link java.util.concurrent.Executor} on which all |
| * listeners will be called. |
| * @deprecated not really deprecated but hidden for now as it's a prototype. |
| */ |
| @Deprecated |
| abstract void enableNetworkQualityEstimatorForTesting( |
| boolean useLocalHostRequests, boolean useSmallerResponses, Executor executor); |
| |
| /** |
| * Registers a listener that gets called whenever the network quality |
| * estimator witnesses a sample round trip time. This must be called |
| * after {@link #enableNetworkQualityEstimator}, and with throw an |
| * exception otherwise. Round trip times may be recorded at various layers |
| * of the network stack, including TCP, QUIC, and at the URL request layer. |
| * The listener is called on the {@link java.util.concurrent.Executor} that |
| * is passed to {@link #enableNetworkQualityEstimator}. |
| * @param listener the listener of round trip times. |
| * @deprecated not really deprecated but hidden for now as it's a prototype. |
| */ |
| @Deprecated public abstract void addRttListener(NetworkQualityRttListener listener); |
| |
| /** |
| * Removes a listener of round trip times if previously registered with |
| * {@link #addRttListener}. This should be called after a |
| * {@link NetworkQualityRttListener} is added in order to stop receiving |
| * observations. |
| * @param listener the listener of round trip times. |
| * @deprecated not really deprecated but hidden for now as it's a prototype. |
| */ |
| @Deprecated public abstract void removeRttListener(NetworkQualityRttListener listener); |
| |
| /** |
| * Registers a listener that gets called whenever the network quality |
| * estimator witnesses a sample throughput measurement. This must be called |
| * after {@link #enableNetworkQualityEstimator}. Throughput observations |
| * are computed by measuring bytes read over the active network interface |
| * at times when at least one URL response is being received. The listener |
| * is called on the {@link java.util.concurrent.Executor} that is passed to |
| * {@link #enableNetworkQualityEstimator}. |
| * @param listener the listener of throughput. |
| * @deprecated not really deprecated but hidden for now as it's a prototype. |
| */ |
| @Deprecated |
| public abstract void addThroughputListener(NetworkQualityThroughputListener listener); |
| |
| /** |
| * Removes a listener of throughput. This should be called after a |
| * {@link NetworkQualityThroughputListener} is added with |
| * {@link #addThroughputListener} in order to stop receiving observations. |
| * @param listener the listener of throughput. |
| * @deprecated not really deprecated but hidden for now as it's a prototype. |
| */ |
| @Deprecated |
| public abstract void removeThroughputListener(NetworkQualityThroughputListener listener); |
| |
| /** |
| * Establishes a new connection to the resource specified by the {@link URL} {@code url}. |
| * <p> |
| * <b>Note:</b> Cronet's {@link java.net.HttpURLConnection} implementation is subject to certain |
| * limitations, see {@link #createURLStreamHandlerFactory} for details. |
| * |
| * @param url URL of resource to connect to. |
| * @return an {@link java.net.HttpURLConnection} instance implemented by this CronetEngine. |
| */ |
| public abstract URLConnection openConnection(URL url); |
| |
| /** |
| * Establishes a new connection to the resource specified by the {@link URL} {@code url} |
| * using the given proxy. |
| * <p> |
| * <b>Note:</b> Cronet's {@link java.net.HttpURLConnection} implementation is subject to certain |
| * limitations, see {@link #createURLStreamHandlerFactory} for details. |
| * |
| * @param url URL of resource to connect to. |
| * @param proxy proxy to use when establishing connection. |
| * @return an {@link java.net.HttpURLConnection} instance implemented by this CronetEngine. |
| * @hide |
| * @deprecated Marked as deprecated because @hide doesn't properly hide but |
| * javadocs are built with nodeprecated="yes". |
| * TODO(pauljensen): Expose once implemented, http://crbug.com/418111 |
| */ |
| @SuppressWarnings("DepAnn") public abstract URLConnection openConnection(URL url, Proxy proxy); |
| |
| /** |
| * Creates a {@link URLStreamHandlerFactory} to handle HTTP and HTTPS |
| * traffic. An instance of this class can be installed via |
| * {@link URL#setURLStreamHandlerFactory} thus using this CronetEngine by default for |
| * all requests created via {@link URL#openConnection}. |
| * <p> |
| * Cronet does not use certain HTTP features provided via the system: |
| * <ul> |
| * <li>the HTTP cache installed via |
| * {@link android.net.http.HttpResponseCache#install(java.io.File, long) |
| * HttpResponseCache.install()}</li> |
| * <li>the HTTP authentication method installed via |
| * {@link java.net.Authenticator#setDefault}</li> |
| * <li>the HTTP cookie storage installed via {@link java.net.CookieHandler#setDefault}</li> |
| * </ul> |
| * <p> |
| * While Cronet supports and encourages requests using the HTTPS protocol, |
| * Cronet does not provide support for the |
| * {@link javax.net.ssl.HttpsURLConnection} API. This lack of support also |
| * includes not using certain HTTPS features provided via the system: |
| * <ul> |
| * <li>the HTTPS hostname verifier installed via {@link |
| * javax.net.ssl.HttpsURLConnection#setDefaultHostnameVerifier(javax.net.ssl.HostnameVerifier) |
| * HttpsURLConnection.setDefaultHostnameVerifier()}</li> |
| * <li>the HTTPS socket factory installed via {@link |
| * javax.net.ssl.HttpsURLConnection#setDefaultSSLSocketFactory(javax.net.ssl.SSLSocketFactory) |
| * HttpsURLConnection.setDefaultSSLSocketFactory()}</li> |
| * </ul> |
| * |
| * @return an {@link URLStreamHandlerFactory} instance implemented by this |
| * CronetEngine. |
| */ |
| public abstract URLStreamHandlerFactory createURLStreamHandlerFactory(); |
| |
| /** |
| * Creates a {@link CronetEngine} with the given {@link Builder}. |
| * |
| * @param builder builder to used for creating the CronetEngine instance. |
| * @return the created CronetEngine instance. |
| * @deprecated Use {@link CronetEngine.Builder}. |
| */ |
| @Deprecated |
| public static CronetEngine createContext(Builder builder) { |
| CronetEngine cronetEngine = null; |
| if (builder.getUserAgent().isEmpty()) { |
| builder.setUserAgent(builder.getDefaultUserAgent()); |
| } |
| if (!builder.legacyMode()) { |
| cronetEngine = createCronetEngine(builder); |
| } |
| if (cronetEngine == null) { |
| // TODO(mef): Fallback to stub implementation. Once stub |
| // implementation is available merge with createCronetFactory. |
| cronetEngine = createCronetEngine(builder); |
| } |
| Log.i(TAG, "Using network stack: " + cronetEngine.getVersionString()); |
| return cronetEngine; |
| } |
| |
| private static CronetEngine createCronetEngine(Builder builder) { |
| CronetEngine cronetEngine = null; |
| try { |
| Class<? extends CronetEngine> engineClass = |
| CronetEngine.class.getClassLoader() |
| .loadClass(CRONET_URL_REQUEST_CONTEXT) |
| .asSubclass(CronetEngine.class); |
| Constructor<? extends CronetEngine> constructor = |
| engineClass.getConstructor(Builder.class); |
| CronetEngine possibleEngine = constructor.newInstance(builder); |
| if (possibleEngine.isEnabled()) { |
| cronetEngine = possibleEngine; |
| } |
| } catch (ClassNotFoundException e) { |
| // Leave as null. |
| } catch (Exception e) { |
| throw new IllegalStateException("Cannot instantiate: " + CRONET_URL_REQUEST_CONTEXT, e); |
| } |
| return cronetEngine; |
| } |
| } |