1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CONTENT_BROWSER_LOADER_RESOURCE_SCHEDULER_H_ 6 #define CONTENT_BROWSER_LOADER_RESOURCE_SCHEDULER_H_ 7 8 #include <map> 9 #include <set> 10 11 #include "base/basictypes.h" 12 #include "base/compiler_specific.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/threading/non_thread_safe.h" 15 #include "content/common/content_export.h" 16 #include "net/base/priority_queue.h" 17 #include "net/base/request_priority.h" 18 19 namespace net { 20 class HostPortPair; 21 class URLRequest; 22 } 23 24 namespace content { 25 class ResourceThrottle; 26 27 // There is one ResourceScheduler. All renderer-initiated HTTP requests are 28 // expected to pass through it. 29 // 30 // There are two types of input to the scheduler: 31 // 1. Requests to start, cancel, or finish fetching a resource. 32 // 2. Notifications for renderer events, such as new tabs, navigation and 33 // painting. 34 // 35 // These input come from different threads, so they may not be in sync. The UI 36 // thread is considered the authority on renderer lifetime, which means some 37 // IPCs may be meaningless if they arrive after the UI thread signals a renderer 38 // has been deleted. 39 // 40 // The ResourceScheduler tracks many Clients, which should correlate with tabs. 41 // A client is uniquely identified by its child_id and route_id. 42 // 43 // Each Client may have many Requests in flight. Requests are uniquely 44 // identified within a Client by its ScheduledResourceRequest. 45 // 46 // Users should call ScheduleRequest() to notify this ResourceScheduler of a 47 // new request. The returned ResourceThrottle should be destroyed when the load 48 // finishes or is canceled. 49 // 50 // The scheduler may defer issuing the request via the ResourceThrottle 51 // interface or it may alter the request's priority by calling set_priority() on 52 // the URLRequest. 53 class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe { 54 public: 55 ResourceScheduler(); 56 ~ResourceScheduler(); 57 58 // Requests that this ResourceScheduler schedule, and eventually loads, the 59 // specified |url_request|. Caller should delete the returned ResourceThrottle 60 // when the load completes or is canceled. 61 scoped_ptr<ResourceThrottle> ScheduleRequest( 62 int child_id, int route_id, net::URLRequest* url_request); 63 64 // Signals from the UI thread, posted as tasks on the IO thread: 65 66 // Called when a renderer is created. 67 void OnClientCreated(int child_id, int route_id); 68 69 // Called when a renderer is destroyed. 70 void OnClientDeleted(int child_id, int route_id); 71 72 // Signals from IPC messages directly from the renderers: 73 74 // Called when a client navigates to a new main document. 75 void OnNavigate(int child_id, int route_id); 76 77 // Called when the client has parsed the <body> element. This is a signal that 78 // resource loads won't interfere with first paint. 79 void OnWillInsertBody(int child_id, int route_id); 80 81 private: 82 class RequestQueue; 83 class ScheduledResourceRequest; 84 struct Client; 85 86 typedef int64 ClientId; 87 typedef std::map<ClientId, Client*> ClientMap; 88 typedef std::set<ScheduledResourceRequest*> RequestSet; 89 90 // Called when a ScheduledResourceRequest is destroyed. 91 void RemoveRequest(ScheduledResourceRequest* request); 92 93 // Unthrottles the |request| and adds it to |client|. 94 void StartRequest(ScheduledResourceRequest* request, Client* client); 95 96 // Update the queue position for |request|, possibly causing it to start 97 // loading. 98 // 99 // Queues are maintained for each priority level. When |request| is 100 // reprioritized, it will move to the end of the queue for that priority 101 // level. 102 void ReprioritizeRequest(ScheduledResourceRequest* request, 103 net::RequestPriority new_priority); 104 105 // Attempts to load any pending requests in |client|, based on the 106 // results of ShouldStartRequest(). 107 void LoadAnyStartablePendingRequests(Client* client); 108 109 // Returns the number of requests with priority < LOW that are currently in 110 // flight. 111 void GetNumDelayableRequestsInFlight( 112 Client* client, 113 const net::HostPortPair& active_request_host, 114 size_t* total_delayable, 115 size_t* total_for_active_host) const; 116 117 enum ShouldStartReqResult { 118 DO_NOT_START_REQUEST_AND_STOP_SEARCHING = -2, 119 DO_NOT_START_REQUEST_AND_KEEP_SEARCHING = -1, 120 START_REQUEST = 1, 121 }; 122 123 // Returns true if the request should start. This is the core scheduling 124 // algorithm. 125 ShouldStartReqResult ShouldStartRequest(ScheduledResourceRequest* request, 126 Client* client) const; 127 128 // Returns the client ID for the given |child_id| and |route_id| combo. 129 ClientId MakeClientId(int child_id, int route_id); 130 131 ClientMap client_map_; 132 RequestSet unowned_requests_; 133 }; 134 135 } // namespace content 136 137 #endif // CONTENT_BROWSER_LOADER_RESOURCE_SCHEDULER_H_ 138