| 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 #include "content/browser/loader/resource_scheduler.h" | 5 #include "content/browser/loader/resource_scheduler.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 #include <set> | 8 #include <set> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 NetQueue::iterator GetNextHighestIterator() { | 129 NetQueue::iterator GetNextHighestIterator() { |
| 130 return queue_.begin(); | 130 return queue_.begin(); |
| 131 } | 131 } |
| 132 | 132 |
| 133 NetQueue::iterator End() { | 133 NetQueue::iterator End() { |
| 134 return queue_.end(); | 134 return queue_.end(); |
| 135 } | 135 } |
| 136 | 136 |
| 137 // Returns true if |request| is queued. | 137 // Returns true if |request| is queued. |
| 138 bool IsQueued(ScheduledResourceRequest* request) const { | 138 bool IsQueued(ScheduledResourceRequest* request) const { |
| 139 return ContainsKey(pointers_, request); | 139 return base::ContainsKey(pointers_, request); |
| 140 } | 140 } |
| 141 | 141 |
| 142 // Returns true if no requests are queued. | 142 // Returns true if no requests are queued. |
| 143 bool IsEmpty() const { return queue_.size() == 0; } | 143 bool IsEmpty() const { return queue_.size() == 0; } |
| 144 | 144 |
| 145 private: | 145 private: |
| 146 typedef std::map<ScheduledResourceRequest*, NetQueue::iterator> PointerMap; | 146 typedef std::map<ScheduledResourceRequest*, NetQueue::iterator> PointerMap; |
| 147 | 147 |
| 148 uint32_t MakeFifoOrderingId() { | 148 uint32_t MakeFifoOrderingId() { |
| 149 fifo_ordering_ids_ += 1; | 149 fifo_ordering_ids_ += 1; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 return a->get_request_priority_params().GreaterThan( | 295 return a->get_request_priority_params().GreaterThan( |
| 296 b->get_request_priority_params()); | 296 b->get_request_priority_params()); |
| 297 | 297 |
| 298 // If priority/intra_priority is the same, fall back to fifo ordering. | 298 // If priority/intra_priority is the same, fall back to fifo ordering. |
| 299 // std::multiset doesn't guarantee this until c++11. | 299 // std::multiset doesn't guarantee this until c++11. |
| 300 return a->fifo_ordering() < b->fifo_ordering(); | 300 return a->fifo_ordering() < b->fifo_ordering(); |
| 301 } | 301 } |
| 302 | 302 |
| 303 void ResourceScheduler::RequestQueue::Insert( | 303 void ResourceScheduler::RequestQueue::Insert( |
| 304 ScheduledResourceRequest* request) { | 304 ScheduledResourceRequest* request) { |
| 305 DCHECK(!ContainsKey(pointers_, request)); | 305 DCHECK(!base::ContainsKey(pointers_, request)); |
| 306 request->set_fifo_ordering(MakeFifoOrderingId()); | 306 request->set_fifo_ordering(MakeFifoOrderingId()); |
| 307 pointers_[request] = queue_.insert(request); | 307 pointers_[request] = queue_.insert(request); |
| 308 } | 308 } |
| 309 | 309 |
| 310 // Each client represents a tab. | 310 // Each client represents a tab. |
| 311 class ResourceScheduler::Client { | 311 class ResourceScheduler::Client { |
| 312 public: | 312 public: |
| 313 explicit Client(ResourceScheduler* scheduler) | 313 explicit Client(ResourceScheduler* scheduler) |
| 314 : is_loaded_(false), | 314 : is_loaded_(false), |
| 315 has_html_body_(false), | 315 has_html_body_(false), |
| (...skipping 11 matching lines...) Expand all Loading... |
| 327 // New requests can be started synchronously without issue. | 327 // New requests can be started synchronously without issue. |
| 328 StartRequest(request, START_SYNC); | 328 StartRequest(request, START_SYNC); |
| 329 } else { | 329 } else { |
| 330 pending_requests_.Insert(request); | 330 pending_requests_.Insert(request); |
| 331 } | 331 } |
| 332 } | 332 } |
| 333 | 333 |
| 334 void RemoveRequest(ScheduledResourceRequest* request) { | 334 void RemoveRequest(ScheduledResourceRequest* request) { |
| 335 if (pending_requests_.IsQueued(request)) { | 335 if (pending_requests_.IsQueued(request)) { |
| 336 pending_requests_.Erase(request); | 336 pending_requests_.Erase(request); |
| 337 DCHECK(!ContainsKey(in_flight_requests_, request)); | 337 DCHECK(!base::ContainsKey(in_flight_requests_, request)); |
| 338 } else { | 338 } else { |
| 339 EraseInFlightRequest(request); | 339 EraseInFlightRequest(request); |
| 340 | 340 |
| 341 // Removing this request may have freed up another to load. | 341 // Removing this request may have freed up another to load. |
| 342 LoadAnyStartablePendingRequests(); | 342 LoadAnyStartablePendingRequests(); |
| 343 } | 343 } |
| 344 } | 344 } |
| 345 | 345 |
| 346 RequestSet StartAndRemoveAllRequests() { | 346 RequestSet StartAndRemoveAllRequests() { |
| 347 // First start any pending requests so that they will be moved into | 347 // First start any pending requests so that they will be moved into |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 } | 391 } |
| 392 } | 392 } |
| 393 | 393 |
| 394 void ReprioritizeRequest(ScheduledResourceRequest* request, | 394 void ReprioritizeRequest(ScheduledResourceRequest* request, |
| 395 RequestPriorityParams old_priority_params, | 395 RequestPriorityParams old_priority_params, |
| 396 RequestPriorityParams new_priority_params) { | 396 RequestPriorityParams new_priority_params) { |
| 397 request->url_request()->SetPriority(new_priority_params.priority); | 397 request->url_request()->SetPriority(new_priority_params.priority); |
| 398 request->set_request_priority_params(new_priority_params); | 398 request->set_request_priority_params(new_priority_params); |
| 399 SetRequestAttributes(request, DetermineRequestAttributes(request)); | 399 SetRequestAttributes(request, DetermineRequestAttributes(request)); |
| 400 if (!pending_requests_.IsQueued(request)) { | 400 if (!pending_requests_.IsQueued(request)) { |
| 401 DCHECK(ContainsKey(in_flight_requests_, request)); | 401 DCHECK(base::ContainsKey(in_flight_requests_, request)); |
| 402 // Request has already started. | 402 // Request has already started. |
| 403 return; | 403 return; |
| 404 } | 404 } |
| 405 | 405 |
| 406 pending_requests_.Erase(request); | 406 pending_requests_.Erase(request); |
| 407 pending_requests_.Insert(request); | 407 pending_requests_.Insert(request); |
| 408 | 408 |
| 409 if (new_priority_params.priority > old_priority_params.priority) { | 409 if (new_priority_params.priority > old_priority_params.priority) { |
| 410 // Check if this request is now able to load at its new priority. | 410 // Check if this request is now able to load at its new priority. |
| 411 LoadAnyStartablePendingRequests(); | 411 LoadAnyStartablePendingRequests(); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 for (RequestQueue::NetQueue::const_iterator | 451 for (RequestQueue::NetQueue::const_iterator |
| 452 it = pending_requests_.GetNextHighestIterator(); | 452 it = pending_requests_.GetNextHighestIterator(); |
| 453 it != pending_requests_.End(); ++it) { | 453 it != pending_requests_.End(); ++it) { |
| 454 if (RequestAttributesAreSet((*it)->attributes(), attributes)) | 454 if (RequestAttributesAreSet((*it)->attributes(), attributes)) |
| 455 matching_request_count++; | 455 matching_request_count++; |
| 456 if (*it == current_request) | 456 if (*it == current_request) |
| 457 current_request_is_pending = true; | 457 current_request_is_pending = true; |
| 458 } | 458 } |
| 459 // Account for the current request if it is not in one of the lists yet. | 459 // Account for the current request if it is not in one of the lists yet. |
| 460 if (current_request && | 460 if (current_request && |
| 461 !ContainsKey(in_flight_requests_, current_request) && | 461 !base::ContainsKey(in_flight_requests_, current_request) && |
| 462 !current_request_is_pending) { | 462 !current_request_is_pending) { |
| 463 if (RequestAttributesAreSet(current_request->attributes(), attributes)) | 463 if (RequestAttributesAreSet(current_request->attributes(), attributes)) |
| 464 matching_request_count++; | 464 matching_request_count++; |
| 465 } | 465 } |
| 466 } | 466 } |
| 467 return matching_request_count; | 467 return matching_request_count; |
| 468 } | 468 } |
| 469 | 469 |
| 470 bool RequestAttributesAreSet(RequestAttributes request_attributes, | 470 bool RequestAttributesAreSet(RequestAttributes request_attributes, |
| 471 RequestAttributes matching_attributes) const { | 471 RequestAttributes matching_attributes) const { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 497 kAttributeInFlight | kAttributeDelayable, request), | 497 kAttributeInFlight | kAttributeDelayable, request), |
| 498 in_flight_delayable_count_); | 498 in_flight_delayable_count_); |
| 499 DCHECK_EQ(CountRequestsWithAttributes(kAttributeLayoutBlocking, request), | 499 DCHECK_EQ(CountRequestsWithAttributes(kAttributeLayoutBlocking, request), |
| 500 total_layout_blocking_count_); | 500 total_layout_blocking_count_); |
| 501 } | 501 } |
| 502 | 502 |
| 503 RequestAttributes DetermineRequestAttributes( | 503 RequestAttributes DetermineRequestAttributes( |
| 504 ScheduledResourceRequest* request) { | 504 ScheduledResourceRequest* request) { |
| 505 RequestAttributes attributes = kAttributeNone; | 505 RequestAttributes attributes = kAttributeNone; |
| 506 | 506 |
| 507 if (ContainsKey(in_flight_requests_, request)) | 507 if (base::ContainsKey(in_flight_requests_, request)) |
| 508 attributes |= kAttributeInFlight; | 508 attributes |= kAttributeInFlight; |
| 509 | 509 |
| 510 if (RequestAttributesAreSet(request->attributes(), | 510 if (RequestAttributesAreSet(request->attributes(), |
| 511 kAttributeLayoutBlocking)) { | 511 kAttributeLayoutBlocking)) { |
| 512 // If a request is already marked as layout-blocking make sure to keep the | 512 // If a request is already marked as layout-blocking make sure to keep the |
| 513 // attribute across redirects. | 513 // attribute across redirects. |
| 514 attributes |= kAttributeLayoutBlocking; | 514 attributes |= kAttributeLayoutBlocking; |
| 515 } else if (!has_html_body_ && | 515 } else if (!has_html_body_ && |
| 516 request->url_request()->priority() > | 516 request->url_request()->priority() > |
| 517 kLayoutBlockingPriorityThreshold) { | 517 kLayoutBlockingPriorityThreshold) { |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 return std::move(request); | 764 return std::move(request); |
| 765 } | 765 } |
| 766 | 766 |
| 767 Client* client = it->second; | 767 Client* client = it->second; |
| 768 client->ScheduleRequest(url_request, request.get()); | 768 client->ScheduleRequest(url_request, request.get()); |
| 769 return std::move(request); | 769 return std::move(request); |
| 770 } | 770 } |
| 771 | 771 |
| 772 void ResourceScheduler::RemoveRequest(ScheduledResourceRequest* request) { | 772 void ResourceScheduler::RemoveRequest(ScheduledResourceRequest* request) { |
| 773 DCHECK(CalledOnValidThread()); | 773 DCHECK(CalledOnValidThread()); |
| 774 if (ContainsKey(unowned_requests_, request)) { | 774 if (base::ContainsKey(unowned_requests_, request)) { |
| 775 unowned_requests_.erase(request); | 775 unowned_requests_.erase(request); |
| 776 return; | 776 return; |
| 777 } | 777 } |
| 778 | 778 |
| 779 ClientMap::iterator client_it = client_map_.find(request->client_id()); | 779 ClientMap::iterator client_it = client_map_.find(request->client_id()); |
| 780 if (client_it == client_map_.end()) { | 780 if (client_it == client_map_.end()) { |
| 781 return; | 781 return; |
| 782 } | 782 } |
| 783 | 783 |
| 784 Client* client = client_it->second; | 784 Client* client = client_it->second; |
| 785 client->RemoveRequest(request); | 785 client->RemoveRequest(request); |
| 786 } | 786 } |
| 787 | 787 |
| 788 void ResourceScheduler::OnClientCreated(int child_id, | 788 void ResourceScheduler::OnClientCreated(int child_id, |
| 789 int route_id) { | 789 int route_id) { |
| 790 DCHECK(CalledOnValidThread()); | 790 DCHECK(CalledOnValidThread()); |
| 791 ClientId client_id = MakeClientId(child_id, route_id); | 791 ClientId client_id = MakeClientId(child_id, route_id); |
| 792 DCHECK(!ContainsKey(client_map_, client_id)); | 792 DCHECK(!base::ContainsKey(client_map_, client_id)); |
| 793 | 793 |
| 794 Client* client = new Client(this); | 794 Client* client = new Client(this); |
| 795 client_map_[client_id] = client; | 795 client_map_[client_id] = client; |
| 796 } | 796 } |
| 797 | 797 |
| 798 void ResourceScheduler::OnClientDeleted(int child_id, int route_id) { | 798 void ResourceScheduler::OnClientDeleted(int child_id, int route_id) { |
| 799 DCHECK(CalledOnValidThread()); | 799 DCHECK(CalledOnValidThread()); |
| 800 ClientId client_id = MakeClientId(child_id, route_id); | 800 ClientId client_id = MakeClientId(child_id, route_id); |
| 801 ClientMap::iterator it = client_map_.find(client_id); | 801 ClientMap::iterator it = client_map_.find(client_id); |
| 802 DCHECK(it != client_map_.end()); | 802 DCHECK(it != client_map_.end()); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 923 client->ReprioritizeRequest(scheduled_resource_request, old_priority_params, | 923 client->ReprioritizeRequest(scheduled_resource_request, old_priority_params, |
| 924 new_priority_params); | 924 new_priority_params); |
| 925 } | 925 } |
| 926 | 926 |
| 927 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( | 927 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( |
| 928 int child_id, int route_id) { | 928 int child_id, int route_id) { |
| 929 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; | 929 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; |
| 930 } | 930 } |
| 931 | 931 |
| 932 } // namespace content | 932 } // namespace content |
| OLD | NEW |