Chromium Code Reviews| 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 <set> | 5 #include <set> |
| 6 | 6 |
| 7 #include "content/browser/loader/resource_scheduler.h" | 7 #include "content/browser/loader/resource_scheduler.h" |
| 8 | 8 |
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
| 10 #include "content/common/resource_messages.h" | 10 #include "content/common/resource_messages.h" |
| 11 #include "content/browser/loader/resource_message_delegate.h" | 11 #include "content/browser/loader/resource_message_delegate.h" |
| 12 #include "content/public/browser/browser_thread.h" | |
| 12 #include "content/public/browser/resource_controller.h" | 13 #include "content/public/browser/resource_controller.h" |
| 13 #include "content/public/browser/resource_request_info.h" | 14 #include "content/public/browser/resource_request_info.h" |
| 14 #include "content/public/browser/resource_throttle.h" | 15 #include "content/public/browser/resource_throttle.h" |
| 16 #include "content/public/browser/web_contents_observer.h" | |
| 15 #include "ipc/ipc_message_macros.h" | 17 #include "ipc/ipc_message_macros.h" |
| 16 #include "net/base/host_port_pair.h" | 18 #include "net/base/host_port_pair.h" |
| 17 #include "net/base/load_flags.h" | 19 #include "net/base/load_flags.h" |
| 18 #include "net/base/request_priority.h" | 20 #include "net/base/request_priority.h" |
| 19 #include "net/http/http_server_properties.h" | 21 #include "net/http/http_server_properties.h" |
| 20 #include "net/url_request/url_request.h" | 22 #include "net/url_request/url_request.h" |
| 21 #include "net/url_request/url_request_context.h" | 23 #include "net/url_request/url_request_context.h" |
| 22 | 24 |
| 23 namespace content { | 25 namespace content { |
| 24 | 26 |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 220 return a->fifo_ordering() < b->fifo_ordering(); | 222 return a->fifo_ordering() < b->fifo_ordering(); |
| 221 } | 223 } |
| 222 | 224 |
| 223 void ResourceScheduler::RequestQueue::Insert( | 225 void ResourceScheduler::RequestQueue::Insert( |
| 224 ScheduledResourceRequest* request) { | 226 ScheduledResourceRequest* request) { |
| 225 DCHECK(!ContainsKey(pointers_, request)); | 227 DCHECK(!ContainsKey(pointers_, request)); |
| 226 request->set_fifo_ordering(MakeFifoOrderingId()); | 228 request->set_fifo_ordering(MakeFifoOrderingId()); |
| 227 pointers_[request] = queue_.insert(request); | 229 pointers_[request] = queue_.insert(request); |
| 228 } | 230 } |
| 229 | 231 |
| 232 // VisualObserver lives on UI thread | |
| 233 class ResourceScheduler::VisualObserver : public content::WebContentsObserver { | |
| 234 public: | |
| 235 explicit VisualObserver(WebContentsImpl* web_contents); | |
| 236 virtual ~VisualObserver() { } | |
| 237 | |
| 238 void SetClient(Client* client); | |
| 239 bool IsVisible(); | |
| 240 | |
| 241 // WebContentsObserver implementation. | |
| 242 virtual void WasShown() OVERRIDE; | |
| 243 virtual void WasHidden() OVERRIDE; | |
| 244 | |
| 245 private: | |
| 246 Client* client_; | |
| 247 }; | |
| 248 | |
| 230 // Each client represents a tab. | 249 // Each client represents a tab. |
| 231 class ResourceScheduler::Client { | 250 class ResourceScheduler::Client { |
| 232 public: | 251 public: |
| 233 explicit Client(ResourceScheduler* scheduler) | 252 explicit Client(ResourceScheduler* scheduler, |
| 253 VisualObserver* visual_observer, | |
| 254 bool is_visible) | |
| 234 : is_audible_(false), | 255 : is_audible_(false), |
| 235 is_visible_(false), | 256 is_visible_(is_visible), |
| 236 is_loaded_(false), | 257 is_loaded_(false), |
| 237 is_paused_(false), | 258 is_paused_(false), |
| 238 has_body_(false), | 259 has_body_(false), |
| 239 using_spdy_proxy_(false), | 260 using_spdy_proxy_(false), |
| 240 total_delayable_count_(0), | 261 total_delayable_count_(0), |
| 241 throttle_state_(ResourceScheduler::THROTTLED) { | 262 throttle_state_(ResourceScheduler::THROTTLED), |
| 263 visual_observer_(visual_observer) { | |
| 242 scheduler_ = scheduler; | 264 scheduler_ = scheduler; |
| 265 if (visual_observer) | |
| 266 BrowserThread::PostTask( | |
| 267 BrowserThread::UI, FROM_HERE, | |
| 268 base::Bind(&ResourceScheduler::VisualObserver::SetClient, | |
| 269 base::Unretained(visual_observer_), | |
| 270 base::Unretained(this))); | |
| 243 } | 271 } |
| 244 | 272 |
| 245 ~Client() { | 273 virtual ~Client() { |
| 246 // Update to default state and pause to ensure the scheduler has a | 274 // Update to default state and pause to ensure the scheduler has a |
| 247 // correct count of relevant types of clients. | 275 // correct count of relevant types of clients. |
| 248 is_visible_ = false; | 276 is_visible_ = false; |
| 249 is_audible_ = false; | 277 is_audible_ = false; |
| 250 is_paused_ = true; | 278 is_paused_ = true; |
| 251 UpdateThrottleState(); | 279 UpdateThrottleState(); |
| 280 BrowserThread::PostTask( | |
| 281 BrowserThread::UI, FROM_HERE, | |
| 282 base::Bind(&ResourceScheduler::DeleteVisualObserver, | |
| 283 base::Unretained(scheduler_), | |
| 284 base::Unretained(visual_observer_))); | |
| 252 } | 285 } |
| 253 | 286 |
| 254 void ScheduleRequest( | 287 void ScheduleRequest( |
| 255 net::URLRequest* url_request, | 288 net::URLRequest* url_request, |
| 256 ScheduledResourceRequest* request) { | 289 ScheduledResourceRequest* request) { |
| 257 if (ShouldStartRequest(request) == START_REQUEST) { | 290 if (ShouldStartRequest(request) == START_REQUEST) { |
| 258 StartRequest(request); | 291 StartRequest(request); |
| 259 } else { | 292 } else { |
| 260 pending_requests_.Insert(request); | 293 pending_requests_.Insert(request); |
| 261 } | 294 } |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 281 (*it)->set_accounted_as_delayable_request(false); | 314 (*it)->set_accounted_as_delayable_request(false); |
| 282 } | 315 } |
| 283 ClearInFlightRequests(); | 316 ClearInFlightRequests(); |
| 284 return unowned_requests; | 317 return unowned_requests; |
| 285 } | 318 } |
| 286 | 319 |
| 287 bool is_active() const { return is_visible_ || is_audible_; } | 320 bool is_active() const { return is_visible_ || is_audible_; } |
| 288 | 321 |
| 289 bool is_loaded() const { return is_loaded_; } | 322 bool is_loaded() const { return is_loaded_; } |
| 290 | 323 |
| 324 bool IsVisible() const { return is_visible_; } | |
| 325 | |
| 291 void OnAudibilityChanged(bool is_audible) { | 326 void OnAudibilityChanged(bool is_audible) { |
| 292 if (is_audible == is_audible_) { | 327 if (is_audible == is_audible_) { |
| 293 return; | 328 return; |
| 294 } | 329 } |
| 295 is_audible_ = is_audible; | 330 is_audible_ = is_audible; |
| 296 UpdateThrottleState(); | 331 UpdateThrottleState(); |
| 297 } | 332 } |
| 298 | 333 |
| 299 void OnVisibilityChanged(bool is_visible) { | 334 void OnVisibilityChanged(bool is_visible) { |
| 300 if (is_visible == is_visible_) { | 335 if (is_visible == is_visible_) { |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 652 bool is_loaded_; | 687 bool is_loaded_; |
| 653 bool is_paused_; | 688 bool is_paused_; |
| 654 bool has_body_; | 689 bool has_body_; |
| 655 bool using_spdy_proxy_; | 690 bool using_spdy_proxy_; |
| 656 RequestQueue pending_requests_; | 691 RequestQueue pending_requests_; |
| 657 RequestSet in_flight_requests_; | 692 RequestSet in_flight_requests_; |
| 658 ResourceScheduler* scheduler_; | 693 ResourceScheduler* scheduler_; |
| 659 // The number of delayable in-flight requests. | 694 // The number of delayable in-flight requests. |
| 660 size_t total_delayable_count_; | 695 size_t total_delayable_count_; |
| 661 ResourceScheduler::ClientThrottleState throttle_state_; | 696 ResourceScheduler::ClientThrottleState throttle_state_; |
| 697 VisualObserver* visual_observer_; | |
| 662 }; | 698 }; |
| 663 | 699 |
| 700 ResourceScheduler::VisualObserver::VisualObserver(WebContentsImpl* web_contents) | |
| 701 : client_(NULL) { | |
| 702 Observe(web_contents); | |
| 703 } | |
| 704 | |
| 705 void ResourceScheduler::VisualObserver::SetClient(Client* client) { | |
| 706 client_ = client; | |
| 707 } | |
| 708 | |
| 709 // WebContentsObserver implementation. | |
| 710 void ResourceScheduler::VisualObserver::WasShown() { | |
| 711 if (client_) | |
|
mmenke
2014/08/19 14:38:27
So we ignore events if the visibility changes if w
Zhen Wang
2014/08/19 17:53:41
Yes. It may happen that the Client hasn't been cre
| |
| 712 BrowserThread::PostTask( | |
| 713 BrowserThread::IO, FROM_HERE, | |
| 714 base::Bind(&ResourceScheduler::Client::OnVisibilityChanged, | |
| 715 base::Unretained(client_), | |
| 716 true)); | |
|
mmenke
2014/08/19 14:38:27
This isn't safe. The client may already have been
Zhen Wang
2014/08/19 17:53:41
I think you are right. I override OnRenderViewHost
| |
| 717 } | |
| 718 | |
| 719 // WebContentsObserver implementation. | |
| 720 void ResourceScheduler::VisualObserver::WasHidden() { | |
| 721 if (client_) | |
| 722 BrowserThread::PostTask( | |
| 723 BrowserThread::IO, FROM_HERE, | |
| 724 base::Bind(&ResourceScheduler::Client::OnVisibilityChanged, | |
| 725 base::Unretained(client_), | |
| 726 false)); | |
| 727 } | |
| 728 | |
| 729 ResourceScheduler::VisualObserver* ResourceScheduler::CreateVisualObserver( | |
| 730 WebContentsImpl* web_content) { | |
| 731 return new ResourceScheduler::VisualObserver(web_content); | |
| 732 } | |
| 733 | |
| 734 void ResourceScheduler::DeleteVisualObserver(VisualObserver* observer) { | |
| 735 delete observer; | |
| 736 } | |
| 737 | |
| 664 ResourceScheduler::ResourceScheduler() | 738 ResourceScheduler::ResourceScheduler() |
| 665 : should_coalesce_(false), | 739 : should_coalesce_(false), |
| 666 should_throttle_(false), | 740 should_throttle_(false), |
| 667 active_clients_loading_(0), | 741 active_clients_loading_(0), |
| 668 coalesced_clients_(0), | 742 coalesced_clients_(0), |
| 669 coalescing_timer_(new base::Timer(true /* retain_user_task */, | 743 coalescing_timer_(new base::Timer(true /* retain_user_task */, |
| 670 true /* is_repeating */)) { | 744 true /* is_repeating */)) { |
| 671 } | 745 } |
| 672 | 746 |
| 673 ResourceScheduler::~ResourceScheduler() { | 747 ResourceScheduler::~ResourceScheduler() { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 724 | 798 |
| 725 ClientMap::iterator client_it = client_map_.find(request->client_id()); | 799 ClientMap::iterator client_it = client_map_.find(request->client_id()); |
| 726 if (client_it == client_map_.end()) { | 800 if (client_it == client_map_.end()) { |
| 727 return; | 801 return; |
| 728 } | 802 } |
| 729 | 803 |
| 730 Client* client = client_it->second; | 804 Client* client = client_it->second; |
| 731 client->RemoveRequest(request); | 805 client->RemoveRequest(request); |
| 732 } | 806 } |
| 733 | 807 |
| 734 void ResourceScheduler::OnClientCreated(int child_id, int route_id) { | 808 void ResourceScheduler::OnClientCreated(int child_id, |
| 809 int route_id, | |
| 810 VisualObserver* visual_observer, | |
| 811 bool is_visible) { | |
| 735 DCHECK(CalledOnValidThread()); | 812 DCHECK(CalledOnValidThread()); |
| 736 ClientId client_id = MakeClientId(child_id, route_id); | 813 ClientId client_id = MakeClientId(child_id, route_id); |
| 737 DCHECK(!ContainsKey(client_map_, client_id)); | 814 DCHECK(!ContainsKey(client_map_, client_id)); |
| 738 | 815 |
| 739 Client* client = new Client(this); | 816 Client* client = new Client(this, visual_observer, is_visible); |
| 740 client_map_[client_id] = client; | 817 client_map_[client_id] = client; |
| 741 | 818 |
| 742 // TODO(aiolos): set Client visibility/audibility when signals are added | 819 // TODO(aiolos): set Client visibility/audibility when signals are added |
| 743 // this will UNTHROTTLE Clients as needed | 820 // this will UNTHROTTLE Clients as needed |
| 744 client->UpdateThrottleState(); | 821 client->UpdateThrottleState(); |
| 745 } | 822 } |
| 746 | 823 |
| 747 void ResourceScheduler::OnClientDeleted(int child_id, int route_id) { | 824 void ResourceScheduler::OnClientDeleted(int child_id, int route_id) { |
| 748 DCHECK(CalledOnValidThread()); | 825 DCHECK(CalledOnValidThread()); |
| 749 ClientId client_id = MakeClientId(child_id, route_id); | 826 ClientId client_id = MakeClientId(child_id, route_id); |
| 827 | |
| 750 DCHECK(ContainsKey(client_map_, client_id)); | 828 DCHECK(ContainsKey(client_map_, client_id)); |
| 751 ClientMap::iterator it = client_map_.find(client_id); | 829 ClientMap::iterator it = client_map_.find(client_id); |
| 752 if (it == client_map_.end()) | 830 if (it == client_map_.end()) |
| 753 return; | 831 return; |
| 754 | 832 |
| 755 Client* client = it->second; | 833 Client* client = it->second; |
| 756 // FYI, ResourceDispatcherHost cancels all of the requests after this function | 834 // FYI, ResourceDispatcherHost cancels all of the requests after this function |
| 757 // is called. It should end up canceling all of the requests except for a | 835 // is called. It should end up canceling all of the requests except for a |
| 758 // cross-renderer navigation. | 836 // cross-renderer navigation. |
| 759 RequestSet client_unowned_requests = client->RemoveAllRequests(); | 837 RequestSet client_unowned_requests = client->RemoveAllRequests(); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 810 } | 888 } |
| 811 | 889 |
| 812 void ResourceScheduler::OnAudibilityChanged(int child_id, | 890 void ResourceScheduler::OnAudibilityChanged(int child_id, |
| 813 int route_id, | 891 int route_id, |
| 814 bool is_audible) { | 892 bool is_audible) { |
| 815 Client* client = GetClient(child_id, route_id); | 893 Client* client = GetClient(child_id, route_id); |
| 816 DCHECK(client); | 894 DCHECK(client); |
| 817 client->OnAudibilityChanged(is_audible); | 895 client->OnAudibilityChanged(is_audible); |
| 818 } | 896 } |
| 819 | 897 |
| 820 void ResourceScheduler::OnVisibilityChanged(int child_id, | |
| 821 int route_id, | |
| 822 bool is_visible) { | |
| 823 Client* client = GetClient(child_id, route_id); | |
| 824 DCHECK(client); | |
| 825 client->OnVisibilityChanged(is_visible); | |
| 826 } | |
| 827 | |
| 828 void ResourceScheduler::OnLoadingStateChanged(int child_id, | 898 void ResourceScheduler::OnLoadingStateChanged(int child_id, |
| 829 int route_id, | 899 int route_id, |
| 830 bool is_loaded) { | 900 bool is_loaded) { |
| 831 Client* client = GetClient(child_id, route_id); | 901 Client* client = GetClient(child_id, route_id); |
| 832 DCHECK(client); | 902 DCHECK(client); |
| 833 client->OnLoadingStateChanged(is_loaded); | 903 client->OnLoadingStateChanged(is_loaded); |
| 834 } | 904 } |
| 835 | 905 |
| 906 bool ResourceScheduler::IsClientVisibleForTesting(int child_id, int route_id) { | |
| 907 Client* client = GetClient(child_id, route_id); | |
| 908 DCHECK(client); | |
| 909 return client->IsVisible(); | |
| 910 } | |
| 911 | |
| 836 ResourceScheduler::Client* ResourceScheduler::GetClient(int child_id, | 912 ResourceScheduler::Client* ResourceScheduler::GetClient(int child_id, |
| 837 int route_id) { | 913 int route_id) { |
| 838 ClientId client_id = MakeClientId(child_id, route_id); | 914 ClientId client_id = MakeClientId(child_id, route_id); |
| 839 ClientMap::iterator client_it = client_map_.find(client_id); | 915 ClientMap::iterator client_it = client_map_.find(client_id); |
| 840 if (client_it == client_map_.end()) { | 916 if (client_it == client_map_.end()) { |
| 841 return NULL; | 917 return NULL; |
| 842 } | 918 } |
| 843 return client_it->second; | 919 return client_it->second; |
| 844 } | 920 } |
| 845 | 921 |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 960 client->ReprioritizeRequest( | 1036 client->ReprioritizeRequest( |
| 961 request, old_priority_params, new_priority_params); | 1037 request, old_priority_params, new_priority_params); |
| 962 } | 1038 } |
| 963 | 1039 |
| 964 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( | 1040 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( |
| 965 int child_id, int route_id) { | 1041 int child_id, int route_id) { |
| 966 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; | 1042 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; |
| 967 } | 1043 } |
| 968 | 1044 |
| 969 } // namespace content | 1045 } // namespace content |
| OLD | NEW |