Chromium Code Reviews| Index: components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBuilderImpl.java |
| diff --git a/components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBuilderImpl.java b/components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBuilderImpl.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b602a25e4e7705e50c4118aea980a171fe122108 |
| --- /dev/null |
| +++ b/components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBuilderImpl.java |
| @@ -0,0 +1,673 @@ |
| +// Copyright 2016 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.impl; |
| + |
| +import android.content.Context; |
| +import android.support.annotation.IntDef; |
| + |
| +import org.chromium.base.Log; |
| +import org.chromium.base.VisibleForTesting; |
| +import org.chromium.net.CronetEngine; |
| +import org.chromium.net.ICronetEngineBuilder; |
| + |
| +import java.io.File; |
| +import java.lang.annotation.Retention; |
| +import java.lang.annotation.RetentionPolicy; |
| +import java.net.IDN; |
| +import java.util.Date; |
| +import java.util.HashSet; |
| +import java.util.LinkedList; |
| +import java.util.List; |
| +import java.util.Set; |
| +import java.util.regex.Pattern; |
| + |
| +/** |
| + * Implementation of {@link ICronetEngineBuilder}. |
| + */ |
| +public class CronetEngineBuilderImpl extends ICronetEngineBuilder { |
| + /** |
| + * A hint that a host supports QUIC. |
| + */ |
| + public static class QuicHint { |
| + // The host. |
| + final String mHost; |
| + // Port of the server that supports QUIC. |
| + final int mPort; |
| + // Alternate protocol port. |
| + final int mAlternatePort; |
| + |
| + QuicHint(String host, int port, int alternatePort) { |
| + mHost = host; |
| + mPort = port; |
| + mAlternatePort = alternatePort; |
| + } |
| + } |
| + |
| + /** |
| + * A public key pin. |
| + */ |
| + public static class Pkp { |
| + // Host to pin for. |
| + final String mHost; |
| + // Array of SHA-256 hashes of keys. |
| + final byte[][] mHashes; |
| + // Should pin apply to subdomains? |
| + final boolean mIncludeSubdomains; |
| + // When the pin expires. |
| + final Date mExpirationDate; |
| + |
| + Pkp(String host, byte[][] hashes, boolean includeSubdomains, Date expirationDate) { |
| + mHost = host; |
| + mHashes = hashes; |
| + mIncludeSubdomains = includeSubdomains; |
| + mExpirationDate = expirationDate; |
| + } |
| + } |
| + |
| + private static final String TAG = "CronetEngineBuilder"; |
| + private static final Pattern INVALID_PKP_HOST_NAME = Pattern.compile("^[0-9\\.]*$"); |
| + |
| + // Private fields are simply storage of configuration for the resulting CronetEngine. |
| + // See setters below for verbose descriptions. |
| + private final Context mContext; |
| + private final List<QuicHint> mQuicHints = new LinkedList<>(); |
| + private final List<Pkp> mPkps = new LinkedList<>(); |
| + private boolean mPublicKeyPinningBypassForLocalTrustAnchorsEnabled; |
| + private String mUserAgent; |
| + private String mStoragePath; |
| + private boolean mLegacyModeEnabled; |
| + private CronetEngine.Builder.LibraryLoader mLibraryLoader; |
| + private String mLibraryName; |
| + private boolean mQuicEnabled; |
| + private boolean mHttp2Enabled; |
| + private boolean mSdchEnabled; |
| + private String mDataReductionProxyKey; |
| + private String mDataReductionProxyPrimaryProxy; |
| + private String mDataReductionProxyFallbackProxy; |
| + private String mDataReductionProxySecureProxyCheckUrl; |
| + private boolean mDisableCache; |
| + private int mHttpCacheMode; |
| + private long mHttpCacheMaxSize; |
| + private String mExperimentalOptions; |
| + private long mMockCertVerifier; |
| + private boolean mNetworkQualityEstimatorEnabled; |
| + private String mCertVerifierData; |
| + |
| + /** |
| + * Default config enables SPDY, disables QUIC, SDCH and HTTP cache. |
| + * @param context Android {@link Context} for engine to use. |
| + */ |
| + public CronetEngineBuilderImpl(Context context) { |
| + mContext = context; |
| + setLibraryName("cronet"); |
| + enableLegacyMode(false); |
| + enableQuic(false); |
| + enableHttp2(true); |
| + enableSdch(false); |
| + enableHttpCache(HTTP_CACHE_DISABLED, 0); |
| + enableNetworkQualityEstimator(false); |
| + enablePublicKeyPinningBypassForLocalTrustAnchors(true); |
| + } |
| + |
| + /** |
| + * Constructs a User-Agent string including application name and version, |
| + * system build version, model and id, and Cronet version. |
| + * |
| + * @return User-Agent string. |
| + */ |
|
pauljensen
2016/09/26 14:51:22
Add @Override to all these functions and remove co
kapishnikov
2016/09/27 18:38:26
Should we add Javadocs to ICronetEngineBuilder in
pauljensen
2016/09/27 19:08:09
Definitly add @Override; I'd prefer no docs, perha
kapishnikov
2016/09/28 00:20:49
Done.
|
| + public String getDefaultUserAgent() { |
| + return UserAgent.from(mContext); |
| + } |
| + |
| + /** |
| + * Overrides the User-Agent header for all requests. An explicitly |
| + * set User-Agent header (set using |
| + * {@link org.chromium.net.UrlRequest.Builder#addHeader(String, String)}) |
| + * will override a value set using this function. |
| + * |
| + * @param userAgent the User-Agent string to use for all requests. |
| + * @return the builder to facilitate chaining. |
| + */ |
| + public CronetEngineBuilderImpl setUserAgent(String userAgent) { |
| + mUserAgent = userAgent; |
| + return this; |
| + } |
| + |
| + String getUserAgent() { |
| + return mUserAgent; |
| + } |
| + |
| + /** |
| + * 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 CronetEngineBuilderImpl setStoragePath(String value) { |
| + if (!new File(value).isDirectory()) { |
| + throw new IllegalArgumentException("Storage path must be set to existing directory"); |
| + } |
| + mStoragePath = value; |
| + return this; |
| + } |
| + |
| + String storagePath() { |
| + return mStoragePath; |
| + } |
| + |
| + /** |
| + * Sets whether the resulting {@link CronetEngine} uses an |
| + * implementation based on the system's |
| + * {@link java.net.HttpURLConnection} implementation, or if this is |
| + * only done as a backup if the native implementation fails to load. |
| + * Defaults to disabled. |
| + * @param value {@code true} makes the resulting {@link CronetEngine} |
| + * use an implementation based on the system's |
| + * {@link java.net.HttpURLConnection} implementation |
| + * without trying to load the native implementation. |
| + * {@code false} makes the resulting {@code CronetEngine} |
| + * use the native implementation, or if that fails to load, |
| + * falls back to an implementation based on the system's |
| + * {@link java.net.HttpURLConnection} implementation. |
| + * @return the builder to facilitate chaining. |
| + */ |
| + public CronetEngineBuilderImpl enableLegacyMode(boolean value) { |
| + mLegacyModeEnabled = value; |
| + return this; |
| + } |
| + |
| + private boolean legacyMode() { |
| + return mLegacyModeEnabled; |
| + } |
| + |
| + /** |
| + * Overrides the name of the native library backing Cronet. |
| + * @param libName the name of the native library backing Cronet. |
| + * @return the builder to facilitate chaining. |
| + */ |
| + public CronetEngineBuilderImpl setLibraryName(String libName) { |
| + mLibraryName = libName; |
| + return this; |
| + } |
| + |
| + String libraryName() { |
| + return mLibraryName; |
| + } |
| + |
| + /** |
| + * Sets a {@link CronetEngine.Builder.LibraryLoader} to be used to load the native library. |
| + * If not set, the library will be loaded using {@link System#loadLibrary}. |
| + * @param loader {@code LibraryLoader} to be used to load the native library. |
| + * @return the builder to facilitate chaining. |
| + */ |
| + public CronetEngineBuilderImpl setLibraryLoader(CronetEngine.Builder.LibraryLoader loader) { |
| + mLibraryLoader = loader; |
| + return this; |
| + } |
| + |
| + CronetEngine.Builder.LibraryLoader libraryLoader() { |
| + return mLibraryLoader; |
| + } |
| + |
| + /** |
| + * Sets whether <a href="https://www.chromium.org/quic">QUIC</a> protocol |
| + * is enabled. Defaults to disabled. If QUIC is enabled, then QUIC User Agent Id |
| + * containing application name and Cronet version is sent to the server. |
| + * @param value {@code true} to enable QUIC, {@code false} to disable. |
| + * @return the builder to facilitate chaining. |
| + */ |
| + public CronetEngineBuilderImpl enableQuic(boolean value) { |
| + mQuicEnabled = value; |
| + return this; |
| + } |
| + |
| + boolean quicEnabled() { |
| + return mQuicEnabled; |
| + } |
| + |
| + /** |
| + * Constructs default QUIC User Agent Id string including application name |
| + * and Cronet version. Returns empty string if QUIC is not enabled. |
| + * |
| + * @param context Android {@link Context} to get package name from. |
| + * @return QUIC User Agent ID string. |
| + */ |
| + // TODO(mef): remove |context| parameter when legacy ChromiumUrlRequestContext is removed. |
| + String getDefaultQuicUserAgentId(Context context) { |
| + return mQuicEnabled ? UserAgent.getQuicUserAgentIdFrom(context) : ""; |
| + } |
| + |
| + /** |
| + * Sets whether <a href="https://tools.ietf.org/html/rfc7540">HTTP/2</a> |
| + * protocol is enabled. Defaults to enabled. |
| + * @param value {@code true} to enable HTTP/2, {@code false} to disable. |
| + * @return the builder to facilitate chaining. |
| + */ |
| + public CronetEngineBuilderImpl enableHttp2(boolean value) { |
| + mHttp2Enabled = value; |
| + return this; |
| + } |
| + |
| + boolean http2Enabled() { |
| + return mHttp2Enabled; |
| + } |
| + |
| + /** |
| + * 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. |
| + * @param value {@code true} to enable SDCH, {@code false} to disable. |
| + * @return the builder to facilitate chaining. |
| + */ |
| + public CronetEngineBuilderImpl enableSdch(boolean value) { |
| + mSdchEnabled = value; |
| + return this; |
| + } |
| + |
| + boolean sdchEnabled() { |
| + return mSdchEnabled; |
| + } |
| + |
| + /** |
| + * 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 CronetEngineBuilderImpl enableDataReductionProxy(String key) { |
| + mDataReductionProxyKey = key; |
| + return this; |
| + } |
| + |
| + String dataReductionProxyKey() { |
| + return mDataReductionProxyKey; |
| + } |
| + |
| + /** |
| + * 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. |
| + */ |
| + public CronetEngineBuilderImpl 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"); |
| + } |
| + mDataReductionProxyPrimaryProxy = primaryProxy; |
| + mDataReductionProxyFallbackProxy = fallbackProxy; |
| + mDataReductionProxySecureProxyCheckUrl = secureProxyCheckUrl; |
| + return this; |
| + } |
| + |
| + String dataReductionProxyPrimaryProxy() { |
| + return mDataReductionProxyPrimaryProxy; |
| + } |
| + |
| + String dataReductionProxyFallbackProxy() { |
| + return mDataReductionProxyFallbackProxy; |
| + } |
| + |
| + String dataReductionProxySecureProxyCheckUrl() { |
| + return mDataReductionProxySecureProxyCheckUrl; |
| + } |
| + |
| + @IntDef({ |
| + HTTP_CACHE_DISABLED, HTTP_CACHE_IN_MEMORY, HTTP_CACHE_DISK_NO_HTTP, HTTP_CACHE_DISK, |
| + }) |
| + @Retention(RetentionPolicy.SOURCE) |
| + public @interface HttpCacheSetting {} |
| + |
| + /** |
| + * Setting to disable HTTP cache. Some data may still be temporarily stored in memory. |
| + * Passed to {@link #enableHttpCache}. |
| + */ |
| + 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}. |
| + */ |
| + 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}. |
| + */ |
| + 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 CronetEngineBuilderImpl enableHttpCache(@HttpCacheSetting int cacheMode, long maxSize) { |
| + if (cacheMode == HTTP_CACHE_DISK || cacheMode == HTTP_CACHE_DISK_NO_HTTP) { |
| + if (storagePath() == null) { |
| + throw new IllegalArgumentException("Storage path must be set"); |
| + } |
| + } else { |
| + if (storagePath() != null) { |
| + throw new IllegalArgumentException("Storage path must not be set"); |
| + } |
| + } |
| + mDisableCache = (cacheMode == HTTP_CACHE_DISABLED || cacheMode == HTTP_CACHE_DISK_NO_HTTP); |
| + mHttpCacheMaxSize = maxSize; |
| + |
| + switch (cacheMode) { |
| + case HTTP_CACHE_DISABLED: |
| + mHttpCacheMode = HttpCacheType.DISABLED; |
| + break; |
| + case HTTP_CACHE_DISK_NO_HTTP: |
| + case HTTP_CACHE_DISK: |
| + mHttpCacheMode = HttpCacheType.DISK; |
| + break; |
| + case HTTP_CACHE_IN_MEMORY: |
| + mHttpCacheMode = HttpCacheType.MEMORY; |
| + break; |
| + default: |
| + throw new IllegalArgumentException("Unknown cache mode"); |
| + } |
| + return this; |
| + } |
| + |
| + boolean cacheDisabled() { |
| + return mDisableCache; |
| + } |
| + |
| + long httpCacheMaxSize() { |
| + return mHttpCacheMaxSize; |
| + } |
| + |
| + int httpCacheMode() { |
| + return mHttpCacheMode; |
| + } |
| + |
| + /** |
| + * 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 CronetEngineBuilderImpl addQuicHint(String host, int port, int alternatePort) { |
| + if (host.contains("/")) { |
| + throw new IllegalArgumentException("Illegal QUIC Hint Host: " + host); |
| + } |
| + mQuicHints.add(new QuicHint(host, port, alternatePort)); |
| + return this; |
| + } |
| + |
| + List<QuicHint> quicHints() { |
| + return mQuicHints; |
| + } |
| + |
| + /** |
| + * <p> |
| + * Pins a set of public keys for a given host. By pinning a set of public keys, |
| + * {@code pinsSha256}, communication with {@code hostName} is required to |
| + * authenticate with a certificate with a public key from the set of pinned ones. |
| + * An app can pin the public key of the root certificate, any of the intermediate |
| + * certificates or the end-entry certificate. Authentication will fail and secure |
| + * communication will not be established if none of the public keys is present in the |
| + * host's certificate chain, even if the host attempts to authenticate with a |
| + * certificate allowed by the device's trusted store of certificates. |
| + * </p> |
| + * <p> |
| + * Calling this method multiple times with the same host name overrides the previously |
| + * set pins for the host. |
| + * </p> |
| + * <p> |
| + * More information about the public key pinning can be found in |
| + * <a href="https://tools.ietf.org/html/rfc7469">RFC 7469</a>. |
| + * </p> |
| + * |
| + * @param hostName name of the host to which the public keys should be pinned. A host that |
| + * consists only of digits and the dot character is treated as invalid. |
| + * @param pinsSha256 a set of pins. Each pin is the SHA-256 cryptographic |
| + * hash of the DER-encoded ASN.1 representation of the Subject Public |
| + * Key Info (SPKI) of the host's X.509 certificate. Use |
| + * {@link java.security.cert.Certificate#getPublicKey() |
| + * Certificate.getPublicKey()} and |
| + * {@link java.security.Key#getEncoded() Key.getEncoded()} |
| + * to obtain DER-encoded ASN.1 representation of the SPKI. |
| + * Although, the method does not mandate the presence of the backup pin |
| + * that can be used if the control of the primary private key has been |
| + * lost, it is highly recommended to supply one. |
| + * @param includeSubdomains indicates whether the pinning policy should be applied to |
| + * subdomains of {@code hostName}. |
| + * @param expirationDate specifies the expiration date for the pins. |
| + * @return the builder to facilitate chaining. |
| + * @throws NullPointerException if any of the input parameters are {@code null}. |
| + * @throws IllegalArgumentException if the given host name is invalid or {@code pinsSha256} |
| + * contains a byte array that does not represent a valid |
| + * SHA-256 hash. |
| + */ |
| + public CronetEngineBuilderImpl addPublicKeyPins(String hostName, Set<byte[]> pinsSha256, |
| + boolean includeSubdomains, Date expirationDate) { |
| + if (hostName == null) { |
| + throw new NullPointerException("The hostname cannot be null"); |
| + } |
| + if (pinsSha256 == null) { |
| + throw new NullPointerException("The set of SHA256 pins cannot be null"); |
| + } |
| + if (expirationDate == null) { |
| + throw new NullPointerException("The pin expiration date cannot be null"); |
| + } |
| + String idnHostName = validateHostNameForPinningAndConvert(hostName); |
| + // Convert the pin to BASE64 encoding. The hash set will eliminate duplications. |
| + Set<byte[]> hashes = new HashSet<>(pinsSha256.size()); |
| + for (byte[] pinSha256 : pinsSha256) { |
| + if (pinSha256 == null || pinSha256.length != 32) { |
| + throw new IllegalArgumentException("Public key pin is invalid"); |
| + } |
| + hashes.add(pinSha256); |
| + } |
| + // Add new element to PKP list. |
| + mPkps.add(new Pkp(idnHostName, hashes.toArray(new byte[hashes.size()][]), includeSubdomains, |
| + expirationDate)); |
| + return this; |
| + } |
| + |
| + /** |
| + * Returns list of public key pins. |
| + * @return list of public key pins. |
| + */ |
| + List<Pkp> publicKeyPins() { |
| + return mPkps; |
| + } |
| + |
| + /** |
| + * Enables or disables public key pinning bypass for local trust anchors. Disabling the |
| + * bypass for local trust anchors is highly discouraged since it may prohibit the app |
| + * from communicating with the pinned hosts. E.g., a user may want to send all traffic |
| + * through an SSL enabled proxy by changing the device proxy settings and adding the |
| + * proxy certificate to the list of local trust anchor. Disabling the bypass will most |
| + * likly prevent the app from sending any traffic to the pinned hosts. For more |
| + * information see 'How does key pinning interact with local proxies and filters?' at |
| + * https://www.chromium.org/Home/chromium-security/security-faq |
| + * |
| + * @param value {@code true} to enable the bypass, {@code false} to disable. |
| + * @return the builder to facilitate chaining. |
| + */ |
| + public CronetEngineBuilderImpl enablePublicKeyPinningBypassForLocalTrustAnchors(boolean value) { |
| + mPublicKeyPinningBypassForLocalTrustAnchorsEnabled = value; |
| + return this; |
| + } |
| + |
| + boolean publicKeyPinningBypassForLocalTrustAnchorsEnabled() { |
| + return mPublicKeyPinningBypassForLocalTrustAnchorsEnabled; |
| + } |
| + |
| + /** |
| + * Checks whether a given string represents a valid host name for PKP and converts it |
| + * to ASCII Compatible Encoding representation according to RFC 1122, RFC 1123 and |
| + * RFC 3490. This method is more restrictive than required by RFC 7469. Thus, a host |
| + * that contains digits and the dot character only is considered invalid. |
| + * |
| + * Note: Currently Cronet doesn't have native implementation of host name validation that |
| + * can be used. There is code that parses a provided URL but doesn't ensure its |
| + * correctness. The implementation relies on {@code getaddrinfo} function. |
| + * |
| + * @param hostName host name to check and convert. |
| + * @return true if the string is a valid host name. |
| + * @throws IllegalArgumentException if the the given string does not represent a valid |
| + * hostname. |
| + */ |
| + private static String validateHostNameForPinningAndConvert(String hostName) |
| + throws IllegalArgumentException { |
| + if (INVALID_PKP_HOST_NAME.matcher(hostName).matches()) { |
| + throw new IllegalArgumentException("Hostname " + hostName + " is illegal." |
| + + " A hostname should not consist of digits and/or dots only."); |
| + } |
| + // Workaround for crash, see crbug.com/634914 |
| + if (hostName.length() > 255) { |
| + throw new IllegalArgumentException("Hostname " + hostName + " is too long." |
| + + " The name of the host does not comply with RFC 1122 and RFC 1123."); |
| + } |
| + try { |
| + return IDN.toASCII(hostName, IDN.USE_STD3_ASCII_RULES); |
| + } catch (IllegalArgumentException ex) { |
| + throw new IllegalArgumentException("Hostname " + hostName + " is illegal." |
| + + " The name of the host does not comply with RFC 1122 and RFC 1123."); |
| + } |
| + } |
| + |
| + /** |
| + * Sets experimental options to be used in Cronet. |
| + * |
| + * @param options JSON formatted experimental options. |
| + * @return the builder to facilitate chaining. |
| + */ |
| + public CronetEngineBuilderImpl setExperimentalOptions(String options) { |
| + mExperimentalOptions = options; |
| + return this; |
| + } |
| + |
| + public String experimentalOptions() { |
| + return mExperimentalOptions; |
| + } |
| + |
| + /** |
| + * Sets a native MockCertVerifier for testing. See |
| + * {@code MockCertVerifier.createMockCertVerifier} for a method that |
| + * can be used to create a MockCertVerifier. |
| + * @param mockCertVerifier pointer to native MockCertVerifier. |
| + * @return the builder to facilitate chaining. |
| + */ |
| + @VisibleForTesting |
| + public CronetEngineBuilderImpl setMockCertVerifierForTesting(long mockCertVerifier) { |
| + mMockCertVerifier = mockCertVerifier; |
| + return this; |
| + } |
| + |
| + long mockCertVerifier() { |
| + return mMockCertVerifier; |
| + } |
| + |
| + /** |
| + * @return true if the network quality estimator has been enabled for |
| + * this builder. |
| + */ |
| + boolean networkQualityEstimatorEnabled() { |
| + return mNetworkQualityEstimatorEnabled; |
| + } |
| + |
| + /** |
| + * Initializes CachingCertVerifier's cache with certVerifierData which has |
| + * the results of certificate verification. |
| + * @param certVerifierData a serialized representation of certificate |
| + * verification results. |
| + * @return the builder to facilitate chaining. |
| + */ |
| + public CronetEngineBuilderImpl setCertVerifierData(String certVerifierData) { |
| + mCertVerifierData = certVerifierData; |
| + return this; |
| + } |
| + |
| + /** |
| + * 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 org.chromium.net.ExperimentalCronetEngine#addRttListener} and |
| + * {@link org.chromium.net.ExperimentalCronetEngine#addThroughputListener} and |
| + * removed with {@link org.chromium.net.ExperimentalCronetEngine#removeRttListener} and |
| + * {@link org.chromium.net.ExperimentalCronetEngine#removeThroughputListener}. |
| + * The estimator uses memory and CPU only when enabled. |
| + * @param value {@code true} to enable network quality estimator, |
| + * {@code false} to disable. |
| + * @return the builder to facilitate chaining. |
| + */ |
| + @Override |
| + public CronetEngineBuilderImpl enableNetworkQualityEstimator(boolean value) { |
| + mNetworkQualityEstimatorEnabled = value; |
| + return this; |
| + } |
| + |
| + String certVerifierData() { |
| + return mCertVerifierData; |
| + } |
| + |
| + /** |
| + * Returns {@link Context} for builder. |
| + * |
| + * @return {@link Context} for builder. |
| + */ |
| + public Context getContext() { |
| + return mContext; |
| + } |
| + |
| + /** |
| + * Build a {@link CronetEngine} using this builder's configuration. |
| + * @return constructed {@link CronetEngine}. |
| + */ |
| + public CronetEngine build() { |
| + if (getUserAgent() == null) { |
| + setUserAgent(getDefaultUserAgent()); |
| + } |
| + CronetEngine cronetEngine = null; |
| + if (!legacyMode()) { |
| + cronetEngine = CronetEngineBase.createCronetEngine(this); |
| + } |
| + if (cronetEngine == null) { |
| + cronetEngine = new JavaCronetEngine(getUserAgent()); |
| + } |
| + Log.i(TAG, "Using network stack: " + cronetEngine.getVersionString()); |
| + // Clear MOCK_CERT_VERIFIER reference if there is any, since |
| + // the ownership has been transferred to the engine. |
| + mMockCertVerifier = 0; |
| + return cronetEngine; |
| + } |
| +} |