OLD | NEW |
(Empty) | |
| 1 # Life of a URLRequest |
| 2 |
| 3 This document is intended as an overview of the core layers of the network |
| 4 stack, their basic responsibilities, how they fit together, and where some of |
| 5 the pain points are, without going into too much detail. Though it touches a |
| 6 bit on child processes and the content/loader stack, the focus is on net/ |
| 7 itself. |
| 8 |
| 9 It's particularly targeted at people new to the Chrome network stack, but |
| 10 should also be useful for team members who may be experts at some parts of the |
| 11 stack, but are largely unfamiliar with other components. It starts by walking |
| 12 through how a basic request issued by another process works its way through the |
| 13 network stack, and then moves on to discuss how various components plug in. |
| 14 |
| 15 If you notice any inaccuracies in this document, or feel that things could be |
| 16 better explained, please do not hesitate to submit patches. |
| 17 |
| 18 # Anatomy of the Network Stack |
| 19 |
| 20 The top-level network stack object is the URLRequextContext. The context has |
| 21 non-owning pointers to everything needed to create and issue a URLRequest. The |
| 22 context must outlive all requests that use it. Creating a context is a rather |
| 23 complicated process, and it's recommended that most consumers use |
| 24 URLRequestContextBuilder to do this. |
| 25 |
| 26 Chrome has a number of different URLRequestContexts, as there is often a need to |
| 27 keep cookies, caches, and socket pools separate for different types of requests. |
| 28 Here are the ones that the network team owns: |
| 29 |
| 30 * The proxy URLRequestContext, owned by the IOThread and used to get PAC |
| 31 scripts while avoiding re-entrancy. |
| 32 * The system URLRequestContext, also owned by the IOThread, used for requests |
| 33 that aren't associated with a profile. |
| 34 * Each profile, including incognito profiles, has a number of URLRequestContexts |
| 35 that are created as needed: |
| 36 * The main URLRequestContext is mostly created in ProfileIOData, though it |
| 37 has a couple components that are passed in from content's StoragePartition |
| 38 code. Several other components are shared with the system URLRequestContext, |
| 39 like the HostResolver. |
| 40 * Each non-incognito profile also has a media request context, which uses a |
| 41 different on-disk cache than the main request context. This prevents a |
| 42 single huge media file from evicting everything else in the cache. |
| 43 * On desktop platforms, each profile has a request context for extensions. |
| 44 * Each profile has two contexts for each isolated app (One for media, one |
| 45 for everything else). |
| 46 |
| 47 The primary use of the URLRequestContext is to create URLRequest objects using |
| 48 URLRequestContext::CreateRequest(). The URLRequest is the main interface used |
| 49 by consumers of the network stack. It is used to make the actual requests to a |
| 50 server. Each URLRequest tracks a single request across all redirects until an |
| 51 error occurs, it's canceled, or a final response is received, with a (possibly |
| 52 empty) body. |
| 53 |
| 54 The HttpNetworkSession is another major network stack object. It owns the |
| 55 HttpStreamFactory, the socket pools, and the HTTP/2 and QUIC session pools. It |
| 56 also has non-owning pointers to the network stack objects that more directly |
| 57 deal with sockets. |
| 58 |
| 59 This document does not mention either of these objects much, but at layers |
| 60 above the HttpStreamFactory, objects often grab their dependencies from the |
| 61 URLRequestContext, while the HttpStreamFactory and layers below it generally |
| 62 get their dependencies from the HttpNetworkSession. |
| 63 |
| 64 |
| 65 # How many "Delegates"? |
| 66 |
| 67 The network stack informs the embedder of important events for a request using |
| 68 two main interfaces: the URLRequest::Delegate interface and the NetworkDelegate |
| 69 interface. |
| 70 |
| 71 The URLRequest::Delegate interface consists of a small set of callbacks needed |
| 72 to let the embedder drive a request forward. URLRequest::Delegates generally own |
| 73 the URLRequest. |
| 74 |
| 75 The NetworkDelegate is an object pointed to by the URLRequestContext and shared |
| 76 by all requests, and includes callbacks corresponding to most of the |
| 77 URLRequest::Delegate's callbacks, as well as an assortment of other methods. The |
| 78 NetworkDelegate is optional, while the URLRequest::Delegate is not. |
| 79 |
| 80 |
| 81 # Life of a Simple URLRequest |
| 82 |
| 83 A request for data is normally dispatched from a child to the browser process. |
| 84 There a URLRequest is created to drive the request. A protocol-specific job |
| 85 (e.g. HTTP, data, file) is attached to the request. That job first checks the |
| 86 cache, and then creates a network connection object, if necessary, to actually |
| 87 fetch the data. That connection object interacts with network socket pools to |
| 88 potentially re-use sockets; the socket pools create and connect a socket if |
| 89 there is no appropriate existing socket. Once that socket exists, the HTTP |
| 90 request is dispatched, the response read and parsed, and the result returned |
| 91 back up the stack and sent over to the child process. |
| 92 |
| 93 Of course, it's not quite that simple :-}. |
| 94 |
| 95 Consider a simple request issued by a child process. Suppose it's an HTTP |
| 96 request, the response is uncompressed, no matching entry in the cache, and there |
| 97 are no idle sockets connected to the server in the socket pool. |
| 98 |
| 99 Continuing with a "simple" URLRequest, here's a bit more detail on how things |
| 100 work. |
| 101 |
| 102 ### Request starts in a child process |
| 103 |
| 104 Summary: |
| 105 |
| 106 * ResourceDispatcher creates an IPCResourceLoaderBridge. |
| 107 * The IPCResourceLoaderBridge asks ResourceDispatcher to start the request. |
| 108 * ResourceDispatcher sends an IPC to the ResourceDispatcherHost in the |
| 109 browser process. |
| 110 |
| 111 Chrome has a single browser process, which handles network requests and tab |
| 112 management, among other things, and multiple child processes, which are |
| 113 generally sandboxed so can't send out network requests directly. There are |
| 114 multiple types of child processes (renderer, GPU, plugin, etc). The renderer |
| 115 processes are the ones that layout webpages and run HTML. |
| 116 |
| 117 Each child process has at most one ResourceDispatcher, which is responsible for |
| 118 all URL request-related communication with the browser process. When something |
| 119 in another process needs to issue a resource request, it calls into the |
| 120 ResourceDispatcher, which returns an IPCResourceLoaderBridge to the caller. |
| 121 The caller uses the bridge to start a request. When started, the |
| 122 ResourceDispatcher assigns the request a per-renderer ID, and then sends the |
| 123 ID, along with all information needed to issue the request, to the |
| 124 ResourceDispatcherHost in the browser process. |
| 125 |
| 126 ### ResourceDispatcherHost sets up the request in the browser process |
| 127 |
| 128 Summary: |
| 129 |
| 130 * ResourceDispatcherHost uses the URLRequestContext to create the URLRequest. |
| 131 * ResourceDispatcherHost creates a ResourceLoader and a chain of |
| 132 ResourceHandlers to manage the URLRequest. |
| 133 * ResourceLoader starts the URLRequest. |
| 134 |
| 135 The ResourceDispatcherHost (RDH), along with most of the network stack, lives |
| 136 on the browser process's IO thread. The browser process only has one RDH, |
| 137 which is responsible for handling all network requests initiated by |
| 138 ResourceDispatchers in all child processes, not just renderer processes. |
| 139 Requests initiated in the browser process don't go through the RDH, with some |
| 140 exceptions. |
| 141 |
| 142 When the RDH sees the request, it calls into a URLRequestContext to create the |
| 143 URLRequest. The URLRequestContext has pointers to all the network stack |
| 144 objects needed to issue the request over the network, such as the cache, cookie |
| 145 store, and host resolver. The RDH then creates a chain of ResourceHandlers |
| 146 each of which can monitor/modify/delay/cancel the URLRequest and the |
| 147 information it returns. The only one of these I'll talk about here is the |
| 148 AsyncResourceHandler, which is the last ResourceHandler in the chain. The RDH |
| 149 then creates a ResourceLoader (which is the URLRequest::Delegate), passes |
| 150 ownership of the URLRequest and the ResourceHandler chain to it, and then starts |
| 151 the ResourceLoader. |
| 152 |
| 153 The ResourceLoader checks that none of the ResourceHandlers want to cancel, |
| 154 modify, or delay the request, and then finally starts the URLRequest. |
| 155 |
| 156 ### Check the cache, request an HttpStream |
| 157 |
| 158 Summary: |
| 159 |
| 160 * The URLRequest asks the URLRequestJobFactory to create a URLRequestJob, in |
| 161 this case, a URLRequestHttpJob. |
| 162 * The URLRequestHttpJob asks the HttpCache to create an HttpTransaction |
| 163 (always an HttpCache::Transaction). |
| 164 * The HttpCache::Transaction sees there's no cache entry for the request, |
| 165 and creates an HttpNetworkTransaction. |
| 166 * The HttpNetworkTransaction calls into the HttpStreamFactory to request an |
| 167 HttpStream. |
| 168 |
| 169 The URLRequest then calls into the URLRequestJobFactory to create a |
| 170 URLRequestJob and then starts it. In the case of an HTTP or HTTPS request, this |
| 171 will be a URLRequestHttpJob. The URLRequestHttpJob attaches cookies to the |
| 172 request, if needed. |
| 173 |
| 174 The URLRequestHttpJob calls into the HttpCache to create an |
| 175 HttpCache::Transaction. If there's no matching entry in the cache, the |
| 176 HttpCache::Transaction will just call into the HttpNetworkLayer to create an |
| 177 HttpNetworkTransaction, and transparently wrap it. The HttpNetworkTransaction |
| 178 then calls into the HttpStreamFactory to request an HttpStream to the server. |
| 179 |
| 180 ### Create an HttpStream |
| 181 |
| 182 Summary: |
| 183 |
| 184 * HttpStreamFactory creates an HttpStreamFactoryImpl::Job. |
| 185 * HttpStreamFactoryImpl::Job calls into the TransportClientSocketPool to |
| 186 populate an ClientSocketHandle. |
| 187 * TransportClientSocketPool has no idle sockets, so it creates a |
| 188 TransportConnectJob and starts it. |
| 189 * TransportConnectJob creates a StreamSocket and establishes a connection. |
| 190 * TransportClientSocketPool puts the StreamSocket in the ClientSocketHandle, |
| 191 and calls into HttpStreamFactoryImpl::Job. |
| 192 * HttpStreamFactoryImpl::Job creates an HttpBasicStream, which takes |
| 193 ownership of the ClientSocketHandle. |
| 194 * It returns the HttpBasicStream to the HttpNetworkTransaction. |
| 195 |
| 196 The HttpStreamFactoryImpl::Job creates a ClientSocketHandle to hold a socket, |
| 197 once connected, and passes it into the ClientSocketPoolManager. The |
| 198 ClientSocketPoolManager assembles the TransportSocketParams needed to |
| 199 establish the connection and creates a group name ("host:port") used to |
| 200 identify sockets that can be used interchangeably. |
| 201 |
| 202 The ClientSocketPoolManager directs the request to the |
| 203 TransportClientSocketPool, since there's no proxy and it's an HTTP request. The |
| 204 request is forwarded to the pool's ClientSocketPoolBase<TransportSocketParams>'s |
| 205 ClientSocketPoolBaseHelper. If there isn't already an idle connection, and there |
| 206 are available socket slots, the ClientSocketPoolBaseHelper will create a new |
| 207 TransportConnectJob using the aforementioned params object. This Job will do the |
| 208 actual DNS lookup by calling into the HostResolverImpl, if needed, and then |
| 209 finally establishes a connection. |
| 210 |
| 211 Once the socket is connected, ownership of the socket is passed to the |
| 212 ClientSocketHandle. The HttpStreamFactoryImpl::Job is then informed the |
| 213 connection attempt succeeded, and it then creates an HttpBasicStream, which |
| 214 takes ownership of the ClientSocketHandle. It then passes ownership of the |
| 215 HttpBasicStream back to the HttpNetworkTransaction. |
| 216 |
| 217 ### Send request and read the response headers |
| 218 |
| 219 Summary: |
| 220 |
| 221 * HttpNetworkTransaction gives the request headers to the HttpBasicStream, |
| 222 and tells it to start the request. |
| 223 * HttpBasicStream sends the request, and waits for the response. |
| 224 * The HttpBasicStream sends the response headers back to the |
| 225 HttpNetworkTransaction. |
| 226 * The response headers are sent up to the URLRequest, to the ResourceLoader, |
| 227 and down through the ResourceHandler chain. |
| 228 * They're then sent by the the last ResourceHandler in the chain (the |
| 229 AsyncResourceHandler) to the ResourceDispatcher, with an IPC. |
| 230 |
| 231 The HttpNetworkTransaction passes the request headers to the HttpBasicStream, |
| 232 which uses an HttpStreamParser to (finally) format the request headers and body |
| 233 (if present) and send them to the server. |
| 234 |
| 235 The HttpStreamParser waits to receive the response and then parses the HTTP/1.x |
| 236 response headers, and then passes them up through both the |
| 237 HttpNetworkTransaction and HttpCache::Transaction to the URLRequestHttpJob. The |
| 238 URLRequestHttpJob saves any cookies, if needed, and then passes the headers up |
| 239 to the URLRequest and on to the ResourceLoader. |
| 240 |
| 241 The ResourceLoader passes them through the chain of ResourceHandlers, and then |
| 242 they make their way to the AsyncResourceHandler. The AsyncResourceHandler uses |
| 243 the renderer process ID ("child ID") to figure out which process the request |
| 244 was associated with, and then sends the headers along with the request ID to |
| 245 that process's ResourceDispatcher. The ResourceDispatcher uses the ID to |
| 246 figure out which IPCResourceLoaderBridge the headers should be sent to, which |
| 247 sends them on to whatever created the IPCResourceLoaderBridge in the first |
| 248 place. |
| 249 |
| 250 ### Response body is read |
| 251 |
| 252 Summary: |
| 253 |
| 254 * AsyncResourceHandler allocates a 512k ring buffer of shared memory to read |
| 255 the body of the request. |
| 256 * AsyncResourceHandler tells the ResourceLoader to read the response body to |
| 257 the buffer, 32kB at a time. |
| 258 * AsyncResourceHandler informs the ResourceDispatcher of each read using |
| 259 cross-process IPCs. |
| 260 * ResourceDispatcher tells the AsyncResourceHandler when it's done with the |
| 261 data with each read, so it knows when parts of the buffer can be reused. |
| 262 |
| 263 Without waiting to hear back from the ResourceDispatcher, the ResourceLoader |
| 264 tells its ResourceHandler chain to allocate memory to receive the response |
| 265 body. The AsyncResourceHandler creates a 512KB ring buffer of shared memory, |
| 266 and then passes the first 32KB of it to the ResourceLoader for the first read. |
| 267 The ResourceLoader then passes a 32KB body read request down through the |
| 268 URLRequest all the way down to the HttpResponseParser. Once some data is read, |
| 269 possibly less than 32KB, the number of bytes read makes its way back to the |
| 270 AsyncResourceHandler, which passes the shared memory buffer and the offset and |
| 271 amount of data read to the renderer process. |
| 272 |
| 273 The AsyncResourceHandler relies on ACKs from the renderer to prevent it from |
| 274 overwriting data that the renderer has yet to consume. This process repeats |
| 275 until the response body is completely read. |
| 276 |
| 277 ### URLRequest is destroyed |
| 278 |
| 279 Summary: |
| 280 |
| 281 * When complete, the RDH deletes the ResourceLoader, which deletes the |
| 282 URLRequest and the ResourceHandler chain. |
| 283 * During destruction, the HttpNetworkTransaction determines if the socket is |
| 284 reusable, and if so, tells the HttpBasicStream to return it to the socket pool. |
| 285 |
| 286 When the URLRequest informs the ResourceLoader it's complete, the |
| 287 ResourceLoader tells the ResourceHandlers, and the AsyncResourceHandler tells |
| 288 the ResourceDispatcher the request is complete. The RDH then deletes |
| 289 ResourceLoader, which deletes the URLRequest and ResourceHandler chain. |
| 290 |
| 291 When the HttpNetworkTransaction is being torn down, it figures out if the |
| 292 socket is reusable. If not, it tells the HttpBasicStream to close the socket. |
| 293 Either way, the ClientSocketHandle returns the socket is then returned to the |
| 294 socket pool, either for reuse or so the socket pool knows it has another free |
| 295 socket slot. |
| 296 |
| 297 |
| 298 # Additional Topics |
| 299 |
| 300 ## HTTP Cache |
| 301 |
| 302 The HttpCache::Transaction sits between the URLRequestHttpJob and the |
| 303 HttpNetworkTransaction, and implements the HttpTransaction interface, just like |
| 304 the HttpNetworkTransaction. The HttpCache::Transaction checks if a request can |
| 305 be served out of the cache. If a request needs to be revalidated, it handles |
| 306 sending a 204 revalidation request over the network. It may also break a range |
| 307 request into multiple cached and non-cached contiguous chunks, and may issue |
| 308 multiple network requests for a single range URLRequest. |
| 309 |
| 310 The HttpCache::Transaction uses one of three disk_cache::Backends to actually |
| 311 store the cache's index and files: The in memory backend, the blockfile cache |
| 312 backend, and the simple cache backend. The first is used in incognito. The |
| 313 latter two are both stored on disk, and are used on different platforms. |
| 314 |
| 315 One important detail is that it has a read/write lock for each URL. The lock |
| 316 technically allows multiple reads at once, but since an HttpCache::Transaction |
| 317 always grabs the lock for writing and reading before downgrading it to a read |
| 318 only lock, all requests for the same URL are effectively done serially. The |
| 319 renderer process merges requests for the same URL in many cases, which mitigates |
| 320 this problem to some extent. |
| 321 |
| 322 It's also worth noting that each renderer process also has its own in-memory |
| 323 cache, which has no relation to the cache implemented in net/, which lives in |
| 324 the browser process. |
| 325 |
| 326 ## Cancellation |
| 327 |
| 328 A request can be cancelled by the child process, by any of the |
| 329 ResourceHandlers in the chain, or by the ResourceDispatcherHost itself. When the |
| 330 cancellation message reaches the URLRequest, it passes on the fact it's been |
| 331 cancelled back to the ResourceLoader, which then sends the message down the |
| 332 ResourceHandler chain. |
| 333 |
| 334 When an HttpNetworkTransaction for a cancelled request is being torn down, it |
| 335 figures out if the socket the HttpStream owns can potentially be reused, based |
| 336 on the protocol (HTTP / HTTP/2 / QUIC) and any received headers. If the socket |
| 337 potentially can be reused, an HttpResponseBodyDrainer is created to try and |
| 338 read any remaining body bytes of the HttpStream, if any, before returning the |
| 339 socket to the SocketPool. If this takes too long, or there's an error, the |
| 340 socket is closed instead. Since this all happens at the layer below the cache, |
| 341 any drained bytes are not written to the cache, and as far as the cache layer is |
| 342 concerned, it only has a partial response. |
| 343 |
| 344 ## Redirects |
| 345 |
| 346 The URLRequestHttpJob checks if headers indicate a redirect when it receives |
| 347 them from the next layer down (Typically the HttpCache::Transaction). If they |
| 348 indicate a redirect, it tells the cache the response is complete, ignoring the |
| 349 body, so the cache only has the headers. The cache then treats it as a complete |
| 350 entry, even if the headers indicated there will be a body. |
| 351 |
| 352 The URLRequestHttpJob then checks with the URLRequest if the redirect should be |
| 353 followed. The URLRequest then informs the ResourceLoader about the redirect, to |
| 354 give it a chance to cancel the request. The information makes its way down |
| 355 through the AsyncResourceHandler into the other process, via the |
| 356 ResourceDispatcher. Whatever issued the original request then checks if the |
| 357 redirect should be followed. |
| 358 |
| 359 The ResourceDispatcher then asynchronously sends a message back to either |
| 360 follow the redirect or cancel the request. In either case, the old |
| 361 HttpTransaction is destroyed, and the HttpNetworkTransaction attempts to drain |
| 362 the socket for reuse, just as in the cancellation case. If the redirect is |
| 363 followed, the URLRequest calls into the URLRequestJobFactory to create a new |
| 364 URLRequestJob, and then starts it. |
| 365 |
| 366 ## Filters (gzip, SDCH, etc) |
| 367 |
| 368 When the URLRequestHttpJob receives headers, it sends a list of all |
| 369 Content-Encoding values to Filter::Factory, which creates a (possibly empty) |
| 370 chain of filters. As body bytes are received, they're passed through the |
| 371 filters at the URLRequestJob layer and the decoded bytes are passed back to the |
| 372 URLRequest::Delegate. |
| 373 |
| 374 Since this is done above the cache layer, the cache stores the responses prior |
| 375 to decompression. As a result, if files aren't compressed over the wire, they |
| 376 aren't compressed in the cache, either. This behavior can create problems when |
| 377 responses are SDCH compressed, as a dictionary and a cached file encoded using |
| 378 it may have different lifetimes. |
| 379 |
| 380 ## Socket Pools |
| 381 |
| 382 The ClientSocketPoolManager is responsible for assembling the parameters needed |
| 383 to connect a socket, and then sending the request to the right socket pool. |
| 384 Each socket request sent to a socket pool comes with a socket params object, a |
| 385 ClientSocketHandle, and a "group name". The params object contains all the |
| 386 information a ConnectJob needs to create a connection of a given type, and |
| 387 different types of socket pools take different params types. The |
| 388 ClientSocketHandle will take temporary ownership of a connected socket and |
| 389 return it to the socket pool when done. All connections with the same group name |
| 390 in the same pool can be used to service the same connection requests, so it |
| 391 consists of host, port, protocol, and whether "privacy mode" is enabled for |
| 392 sockets in the goup. |
| 393 |
| 394 All socket pool classes derive from the ClientSocketPoolBase<SocketParamType>. |
| 395 The ClientSocketPoolBase handles managing sockets - which requests to create |
| 396 sockets for, which requests get connected sockets first, which sockets belong |
| 397 to which groups, connection limits per group, keeping track of and closing idle |
| 398 sockets, etc. Each ClientSocketPoolBase subclass has its own ConnectJob type, |
| 399 which establishes a connection using the socket params, before the pool hands |
| 400 out the connected socket. |
| 401 |
| 402 ### Socket Pool Layering |
| 403 |
| 404 Some socket pools are layered on top other socket pools. This is done when a |
| 405 "socket" in a higher layer needs to establish a connection in a lower level |
| 406 pool and then take ownership of it as part of its connection process. For |
| 407 example, each socket in the SSLClientSocketPool is layered on top of a socket |
| 408 in the TransportClientSocketPool. There are a couple additional complexities |
| 409 here. |
| 410 |
| 411 From the perspective of the lower layer pool, all of its sockets that a higher |
| 412 layer pools owns are actively in use, even when the higher layer pool considers |
| 413 them idle. As a result, when a lower layer pool is at its connection limit and |
| 414 needs to make a new connection, it will ask any higher layer pools pools to |
| 415 close an idle connection if they have one, so it can make a new connection. |
| 416 |
| 417 Since sockets in the higher layer pool are also in a group in the lower layer |
| 418 pool, they must have their own distinct group name. This is needed so that, for |
| 419 instance, SSL and HTTP connections won't be grouped together in the |
| 420 TcpClientSocketPool, which the SSLClientSocketPool sits on top of. |
| 421 |
| 422 ### SSL |
| 423 |
| 424 When an SSL connection is needed, the ClientSocketPoolManager assembles the |
| 425 parameters needed both to connect the TCP socket and establish an SSL |
| 426 connection. It then passes them to the SSLClientSocketPool, which creates |
| 427 an SSLConnectJob using them. The SSLConnectJob's first step is to call into the |
| 428 TransportSocketPool to establish a TCP connection. |
| 429 |
| 430 Once a connection is established by the lower layered pool, the SSLConnectJob |
| 431 then starts SSL negotiation. Once that's done, the SSL socket is passed back to |
| 432 the HttpStreamFactoryImpl::Job that initiated the request, and things proceed |
| 433 just as with HTTP. When complete, the socket is returned to the |
| 434 SSLClientSocketPool. |
| 435 |
| 436 ## Proxies |
| 437 |
| 438 Each proxy has its own completely independent set of socket pools. They have |
| 439 their own exclusive TransportSocketPool, their own protocol-specific pool above |
| 440 it, and their own SSLSocketPool above that. HTTPS proxies also have a second |
| 441 SSLSocketPool between the the HttpProxyClientSocketPool and the |
| 442 TransportSocketPool, since they can talk SSL to both the proxy and the |
| 443 destination server, layered on top of each other. |
| 444 |
| 445 The first step the HttpStreamFactoryImpl::Job performs, just before calling |
| 446 into the ClientSocketPoolManager to create a socket, is to pass the URL to the |
| 447 Proxy service to get an ordered list of proxies (if any) that should be tried |
| 448 for that URL. Then when the ClientSocketPoolManager tries to get a socket for |
| 449 the Job, it uses that list of proxies to direct the request to the right socket |
| 450 pool. |
| 451 |
| 452 ## Alternate Protocols |
| 453 |
| 454 ### HTTP/2 (Formerly SPDY) |
| 455 |
| 456 HTTP/2 negotation is performed as part of the SSL handshake, so when |
| 457 HttpStreamFactoryImpl::Job gets a socket, it may have HTTP/2 negotiated over it |
| 458 as well. When it gets a socket with HTTP/2 negotiated as well, the Job creates a |
| 459 SpdySession using the socket and a SpdyHttpStream on top of the SpdySession. |
| 460 The SpdyHttpStream will be passed to the HttpNetworkTransaction, which drives |
| 461 the stream as usual. |
| 462 |
| 463 The SpdySession will be shared with other Jobs connecting to the same server, |
| 464 and future Jobs will find the SpdySession before they try to create a |
| 465 connection. HttpServerProperties also tracks which servers supported HTTP/2 when |
| 466 we last talked to them. We only try to establish a single connection to servers |
| 467 we think speak HTTP/2 when multiple HttpStreamFactoryImpl::Jobs are trying to |
| 468 connect to them, to avoid wasting resources. |
| 469 |
| 470 ### QUIC |
| 471 |
| 472 QUIC works quite a bit differently from HTTP/2. Servers advertise QUIC support |
| 473 with an "Alternate-Protocol" HTTP header in their responses. |
| 474 HttpServerProperties then tracks servers that have advertised QUIC support. |
| 475 |
| 476 When a new request comes in to HttpStreamFactoryImpl for a connection to a |
| 477 server that has advertised QUIC support in the past, it will create a second |
| 478 HttpStreamFactoryImpl::Job for QUIC, which returns an QuicHttpStream on success. |
| 479 The two Jobs (One for QUIC, one for all versions of HTTP) will be raced against |
| 480 each other, and whichever successfully creates an HttpStream first will be used. |
| 481 |
| 482 As with HTTP/2, once a QUIC connection is established, it will be shared with |
| 483 other Jobs connecting to the same server, and future Jobs will just reuse the |
| 484 existing QUIC session. |
| 485 |
| 486 ## Prioritization |
| 487 |
| 488 URLRequests are assigned a priority on creation. It only comes into play in |
| 489 a couple places: |
| 490 |
| 491 * The ResourceScheduler lives outside net/, and in some cases, delays starting |
| 492 low priority requests on a per-tab basis. |
| 493 * DNS lookups are initiated based on the highest priority request for a lookup. |
| 494 * Socket pools hand out and create sockets based on prioritization. However, |
| 495 when a socket becomes idle, it will be assigned to the highest priority request |
| 496 for the server its connected to, even if there's a higher priority request to |
| 497 another server that's waiting on a free socket slot. |
| 498 * HTTP/2 and QUIC both support sending priorities over-the-wire. |
| 499 |
| 500 At the socket pool layer, sockets are only assigned to socket requests once the |
| 501 socket is connected and SSL is negotiated, if needed. This is done so that if |
| 502 a higher priority request for a group reaches the socket pool before a |
| 503 connection is established, the first usable connection goes to the highest |
| 504 priority socket request. |
| 505 |
| 506 ## Non-HTTP Schemes |
| 507 |
| 508 The URLRequestJobFactory has a ProtocolHander for each supported scheme. |
| 509 Non-HTTP URLRequests have their own ProtocolHandlers. Some are implemented in |
| 510 net/, (like FTP, file, and data, though the renderer handles some data URLs |
| 511 internally), and others are implemented in content/ or chrome (like blob, |
| 512 chrome, and chrome-extension). |
OLD | NEW |