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