| // Copyright 2015 The Chromium Authors |
| // 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.net.http.HttpResponseCache; |
| import android.util.Log; |
| |
| import androidx.annotation.VisibleForTesting; |
| |
| import java.io.IOException; |
| import java.lang.reflect.Method; |
| import java.net.URL; |
| import java.net.URLConnection; |
| import java.net.URLStreamHandlerFactory; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.Date; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.concurrent.Executor; |
| |
| import javax.net.ssl.HttpsURLConnection; |
| |
| /** |
| * An engine to process {@link UrlRequest}s, which uses the best HTTP stack available on the current |
| * platform. An instance of this class can be created using {@link Builder}. |
| */ |
| public abstract class CronetEngine { |
| private static final String TAG = CronetEngine.class.getSimpleName(); |
| |
| /** The value of the active request count is unknown */ |
| public static final int ACTIVE_REQUEST_COUNT_UNKNOWN = -1; |
| |
| /** The value of a connection metric is unknown. */ |
| public static final int CONNECTION_METRIC_UNKNOWN = -1; |
| |
| /** |
| * The estimate of the effective connection type is unknown. |
| * |
| * @see #getEffectiveConnectionType |
| */ |
| public static final int EFFECTIVE_CONNECTION_TYPE_UNKNOWN = 0; |
| |
| /** |
| * The device is offline. |
| * |
| * @see #getEffectiveConnectionType |
| */ |
| public static final int EFFECTIVE_CONNECTION_TYPE_OFFLINE = 1; |
| |
| /** |
| * The estimate of the effective connection type is slow 2G. |
| * |
| * @see #getEffectiveConnectionType |
| */ |
| public static final int EFFECTIVE_CONNECTION_TYPE_SLOW_2G = 2; |
| |
| /** |
| * The estimate of the effective connection type is 2G. |
| * |
| * @see #getEffectiveConnectionType |
| */ |
| public static final int EFFECTIVE_CONNECTION_TYPE_2G = 3; |
| |
| /** |
| * The estimate of the effective connection type is 3G. |
| * |
| * @see #getEffectiveConnectionType |
| */ |
| public static final int EFFECTIVE_CONNECTION_TYPE_3G = 4; |
| |
| /** |
| * The estimate of the effective connection type is 4G. |
| * |
| * @see #getEffectiveConnectionType |
| */ |
| public static final int EFFECTIVE_CONNECTION_TYPE_4G = 5; |
| |
| /** The value to be used to undo any previous network binding. */ |
| public static final long UNBIND_NETWORK_HANDLE = -1; |
| |
| /** |
| * 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}. |
| */ |
| // NOTE(kapishnikov): In order to avoid breaking the existing API clients, all future methods |
| // added to this class and other API classes must have default implementation. |
| public static class Builder { |
| private static final String TAG = "CronetEngine.Builder"; |
| |
| /** |
| * A class which provides a method for loading the cronet native library. Apps needing to |
| * implement custom library loading logic can inherit from this class and pass an instance |
| * to |
| * {@link CronetEngine.Builder#setLibraryLoader}. For example, this might be required to |
| * work around {@code UnsatisfiedLinkError}s caused by flaky installation on certain older |
| * devices. |
| */ |
| public abstract static class LibraryLoader { |
| /** |
| * Loads the native library. |
| * |
| * @param libName name of the library to load |
| */ |
| public abstract void loadLibrary(String libName); |
| } |
| |
| /** Reference to the actual builder implementation. {@hide exclude from JavaDoc}. */ |
| protected final ICronetEngineBuilder mBuilderDelegate; |
| |
| /** |
| * Constructs a {@link Builder} object that facilitates creating a {@link CronetEngine}. The |
| * default configuration enables HTTP/2 and QUIC, but disables the HTTP cache. |
| * |
| * @param context Android {@link Context}, which is used by {@link Builder} to retrieve the |
| * application context. A reference to only the application context will be kept, so as to |
| * avoid extending the lifetime of {@code context} unnecessarily. |
| */ |
| public Builder(Context context) { |
| this(createBuilderDelegate(context)); |
| } |
| |
| /** |
| * Constructs {@link Builder} with a given delegate that provides the actual implementation |
| * of the {@code Builder} methods. This constructor is used only by the internal |
| * implementation. |
| * |
| * @param builderDelegate delegate that provides the actual implementation. |
| * <p>{@hide} |
| */ |
| public Builder(ICronetEngineBuilder builderDelegate) { |
| if (builderDelegate instanceof ExperimentalOptionsTranslatingCronetEngineBuilder) { |
| // Already wrapped at the top level, no need to do it again |
| mBuilderDelegate = builderDelegate; |
| } else { |
| mBuilderDelegate = |
| new ExperimentalOptionsTranslatingCronetEngineBuilder(builderDelegate); |
| } |
| } |
| |
| /** |
| * 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 mBuilderDelegate.getDefaultUserAgent(); |
| } |
| |
| /** |
| * Overrides the User-Agent header for all requests. An explicitly set User-Agent header |
| * (set using {@link UrlRequest.Builder#addHeader}) 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 Builder setUserAgent(String userAgent) { |
| mBuilderDelegate.setUserAgent(userAgent); |
| return this; |
| } |
| |
| /** |
| * 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) { |
| mBuilderDelegate.setStoragePath(value); |
| return this; |
| } |
| |
| /** |
| * Sets a {@link 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 Builder setLibraryLoader(LibraryLoader loader) { |
| mBuilderDelegate.setLibraryLoader(loader); |
| return this; |
| } |
| |
| /** |
| * Sets whether <a href="https://www.chromium.org/quic">QUIC</a> protocol is enabled. |
| * Defaults to enabled. 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 Builder enableQuic(boolean value) { |
| mBuilderDelegate.enableQuic(value); |
| return this; |
| } |
| |
| /** |
| * 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 Builder enableHttp2(boolean value) { |
| mBuilderDelegate.enableHttp2(value); |
| return this; |
| } |
| |
| /** |
| * @deprecated SDCH is deprecated in Cronet M63. This method is a no-op. {@hide exclude from |
| * JavaDoc}. |
| */ |
| @Deprecated |
| public Builder enableSdch(boolean value) { |
| return this; |
| } |
| |
| /** |
| * Sets whether <a href="https://tools.ietf.org/html/rfc7932">Brotli</a> compression is |
| * enabled. If enabled, Brotli will be advertised in Accept-Encoding request headers. |
| * Defaults to disabled. |
| * |
| * @param value {@code true} to enable Brotli, {@code false} to disable. |
| * @return the builder to facilitate chaining. |
| */ |
| public Builder enableBrotli(boolean value) { |
| mBuilderDelegate.enableBrotli(value); |
| return this; |
| } |
| |
| /** |
| * 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(int cacheMode, long maxSize) { |
| mBuilderDelegate.enableHttpCache(cacheMode, maxSize); |
| 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) { |
| mBuilderDelegate.addQuicHint(host, port, alternatePort); |
| return this; |
| } |
| |
| /** |
| * 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>Calling this method multiple times with the same host name overrides the previously |
| * set pins for the host. |
| * |
| * <p>More information about the public key pinning can be found in <a |
| * href="https://tools.ietf.org/html/rfc7469">RFC 7469</a>. |
| * |
| * @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 Builder addPublicKeyPins( |
| String hostName, |
| Set<byte[]> pinsSha256, |
| boolean includeSubdomains, |
| Date expirationDate) { |
| mBuilderDelegate.addPublicKeyPins( |
| hostName, pinsSha256, includeSubdomains, expirationDate); |
| return this; |
| } |
| |
| /** |
| * 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 likely 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 Builder enablePublicKeyPinningBypassForLocalTrustAnchors(boolean value) { |
| mBuilderDelegate.enablePublicKeyPinningBypassForLocalTrustAnchors(value); |
| return this; |
| } |
| |
| /** |
| * Sets the thread priority of Cronet's internal thread. |
| * |
| * @param priority the thread priority of Cronet's internal thread. A Linux priority level, |
| * from |
| * -20 for highest scheduling priority to 19 for lowest scheduling priority. For more |
| * information on values, see {@link android.os.Process#setThreadPriority(int, int)} and |
| * {@link android.os.Process#THREAD_PRIORITY_DEFAULT THREAD_PRIORITY_*} values. |
| * @return the builder to facilitate chaining. |
| */ |
| public Builder setThreadPriority(int priority) { |
| mBuilderDelegate.setThreadPriority(priority); |
| 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 |
| * #addRttListener} and |
| * {@link #addThroughputListener} and removed with {@link #removeRttListener} and {@link |
| * #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. |
| */ |
| public Builder enableNetworkQualityEstimator(boolean value) { |
| mBuilderDelegate.enableNetworkQualityEstimator(value); |
| return this; |
| } |
| |
| /** |
| * Configures the behavior of Cronet when using QUIC. For more details, see documentation |
| * of {@link QuicOptions} and the individual methods of {@link QuicOptions.Builder}. |
| * |
| * <p>Only relevant if {@link #enableQuic(boolean)} is enabled. |
| * |
| * @return the builder to facilitate chaining. |
| */ |
| @QuicOptions.Experimental |
| public Builder setQuicOptions(QuicOptions quicOptions) { |
| mBuilderDelegate.setQuicOptions(quicOptions); |
| return this; |
| } |
| |
| /** @see #setQuicOptions(QuicOptions) */ |
| @QuicOptions.Experimental |
| public Builder setQuicOptions(QuicOptions.Builder quicOptionsBuilder) { |
| return setQuicOptions(quicOptionsBuilder.build()); |
| } |
| |
| /** |
| * Configures the behavior of hostname lookup. For more details, see documentation |
| * of {@link DnsOptions} and the individual methods of {@link DnsOptions.Builder}. |
| * |
| * <p>Only relevant if {@link #enableQuic(boolean)} is enabled. |
| * |
| * @return the builder to facilitate chaining. |
| */ |
| @DnsOptions.Experimental |
| public Builder setDnsOptions(DnsOptions dnsOptions) { |
| mBuilderDelegate.setDnsOptions(dnsOptions); |
| return this; |
| } |
| |
| /** @see #setDnsOptions(DnsOptions) */ |
| @DnsOptions.Experimental |
| public Builder setDnsOptions(DnsOptions.Builder dnsOptions) { |
| return setDnsOptions(dnsOptions.build()); |
| } |
| |
| /** |
| * Configures the behavior of connection migration. For more details, see documentation |
| * of {@link ConnectionMigrationOptions} and the individual methods of {@link |
| * ConnectionMigrationOptions.Builder}. |
| * |
| * <p>Only relevant if {@link #enableQuic(boolean)} is enabled. |
| * |
| * @return the builder to facilitate chaining. |
| */ |
| @ConnectionMigrationOptions.Experimental |
| public Builder setConnectionMigrationOptions( |
| ConnectionMigrationOptions connectionMigrationOptions) { |
| mBuilderDelegate.setConnectionMigrationOptions(connectionMigrationOptions); |
| return this; |
| } |
| |
| /** @see #setConnectionMigrationOptions(ConnectionMigrationOptions) */ |
| @ConnectionMigrationOptions.Experimental |
| public Builder setConnectionMigrationOptions( |
| ConnectionMigrationOptions.Builder connectionMigrationOptionsBuilder) { |
| return setConnectionMigrationOptions(connectionMigrationOptionsBuilder.build()); |
| } |
| |
| /** |
| * Build a {@link CronetEngine} using this builder's configuration. |
| * |
| * @return constructed {@link CronetEngine}. |
| */ |
| public CronetEngine build() { |
| int implLevel = getImplementationApiLevel(); |
| if (implLevel != -1 && implLevel < getMaximumApiLevel()) { |
| Log.w( |
| TAG, |
| "The implementation version is lower than the API version. Calls to " |
| + "methods added in API " |
| + (implLevel + 1) |
| + " and newer will " |
| + "likely have no effect."); |
| } |
| |
| return mBuilderDelegate.build(); |
| } |
| |
| /** |
| * Creates an implementation of {@link ICronetEngineBuilder} that can be used to delegate |
| * the builder calls to. The method uses {@link CronetProvider} to obtain the list of |
| * available providers. |
| * |
| * @param context Android Context to use. |
| * @return the created {@code ICronetEngineBuilder}. |
| */ |
| private static ICronetEngineBuilder createBuilderDelegate(Context context) { |
| List<CronetProvider> providers = |
| new ArrayList<>(CronetProvider.getAllProviders(context)); |
| CronetProvider provider = getEnabledCronetProviders(context, providers).get(0); |
| if (Log.isLoggable(TAG, Log.DEBUG)) { |
| Log.d( |
| TAG, |
| String.format( |
| "Using '%s' provider for creating CronetEngine.Builder.", |
| provider)); |
| } |
| return provider.createBuilder().mBuilderDelegate; |
| } |
| |
| /** |
| * Returns the list of available and enabled {@link CronetProvider}. The returned list is |
| * sorted based on the provider versions and types. |
| * |
| * @param context Android Context to use. |
| * @param providers the list of enabled and disabled providers to filter out and sort. |
| * @return the sorted list of enabled providers. The list contains at least one provider. |
| * @throws RuntimeException is the list of providers is empty or all of the providers are |
| * disabled. |
| */ |
| @VisibleForTesting |
| static List<CronetProvider> getEnabledCronetProviders( |
| Context context, List<CronetProvider> providers) { |
| // Check that there is at least one available provider. |
| if (providers.isEmpty()) { |
| throw new RuntimeException( |
| "Unable to find any Cronet provider." |
| + " Have you included all necessary jars?"); |
| } |
| |
| // Exclude disabled providers from the list. |
| for (Iterator<CronetProvider> i = providers.iterator(); i.hasNext(); ) { |
| CronetProvider provider = i.next(); |
| if (!provider.isEnabled()) { |
| i.remove(); |
| } |
| } |
| |
| // Check that there is at least one enabled provider. |
| if (providers.isEmpty()) { |
| throw new RuntimeException( |
| "All available Cronet providers are disabled." |
| + " A provider should be enabled before it can be used."); |
| } |
| |
| // Sort providers based on version and type. |
| Collections.sort( |
| providers, |
| new Comparator<CronetProvider>() { |
| @Override |
| public int compare(CronetProvider p1, CronetProvider p2) { |
| // The fallback provider should always be at the end of the list. |
| if (CronetProvider.PROVIDER_NAME_FALLBACK.equals(p1.getName())) { |
| return 1; |
| } |
| if (CronetProvider.PROVIDER_NAME_FALLBACK.equals(p2.getName())) { |
| return -1; |
| } |
| // A provider with higher version should go first. |
| return -compareVersions(p1.getVersion(), p2.getVersion()); |
| } |
| }); |
| return providers; |
| } |
| |
| /** |
| * Compares two strings that contain versions. The string should only contain dot-separated |
| * segments that contain an arbitrary number of digits digits [0-9]. |
| * |
| * @param s1 the first string. |
| * @param s2 the second string. |
| * @return -1 if s1<s2, +1 if s1>s2 and 0 if s1=s2. If two versions are equal, the version |
| * with |
| * the higher number of segments is considered to be higher. |
| * @throws IllegalArgumentException if any of the strings contains an illegal version |
| * number. |
| */ |
| @VisibleForTesting |
| static int compareVersions(String s1, String s2) { |
| if (s1 == null || s2 == null) { |
| throw new IllegalArgumentException("The input values cannot be null"); |
| } |
| String[] s1segments = s1.split("\\."); |
| String[] s2segments = s2.split("\\."); |
| for (int i = 0; i < s1segments.length && i < s2segments.length; i++) { |
| try { |
| int s1segment = Integer.parseInt(s1segments[i]); |
| int s2segment = Integer.parseInt(s2segments[i]); |
| if (s1segment != s2segment) { |
| return Integer.signum(s1segment - s2segment); |
| } |
| } catch (NumberFormatException e) { |
| throw new IllegalArgumentException( |
| "Unable to convert version segments into" |
| + " integers: " |
| + s1segments[i] |
| + " & " |
| + s2segments[i], |
| e); |
| } |
| } |
| return Integer.signum(s1segments.length - s2segments.length); |
| } |
| |
| private int getMaximumApiLevel() { |
| return ApiVersion.getMaximumAvailableApiLevel(); |
| } |
| |
| /** |
| * Returns the implementation version, the implementation being represented by the delegate |
| * builder, or {@code -1} if the version couldn't be retrieved. |
| */ |
| private int getImplementationApiLevel() { |
| try { |
| ClassLoader implClassLoader = mBuilderDelegate.getClass().getClassLoader(); |
| Class<?> implVersionClass = |
| implClassLoader.loadClass("org.chromium.net.impl.ImplVersion"); |
| Method getApiLevel = implVersionClass.getMethod("getApiLevel"); |
| int implementationApiLevel = (Integer) getApiLevel.invoke(null); |
| |
| return implementationApiLevel; |
| } catch (Exception e) { |
| // Any exception in the block above isn't critical, don't bother the app about it. |
| return -1; |
| } |
| } |
| } |
| |
| /** @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. |
| * |
| * <p>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 will contain events emitted by all live |
| * CronetEngines. 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. This option presents a privacy risk, since it exposes the |
| * user's credentials, and should only be used with the user's consent and in situations where |
| * the log won't be public. {@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 this method. |
| * |
| * <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(); |
| |
| /** |
| * 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. |
| * @throws IOException if an error occurs while opening the connection. |
| */ |
| public abstract URLConnection openConnection(URL url) throws IOException; |
| |
| /** |
| * 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 HttpResponseCache#install(java.io.File, long) |
| * HttpResponseCache.install()} |
| * <li>the HTTP authentication method installed via {@link java.net.Authenticator#setDefault} |
| * <li>the HTTP cookie storage installed via {@link java.net.CookieHandler#setDefault} |
| * </ul> |
| * |
| * <p>While Cronet supports and encourages requests using the HTTPS protocol, Cronet does not |
| * provide support for the {@link 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 |
| * HttpsURLConnection#setDefaultHostnameVerifier(javax.net.ssl.HostnameVerifier) |
| * HttpsURLConnection.setDefaultHostnameVerifier()} |
| * <li>the HTTPS socket factory installed via {@link |
| * HttpsURLConnection#setDefaultSSLSocketFactory(javax.net.ssl.SSLSocketFactory) |
| * HttpsURLConnection.setDefaultSSLSocketFactory()} |
| * </ul> |
| * |
| * @return an {@link URLStreamHandlerFactory} instance implemented by this CronetEngine. |
| */ |
| public abstract URLStreamHandlerFactory createURLStreamHandlerFactory(); |
| |
| /** |
| * Creates a builder for {@link UrlRequest}. All callbacks for generated {@link UrlRequest} |
| * objects will be invoked on {@code executor}'s threads. {@code executor} must not run tasks on |
| * the thread calling {@link Executor#execute} to prevent blocking networking operations and |
| * causing exceptions during shutdown. |
| * |
| * @param url URL for the generated requests. |
| * @param callback callback object that gets invoked on different events. |
| * @param executor {@link Executor} on which all callbacks will be invoked. |
| */ |
| public abstract UrlRequest.Builder newUrlRequestBuilder( |
| String url, UrlRequest.Callback callback, Executor executor); |
| |
| /** |
| * Creates a builder for {@link BidirectionalStream} objects. All callbacks for generated {@code |
| * BidirectionalStream} objects will be invoked on {@code executor}. {@code executor} must not |
| * run tasks on the current thread, otherwise the networking operations may block and exceptions |
| * may be thrown at shutdown time. |
| * |
| * @param url URL for the generated streams. |
| * @param callback the {@link BidirectionalStream.Callback} object that gets invoked upon |
| * different events occurring. |
| * @param executor the {@link Executor} on which {@code callback} methods will be invoked. |
| * @return the created builder. |
| * |
| * {@hide} |
| */ |
| public BidirectionalStream.Builder newBidirectionalStreamBuilder( |
| String url, BidirectionalStream.Callback callback, Executor executor) { |
| throw new UnsupportedOperationException("Not implemented."); |
| } |
| |
| /** |
| * Returns the number of active requests. |
| * <p> |
| * A request becomes "active" in UrlRequest.start(), assuming that method |
| * does not throw an exception. It becomes inactive when all callbacks have |
| * returned and no additional callbacks can be triggered in the future. In |
| * practice, that means the request is inactive once |
| * onSucceeded/onCanceled/onFailed has returned and all request finished |
| * listeners have returned. |
| * |
| * <a href="https://developer.android.com/guide/topics/connectivity/cronet/lifecycle">Cronet |
| * requests's lifecycle</a> for more information. |
| */ |
| public int getActiveRequestCount() { |
| return ACTIVE_REQUEST_COUNT_UNKNOWN; |
| } |
| |
| /** |
| * Registers a listener that gets called after the end of each request with the request info. |
| * |
| * <p>The listener is called on an {@link java.util.concurrent.Executor} provided by the |
| * listener. |
| * |
| * @param listener the listener for finished requests. |
| */ |
| public void addRequestFinishedListener(RequestFinishedInfo.Listener listener) {} |
| |
| /** |
| * Removes a finished request listener. |
| * |
| * @param listener the listener to remove. |
| */ |
| public void removeRequestFinishedListener(RequestFinishedInfo.Listener listener) {} |
| |
| /** |
| * Returns the HTTP RTT estimate (in milliseconds) computed by the network quality estimator. |
| * Set to {@link #CONNECTION_METRIC_UNKNOWN} if the value is unavailable. This must be called |
| * after |
| * {@link Builder#enableNetworkQualityEstimator}, and will throw an exception otherwise. |
| * |
| * @return Estimate of the HTTP RTT in milliseconds. |
| */ |
| public int getHttpRttMs() { |
| return CONNECTION_METRIC_UNKNOWN; |
| } |
| |
| /** |
| * Returns the transport RTT estimate (in milliseconds) computed by the network quality |
| * estimator. Set to {@link #CONNECTION_METRIC_UNKNOWN} if the value is unavailable. This must |
| * be called after {@link Builder#enableNetworkQualityEstimator}, and will throw an exception |
| * otherwise. |
| * |
| * @return Estimate of the transport RTT in milliseconds. |
| */ |
| public int getTransportRttMs() { |
| return CONNECTION_METRIC_UNKNOWN; |
| } |
| |
| /** |
| * Returns the downstream throughput estimate (in kilobits per second) computed by the network |
| * quality estimator. Set to {@link #CONNECTION_METRIC_UNKNOWN} if the value is unavailable. |
| * This must be called after {@link Builder#enableNetworkQualityEstimator}, and will throw an |
| * exception otherwise. |
| * |
| * @return Estimate of the downstream throughput in kilobits per second. |
| */ |
| public int getDownstreamThroughputKbps() { |
| return CONNECTION_METRIC_UNKNOWN; |
| } |
| |
| /** |
| * Starts NetLog logging to a specified directory with a bounded size. The NetLog will contain |
| * events emitted by all live CronetEngines. The NetLog is useful for debugging. Once logging |
| * has stopped {@link #stopNetLog}, the data will be written to netlog.json in {@code dirPath}. |
| * If logging is interrupted, you can stitch the files found in .inprogress subdirectory |
| * manually using: |
| * https://chromium.googlesource.com/chromium/src/+/main/net/tools/stitch_net_log_files.py. The |
| * log can be viewed using a Chrome browser navigated to chrome://net-internals/#import. |
| * |
| * @param dirPath the directory where the netlog.json file will be created. dirPath must already |
| * exist. NetLog files must not exist in the directory. 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. This option presents a privacy risk, since it exposes the |
| * user's credentials, and should only be used with the user's consent and in situations where |
| * the log won't be public. {@code false} to just include basic events. |
| * @param maxSize the maximum total disk space in bytes that should be used by NetLog. Actual |
| * disk |
| * space usage may exceed this limit slightly. |
| */ |
| public void startNetLogToDisk(String dirPath, boolean logAll, int maxSize) {} |
| |
| /** |
| * Binds the engine to the specified network handle. All requests created through this engine |
| * will use the network associated to this handle. If this network disconnects all requests will |
| * fail, the exact error will depend on the stage of request processing when the network |
| * disconnects. Network handles can be obtained through {@code Network#getNetworkHandle}. Only |
| * available starting from Android Marshmallow. |
| * |
| * @param networkHandle the network handle to bind the engine to. Specify {@link |
| * #UNBIND_NETWORK_HANDLE} to unbind. |
| */ |
| public void bindToNetwork(long networkHandle) {} |
| |
| /** |
| * Returns an estimate of the effective connection type computed by the network quality |
| * estimator. Call {@link Builder#enableNetworkQualityEstimator} to begin computing this value. |
| * |
| * @return the estimated connection type. The returned value is one of {@link |
| * #EFFECTIVE_CONNECTION_TYPE_UNKNOWN EFFECTIVE_CONNECTION_TYPE_* }. |
| */ |
| public int getEffectiveConnectionType() { |
| return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
| } |
| |
| /** |
| * Configures the network quality estimator for testing. This must be called before round trip |
| * time and throughput listeners are added, and after the network quality estimator has been |
| * enabled. |
| * |
| * @param useLocalHostRequests include requests to localhost in estimates. |
| * @param useSmallerResponses include small responses in throughput estimates. |
| * @param disableOfflineCheck when set to true, disables the device offline checks when |
| * computing |
| * the effective connection type or when writing the prefs. |
| */ |
| public void configureNetworkQualityEstimatorForTesting( |
| boolean useLocalHostRequests, |
| boolean useSmallerResponses, |
| boolean disableOfflineCheck) {} |
| |
| /** |
| * Registers a listener that gets called whenever the network quality estimator witnesses a |
| * sample round trip time. This must be called after {@link |
| * Builder#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 |
| * Builder#enableNetworkQualityEstimator}. |
| * |
| * @param listener the listener of round trip times. |
| */ |
| public 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. |
| */ |
| public 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 |
| * Builder#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 Builder#enableNetworkQualityEstimator}. |
| * |
| * @param listener the listener of throughput. |
| */ |
| public 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. |
| */ |
| public void removeThroughputListener(NetworkQualityThroughputListener listener) {} |
| } |