| 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..594e0cbeb5f0ad50e7e4e817252493db0066d88d
|
| --- /dev/null
|
| +++ b/components/cronet/android/java/src/org/chromium/net/impl/CronetEngineBuilderImpl.java
|
| @@ -0,0 +1,674 @@
|
| +// 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.HttpCacheType;
|
| +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 implements 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.
|
| + */
|
| + 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;
|
| + }
|
| +}
|
|
|