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