OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This is the browser side of the resource dispatcher, it receives requests | |
6 // from the child process (i.e. [Renderer, Plugin, Worker]ProcessHost), and | |
7 // dispatches them to URLRequests. It then forwards the messages from the | |
8 // URLRequests back to the correct process for handling. | |
9 // | |
10 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc
e-loading | |
11 | |
12 #ifndef CHROME_BROWSER_RENDERER_HOST_RESOURCE_DISPATCHER_HOST_H_ | 5 #ifndef CHROME_BROWSER_RENDERER_HOST_RESOURCE_DISPATCHER_HOST_H_ |
13 #define CHROME_BROWSER_RENDERER_HOST_RESOURCE_DISPATCHER_HOST_H_ | 6 #define CHROME_BROWSER_RENDERER_HOST_RESOURCE_DISPATCHER_HOST_H_ |
14 #pragma once | 7 #pragma once |
15 | 8 |
16 #include <map> | 9 // TODO(jam): remove this file when all files have been converted. |
17 #include <string> | 10 #include "content/browser/renderer_host/resource_dispatcher_host.h" |
18 #include <vector> | |
19 | |
20 #include "base/basictypes.h" | |
21 #include "base/gtest_prod_util.h" | |
22 #include "base/observer_list.h" | |
23 #include "base/scoped_ptr.h" | |
24 #include "base/timer.h" | |
25 #include "chrome/common/child_process_info.h" | |
26 #include "chrome/common/notification_type.h" | |
27 #include "chrome/browser/renderer_host/resource_queue.h" | |
28 #include "ipc/ipc_message.h" | |
29 #include "net/url_request/url_request.h" | |
30 #include "webkit/glue/resource_type.h" | |
31 | |
32 class CrossSiteResourceHandler; | |
33 class DownloadFileManager; | |
34 class DownloadRequestLimiter; | |
35 class LoginHandler; | |
36 class NotificationDetails; | |
37 class PluginService; | |
38 class ResourceDispatcherHostRequestInfo; | |
39 class ResourceHandler; | |
40 class ResourceMessageFilter; | |
41 class SafeBrowsingService; | |
42 class SaveFileManager; | |
43 class SSLClientAuthHandler; | |
44 class UserScriptListener; | |
45 class WebKitThread; | |
46 struct DownloadSaveInfo; | |
47 struct GlobalRequestID; | |
48 struct ViewHostMsg_Resource_Request; | |
49 struct ViewMsg_ClosePage_Params; | |
50 | |
51 namespace net { | |
52 class URLRequestContext; | |
53 } // namespace net | |
54 | |
55 namespace webkit_blob { | |
56 class DeletableFileReference; | |
57 } | |
58 | |
59 class ResourceDispatcherHost : public net::URLRequest::Delegate { | |
60 public: | |
61 class Observer { | |
62 public: | |
63 virtual ~Observer() {} | |
64 virtual void OnRequestStarted(ResourceDispatcherHost* resource_dispatcher, | |
65 net::URLRequest* request) = 0; | |
66 virtual void OnResponseCompleted( | |
67 ResourceDispatcherHost* resource_dispatcher, | |
68 net::URLRequest* request) = 0; | |
69 virtual void OnReceivedRedirect(ResourceDispatcherHost* resource_dispatcher, | |
70 net::URLRequest* request, | |
71 const GURL& new_url) = 0; | |
72 }; | |
73 | |
74 ResourceDispatcherHost(); | |
75 ~ResourceDispatcherHost(); | |
76 | |
77 void Initialize(); | |
78 | |
79 // Puts the resource dispatcher host in an inactive state (unable to begin | |
80 // new requests). Cancels all pending requests. | |
81 void Shutdown(); | |
82 | |
83 // Returns true if the message was a resource message that was processed. | |
84 // If it was, message_was_ok will be false iff the message was corrupt. | |
85 bool OnMessageReceived(const IPC::Message& message, | |
86 ResourceMessageFilter* filter, | |
87 bool* message_was_ok); | |
88 | |
89 // Initiates a download from the browser process (as opposed to a resource | |
90 // request from the renderer or another child process). | |
91 void BeginDownload(const GURL& url, | |
92 const GURL& referrer, | |
93 const DownloadSaveInfo& save_info, | |
94 bool prompt_for_save_location, | |
95 int process_unique_id, | |
96 int route_id, | |
97 net::URLRequestContext* request_context); | |
98 | |
99 // Initiates a save file from the browser process (as opposed to a resource | |
100 // request from the renderer or another child process). | |
101 void BeginSaveFile(const GURL& url, | |
102 const GURL& referrer, | |
103 int process_unique_id, | |
104 int route_id, | |
105 net::URLRequestContext* request_context); | |
106 | |
107 // Cancels the given request if it still exists. We ignore cancels from the | |
108 // renderer in the event of a download. | |
109 void CancelRequest(int process_unique_id, | |
110 int request_id, | |
111 bool from_renderer); | |
112 | |
113 // Follows a deferred redirect for the given request. | |
114 // new_first_party_for_cookies, if non-empty, is the new cookie policy URL | |
115 // for the redirected URL. If the cookie policy URL needs changing, pass | |
116 // true as has_new_first_party_for_cookies and the new cookie policy URL as | |
117 // new_first_party_for_cookies. Otherwise, pass false as | |
118 // has_new_first_party_for_cookies, and new_first_party_for_cookies will not | |
119 // be used. | |
120 void FollowDeferredRedirect(int process_unique_id, | |
121 int request_id, | |
122 bool has_new_first_party_for_cookies, | |
123 const GURL& new_first_party_for_cookies); | |
124 | |
125 // Starts a request that was deferred during ResourceHandler::OnWillStart(). | |
126 void StartDeferredRequest(int process_unique_id, int request_id); | |
127 | |
128 // Returns true if it's ok to send the data. If there are already too many | |
129 // data messages pending, it pauses the request and returns false. In this | |
130 // case the caller should not send the data. | |
131 bool WillSendData(int process_unique_id, int request_id); | |
132 | |
133 // Pauses or resumes network activity for a particular request. | |
134 void PauseRequest(int process_unique_id, int request_id, bool pause); | |
135 | |
136 // Returns the number of pending requests. This is designed for the unittests | |
137 int pending_requests() const { | |
138 return static_cast<int>(pending_requests_.size()); | |
139 } | |
140 | |
141 // Intended for unit-tests only. Returns the memory cost of all the | |
142 // outstanding requests (pending and blocked) for |process_unique_id|. | |
143 int GetOutstandingRequestsMemoryCost(int process_unique_id) const; | |
144 | |
145 // Intended for unit-tests only. Overrides the outstanding requests bound. | |
146 void set_max_outstanding_requests_cost_per_process(int limit) { | |
147 max_outstanding_requests_cost_per_process_ = limit; | |
148 } | |
149 | |
150 // The average private bytes increase of the browser for each new pending | |
151 // request. Experimentally obtained. | |
152 static const int kAvgBytesPerOutstandingRequest = 4400; | |
153 | |
154 DownloadFileManager* download_file_manager() const { | |
155 return download_file_manager_; | |
156 } | |
157 | |
158 DownloadRequestLimiter* download_request_limiter() const { | |
159 return download_request_limiter_.get(); | |
160 } | |
161 | |
162 SaveFileManager* save_file_manager() const { | |
163 return save_file_manager_; | |
164 } | |
165 | |
166 SafeBrowsingService* safe_browsing_service() const { | |
167 return safe_browsing_; | |
168 } | |
169 | |
170 WebKitThread* webkit_thread() const { | |
171 return webkit_thread_.get(); | |
172 } | |
173 | |
174 // Called when the onunload handler for a cross-site request has finished. | |
175 void OnClosePageACK(const ViewMsg_ClosePage_Params& params); | |
176 | |
177 // Force cancels any pending requests for the given process. | |
178 void CancelRequestsForProcess(int process_unique_id); | |
179 | |
180 // Force cancels any pending requests for the given route id. This method | |
181 // acts like CancelRequestsForProcess when route_id is -1. | |
182 void CancelRequestsForRoute(int process_unique_id, int route_id); | |
183 | |
184 // net::URLRequest::Delegate | |
185 virtual void OnReceivedRedirect(net::URLRequest* request, | |
186 const GURL& new_url, | |
187 bool* defer_redirect); | |
188 virtual void OnAuthRequired(net::URLRequest* request, | |
189 net::AuthChallengeInfo* auth_info); | |
190 virtual void OnCertificateRequested( | |
191 net::URLRequest* request, | |
192 net::SSLCertRequestInfo* cert_request_info); | |
193 virtual void OnSSLCertificateError(net::URLRequest* request, | |
194 int cert_error, | |
195 net::X509Certificate* cert); | |
196 virtual void OnGetCookies(net::URLRequest* request, | |
197 bool blocked_by_policy); | |
198 virtual void OnSetCookie(net::URLRequest* request, | |
199 const std::string& cookie_line, | |
200 const net::CookieOptions& options, | |
201 bool blocked_by_policy); | |
202 virtual void OnResponseStarted(net::URLRequest* request); | |
203 virtual void OnReadCompleted(net::URLRequest* request, int bytes_read); | |
204 void OnResponseCompleted(net::URLRequest* request); | |
205 | |
206 // Helper functions to get our extra data out of a request. The given request | |
207 // must have been one we created so that it has the proper extra data pointer. | |
208 static ResourceDispatcherHostRequestInfo* InfoForRequest( | |
209 net::URLRequest* request); | |
210 static const ResourceDispatcherHostRequestInfo* InfoForRequest( | |
211 const net::URLRequest* request); | |
212 | |
213 // Extracts the render view/process host's identifiers from the given request | |
214 // and places them in the given out params (both required). If there are no | |
215 // such IDs associated with the request (such as non-page-related requests), | |
216 // this function will return false and both out params will be -1. | |
217 static bool RenderViewForRequest(const net::URLRequest* request, | |
218 int* render_process_host_id, | |
219 int* render_view_host_id); | |
220 | |
221 // Adds an observer. The observer will be called on the IO thread. To | |
222 // observe resource events on the UI thread, subscribe to the | |
223 // NOTIFY_RESOURCE_* notifications of the notification service. | |
224 void AddObserver(Observer* obs); | |
225 | |
226 // Removes an observer. | |
227 void RemoveObserver(Observer* obs); | |
228 | |
229 // Retrieves a net::URLRequest. Must be called from the IO thread. | |
230 net::URLRequest* GetURLRequest(const GlobalRequestID& request_id) const; | |
231 | |
232 // Notifies our observers that a request has been cancelled. | |
233 void NotifyResponseCompleted(net::URLRequest* request, int process_unique_id); | |
234 | |
235 void RemovePendingRequest(int process_unique_id, int request_id); | |
236 | |
237 // Causes all new requests for the route identified by | |
238 // |process_unique_id| and |route_id| to be blocked (not being | |
239 // started) until ResumeBlockedRequestsForRoute or | |
240 // CancelBlockedRequestsForRoute is called. | |
241 void BlockRequestsForRoute(int process_unique_id, int route_id); | |
242 | |
243 // Resumes any blocked request for the specified route id. | |
244 void ResumeBlockedRequestsForRoute(int process_unique_id, int route_id); | |
245 | |
246 // Cancels any blocked request for the specified route id. | |
247 void CancelBlockedRequestsForRoute(int process_unique_id, int route_id); | |
248 | |
249 // Decrements the pending_data_count for the request and resumes | |
250 // the request if it was paused due to too many pending data | |
251 // messages sent. | |
252 void DataReceivedACK(int process_unique_id, int request_id); | |
253 | |
254 // Maintains a collection of temp files created in support of | |
255 // the download_to_file capability. Used to grant access to the | |
256 // child process and to defer deletion of the file until it's | |
257 // no longer needed. | |
258 void RegisterDownloadedTempFile( | |
259 int child_id, int request_id, | |
260 webkit_blob::DeletableFileReference* reference); | |
261 void UnregisterDownloadedTempFile(int child_id, int request_id); | |
262 | |
263 // Needed for the sync IPC message dispatcher macros. | |
264 bool Send(IPC::Message* message); | |
265 | |
266 // Controls if we launch or squash prefetch requests as they arrive | |
267 // from renderers. | |
268 static bool is_prefetch_enabled(); | |
269 static void set_is_prefetch_enabled(bool value); | |
270 | |
271 private: | |
272 FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, | |
273 TestBlockedRequestsProcessDies); | |
274 FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, | |
275 IncrementOutstandingRequestsMemoryCost); | |
276 FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, | |
277 CalculateApproximateMemoryCost); | |
278 FRIEND_TEST_ALL_PREFIXES(ApplyExtensionLocalizationFilterTest, WrongScheme); | |
279 FRIEND_TEST_ALL_PREFIXES(ApplyExtensionLocalizationFilterTest, GoodScheme); | |
280 FRIEND_TEST_ALL_PREFIXES(ApplyExtensionLocalizationFilterTest, | |
281 GoodSchemeWrongResourceType); | |
282 | |
283 class ShutdownTask; | |
284 | |
285 friend class ShutdownTask; | |
286 | |
287 // Associates the given info with the given request. The info will then be | |
288 // owned by the request. | |
289 void SetRequestInfo(net::URLRequest* request, | |
290 ResourceDispatcherHostRequestInfo* info); | |
291 | |
292 // A shutdown helper that runs on the IO thread. | |
293 void OnShutdown(); | |
294 | |
295 // Returns true if the request is paused. | |
296 bool PauseRequestIfNeeded(ResourceDispatcherHostRequestInfo* info); | |
297 | |
298 // Resumes the given request by calling OnResponseStarted or OnReadCompleted. | |
299 void ResumeRequest(const GlobalRequestID& request_id); | |
300 | |
301 // Internal function to start reading for the first time. | |
302 void StartReading(net::URLRequest* request); | |
303 | |
304 // Reads data from the response using our internal buffer as async IO. | |
305 // Returns true if data is available immediately, false otherwise. If the | |
306 // return value is false, we will receive a OnReadComplete() callback later. | |
307 bool Read(net::URLRequest* request, int* bytes_read); | |
308 | |
309 // Internal function to finish an async IO which has completed. Returns | |
310 // true if there is more data to read (e.g. we haven't read EOF yet and | |
311 // no errors have occurred). | |
312 bool CompleteRead(net::URLRequest*, int* bytes_read); | |
313 | |
314 // Internal function to finish handling the ResponseStarted message. Returns | |
315 // true on success. | |
316 bool CompleteResponseStarted(net::URLRequest* request); | |
317 | |
318 // Helper function for regular and download requests. | |
319 void BeginRequestInternal(net::URLRequest* request); | |
320 | |
321 // Helper function that cancels |request|. | |
322 void CancelRequestInternal(net::URLRequest* request, bool from_renderer); | |
323 | |
324 // Helper function that inserts |request| into the resource queue. | |
325 void InsertIntoResourceQueue( | |
326 net::URLRequest* request, | |
327 const ResourceDispatcherHostRequestInfo& request_info); | |
328 | |
329 // Updates the "cost" of outstanding requests for |process_unique_id|. | |
330 // The "cost" approximates how many bytes are consumed by all the in-memory | |
331 // data structures supporting this request (net::URLRequest object, | |
332 // HttpNetworkTransaction, etc...). | |
333 // The value of |cost| is added to the running total, and the resulting | |
334 // sum is returned. | |
335 int IncrementOutstandingRequestsMemoryCost(int cost, | |
336 int process_unique_id); | |
337 | |
338 // Estimate how much heap space |request| will consume to run. | |
339 static int CalculateApproximateMemoryCost(net::URLRequest* request); | |
340 | |
341 // The list of all requests that we have pending. This list is not really | |
342 // optimized, and assumes that we have relatively few requests pending at once | |
343 // since some operations require brute-force searching of the list. | |
344 // | |
345 // It may be enhanced in the future to provide some kind of prioritization | |
346 // mechanism. We should also consider a hashtable or binary tree if it turns | |
347 // out we have a lot of things here. | |
348 typedef std::map<GlobalRequestID, net::URLRequest*> PendingRequestList; | |
349 | |
350 // Deletes the pending request identified by the iterator passed in. | |
351 // This function will invalidate the iterator passed in. Callers should | |
352 // not rely on this iterator being valid on return. | |
353 void RemovePendingRequest(const PendingRequestList::iterator& iter); | |
354 | |
355 // Notify our observers that we started receiving a response for a request. | |
356 void NotifyResponseStarted(net::URLRequest* request, int process_unique_id); | |
357 | |
358 // Notify our observers that a request has been redirected. | |
359 void NotifyReceivedRedirect(net::URLRequest* request, | |
360 int process_unique_id, | |
361 const GURL& new_url); | |
362 | |
363 // Tries to handle the url with an external protocol. If the request is | |
364 // handled, the function returns true. False otherwise. | |
365 bool HandleExternalProtocol(int request_id, | |
366 int process_unique_id, | |
367 int route_id, | |
368 const GURL& url, | |
369 ResourceType::Type resource_type, | |
370 ResourceHandler* handler); | |
371 | |
372 // Checks all pending requests and updates the load states and upload | |
373 // progress if necessary. | |
374 void UpdateLoadStates(); | |
375 | |
376 // Checks the upload state and sends an update if one is necessary. | |
377 bool MaybeUpdateUploadProgress(ResourceDispatcherHostRequestInfo *info, | |
378 net::URLRequest *request); | |
379 | |
380 // Resumes or cancels (if |cancel_requests| is true) any blocked requests. | |
381 void ProcessBlockedRequestsForRoute(int process_unique_id, | |
382 int route_id, | |
383 bool cancel_requests); | |
384 | |
385 void OnRequestResource(const IPC::Message& msg, | |
386 int request_id, | |
387 const ViewHostMsg_Resource_Request& request_data); | |
388 void OnSyncLoad(int request_id, | |
389 const ViewHostMsg_Resource_Request& request_data, | |
390 IPC::Message* sync_result); | |
391 void BeginRequest(int request_id, | |
392 const ViewHostMsg_Resource_Request& request_data, | |
393 IPC::Message* sync_result, // only valid for sync | |
394 int route_id); // only valid for async | |
395 void OnDataReceivedACK(int request_id); | |
396 void OnDataDownloadedACK(int request_id); | |
397 void OnUploadProgressACK(int request_id); | |
398 void OnCancelRequest(int request_id); | |
399 void OnFollowRedirect(int request_id, | |
400 bool has_new_first_party_for_cookies, | |
401 const GURL& new_first_party_for_cookies); | |
402 void OnReleaseDownloadedFile(int request_id); | |
403 | |
404 ResourceHandler* CreateSafeBrowsingResourceHandler( | |
405 ResourceHandler* handler, int child_id, int route_id, | |
406 ResourceType::Type resource_type); | |
407 | |
408 // Creates ResourceDispatcherHostRequestInfo for a browser-initiated request | |
409 // (a download or a page save). |download| should be true if the request | |
410 // is a file download. | |
411 ResourceDispatcherHostRequestInfo* CreateRequestInfoForBrowserRequest( | |
412 ResourceHandler* handler, int child_id, int route_id, bool download); | |
413 | |
414 // Returns true if |request| is in |pending_requests_|. | |
415 bool IsValidRequest(net::URLRequest* request); | |
416 | |
417 // Sets replace_extension_localization_templates on all text/css requests that | |
418 // have "chrome-extension://" scheme. | |
419 static void ApplyExtensionLocalizationFilter( | |
420 const GURL& url, | |
421 const ResourceType::Type& resource_type, | |
422 ResourceDispatcherHostRequestInfo* request_info); | |
423 | |
424 // Determine request priority based on how critical this resource typically | |
425 // is to user-perceived page load performance. | |
426 static net::RequestPriority DetermineRequestPriority(ResourceType::Type type); | |
427 | |
428 // Sends the given notification on the UI thread. The RenderViewHost's | |
429 // controller is used as the source. | |
430 template <class T> | |
431 static void NotifyOnUI(NotificationType type, | |
432 int render_process_id, | |
433 int render_view_id, | |
434 T* detail); | |
435 | |
436 PendingRequestList pending_requests_; | |
437 | |
438 // Collection of temp files downloaded for child processes via | |
439 // the download_to_file mechanism. We avoid deleting them until | |
440 // the client no longer needs them. | |
441 typedef std::map<int, scoped_refptr<webkit_blob::DeletableFileReference> > | |
442 DeletableFilesMap; // key is request id | |
443 typedef std::map<int, DeletableFilesMap> | |
444 RegisteredTempFiles; // key is child process id | |
445 RegisteredTempFiles registered_temp_files_; | |
446 | |
447 // A timer that periodically calls UpdateLoadStates while pending_requests_ | |
448 // is not empty. | |
449 base::RepeatingTimer<ResourceDispatcherHost> update_load_states_timer_; | |
450 | |
451 // Handles the resource requests from the moment we want to start them. | |
452 ResourceQueue resource_queue_; | |
453 | |
454 // We own the download file writing thread and manager | |
455 scoped_refptr<DownloadFileManager> download_file_manager_; | |
456 | |
457 // Determines whether a download is allowed. | |
458 scoped_refptr<DownloadRequestLimiter> download_request_limiter_; | |
459 | |
460 // We own the save file manager. | |
461 scoped_refptr<SaveFileManager> save_file_manager_; | |
462 | |
463 scoped_refptr<UserScriptListener> user_script_listener_; | |
464 | |
465 scoped_refptr<SafeBrowsingService> safe_browsing_; | |
466 | |
467 // We own the WebKit thread and see to its destruction. | |
468 scoped_ptr<WebKitThread> webkit_thread_; | |
469 | |
470 // Request ID for browser initiated requests. request_ids generated by | |
471 // child processes are counted up from 0, while browser created requests | |
472 // start at -2 and go down from there. (We need to start at -2 because -1 is | |
473 // used as a special value all over the resource_dispatcher_host for | |
474 // uninitialized variables.) This way, we no longer have the unlikely (but | |
475 // observed in the real world!) event where we have two requests with the same | |
476 // request_id_. | |
477 int request_id_; | |
478 | |
479 // List of objects observing resource dispatching. | |
480 ObserverList<Observer> observer_list_; | |
481 | |
482 // For running tasks. | |
483 ScopedRunnableMethodFactory<ResourceDispatcherHost> method_runner_; | |
484 | |
485 // True if the resource dispatcher host has been shut down. | |
486 bool is_shutdown_; | |
487 | |
488 typedef std::vector<net::URLRequest*> BlockedRequestsList; | |
489 typedef std::pair<int, int> ProcessRouteIDs; | |
490 typedef std::map<ProcessRouteIDs, BlockedRequestsList*> BlockedRequestMap; | |
491 BlockedRequestMap blocked_requests_map_; | |
492 | |
493 // Maps the process_unique_ids to the approximate number of bytes | |
494 // being used to service its resource requests. No entry implies 0 cost. | |
495 typedef std::map<int, int> OutstandingRequestsMemoryCostMap; | |
496 OutstandingRequestsMemoryCostMap outstanding_requests_memory_cost_map_; | |
497 | |
498 // |max_outstanding_requests_cost_per_process_| is the upper bound on how | |
499 // many outstanding requests can be issued per child process host. | |
500 // The constraint is expressed in terms of bytes (where the cost of | |
501 // individual requests is given by CalculateApproximateMemoryCost). | |
502 // The total number of outstanding requests is roughly: | |
503 // (max_outstanding_requests_cost_per_process_ / | |
504 // kAvgBytesPerOutstandingRequest) | |
505 int max_outstanding_requests_cost_per_process_; | |
506 | |
507 // Used during IPC message dispatching so that the handlers can get a pointer | |
508 // to the source of the message. | |
509 ResourceMessageFilter* filter_; | |
510 | |
511 static bool is_prefetch_enabled_; | |
512 | |
513 DISALLOW_COPY_AND_ASSIGN(ResourceDispatcherHost); | |
514 }; | |
515 | 11 |
516 #endif // CHROME_BROWSER_RENDERER_HOST_RESOURCE_DISPATCHER_HOST_H_ | 12 #endif // CHROME_BROWSER_RENDERER_HOST_RESOURCE_DISPATCHER_HOST_H_ |
OLD | NEW |