Home | History | Annotate | Download | only in okhttp
      1 /*
      2  * Copyright (C) 2012 Square, Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.squareup.okhttp;
     17 
     18 import com.squareup.okhttp.internal.Internal;
     19 import com.squareup.okhttp.internal.InternalCache;
     20 import com.squareup.okhttp.internal.Network;
     21 import com.squareup.okhttp.internal.RouteDatabase;
     22 import com.squareup.okhttp.internal.Util;
     23 import com.squareup.okhttp.internal.http.AuthenticatorAdapter;
     24 import com.squareup.okhttp.internal.http.HttpEngine;
     25 import com.squareup.okhttp.internal.http.RouteException;
     26 import com.squareup.okhttp.internal.http.Transport;
     27 import com.squareup.okhttp.internal.tls.OkHostnameVerifier;
     28 import java.io.IOException;
     29 import java.net.CookieHandler;
     30 import java.net.Proxy;
     31 import java.net.ProxySelector;
     32 import java.net.URLConnection;
     33 import java.security.GeneralSecurityException;
     34 import java.util.ArrayList;
     35 import java.util.List;
     36 import java.util.concurrent.TimeUnit;
     37 import javax.net.SocketFactory;
     38 import javax.net.ssl.HostnameVerifier;
     39 import javax.net.ssl.SSLContext;
     40 import javax.net.ssl.SSLSocket;
     41 import javax.net.ssl.SSLSocketFactory;
     42 import okio.BufferedSink;
     43 import okio.BufferedSource;
     44 
     45 /**
     46  * Configures and creates HTTP connections. Most applications can use a single
     47  * OkHttpClient for all of their HTTP requests - benefiting from a shared
     48  * response cache, thread pool, connection re-use, etc.
     49  *
     50  * <p>Instances of OkHttpClient are intended to be fully configured before they're
     51  * shared - once shared they should be treated as immutable and can safely be used
     52  * to concurrently open new connections. If required, threads can call
     53  * {@link #clone()} to make a shallow copy of the OkHttpClient that can be
     54  * safely modified with further configuration changes.
     55  */
     56 public class OkHttpClient implements Cloneable {
     57   private static final List<Protocol> DEFAULT_PROTOCOLS = Util.immutableList(
     58       Protocol.HTTP_2, Protocol.SPDY_3, Protocol.HTTP_1_1);
     59 
     60   private static final List<ConnectionSpec> DEFAULT_CONNECTION_SPECS = Util.immutableList(
     61       ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS, ConnectionSpec.CLEARTEXT);
     62 
     63   static {
     64     Internal.instance = new Internal() {
     65       @Override public Transport newTransport(
     66           Connection connection, HttpEngine httpEngine) throws IOException {
     67         return connection.newTransport(httpEngine);
     68       }
     69 
     70       @Override public boolean clearOwner(Connection connection) {
     71         return connection.clearOwner();
     72       }
     73 
     74       @Override public void closeIfOwnedBy(Connection connection, Object owner) throws IOException {
     75         connection.closeIfOwnedBy(owner);
     76       }
     77 
     78       @Override public int recycleCount(Connection connection) {
     79         return connection.recycleCount();
     80       }
     81 
     82       @Override public void setProtocol(Connection connection, Protocol protocol) {
     83         connection.setProtocol(protocol);
     84       }
     85 
     86       @Override public void setOwner(Connection connection, HttpEngine httpEngine) {
     87         connection.setOwner(httpEngine);
     88       }
     89 
     90       @Override public boolean isReadable(Connection pooled) {
     91         return pooled.isReadable();
     92       }
     93 
     94       @Override public void addLenient(Headers.Builder builder, String line) {
     95         builder.addLenient(line);
     96       }
     97 
     98       @Override public void addLenient(Headers.Builder builder, String name, String value) {
     99         builder.addLenient(name, value);
    100       }
    101 
    102       @Override public void setCache(OkHttpClient client, InternalCache internalCache) {
    103         client.setInternalCache(internalCache);
    104       }
    105 
    106       @Override public InternalCache internalCache(OkHttpClient client) {
    107         return client.internalCache();
    108       }
    109 
    110       @Override public void recycle(ConnectionPool pool, Connection connection) {
    111         pool.recycle(connection);
    112       }
    113 
    114       @Override public RouteDatabase routeDatabase(OkHttpClient client) {
    115         return client.routeDatabase();
    116       }
    117 
    118       @Override public Network network(OkHttpClient client) {
    119         return client.network;
    120       }
    121 
    122       @Override public void setNetwork(OkHttpClient client, Network network) {
    123         client.network = network;
    124       }
    125 
    126       @Override public void connectAndSetOwner(OkHttpClient client, Connection connection,
    127           HttpEngine owner, Request request) throws RouteException {
    128         connection.connectAndSetOwner(client, owner, request);
    129       }
    130 
    131       @Override
    132       public void callEnqueue(Call call, Callback responseCallback, boolean forWebSocket) {
    133         call.enqueue(responseCallback, forWebSocket);
    134       }
    135 
    136       @Override public void callEngineReleaseConnection(Call call) throws IOException {
    137         call.engine.releaseConnection();
    138       }
    139 
    140       @Override public Connection callEngineGetConnection(Call call) {
    141         return call.engine.getConnection();
    142       }
    143 
    144       @Override public BufferedSource connectionRawSource(Connection connection) {
    145         return connection.rawSource();
    146       }
    147 
    148       @Override public BufferedSink connectionRawSink(Connection connection) {
    149         return connection.rawSink();
    150       }
    151 
    152       @Override public void connectionSetOwner(Connection connection, Object owner) {
    153         connection.setOwner(owner);
    154       }
    155 
    156       @Override
    157       public void apply(ConnectionSpec tlsConfiguration, SSLSocket sslSocket, boolean isFallback) {
    158         tlsConfiguration.apply(sslSocket, isFallback);
    159       }
    160     };
    161   }
    162 
    163   /** Lazily-initialized. */
    164   private static SSLSocketFactory defaultSslSocketFactory;
    165 
    166   private final RouteDatabase routeDatabase;
    167   private Dispatcher dispatcher;
    168   private Proxy proxy;
    169   private List<Protocol> protocols;
    170   private List<ConnectionSpec> connectionSpecs;
    171   private final List<Interceptor> interceptors = new ArrayList<>();
    172   private final List<Interceptor> networkInterceptors = new ArrayList<>();
    173   private ProxySelector proxySelector;
    174   private CookieHandler cookieHandler;
    175 
    176   /** Non-null if this client is caching; possibly by {@code cache}. */
    177   private InternalCache internalCache;
    178   private Cache cache;
    179 
    180   private SocketFactory socketFactory;
    181   private SSLSocketFactory sslSocketFactory;
    182   private HostnameVerifier hostnameVerifier;
    183   private CertificatePinner certificatePinner;
    184   private Authenticator authenticator;
    185   private ConnectionPool connectionPool;
    186   private Network network;
    187   private boolean followSslRedirects = true;
    188   private boolean followRedirects = true;
    189   private boolean retryOnConnectionFailure = true;
    190   private int connectTimeout;
    191   private int readTimeout;
    192   private int writeTimeout;
    193 
    194   public OkHttpClient() {
    195     routeDatabase = new RouteDatabase();
    196     dispatcher = new Dispatcher();
    197   }
    198 
    199   private OkHttpClient(OkHttpClient okHttpClient) {
    200     this.routeDatabase = okHttpClient.routeDatabase;
    201     this.dispatcher = okHttpClient.dispatcher;
    202     this.proxy = okHttpClient.proxy;
    203     this.protocols = okHttpClient.protocols;
    204     this.connectionSpecs = okHttpClient.connectionSpecs;
    205     this.interceptors.addAll(okHttpClient.interceptors);
    206     this.networkInterceptors.addAll(okHttpClient.networkInterceptors);
    207     this.proxySelector = okHttpClient.proxySelector;
    208     this.cookieHandler = okHttpClient.cookieHandler;
    209     this.cache = okHttpClient.cache;
    210     this.internalCache = cache != null ? cache.internalCache : okHttpClient.internalCache;
    211     this.socketFactory = okHttpClient.socketFactory;
    212     this.sslSocketFactory = okHttpClient.sslSocketFactory;
    213     this.hostnameVerifier = okHttpClient.hostnameVerifier;
    214     this.certificatePinner = okHttpClient.certificatePinner;
    215     this.authenticator = okHttpClient.authenticator;
    216     this.connectionPool = okHttpClient.connectionPool;
    217     this.network = okHttpClient.network;
    218     this.followSslRedirects = okHttpClient.followSslRedirects;
    219     this.followRedirects = okHttpClient.followRedirects;
    220     this.retryOnConnectionFailure = okHttpClient.retryOnConnectionFailure;
    221     this.connectTimeout = okHttpClient.connectTimeout;
    222     this.readTimeout = okHttpClient.readTimeout;
    223     this.writeTimeout = okHttpClient.writeTimeout;
    224   }
    225 
    226   /**
    227    * Sets the default connect timeout for new connections. A value of 0 means no timeout, otherwise
    228    * values must be between 1 and {@link Integer#MAX_VALUE} when converted to milliseconds.
    229    *
    230    * @see URLConnection#setConnectTimeout(int)
    231    */
    232   public void setConnectTimeout(long timeout, TimeUnit unit) {
    233     if (timeout < 0) throw new IllegalArgumentException("timeout < 0");
    234     if (unit == null) throw new IllegalArgumentException("unit == null");
    235     long millis = unit.toMillis(timeout);
    236     if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException("Timeout too large.");
    237     if (millis == 0 && timeout > 0) throw new IllegalArgumentException("Timeout too small.");
    238     connectTimeout = (int) millis;
    239   }
    240 
    241   /** Default connect timeout (in milliseconds). */
    242   public int getConnectTimeout() {
    243     return connectTimeout;
    244   }
    245 
    246   /**
    247    * Sets the default read timeout for new connections. A value of 0 means no timeout, otherwise
    248    * values must be between 1 and {@link Integer#MAX_VALUE} when converted to milliseconds.
    249    *
    250    * @see URLConnection#setReadTimeout(int)
    251    */
    252   public void setReadTimeout(long timeout, TimeUnit unit) {
    253     if (timeout < 0) throw new IllegalArgumentException("timeout < 0");
    254     if (unit == null) throw new IllegalArgumentException("unit == null");
    255     long millis = unit.toMillis(timeout);
    256     if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException("Timeout too large.");
    257     if (millis == 0 && timeout > 0) throw new IllegalArgumentException("Timeout too small.");
    258     readTimeout = (int) millis;
    259   }
    260 
    261   /** Default read timeout (in milliseconds). */
    262   public int getReadTimeout() {
    263     return readTimeout;
    264   }
    265 
    266   /**
    267    * Sets the default write timeout for new connections. A value of 0 means no timeout, otherwise
    268    * values must be between 1 and {@link Integer#MAX_VALUE} when converted to milliseconds.
    269    */
    270   public void setWriteTimeout(long timeout, TimeUnit unit) {
    271     if (timeout < 0) throw new IllegalArgumentException("timeout < 0");
    272     if (unit == null) throw new IllegalArgumentException("unit == null");
    273     long millis = unit.toMillis(timeout);
    274     if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException("Timeout too large.");
    275     if (millis == 0 && timeout > 0) throw new IllegalArgumentException("Timeout too small.");
    276     writeTimeout = (int) millis;
    277   }
    278 
    279   /** Default write timeout (in milliseconds). */
    280   public int getWriteTimeout() {
    281     return writeTimeout;
    282   }
    283 
    284   /**
    285    * Sets the HTTP proxy that will be used by connections created by this
    286    * client. This takes precedence over {@link #setProxySelector}, which is
    287    * only honored when this proxy is null (which it is by default). To disable
    288    * proxy use completely, call {@code setProxy(Proxy.NO_PROXY)}.
    289    */
    290   public OkHttpClient setProxy(Proxy proxy) {
    291     this.proxy = proxy;
    292     return this;
    293   }
    294 
    295   public Proxy getProxy() {
    296     return proxy;
    297   }
    298 
    299   /**
    300    * Sets the proxy selection policy to be used if no {@link #setProxy proxy}
    301    * is specified explicitly. The proxy selector may return multiple proxies;
    302    * in that case they will be tried in sequence until a successful connection
    303    * is established.
    304    *
    305    * <p>If unset, the {@link ProxySelector#getDefault() system-wide default}
    306    * proxy selector will be used.
    307    */
    308   public OkHttpClient setProxySelector(ProxySelector proxySelector) {
    309     this.proxySelector = proxySelector;
    310     return this;
    311   }
    312 
    313   public ProxySelector getProxySelector() {
    314     return proxySelector;
    315   }
    316 
    317   /**
    318    * Sets the cookie handler to be used to read outgoing cookies and write
    319    * incoming cookies.
    320    *
    321    * <p>If unset, the {@link CookieHandler#getDefault() system-wide default}
    322    * cookie handler will be used.
    323    */
    324   public OkHttpClient setCookieHandler(CookieHandler cookieHandler) {
    325     this.cookieHandler = cookieHandler;
    326     return this;
    327   }
    328 
    329   public CookieHandler getCookieHandler() {
    330     return cookieHandler;
    331   }
    332 
    333   /** Sets the response cache to be used to read and write cached responses. */
    334   void setInternalCache(InternalCache internalCache) {
    335     this.internalCache = internalCache;
    336     this.cache = null;
    337   }
    338 
    339   InternalCache internalCache() {
    340     return internalCache;
    341   }
    342 
    343   public OkHttpClient setCache(Cache cache) {
    344     this.cache = cache;
    345     this.internalCache = null;
    346     return this;
    347   }
    348 
    349   public Cache getCache() {
    350     return cache;
    351   }
    352 
    353   /**
    354    * Sets the socket factory used to create connections.
    355    *
    356    * <p>If unset, the {@link SocketFactory#getDefault() system-wide default}
    357    * socket factory will be used.
    358    */
    359   public OkHttpClient setSocketFactory(SocketFactory socketFactory) {
    360     this.socketFactory = socketFactory;
    361     return this;
    362   }
    363 
    364   public SocketFactory getSocketFactory() {
    365     return socketFactory;
    366   }
    367 
    368   /**
    369    * Sets the socket factory used to secure HTTPS connections.
    370    *
    371    * <p>If unset, a lazily created SSL socket factory will be used.
    372    */
    373   public OkHttpClient setSslSocketFactory(SSLSocketFactory sslSocketFactory) {
    374     this.sslSocketFactory = sslSocketFactory;
    375     return this;
    376   }
    377 
    378   public SSLSocketFactory getSslSocketFactory() {
    379     return sslSocketFactory;
    380   }
    381 
    382   /**
    383    * Sets the verifier used to confirm that response certificates apply to
    384    * requested hostnames for HTTPS connections.
    385    *
    386    * <p>If unset, a default hostname verifier will be used.
    387    */
    388   public OkHttpClient setHostnameVerifier(HostnameVerifier hostnameVerifier) {
    389     this.hostnameVerifier = hostnameVerifier;
    390     return this;
    391   }
    392 
    393   public HostnameVerifier getHostnameVerifier() {
    394     return hostnameVerifier;
    395   }
    396 
    397   /**
    398    * Sets the certificate pinner that constrains which certificates are trusted.
    399    * By default HTTPS connections rely on only the {@link #setSslSocketFactory
    400    * SSL socket factory} to establish trust. Pinning certificates avoids the
    401    * need to trust certificate authorities.
    402    */
    403   public OkHttpClient setCertificatePinner(CertificatePinner certificatePinner) {
    404     this.certificatePinner = certificatePinner;
    405     return this;
    406   }
    407 
    408   public CertificatePinner getCertificatePinner() {
    409     return certificatePinner;
    410   }
    411 
    412   /**
    413    * Sets the authenticator used to respond to challenges from the remote web
    414    * server or proxy server.
    415    *
    416    * <p>If unset, the {@link java.net.Authenticator#setDefault system-wide default}
    417    * authenticator will be used.
    418    */
    419   public OkHttpClient setAuthenticator(Authenticator authenticator) {
    420     this.authenticator = authenticator;
    421     return this;
    422   }
    423 
    424   public Authenticator getAuthenticator() {
    425     return authenticator;
    426   }
    427 
    428   /**
    429    * Sets the connection pool used to recycle HTTP and HTTPS connections.
    430    *
    431    * <p>If unset, the {@link ConnectionPool#getDefault() system-wide
    432    * default} connection pool will be used.
    433    */
    434   public OkHttpClient setConnectionPool(ConnectionPool connectionPool) {
    435     this.connectionPool = connectionPool;
    436     return this;
    437   }
    438 
    439   public ConnectionPool getConnectionPool() {
    440     return connectionPool;
    441   }
    442 
    443   /**
    444    * Configure this client to follow redirects from HTTPS to HTTP and from HTTP
    445    * to HTTPS.
    446    *
    447    * <p>If unset, protocol redirects will be followed. This is different than
    448    * the built-in {@code HttpURLConnection}'s default.
    449    */
    450   public OkHttpClient setFollowSslRedirects(boolean followProtocolRedirects) {
    451     this.followSslRedirects = followProtocolRedirects;
    452     return this;
    453   }
    454 
    455   public boolean getFollowSslRedirects() {
    456     return followSslRedirects;
    457   }
    458 
    459   /** Configure this client to follow redirects. If unset, redirects be followed. */
    460   public void setFollowRedirects(boolean followRedirects) {
    461     this.followRedirects = followRedirects;
    462   }
    463 
    464   public boolean getFollowRedirects() {
    465     return followRedirects;
    466   }
    467 
    468   /**
    469    * Configure this client to retry or not when a connectivity problem is encountered. By default,
    470    * this client silently recovers from the following problems:
    471    *
    472    * <ul>
    473    *   <li><strong>Unreachable IP addresses.</strong> If the URL's host has multiple IP addresses,
    474    *       failure to reach any individual IP address doesn't fail the overall request. This can
    475    *       increase availability of multi-homed services.
    476    *   <li><strong>Stale pooled connections.</strong> The {@link ConnectionPool} reuses sockets
    477    *       to decrease request latency, but these connections will occasionally time out.
    478    *   <li><strong>Unreachable proxy servers.</strong> A {@link ProxySelector} can be used to
    479    *       attempt multiple proxy servers in sequence, eventually falling back to a direct
    480    *       connection.
    481    * </ul>
    482    *
    483    * Set this to false to avoid retrying requests when doing so is destructive. In this case the
    484    * calling application should do its own recovery of connectivity failures.
    485    */
    486   public void setRetryOnConnectionFailure(boolean retryOnConnectionFailure) {
    487     this.retryOnConnectionFailure = retryOnConnectionFailure;
    488   }
    489 
    490   public boolean getRetryOnConnectionFailure() {
    491     return retryOnConnectionFailure;
    492   }
    493 
    494   RouteDatabase routeDatabase() {
    495     return routeDatabase;
    496   }
    497 
    498   /**
    499    * Sets the dispatcher used to set policy and execute asynchronous requests.
    500    * Must not be null.
    501    */
    502   public OkHttpClient setDispatcher(Dispatcher dispatcher) {
    503     if (dispatcher == null) throw new IllegalArgumentException("dispatcher == null");
    504     this.dispatcher = dispatcher;
    505     return this;
    506   }
    507 
    508   public Dispatcher getDispatcher() {
    509     return dispatcher;
    510   }
    511 
    512   /**
    513    * Configure the protocols used by this client to communicate with remote
    514    * servers. By default this client will prefer the most efficient transport
    515    * available, falling back to more ubiquitous protocols. Applications should
    516    * only call this method to avoid specific compatibility problems, such as web
    517    * servers that behave incorrectly when SPDY is enabled.
    518    *
    519    * <p>The following protocols are currently supported:
    520    * <ul>
    521    *   <li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">http/1.1</a>
    522    *   <li><a href="http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1">spdy/3.1</a>
    523    *   <li><a href="http://tools.ietf.org/html/draft-ietf-httpbis-http2-17">h2</a>
    524    * </ul>
    525    *
    526    * <p><strong>This is an evolving set.</strong> Future releases include
    527    * support for transitional protocols. The http/1.1 transport will never be
    528    * dropped.
    529    *
    530    * <p>If multiple protocols are specified, <a
    531    * href="http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg">ALPN</a>
    532    * will be used to negotiate a transport.
    533    *
    534    * <p>{@link Protocol#HTTP_1_0} is not supported in this set. Requests are
    535    * initiated with {@code HTTP/1.1} only. If the server responds with {@code
    536    * HTTP/1.0}, that will be exposed by {@link Response#protocol()}.
    537    *
    538    * @param protocols the protocols to use, in order of preference. The list
    539    *     must contain {@link Protocol#HTTP_1_1}. It must not contain null or
    540    *     {@link Protocol#HTTP_1_0}.
    541    */
    542   public OkHttpClient setProtocols(List<Protocol> protocols) {
    543     protocols = Util.immutableList(protocols);
    544     if (!protocols.contains(Protocol.HTTP_1_1)) {
    545       throw new IllegalArgumentException("protocols doesn't contain http/1.1: " + protocols);
    546     }
    547     if (protocols.contains(Protocol.HTTP_1_0)) {
    548       throw new IllegalArgumentException("protocols must not contain http/1.0: " + protocols);
    549     }
    550     if (protocols.contains(null)) {
    551       throw new IllegalArgumentException("protocols must not contain null");
    552     }
    553     this.protocols = Util.immutableList(protocols);
    554     return this;
    555   }
    556 
    557   public List<Protocol> getProtocols() {
    558     return protocols;
    559   }
    560 
    561   public OkHttpClient setConnectionSpecs(List<ConnectionSpec> connectionSpecs) {
    562     this.connectionSpecs = Util.immutableList(connectionSpecs);
    563     return this;
    564   }
    565 
    566   public List<ConnectionSpec> getConnectionSpecs() {
    567     return connectionSpecs;
    568   }
    569 
    570   /**
    571    * Returns a modifiable list of interceptors that observe the full span of each call: from before
    572    * the connection is established (if any) until after the response source is selected (either the
    573    * origin server, cache, or both).
    574    */
    575   public List<Interceptor> interceptors() {
    576     return interceptors;
    577   }
    578 
    579   /**
    580    * Returns a modifiable list of interceptors that observe a single network request and response.
    581    * These interceptors must call {@link Interceptor.Chain#proceed} exactly once: it is an error for
    582    * a network interceptor to short-circuit or repeat a network request.
    583    */
    584   public List<Interceptor> networkInterceptors() {
    585     return networkInterceptors;
    586   }
    587 
    588   /**
    589    * Prepares the {@code request} to be executed at some point in the future.
    590    */
    591   public Call newCall(Request request) {
    592     return new Call(this, request);
    593   }
    594 
    595   /**
    596    * Cancels all scheduled or in-flight calls tagged with {@code tag}. Requests
    597    * that are already complete cannot be canceled.
    598    */
    599   public OkHttpClient cancel(Object tag) {
    600     getDispatcher().cancel(tag);
    601     return this;
    602   }
    603 
    604   /**
    605    * Returns a shallow copy of this OkHttpClient that uses the system-wide
    606    * default for each field that hasn't been explicitly configured.
    607    */
    608   OkHttpClient copyWithDefaults() {
    609     OkHttpClient result = new OkHttpClient(this);
    610     if (result.proxySelector == null) {
    611       result.proxySelector = ProxySelector.getDefault();
    612     }
    613     if (result.cookieHandler == null) {
    614       result.cookieHandler = CookieHandler.getDefault();
    615     }
    616     if (result.socketFactory == null) {
    617       result.socketFactory = SocketFactory.getDefault();
    618     }
    619     if (result.sslSocketFactory == null) {
    620       result.sslSocketFactory = getDefaultSSLSocketFactory();
    621     }
    622     if (result.hostnameVerifier == null) {
    623       result.hostnameVerifier = OkHostnameVerifier.INSTANCE;
    624     }
    625     if (result.certificatePinner == null) {
    626       result.certificatePinner = CertificatePinner.DEFAULT;
    627     }
    628     if (result.authenticator == null) {
    629       result.authenticator = AuthenticatorAdapter.INSTANCE;
    630     }
    631     if (result.connectionPool == null) {
    632       result.connectionPool = ConnectionPool.getDefault();
    633     }
    634     if (result.protocols == null) {
    635       result.protocols = DEFAULT_PROTOCOLS;
    636     }
    637     if (result.connectionSpecs == null) {
    638       result.connectionSpecs = DEFAULT_CONNECTION_SPECS;
    639     }
    640     if (result.network == null) {
    641       result.network = Network.DEFAULT;
    642     }
    643     return result;
    644   }
    645 
    646   /**
    647    * Java and Android programs default to using a single global SSL context,
    648    * accessible to HTTP clients as {@link SSLSocketFactory#getDefault()}. If we
    649    * used the shared SSL context, when OkHttp enables ALPN for its SPDY-related
    650    * stuff, it would also enable ALPN for other usages, which might crash them
    651    * because ALPN is enabled when it isn't expected to be.
    652    *
    653    * <p>This code avoids that by defaulting to an OkHttp-created SSL context.
    654    * The drawback of this approach is that apps that customize the global SSL
    655    * context will lose these customizations.
    656    */
    657   private synchronized SSLSocketFactory getDefaultSSLSocketFactory() {
    658     if (defaultSslSocketFactory == null) {
    659       try {
    660         SSLContext sslContext = SSLContext.getInstance("TLS");
    661         sslContext.init(null, null, null);
    662         defaultSslSocketFactory = sslContext.getSocketFactory();
    663       } catch (GeneralSecurityException e) {
    664         throw new AssertionError(); // The system has no TLS. Just give up.
    665       }
    666     }
    667     return defaultSslSocketFactory;
    668   }
    669 
    670   /** Returns a shallow copy of this OkHttpClient. */
    671   @Override public OkHttpClient clone() {
    672     return new OkHttpClient(this);
    673   }
    674 }
    675