| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.net; | 5 package org.chromium.net; |
| 6 | 6 |
| 7 import android.content.Context; | 7 import android.content.Context; |
| 8 import android.support.annotation.IntDef; | 8 import android.support.annotation.IntDef; |
| 9 import android.util.Base64; |
| 9 import android.util.Log; | 10 import android.util.Log; |
| 10 | 11 |
| 12 import org.json.JSONArray; |
| 13 import org.json.JSONException; |
| 14 import org.json.JSONObject; |
| 15 |
| 11 import java.io.File; | 16 import java.io.File; |
| 12 import java.lang.annotation.Retention; | 17 import java.lang.annotation.Retention; |
| 13 import java.lang.annotation.RetentionPolicy; | 18 import java.lang.annotation.RetentionPolicy; |
| 14 import java.lang.reflect.Constructor; | 19 import java.lang.reflect.Constructor; |
| 15 import java.net.IDN; | 20 import java.net.IDN; |
| 16 import java.net.Proxy; | 21 import java.net.Proxy; |
| 17 import java.net.URL; | 22 import java.net.URL; |
| 18 import java.net.URLConnection; | 23 import java.net.URLConnection; |
| 19 import java.net.URLStreamHandlerFactory; | 24 import java.net.URLStreamHandlerFactory; |
| 20 import java.util.Date; | 25 import java.util.Date; |
| 21 import java.util.HashSet; | 26 import java.util.HashSet; |
| 22 import java.util.LinkedList; | |
| 23 import java.util.List; | 27 import java.util.List; |
| 24 import java.util.Map; | 28 import java.util.Map; |
| 25 import java.util.Set; | 29 import java.util.Set; |
| 26 import java.util.concurrent.Executor; | 30 import java.util.concurrent.Executor; |
| 27 import java.util.regex.Pattern; | 31 import java.util.regex.Pattern; |
| 28 | 32 |
| 29 /** | 33 /** |
| 30 * An engine to process {@link UrlRequest}s, which uses the best HTTP stack | 34 * An engine to process {@link UrlRequest}s, which uses the best HTTP stack |
| 31 * available on the current platform. | 35 * available on the current platform. |
| 32 */ | 36 */ |
| 33 public abstract class CronetEngine { | 37 public abstract class CronetEngine { |
| 34 /** | 38 /** |
| 35 * A builder for {@link CronetEngine}s, which allows runtime configuration o
f | 39 * A builder for {@link CronetEngine}s, which allows runtime configuration o
f |
| 36 * {@code CronetEngine}. Configuration options are set on the builder and | 40 * {@code CronetEngine}. Configuration options are set on the builder and |
| 37 * then {@link #build} is called to create the {@code CronetEngine}. | 41 * then {@link #build} is called to create the {@code CronetEngine}. |
| 38 */ | 42 */ |
| 39 public static class Builder { | 43 public static class Builder { |
| 40 // A hint that a host supports QUIC. | |
| 41 static class QuicHint { | |
| 42 // The host. | |
| 43 final String mHost; | |
| 44 // Port of the server that supports QUIC. | |
| 45 final int mPort; | |
| 46 // Alternate protocol port. | |
| 47 final int mAlternatePort; | |
| 48 | |
| 49 QuicHint(String host, int port, int alternatePort) { | |
| 50 mHost = host; | |
| 51 mPort = port; | |
| 52 mAlternatePort = alternatePort; | |
| 53 } | |
| 54 } | |
| 55 | |
| 56 // A public key pin. | |
| 57 static class Pkp { | |
| 58 // Host to pin for. | |
| 59 final String mHost; | |
| 60 // Array of SHA-256 hashes of keys. | |
| 61 final byte[][] mHashes; | |
| 62 // Should pin apply to subdomains? | |
| 63 final boolean mIncludeSubdomains; | |
| 64 // When the pin expires. | |
| 65 final Date mExpirationDate; | |
| 66 | |
| 67 Pkp(String host, byte[][] hashes, boolean includeSubdomains, Date ex
pirationDate) { | |
| 68 mHost = host; | |
| 69 mHashes = hashes; | |
| 70 mIncludeSubdomains = includeSubdomains; | |
| 71 mExpirationDate = expirationDate; | |
| 72 } | |
| 73 } | |
| 74 | |
| 75 private static final Pattern INVALID_PKP_HOST_NAME = Pattern.compile("^[
0-9\\.]*$"); | 44 private static final Pattern INVALID_PKP_HOST_NAME = Pattern.compile("^[
0-9\\.]*$"); |
| 76 | 45 |
| 77 // Private fields are simply storage of configuration for the resulting
CronetEngine. | 46 private final JSONObject mConfig; |
| 78 // See setters below for verbose descriptions. | |
| 79 private final Context mContext; | 47 private final Context mContext; |
| 80 private final List<QuicHint> mQuicHints = new LinkedList<QuicHint>(); | |
| 81 private final List<Pkp> mPkps = new LinkedList<Pkp>(); | |
| 82 private String mUserAgent; | |
| 83 private String mStoragePath; | |
| 84 private boolean mLegacyModeEnabled; | |
| 85 private String mLibraryName; | |
| 86 private boolean mQuicEnabled; | |
| 87 private boolean mHttp2Enabled; | |
| 88 private boolean mSdchEnabled; | |
| 89 private String mDataReductionProxyKey; | |
| 90 private String mDataReductionProxyPrimaryProxy; | |
| 91 private String mDataReductionProxyFallbackProxy; | |
| 92 private String mDataReductionProxySecureProxyCheckUrl; | |
| 93 private boolean mDisableCache; | |
| 94 private int mHttpCacheMode; | |
| 95 private long mHttpCacheMaxSize; | |
| 96 private String mExperimentalOptions; | |
| 97 private long mMockCertVerifier; | |
| 98 | 48 |
| 99 /** | 49 /** |
| 100 * Default config enables SPDY, disables QUIC, SDCH and HTTP cache. | 50 * Default config enables SPDY, disables QUIC, SDCH and HTTP cache. |
| 101 * @param context Android {@link Context} for engine to use. | 51 * @param context Android {@link Context} for engine to use. |
| 102 */ | 52 */ |
| 103 public Builder(Context context) { | 53 public Builder(Context context) { |
| 54 mConfig = new JSONObject(); |
| 104 mContext = context; | 55 mContext = context; |
| 105 setLibraryName("cronet"); | |
| 106 enableLegacyMode(false); | 56 enableLegacyMode(false); |
| 107 enableQUIC(false); | 57 enableQUIC(false); |
| 108 enableHTTP2(true); | 58 enableHTTP2(true); |
| 109 enableSDCH(false); | 59 enableSDCH(false); |
| 110 enableHttpCache(HTTP_CACHE_DISABLED, 0); | 60 enableHttpCache(HTTP_CACHE_DISABLED, 0); |
| 111 } | 61 } |
| 112 | 62 |
| 113 /** | 63 /** |
| 114 * Constructs a User-Agent string including Cronet version, and | 64 * Constructs a User-Agent string including Cronet version, and |
| 115 * application name and version. | 65 * application name and version. |
| 116 * | 66 * |
| 117 * @return User-Agent string. | 67 * @return User-Agent string. |
| 118 */ | 68 */ |
| 119 public String getDefaultUserAgent() { | 69 public String getDefaultUserAgent() { |
| 120 return UserAgent.from(mContext); | 70 return UserAgent.from(mContext); |
| 121 } | 71 } |
| 122 | 72 |
| 123 /** | 73 /** |
| 124 * Overrides the User-Agent header for all requests. | 74 * Overrides the User-Agent header for all requests. |
| 125 * @return the builder to facilitate chaining. | 75 * @return the builder to facilitate chaining. |
| 126 */ | 76 */ |
| 127 public Builder setUserAgent(String userAgent) { | 77 public Builder setUserAgent(String userAgent) { |
| 128 mUserAgent = userAgent; | 78 return putString(CronetEngineBuilderList.USER_AGENT, userAgent); |
| 129 return this; | |
| 130 } | 79 } |
| 131 | 80 |
| 132 String getUserAgent() { | 81 String getUserAgent() { |
| 133 return mUserAgent; | 82 return mConfig.optString(CronetEngineBuilderList.USER_AGENT); |
| 134 } | 83 } |
| 135 | 84 |
| 136 /** | 85 /** |
| 137 * Sets directory for HTTP Cache and Cookie Storage. The directory must | 86 * Sets directory for HTTP Cache and Cookie Storage. The directory must |
| 138 * exist. | 87 * exist. |
| 139 * <p> | 88 * <p> |
| 140 * <b>NOTE:</b> Do not use the same storage directory with more than one | 89 * <b>NOTE:</b> Do not use the same storage directory with more than one |
| 141 * {@code CronetEngine} at a time. Access to the storage directory does | 90 * {@code CronetEngine} at a time. Access to the storage directory does |
| 142 * not support concurrent access by multiple {@code CronetEngine}s. | 91 * not support concurrent access by multiple {@code CronetEngine}s. |
| 143 * | 92 * |
| 144 * @param value path to existing directory. | 93 * @param value path to existing directory. |
| 145 * @return the builder to facilitate chaining. | 94 * @return the builder to facilitate chaining. |
| 146 */ | 95 */ |
| 147 public Builder setStoragePath(String value) { | 96 public Builder setStoragePath(String value) { |
| 148 if (!new File(value).isDirectory()) { | 97 if (!new File(value).isDirectory()) { |
| 149 throw new IllegalArgumentException( | 98 throw new IllegalArgumentException( |
| 150 "Storage path must be set to existing directory"); | 99 "Storage path must be set to existing directory"); |
| 151 } | 100 } |
| 152 mStoragePath = value; | 101 |
| 153 return this; | 102 return putString(CronetEngineBuilderList.STORAGE_PATH, value); |
| 154 } | 103 } |
| 155 | 104 |
| 156 String storagePath() { | 105 String storagePath() { |
| 157 return mStoragePath; | 106 return mConfig.optString(CronetEngineBuilderList.STORAGE_PATH); |
| 158 } | 107 } |
| 159 | 108 |
| 160 /** | 109 /** |
| 161 * Sets whether falling back to implementation based on system's | 110 * Sets whether falling back to implementation based on system's |
| 162 * {@link java.net.HttpURLConnection} implementation is enabled. | 111 * {@link java.net.HttpURLConnection} implementation is enabled. |
| 163 * Defaults to disabled. | 112 * Defaults to disabled. |
| 164 * @return the builder to facilitate chaining. | 113 * @return the builder to facilitate chaining. |
| 165 * @deprecated Not supported by the new API. | 114 * @deprecated Not supported by the new API. |
| 166 */ | 115 */ |
| 167 @Deprecated | 116 @Deprecated |
| 168 public Builder enableLegacyMode(boolean value) { | 117 public Builder enableLegacyMode(boolean value) { |
| 169 mLegacyModeEnabled = value; | 118 return putBoolean(CronetEngineBuilderList.ENABLE_LEGACY_MODE, value)
; |
| 170 return this; | |
| 171 } | 119 } |
| 172 | 120 |
| 173 boolean legacyMode() { | 121 boolean legacyMode() { |
| 174 return mLegacyModeEnabled; | 122 return mConfig.optBoolean(CronetEngineBuilderList.ENABLE_LEGACY_MODE
); |
| 175 } | 123 } |
| 176 | 124 |
| 177 /** | 125 /** |
| 178 * Overrides the name of the native library backing Cronet. | 126 * Overrides the name of the native library backing Cronet. |
| 179 * @return the builder to facilitate chaining. | 127 * @return the builder to facilitate chaining. |
| 180 */ | 128 */ |
| 181 Builder setLibraryName(String libName) { | 129 Builder setLibraryName(String libName) { |
| 182 mLibraryName = libName; | 130 return putString(CronetEngineBuilderList.NATIVE_LIBRARY_NAME, libNam
e); |
| 183 return this; | |
| 184 } | 131 } |
| 185 | 132 |
| 186 String libraryName() { | 133 String libraryName() { |
| 187 return mLibraryName; | 134 return mConfig.optString(CronetEngineBuilderList.NATIVE_LIBRARY_NAME
, "cronet"); |
| 188 } | 135 } |
| 189 | 136 |
| 190 /** | 137 /** |
| 191 * Sets whether <a href="https://www.chromium.org/quic">QUIC</a> protoco
l | 138 * Sets whether <a href="https://www.chromium.org/quic">QUIC</a> protoco
l |
| 192 * is enabled. Defaults to disabled. | 139 * is enabled. Defaults to disabled. |
| 193 * @return the builder to facilitate chaining. | 140 * @return the builder to facilitate chaining. |
| 194 */ | 141 */ |
| 195 public Builder enableQUIC(boolean value) { | 142 public Builder enableQUIC(boolean value) { |
| 196 mQuicEnabled = value; | 143 return putBoolean(CronetEngineBuilderList.ENABLE_QUIC, value); |
| 197 return this; | |
| 198 } | |
| 199 | |
| 200 boolean quicEnabled() { | |
| 201 return mQuicEnabled; | |
| 202 } | 144 } |
| 203 | 145 |
| 204 /** | 146 /** |
| 205 * Sets whether <a href="https://tools.ietf.org/html/rfc7540">HTTP/2</a> | 147 * Sets whether <a href="https://tools.ietf.org/html/rfc7540">HTTP/2</a> |
| 206 * protocol is enabled. Defaults to enabled. | 148 * protocol is enabled. Defaults to enabled. |
| 207 * @return the builder to facilitate chaining. | 149 * @return the builder to facilitate chaining. |
| 208 */ | 150 */ |
| 209 public Builder enableHTTP2(boolean value) { | 151 public Builder enableHTTP2(boolean value) { |
| 210 mHttp2Enabled = value; | 152 return putBoolean(CronetEngineBuilderList.ENABLE_SPDY, value); |
| 211 return this; | |
| 212 } | |
| 213 | |
| 214 boolean http2Enabled() { | |
| 215 return mHttp2Enabled; | |
| 216 } | 153 } |
| 217 | 154 |
| 218 /** | 155 /** |
| 219 * Sets whether | 156 * Sets whether |
| 220 * <a | 157 * <a |
| 221 * href="https://lists.w3.org/Archives/Public/ietf-http-wg/2008JulSep/at
t-0441/Shared_Dictionary_Compression_over_HTTP.pdf"> | 158 * href="https://lists.w3.org/Archives/Public/ietf-http-wg/2008JulSep/at
t-0441/Shared_Dictionary_Compression_over_HTTP.pdf"> |
| 222 * SDCH</a> compression is enabled. Defaults to disabled. | 159 * SDCH</a> compression is enabled. Defaults to disabled. |
| 223 * @return the builder to facilitate chaining. | 160 * @return the builder to facilitate chaining. |
| 224 */ | 161 */ |
| 225 public Builder enableSDCH(boolean value) { | 162 public Builder enableSDCH(boolean value) { |
| 226 mSdchEnabled = value; | 163 return putBoolean(CronetEngineBuilderList.ENABLE_SDCH, value); |
| 227 return this; | |
| 228 } | |
| 229 | |
| 230 boolean sdchEnabled() { | |
| 231 return mSdchEnabled; | |
| 232 } | 164 } |
| 233 | 165 |
| 234 /** | 166 /** |
| 235 * Enables | 167 * Enables |
| 236 * <a href="https://developer.chrome.com/multidevice/data-compression">D
ata | 168 * <a href="https://developer.chrome.com/multidevice/data-compression">D
ata |
| 237 * Reduction Proxy</a>. Defaults to disabled. | 169 * Reduction Proxy</a>. Defaults to disabled. |
| 238 * @param key key to use when authenticating with the proxy. | 170 * @param key key to use when authenticating with the proxy. |
| 239 * @return the builder to facilitate chaining. | 171 * @return the builder to facilitate chaining. |
| 240 */ | 172 */ |
| 241 public Builder enableDataReductionProxy(String key) { | 173 public Builder enableDataReductionProxy(String key) { |
| 242 mDataReductionProxyKey = key; | 174 return (putString(CronetEngineBuilderList.DATA_REDUCTION_PROXY_KEY,
key)); |
| 243 return this; | |
| 244 } | |
| 245 | |
| 246 String dataReductionProxyKey() { | |
| 247 return mDataReductionProxyKey; | |
| 248 } | 175 } |
| 249 | 176 |
| 250 /** | 177 /** |
| 251 * Overrides | 178 * Overrides |
| 252 * <a href="https://developer.chrome.com/multidevice/data-compression"> | 179 * <a href="https://developer.chrome.com/multidevice/data-compression"> |
| 253 * Data Reduction Proxy</a> configuration parameters with a primary | 180 * Data Reduction Proxy</a> configuration parameters with a primary |
| 254 * proxy name, fallback proxy name, and a secure proxy check URL. Proxie
s | 181 * proxy name, fallback proxy name, and a secure proxy check URL. Proxie
s |
| 255 * are specified as [scheme://]host[:port]. Used for testing. | 182 * are specified as [scheme://]host[:port]. Used for testing. |
| 256 * @param primaryProxy the primary data reduction proxy to use. | 183 * @param primaryProxy the primary data reduction proxy to use. |
| 257 * @param fallbackProxy a fallback data reduction proxy to use. | 184 * @param fallbackProxy a fallback data reduction proxy to use. |
| 258 * @param secureProxyCheckUrl a URL to fetch to determine if using a sec
ure | 185 * @param secureProxyCheckUrl a URL to fetch to determine if using a sec
ure |
| 259 * proxy is allowed. | 186 * proxy is allowed. |
| 260 * @return the builder to facilitate chaining. | 187 * @return the builder to facilitate chaining. |
| 261 * @hide | 188 * @hide |
| 262 * @deprecated Marked as deprecated because @hide doesn't properly hide
but | 189 * @deprecated Marked as deprecated because @hide doesn't properly hide
but |
| 263 * javadocs are built with nodeprecated="yes". | 190 * javadocs are built with nodeprecated="yes". |
| 264 */ | 191 */ |
| 265 @SuppressWarnings("DepAnn") | 192 @SuppressWarnings("DepAnn") |
| 266 public Builder setDataReductionProxyOptions( | 193 public Builder setDataReductionProxyOptions( |
| 267 String primaryProxy, String fallbackProxy, String secureProxyChe
ckUrl) { | 194 String primaryProxy, String fallbackProxy, String secureProxyChe
ckUrl) { |
| 268 if (primaryProxy.isEmpty() || fallbackProxy.isEmpty() | 195 if (primaryProxy.isEmpty() || fallbackProxy.isEmpty() |
| 269 || secureProxyCheckUrl.isEmpty()) { | 196 || secureProxyCheckUrl.isEmpty()) { |
| 270 throw new IllegalArgumentException( | 197 throw new IllegalArgumentException( |
| 271 "Primary and fallback proxies and check url must be set"
); | 198 "Primary and fallback proxies and check url must be set"
); |
| 272 } | 199 } |
| 273 mDataReductionProxyPrimaryProxy = primaryProxy; | 200 putString(CronetEngineBuilderList.DATA_REDUCTION_PRIMARY_PROXY, prim
aryProxy); |
| 274 mDataReductionProxyFallbackProxy = fallbackProxy; | 201 putString(CronetEngineBuilderList.DATA_REDUCTION_FALLBACK_PROXY, fal
lbackProxy); |
| 275 mDataReductionProxySecureProxyCheckUrl = secureProxyCheckUrl; | 202 putString(CronetEngineBuilderList.DATA_REDUCTION_SECURE_PROXY_CHECK_
URL, |
| 203 secureProxyCheckUrl); |
| 276 return this; | 204 return this; |
| 277 } | 205 } |
| 278 | 206 |
| 279 String dataReductionProxyPrimaryProxy() { | |
| 280 return mDataReductionProxyPrimaryProxy; | |
| 281 } | |
| 282 | |
| 283 String dataReductionProxyFallbackProxy() { | |
| 284 return mDataReductionProxyFallbackProxy; | |
| 285 } | |
| 286 | |
| 287 String dataReductionProxySecureProxyCheckUrl() { | |
| 288 return mDataReductionProxySecureProxyCheckUrl; | |
| 289 } | |
| 290 | |
| 291 /** @deprecated not really deprecated but hidden. */ | 207 /** @deprecated not really deprecated but hidden. */ |
| 292 @IntDef({ | 208 @IntDef({ |
| 293 HTTP_CACHE_DISABLED, HTTP_CACHE_IN_MEMORY, HTTP_CACHE_DISK_NO_HT
TP, HTTP_CACHE_DISK, | 209 HTTP_CACHE_DISABLED, HTTP_CACHE_IN_MEMORY, HTTP_CACHE_DISK_NO_HT
TP, HTTP_CACHE_DISK, |
| 294 }) | 210 }) |
| 295 @Retention(RetentionPolicy.SOURCE) | 211 @Retention(RetentionPolicy.SOURCE) |
| 296 @SuppressWarnings("DepAnn") | 212 @SuppressWarnings("DepAnn") |
| 297 public @interface HttpCacheSetting {} | 213 public @interface HttpCacheSetting {} |
| 298 | 214 |
| 299 /** | 215 /** |
| 300 * Setting to disable HTTP cache. Some data may still be temporarily sto
red in memory. | 216 * Setting to disable HTTP cache. Some data may still be temporarily sto
red in memory. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 326 * Enables or disables caching of HTTP data and other information like Q
UIC | 242 * Enables or disables caching of HTTP data and other information like Q
UIC |
| 327 * server information. | 243 * server information. |
| 328 * @param cacheMode control location and type of cached data. Must be on
e of | 244 * @param cacheMode control location and type of cached data. Must be on
e of |
| 329 * {@link #HTTP_CACHE_DISABLED HTTP_CACHE_*}. | 245 * {@link #HTTP_CACHE_DISABLED HTTP_CACHE_*}. |
| 330 * @param maxSize maximum size in bytes used to cache data (advisory and
maybe | 246 * @param maxSize maximum size in bytes used to cache data (advisory and
maybe |
| 331 * exceeded at times). | 247 * exceeded at times). |
| 332 * @return the builder to facilitate chaining. | 248 * @return the builder to facilitate chaining. |
| 333 */ | 249 */ |
| 334 public Builder enableHttpCache(@HttpCacheSetting int cacheMode, long max
Size) { | 250 public Builder enableHttpCache(@HttpCacheSetting int cacheMode, long max
Size) { |
| 335 if (cacheMode == HTTP_CACHE_DISK || cacheMode == HTTP_CACHE_DISK_NO_
HTTP) { | 251 if (cacheMode == HTTP_CACHE_DISK || cacheMode == HTTP_CACHE_DISK_NO_
HTTP) { |
| 336 if (storagePath() == null) { | 252 if (storagePath().isEmpty()) { |
| 337 throw new IllegalArgumentException("Storage path must be set
"); | 253 throw new IllegalArgumentException("Storage path must be set
"); |
| 338 } | 254 } |
| 339 } else { | 255 } else { |
| 340 if (storagePath() != null) { | 256 if (!storagePath().isEmpty()) { |
| 341 throw new IllegalArgumentException("Storage path must not be
set"); | 257 throw new IllegalArgumentException("Storage path must be emp
ty"); |
| 342 } | 258 } |
| 343 } | 259 } |
| 344 mDisableCache = | 260 putBoolean(CronetEngineBuilderList.LOAD_DISABLE_CACHE, |
| 345 (cacheMode == HTTP_CACHE_DISABLED || cacheMode == HTTP_CACHE
_DISK_NO_HTTP); | 261 cacheMode == HTTP_CACHE_DISABLED || cacheMode == HTTP_CACHE_
DISK_NO_HTTP); |
| 346 mHttpCacheMaxSize = maxSize; | 262 putLong(CronetEngineBuilderList.HTTP_CACHE_MAX_SIZE, maxSize); |
| 347 | 263 |
| 348 switch (cacheMode) { | 264 switch (cacheMode) { |
| 349 case HTTP_CACHE_DISABLED: | 265 case HTTP_CACHE_DISABLED: |
| 350 mHttpCacheMode = HttpCacheType.DISABLED; | 266 return putString(CronetEngineBuilderList.HTTP_CACHE, |
| 351 break; | 267 CronetEngineBuilderList.HTTP_CACHE_DISABLED); |
| 352 case HTTP_CACHE_DISK_NO_HTTP: | 268 case HTTP_CACHE_DISK_NO_HTTP: |
| 353 case HTTP_CACHE_DISK: | 269 case HTTP_CACHE_DISK: |
| 354 mHttpCacheMode = HttpCacheType.DISK; | 270 return putString(CronetEngineBuilderList.HTTP_CACHE, |
| 355 break; | 271 CronetEngineBuilderList.HTTP_CACHE_DISK); |
| 272 |
| 356 case HTTP_CACHE_IN_MEMORY: | 273 case HTTP_CACHE_IN_MEMORY: |
| 357 mHttpCacheMode = HttpCacheType.MEMORY; | 274 return putString(CronetEngineBuilderList.HTTP_CACHE, |
| 358 break; | 275 CronetEngineBuilderList.HTTP_CACHE_MEMORY); |
| 359 default: | |
| 360 throw new IllegalArgumentException("Unknown cache mode"); | |
| 361 } | 276 } |
| 362 return this; | 277 return this; |
| 363 } | 278 } |
| 364 | 279 |
| 365 boolean cacheDisabled() { | |
| 366 return mDisableCache; | |
| 367 } | |
| 368 | |
| 369 long httpCacheMaxSize() { | |
| 370 return mHttpCacheMaxSize; | |
| 371 } | |
| 372 | |
| 373 int httpCacheMode() { | |
| 374 return mHttpCacheMode; | |
| 375 } | |
| 376 | |
| 377 /** | 280 /** |
| 378 * Adds hint that {@code host} supports QUIC. | 281 * Adds hint that {@code host} supports QUIC. |
| 379 * Note that {@link #enableHttpCache enableHttpCache} | 282 * Note that {@link #enableHttpCache enableHttpCache} |
| 380 * ({@link #HTTP_CACHE_DISK}) is needed to take advantage of 0-RTT | 283 * ({@link #HTTP_CACHE_DISK}) is needed to take advantage of 0-RTT |
| 381 * connection establishment between sessions. | 284 * connection establishment between sessions. |
| 382 * | 285 * |
| 383 * @param host hostname of the server that supports QUIC. | 286 * @param host hostname of the server that supports QUIC. |
| 384 * @param port host of the server that supports QUIC. | 287 * @param port host of the server that supports QUIC. |
| 385 * @param alternatePort alternate port to use for QUIC. | 288 * @param alternatePort alternate port to use for QUIC. |
| 386 * @return the builder to facilitate chaining. | 289 * @return the builder to facilitate chaining. |
| 387 */ | 290 */ |
| 388 public Builder addQuicHint(String host, int port, int alternatePort) { | 291 public Builder addQuicHint(String host, int port, int alternatePort) { |
| 389 if (host.contains("/")) { | 292 if (host.contains("/")) { |
| 390 throw new IllegalArgumentException("Illegal QUIC Hint Host: " +
host); | 293 throw new IllegalArgumentException("Illegal QUIC Hint Host: " +
host); |
| 391 } | 294 } |
| 392 mQuicHints.add(new QuicHint(host, port, alternatePort)); | 295 try { |
| 296 JSONArray quicHints = mConfig.optJSONArray(CronetEngineBuilderLi
st.QUIC_HINTS); |
| 297 if (quicHints == null) { |
| 298 quicHints = new JSONArray(); |
| 299 mConfig.put(CronetEngineBuilderList.QUIC_HINTS, quicHints); |
| 300 } |
| 301 |
| 302 JSONObject hint = new JSONObject(); |
| 303 hint.put(CronetEngineBuilderList.QUIC_HINT_HOST, host); |
| 304 hint.put(CronetEngineBuilderList.QUIC_HINT_PORT, port); |
| 305 hint.put(CronetEngineBuilderList.QUIC_HINT_ALT_PORT, alternatePo
rt); |
| 306 quicHints.put(hint); |
| 307 } catch (JSONException e) { |
| 308 // Intentionally do nothing. |
| 309 } |
| 393 return this; | 310 return this; |
| 394 } | 311 } |
| 395 | 312 |
| 396 List<QuicHint> quicHints() { | |
| 397 return mQuicHints; | |
| 398 } | |
| 399 | |
| 400 /** | 313 /** |
| 401 * <p> | 314 * <p> |
| 402 * Pins a set of public keys for a given host. By pinning a set of publi
c keys, | 315 * Pins a set of public keys for a given host. By pinning a set of publi
c keys, |
| 403 * {@code pinsSha256}, communication with {@code hostName} is required t
o | 316 * {@code pinsSha256}, communication with {@code hostName} is required t
o |
| 404 * authenticate with a certificate with a public key from the set of pin
ned ones. | 317 * authenticate with a certificate with a public key from the set of pin
ned ones. |
| 405 * An app can pin the public key of the root certificate, any of the int
ermediate | 318 * An app can pin the public key of the root certificate, any of the int
ermediate |
| 406 * certificates or the end-entry certificate. Authentication will fail a
nd secure | 319 * certificates or the end-entry certificate. Authentication will fail a
nd secure |
| 407 * communication will not be established if none of the public keys is p
resent in the | 320 * communication will not be established if none of the public keys is p
resent in the |
| 408 * host's certificate chain, even if the host attempts to authenticate w
ith a | 321 * host's certificate chain, even if the host attempts to authenticate w
ith a |
| 409 * certificate allowed by the device's trusted store of certificates. | 322 * certificate allowed by the device's trusted store of certificates. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 if (hostName == null) { | 356 if (hostName == null) { |
| 444 throw new NullPointerException("The hostname cannot be null"); | 357 throw new NullPointerException("The hostname cannot be null"); |
| 445 } | 358 } |
| 446 if (pinsSha256 == null) { | 359 if (pinsSha256 == null) { |
| 447 throw new NullPointerException("The set of SHA256 pins cannot be
null"); | 360 throw new NullPointerException("The set of SHA256 pins cannot be
null"); |
| 448 } | 361 } |
| 449 if (expirationDate == null) { | 362 if (expirationDate == null) { |
| 450 throw new NullPointerException("The pin expiration date cannot b
e null"); | 363 throw new NullPointerException("The pin expiration date cannot b
e null"); |
| 451 } | 364 } |
| 452 String idnHostName = validateHostNameForPinningAndConvert(hostName); | 365 String idnHostName = validateHostNameForPinningAndConvert(hostName); |
| 453 // Convert the pin to BASE64 encoding. The hash set will eliminate d
uplications. | 366 try { |
| 454 Set<byte[]> hashes = new HashSet<>(pinsSha256.size()); | 367 // Add PKP_LIST JSON array element if it is not present. |
| 455 for (byte[] pinSha256 : pinsSha256) { | 368 JSONArray pkpList = mConfig.optJSONArray(CronetEngineBuilderList
.PKP_LIST); |
| 456 if (pinSha256 == null || pinSha256.length != 32) { | 369 if (pkpList == null) { |
| 457 throw new IllegalArgumentException("Public key pin is invali
d"); | 370 pkpList = new JSONArray(); |
| 371 mConfig.put(CronetEngineBuilderList.PKP_LIST, pkpList); |
| 458 } | 372 } |
| 459 hashes.add(pinSha256); | 373 |
| 374 // Convert the pin to BASE64 encoding. The hash set will elimina
te duplications. |
| 375 Set<String> hashes = new HashSet<>(pinsSha256.size()); |
| 376 for (byte[] pinSha256 : pinsSha256) { |
| 377 hashes.add(convertSha256ToBase64WithPrefix(pinSha256)); |
| 378 } |
| 379 |
| 380 // Add new element to PKP_LIST JSON array. |
| 381 JSONObject pkp = new JSONObject(); |
| 382 pkp.put(CronetEngineBuilderList.PKP_HOST, idnHostName); |
| 383 pkp.put(CronetEngineBuilderList.PKP_PIN_HASHES, new JSONArray(ha
shes)); |
| 384 pkp.put(CronetEngineBuilderList.PKP_INCLUDE_SUBDOMAINS, includeS
ubdomains); |
| 385 // The expiration time is passed as a double, in seconds since J
anuary 1, 1970. |
| 386 pkp.put(CronetEngineBuilderList.PKP_EXPIRATION_DATE, |
| 387 (double) expirationDate.getTime() / 1000); |
| 388 pkpList.put(pkp); |
| 389 } catch (JSONException e) { |
| 390 // This exception should never happen. |
| 391 throw new RuntimeException( |
| 392 "Failed to add pubic key pins with the given arguments",
e); |
| 460 } | 393 } |
| 461 // Add new element to PKP list. | |
| 462 mPkps.add(new Pkp(idnHostName, hashes.toArray(new byte[hashes.size()
][]), | |
| 463 includeSubdomains, expirationDate)); | |
| 464 return this; | 394 return this; |
| 465 } | 395 } |
| 466 | 396 |
| 467 /** | 397 /** |
| 468 * Returns list of public key pins. | 398 * Converts a given SHA256 array of bytes to BASE64 encoded string and p
repends |
| 399 * {@code sha256/} prefix to it. The format corresponds to the format th
at is expected by |
| 400 * {@code net::HashValue} class. |
| 401 * |
| 402 * @param sha256 SHA256 bytes to convert to BASE64. |
| 403 * @return the BASE64 encoded SHA256 with the prefix. |
| 404 * @throws IllegalArgumentException if the provided pin is invalid. |
| 469 */ | 405 */ |
| 470 List<Pkp> publicKeyPins() { | 406 private static String convertSha256ToBase64WithPrefix(byte[] sha256) { |
| 471 return mPkps; | 407 if (sha256 == null || sha256.length != 32) { |
| 408 throw new IllegalArgumentException("Public key pin is invalid"); |
| 409 } |
| 410 return "sha256/" + Base64.encodeToString(sha256, Base64.NO_WRAP); |
| 472 } | 411 } |
| 473 | 412 |
| 474 /** | 413 /** |
| 475 * Checks whether a given string represents a valid host name for PKP an
d converts it | 414 * Checks whether a given string represents a valid host name for PKP an
d converts it |
| 476 * to ASCII Compatible Encoding representation according to RFC 1122, RF
C 1123 and | 415 * to ASCII Compatible Encoding representation according to RFC 1122, RF
C 1123 and |
| 477 * RFC 3490. This method is more restrictive than required by RFC 7469.
Thus, a host | 416 * RFC 3490. This method is more restrictive than required by RFC 7469.
Thus, a host |
| 478 * that contains digits and the dot character only is considered invalid
. | 417 * that contains digits and the dot character only is considered invalid
. |
| 479 * | 418 * |
| 480 * Note: Currently Cronet doesn't have native implementation of host nam
e validation that | 419 * Note: Currently Cronet doesn't have native implementation of host nam
e validation that |
| 481 * can be used. There is code that parses a provided URL but doesn
't ensure its | 420 * can be used. There is code that parses a provided URL but doesn
't ensure its |
| (...skipping 18 matching lines...) Expand all Loading... |
| 500 } | 439 } |
| 501 } | 440 } |
| 502 | 441 |
| 503 /** | 442 /** |
| 504 * Sets experimental options to be used in Cronet. | 443 * Sets experimental options to be used in Cronet. |
| 505 * | 444 * |
| 506 * @param options JSON formatted experimental options. | 445 * @param options JSON formatted experimental options. |
| 507 * @return the builder to facilitate chaining. | 446 * @return the builder to facilitate chaining. |
| 508 */ | 447 */ |
| 509 public Builder setExperimentalOptions(String options) { | 448 public Builder setExperimentalOptions(String options) { |
| 510 mExperimentalOptions = options; | 449 return putString(CronetEngineBuilderList.EXPERIMENTAL_OPTIONS, optio
ns); |
| 511 return this; | |
| 512 } | |
| 513 | |
| 514 String experimentalOptions() { | |
| 515 return mExperimentalOptions; | |
| 516 } | 450 } |
| 517 | 451 |
| 518 /** | 452 /** |
| 519 * Sets a native MockCertVerifier for testing. | 453 * Sets a native MockCertVerifier for testing. |
| 520 */ | 454 */ |
| 521 Builder setMockCertVerifierForTesting(long mockCertVerifier) { | 455 Builder setMockCertVerifierForTesting(long mockCertVerifier) { |
| 522 mMockCertVerifier = mockCertVerifier; | 456 return putString( |
| 523 return this; | 457 CronetEngineBuilderList.MOCK_CERT_VERIFIER, String.valueOf(m
ockCertVerifier)); |
| 524 } | |
| 525 | |
| 526 long mockCertVerifier() { | |
| 527 return mMockCertVerifier; | |
| 528 } | 458 } |
| 529 | 459 |
| 530 /** | 460 /** |
| 461 * Gets a JSON string representation of the builder. |
| 462 */ |
| 463 String toJSONString() { |
| 464 return mConfig.toString(); |
| 465 } |
| 466 |
| 467 /** |
| 531 * Returns {@link Context} for builder. | 468 * Returns {@link Context} for builder. |
| 532 * | 469 * |
| 533 * @return {@link Context} for builder. | 470 * @return {@link Context} for builder. |
| 534 */ | 471 */ |
| 535 Context getContext() { | 472 Context getContext() { |
| 536 return mContext; | 473 return mContext; |
| 537 } | 474 } |
| 538 | 475 |
| 539 /** | 476 /** |
| 477 * Sets a boolean value in the config. Returns a reference to the same |
| 478 * config object, so you can chain put calls together. |
| 479 * @return the builder to facilitate chaining. |
| 480 */ |
| 481 private Builder putBoolean(String key, boolean value) { |
| 482 try { |
| 483 mConfig.put(key, value); |
| 484 } catch (JSONException e) { |
| 485 // Intentionally do nothing. |
| 486 } |
| 487 return this; |
| 488 } |
| 489 |
| 490 /** |
| 491 * Sets a long value in the config. Returns a reference to the same |
| 492 * config object, so you can chain put calls together. |
| 493 * @return the builder to facilitate chaining. |
| 494 */ |
| 495 private Builder putLong(String key, long value) { |
| 496 try { |
| 497 mConfig.put(key, value); |
| 498 } catch (JSONException e) { |
| 499 // Intentionally do nothing. |
| 500 } |
| 501 return this; |
| 502 } |
| 503 |
| 504 /** |
| 505 * Sets a string value in the config. Returns a reference to the same |
| 506 * config object, so you can chain put calls together. |
| 507 * @return the builder to facilitate chaining. |
| 508 */ |
| 509 private Builder putString(String key, String value) { |
| 510 try { |
| 511 mConfig.put(key, value); |
| 512 } catch (JSONException e) { |
| 513 // Intentionally do nothing. |
| 514 } |
| 515 return this; |
| 516 } |
| 517 |
| 518 /** |
| 540 * Build a {@link CronetEngine} using this builder's configuration. | 519 * Build a {@link CronetEngine} using this builder's configuration. |
| 541 */ | 520 */ |
| 542 public CronetEngine build() { | 521 public CronetEngine build() { |
| 543 CronetEngine engine = createContext(this); | 522 CronetEngine engine = createContext(this); |
| 544 // Clear MOCK_CERT_VERIFIER reference if there is any, since | 523 // Clear MOCK_CERT_VERIFIER reference if there is any, since |
| 545 // the ownership has been transferred to the engine. | 524 // the ownership has been transferred to the engine. |
| 546 mMockCertVerifier = 0; | 525 mConfig.remove(CronetEngineBuilderList.MOCK_CERT_VERIFIER); |
| 547 return engine; | 526 return engine; |
| 548 } | 527 } |
| 549 } | 528 } |
| 550 | 529 |
| 551 private static final String TAG = "UrlRequestFactory"; | 530 private static final String TAG = "UrlRequestFactory"; |
| 552 private static final String CRONET_URL_REQUEST_CONTEXT = | 531 private static final String CRONET_URL_REQUEST_CONTEXT = |
| 553 "org.chromium.net.CronetUrlRequestContext"; | 532 "org.chromium.net.CronetUrlRequestContext"; |
| 554 | 533 |
| 555 /** | 534 /** |
| 556 * Creates a {@link UrlRequest} object. All callbacks will | 535 * Creates a {@link UrlRequest} object. All callbacks will |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 812 /** | 791 /** |
| 813 * Creates a {@link CronetEngine} with the given {@link Builder}. | 792 * Creates a {@link CronetEngine} with the given {@link Builder}. |
| 814 * | 793 * |
| 815 * @param builder builder to used for creating the CronetEngine instance. | 794 * @param builder builder to used for creating the CronetEngine instance. |
| 816 * @return the created CronetEngine instance. | 795 * @return the created CronetEngine instance. |
| 817 * @deprecated Use {@link CronetEngine.Builder}. | 796 * @deprecated Use {@link CronetEngine.Builder}. |
| 818 */ | 797 */ |
| 819 @Deprecated | 798 @Deprecated |
| 820 public static CronetEngine createContext(Builder builder) { | 799 public static CronetEngine createContext(Builder builder) { |
| 821 CronetEngine cronetEngine = null; | 800 CronetEngine cronetEngine = null; |
| 822 if (builder.getUserAgent() == null) { | 801 if (builder.getUserAgent().isEmpty()) { |
| 823 builder.setUserAgent(builder.getDefaultUserAgent()); | 802 builder.setUserAgent(builder.getDefaultUserAgent()); |
| 824 } | 803 } |
| 825 if (!builder.legacyMode()) { | 804 if (!builder.legacyMode()) { |
| 826 cronetEngine = createCronetEngine(builder); | 805 cronetEngine = createCronetEngine(builder); |
| 827 } | 806 } |
| 828 if (cronetEngine == null) { | 807 if (cronetEngine == null) { |
| 829 // TODO(mef): Fallback to stub implementation. Once stub | 808 // TODO(mef): Fallback to stub implementation. Once stub |
| 830 // implementation is available merge with createCronetFactory. | 809 // implementation is available merge with createCronetFactory. |
| 831 cronetEngine = createCronetEngine(builder); | 810 cronetEngine = createCronetEngine(builder); |
| 832 } | 811 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 848 cronetEngine = possibleEngine; | 827 cronetEngine = possibleEngine; |
| 849 } | 828 } |
| 850 } catch (ClassNotFoundException e) { | 829 } catch (ClassNotFoundException e) { |
| 851 // Leave as null. | 830 // Leave as null. |
| 852 } catch (Exception e) { | 831 } catch (Exception e) { |
| 853 throw new IllegalStateException("Cannot instantiate: " + CRONET_URL_
REQUEST_CONTEXT, e); | 832 throw new IllegalStateException("Cannot instantiate: " + CRONET_URL_
REQUEST_CONTEXT, e); |
| 854 } | 833 } |
| 855 return cronetEngine; | 834 return cronetEngine; |
| 856 } | 835 } |
| 857 } | 836 } |
| OLD | NEW |