| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 #ifndef CONTENT_BROWSER_LOADER_RESOURCE_SCHEDULER_H_ | 5 #ifndef CONTENT_BROWSER_LOADER_RESOURCE_SCHEDULER_H_ |
| 6 #define CONTENT_BROWSER_LOADER_RESOURCE_SCHEDULER_H_ | 6 #define CONTENT_BROWSER_LOADER_RESOURCE_SCHEDULER_H_ |
| 7 | 7 |
| 8 #include <map> | 8 #include <map> |
| 9 #include <set> | 9 #include <set> |
| 10 | 10 |
| 11 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
| 12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
| 13 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
| 14 #include "base/threading/non_thread_safe.h" | 14 #include "base/threading/non_thread_safe.h" |
| 15 #include "base/timer/timer.h" | 15 #include "base/timer/timer.h" |
| 16 #include "content/common/content_export.h" | 16 #include "content/common/content_export.h" |
| 17 #include "content/public/browser/resource_throttle.h" |
| 17 #include "net/base/priority_queue.h" | 18 #include "net/base/priority_queue.h" |
| 18 #include "net/base/request_priority.h" | 19 #include "net/base/request_priority.h" |
| 19 | 20 |
| 20 namespace net { | 21 namespace net { |
| 21 class HostPortPair; | 22 class HostPortPair; |
| 22 class URLRequest; | 23 class URLRequest; |
| 23 } | 24 } |
| 24 | 25 |
| 25 namespace content { | 26 namespace content { |
| 26 class ResourceThrottle; | |
| 27 | 27 |
| 28 // There is one ResourceScheduler. All renderer-initiated HTTP requests are | 28 // There is one ResourceScheduler. All renderer-initiated HTTP requests are |
| 29 // expected to pass through it. | 29 // expected to pass through it. |
| 30 // | 30 // |
| 31 // There are two types of input to the scheduler: | 31 // There are two types of input to the scheduler: |
| 32 // 1. Requests to start, cancel, or finish fetching a resource. | 32 // 1. Requests to start, cancel, or finish fetching a resource. |
| 33 // 2. Notifications for renderer events, such as new tabs, navigation and | 33 // 2. Notifications for renderer events, such as new tabs, navigation and |
| 34 // painting. | 34 // painting. |
| 35 // | 35 // |
| 36 // These input come from different threads, so they may not be in sync. The UI | 36 // These input come from different threads, so they may not be in sync. The UI |
| 37 // thread is considered the authority on renderer lifetime, which means some | 37 // thread is considered the authority on renderer lifetime, which means some |
| 38 // IPCs may be meaningless if they arrive after the UI thread signals a renderer | 38 // IPCs may be meaningless if they arrive after the UI thread signals a renderer |
| 39 // has been deleted. | 39 // has been deleted. |
| 40 // | 40 // |
| 41 // The ResourceScheduler tracks many Clients, which should correlate with tabs. | 41 // The ResourceScheduler tracks many Clients, which should correlate with tabs. |
| 42 // A client is uniquely identified by its child_id and route_id. | 42 // A client is uniquely identified by its child_id and route_id. |
| 43 // | 43 // |
| 44 // Each Client may have many Requests in flight. Requests are uniquely | 44 // Each Client may have many Requests in flight. Requests are uniquely |
| 45 // identified within a Client by its ScheduledResourceRequest. | 45 // identified within a Client by its ScheduledResourceRequest. |
| 46 // | 46 // |
| 47 // Users should call ScheduleRequest() to notify this ResourceScheduler of a | 47 // Users should call ScheduleRequest() to notify this ResourceScheduler of a new |
| 48 // new request. The returned ResourceThrottle should be destroyed when the load | 48 // request. The returned ScheduledResourceRequest should be destroyed when the |
| 49 // finishes or is canceled. | 49 // load finishes or is canceled, before the net::URLRequest. |
| 50 // | 50 // |
| 51 // The scheduler may defer issuing the request via the ResourceThrottle | 51 // The scheduler may defer issuing the request via the ResourceThrottle |
| 52 // interface or it may alter the request's priority by calling set_priority() on | 52 // interface or it may alter the request's priority by calling set_priority() on |
| 53 // the URLRequest. | 53 // the URLRequest. |
| 54 class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe { | 54 class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe { |
| 55 public: | 55 public: |
| 56 enum ClientThrottleState { | 56 enum ClientThrottleState { |
| 57 // TODO(aiolos): Add logic to ShouldStartRequest for PAUSED Clients to only | 57 // TODO(aiolos): Add logic to ShouldStartRequest for PAUSED Clients to only |
| 58 // issue synchronous requests. | 58 // issue synchronous requests. |
| 59 // TODO(aiolos): Add max number of THROTTLED Clients, and logic to set | 59 // TODO(aiolos): Add max number of THROTTLED Clients, and logic to set |
| (...skipping 19 matching lines...) Expand all Loading... |
| 79 }; | 79 }; |
| 80 | 80 |
| 81 enum RequestClassification { | 81 enum RequestClassification { |
| 82 NORMAL_REQUEST, | 82 NORMAL_REQUEST, |
| 83 // Low priority in-flight requests | 83 // Low priority in-flight requests |
| 84 IN_FLIGHT_DELAYABLE_REQUEST, | 84 IN_FLIGHT_DELAYABLE_REQUEST, |
| 85 // High-priority requests received before the renderer has a <body> | 85 // High-priority requests received before the renderer has a <body> |
| 86 LAYOUT_BLOCKING_REQUEST, | 86 LAYOUT_BLOCKING_REQUEST, |
| 87 }; | 87 }; |
| 88 | 88 |
| 89 // Handle for a scheduled request. On creation, it will attach itself to the |
| 90 // net::URLRequest it is associated with. On destruction, it will detach |
| 91 // itself. It must be destroyed before the associated URLRequest. |
| 92 class ScheduledResourceRequest : public ResourceThrottle { |
| 93 public: |
| 94 ScheduledResourceRequest(); |
| 95 ~ScheduledResourceRequest() override; |
| 96 |
| 97 virtual void ChangePriority(net::RequestPriority new_priority, |
| 98 int intra_priority_value) = 0; |
| 99 |
| 100 // If there currently exists a ScheduledResourceRequest-implementing object |
| 101 // for |request|, then return it. Otherwise returns nullptr. |
| 102 static ScheduledResourceRequest* ForRequest(net::URLRequest* request); |
| 103 |
| 104 private: |
| 105 DISALLOW_COPY_AND_ASSIGN(ScheduledResourceRequest); |
| 106 }; |
| 107 |
| 89 ResourceScheduler(); | 108 ResourceScheduler(); |
| 90 ~ResourceScheduler(); | 109 ~ResourceScheduler(); |
| 91 | 110 |
| 92 // Use a mock timer when testing. | 111 // Use a mock timer when testing. |
| 93 void set_timer_for_testing(scoped_ptr<base::Timer> timer) { | 112 void set_timer_for_testing(scoped_ptr<base::Timer> timer) { |
| 94 coalescing_timer_.reset(timer.release()); | 113 coalescing_timer_.reset(timer.release()); |
| 95 } | 114 } |
| 96 | 115 |
| 97 // TODO(aiolos): Remove when throttling and coalescing have landed | 116 // TODO(aiolos): Remove when throttling and coalescing have landed |
| 98 void SetThrottleOptionsForTesting(bool should_throttle, bool should_coalesce); | 117 void SetThrottleOptionsForTesting(bool should_throttle, bool should_coalesce); |
| 99 | 118 |
| 100 bool should_coalesce() const { return should_coalesce_; } | 119 bool should_coalesce() const { return should_coalesce_; } |
| 101 bool should_throttle() const { return should_throttle_; } | 120 bool should_throttle() const { return should_throttle_; } |
| 102 | 121 |
| 103 ClientThrottleState GetClientStateForTesting(int child_id, int route_id); | 122 ClientThrottleState GetClientStateForTesting(int child_id, int route_id); |
| 104 | 123 |
| 105 // Requests that this ResourceScheduler schedule, and eventually loads, the | 124 // Requests that this ResourceScheduler schedule, and eventually loads, the |
| 106 // specified |url_request|. Caller should delete the returned ResourceThrottle | 125 // specified |url_request|. Caller should delete the returned |
| 107 // when the load completes or is canceled. | 126 // ScheduledResourceRequest when the load completes or is canceled. |
| 108 scoped_ptr<ResourceThrottle> ScheduleRequest( | 127 scoped_ptr<ScheduledResourceRequest> ScheduleRequest( |
| 109 int child_id, int route_id, net::URLRequest* url_request); | 128 int child_id, |
| 129 int route_id, |
| 130 bool is_async, |
| 131 net::URLRequest* url_request); |
| 110 | 132 |
| 111 // Signals from the UI thread, posted as tasks on the IO thread: | 133 // Signals from the UI thread, posted as tasks on the IO thread: |
| 112 | 134 |
| 113 // Called when a renderer is created. | 135 // Called when a renderer is created. |
| 114 void OnClientCreated(int child_id, | 136 void OnClientCreated(int child_id, |
| 115 int route_id, | 137 int route_id, |
| 116 bool is_visible, | 138 bool is_visible, |
| 117 bool is_audible); | 139 bool is_audible); |
| 118 | 140 |
| 119 // Called when a renderer is destroyed. | 141 // Called when a renderer is destroyed. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 147 | 169 |
| 148 // Called to check if all user observable tabs have completed loading. | 170 // Called to check if all user observable tabs have completed loading. |
| 149 bool active_clients_loaded() const { return active_clients_loading_ == 0; } | 171 bool active_clients_loaded() const { return active_clients_loading_ == 0; } |
| 150 | 172 |
| 151 bool IsClientVisibleForTesting(int child_id, int route_id); | 173 bool IsClientVisibleForTesting(int child_id, int route_id); |
| 152 | 174 |
| 153 // Returns true if at least one client is currently loading. | 175 // Returns true if at least one client is currently loading. |
| 154 bool HasLoadingClients() const; | 176 bool HasLoadingClients() const; |
| 155 | 177 |
| 156 private: | 178 private: |
| 179 friend class ScheduledResourceRequest; |
| 180 |
| 157 // Returns true if limiting of outstanding requests is enabled. | 181 // Returns true if limiting of outstanding requests is enabled. |
| 158 bool limit_outstanding_requests() const { | 182 bool limit_outstanding_requests() const { |
| 159 return limit_outstanding_requests_; | 183 return limit_outstanding_requests_; |
| 160 } | 184 } |
| 161 | 185 |
| 162 // Returns the outstanding request limit. Only valid if | 186 // Returns the outstanding request limit. Only valid if |
| 163 // |IsLimitingOutstandingRequests()|. | 187 // |IsLimitingOutstandingRequests()|. |
| 164 size_t outstanding_request_limit() const { | 188 size_t outstanding_request_limit() const { |
| 165 return outstanding_request_limit_; | 189 return outstanding_request_limit_; |
| 166 } | 190 } |
| 167 | 191 |
| 168 enum ClientState { | 192 enum ClientState { |
| 169 // Observable client. | 193 // Observable client. |
| 170 ACTIVE, | 194 ACTIVE, |
| 171 // Non-observable client. | 195 // Non-observable client. |
| 172 BACKGROUND, | 196 BACKGROUND, |
| 173 // No client found. | 197 // No client found. |
| 174 UNKNOWN, | 198 UNKNOWN, |
| 175 }; | 199 }; |
| 176 | 200 |
| 177 class RequestQueue; | 201 class RequestQueue; |
| 178 class ScheduledResourceRequest; | 202 class ScheduledResourceRequestImpl; |
| 179 struct RequestPriorityParams; | 203 struct RequestPriorityParams; |
| 180 struct ScheduledResourceSorter { | 204 struct ScheduledResourceSorter { |
| 181 bool operator()(const ScheduledResourceRequest* a, | 205 bool operator()(const ScheduledResourceRequestImpl* a, |
| 182 const ScheduledResourceRequest* b) const; | 206 const ScheduledResourceRequestImpl* b) const; |
| 183 }; | 207 }; |
| 184 class Client; | 208 class Client; |
| 185 | 209 |
| 186 typedef int64 ClientId; | 210 typedef int64 ClientId; |
| 187 typedef std::map<ClientId, Client*> ClientMap; | 211 typedef std::map<ClientId, Client*> ClientMap; |
| 188 typedef std::set<ScheduledResourceRequest*> RequestSet; | 212 typedef std::set<ScheduledResourceRequestImpl*> RequestSet; |
| 189 | 213 |
| 190 // Called when a ScheduledResourceRequest is destroyed. | 214 // Called when a ScheduledResourceRequestImpl is destroyed. |
| 191 void RemoveRequest(ScheduledResourceRequest* request); | 215 void RemoveRequest(ScheduledResourceRequestImpl* request); |
| 192 | 216 |
| 193 // These calls may update the ThrottleState of all clients, and have the | 217 // These calls may update the ThrottleState of all clients, and have the |
| 194 // potential to be re-entrant. | 218 // potential to be re-entrant. |
| 195 // Called when a Client newly becomes active loading. | 219 // Called when a Client newly becomes active loading. |
| 196 void IncrementActiveClientsLoading(); | 220 void IncrementActiveClientsLoading(); |
| 197 // Called when an active and loading Client either completes loading or | 221 // Called when an active and loading Client either completes loading or |
| 198 // becomes inactive. | 222 // becomes inactive. |
| 199 void DecrementActiveClientsLoading(); | 223 void DecrementActiveClientsLoading(); |
| 200 | 224 |
| 201 void OnLoadingActiveClientsStateChangedForAllClients(); | 225 void OnLoadingActiveClientsStateChangedForAllClients(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 214 // Returns UNKNOWN if the corresponding client is not found, else returns | 238 // Returns UNKNOWN if the corresponding client is not found, else returns |
| 215 // whether the client is ACTIVE (user-observable) or BACKGROUND. | 239 // whether the client is ACTIVE (user-observable) or BACKGROUND. |
| 216 ClientState GetClientState(ClientId client_id) const; | 240 ClientState GetClientState(ClientId client_id) const; |
| 217 | 241 |
| 218 // Update the queue position for |request|, possibly causing it to start | 242 // Update the queue position for |request|, possibly causing it to start |
| 219 // loading. | 243 // loading. |
| 220 // | 244 // |
| 221 // Queues are maintained for each priority level. When |request| is | 245 // Queues are maintained for each priority level. When |request| is |
| 222 // reprioritized, it will move to the end of the queue for that priority | 246 // reprioritized, it will move to the end of the queue for that priority |
| 223 // level. | 247 // level. |
| 224 void ReprioritizeRequest(ScheduledResourceRequest* request, | 248 void ReprioritizeRequest(ScheduledResourceRequestImpl* request, |
| 225 net::RequestPriority new_priority, | 249 net::RequestPriority new_priority, |
| 226 int intra_priority_value); | 250 int intra_priority_value); |
| 227 | 251 |
| 228 // Returns the client ID for the given |child_id| and |route_id| combo. | 252 // Returns the client ID for the given |child_id| and |route_id| combo. |
| 229 ClientId MakeClientId(int child_id, int route_id); | 253 ClientId MakeClientId(int child_id, int route_id); |
| 230 | 254 |
| 231 // Returns the client for the given |child_id| and |route_id| combo. | 255 // Returns the client for the given |child_id| and |route_id| combo. |
| 232 Client* GetClient(int child_id, int route_id); | 256 Client* GetClient(int child_id, int route_id); |
| 233 | 257 |
| 234 bool should_coalesce_; | 258 bool should_coalesce_; |
| 235 bool should_throttle_; | 259 bool should_throttle_; |
| 236 ClientMap client_map_; | 260 ClientMap client_map_; |
| 237 size_t active_clients_loading_; | 261 size_t active_clients_loading_; |
| 238 size_t coalesced_clients_; | 262 size_t coalesced_clients_; |
| 239 bool limit_outstanding_requests_; | 263 bool limit_outstanding_requests_; |
| 240 size_t outstanding_request_limit_; | 264 size_t outstanding_request_limit_; |
| 241 // This is a repeating timer to initiate requests on COALESCED Clients. | 265 // This is a repeating timer to initiate requests on COALESCED Clients. |
| 242 scoped_ptr<base::Timer> coalescing_timer_; | 266 scoped_ptr<base::Timer> coalescing_timer_; |
| 243 RequestSet unowned_requests_; | 267 RequestSet unowned_requests_; |
| 268 |
| 269 DISALLOW_COPY_AND_ASSIGN(ResourceScheduler); |
| 244 }; | 270 }; |
| 245 | 271 |
| 246 } // namespace content | 272 } // namespace content |
| 247 | 273 |
| 248 #endif // CONTENT_BROWSER_LOADER_RESOURCE_SCHEDULER_H_ | 274 #endif // CONTENT_BROWSER_LOADER_RESOURCE_SCHEDULER_H_ |
| OLD | NEW |