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 |