Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(496)

Side by Side Diff: content/browser/loader/resource_scheduler.cc

Issue 1230133005: Fix Resource Priorities and Scheduling (Chrome Side) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/browser/loader/resource_scheduler.h ('k') | content/public/common/content_switches.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "base/base_switches.h"
8 8 #include "base/basictypes.h"
9 #include "base/command_line.h"
9 #include "base/metrics/field_trial.h" 10 #include "base/metrics/field_trial.h"
10 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
11 #include "base/stl_util.h" 12 #include "base/stl_util.h"
12 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_piece.h" 14 #include "base/strings/string_piece.h"
14 #include "base/time/time.h" 15 #include "base/time/time.h"
15 #include "content/common/resource_messages.h" 16 #include "content/common/resource_messages.h"
16 #include "content/browser/loader/resource_message_delegate.h" 17 #include "content/browser/loader/resource_message_delegate.h"
18 #include "content/browser/loader/resource_scheduler.h"
17 #include "content/public/browser/resource_controller.h" 19 #include "content/public/browser/resource_controller.h"
18 #include "content/public/browser/resource_request_info.h" 20 #include "content/public/browser/resource_request_info.h"
19 #include "content/public/browser/resource_throttle.h" 21 #include "content/public/browser/resource_throttle.h"
22 #include "content/public/common/content_switches.h"
20 #include "ipc/ipc_message_macros.h" 23 #include "ipc/ipc_message_macros.h"
21 #include "net/base/host_port_pair.h" 24 #include "net/base/host_port_pair.h"
22 #include "net/base/load_flags.h" 25 #include "net/base/load_flags.h"
23 #include "net/base/request_priority.h" 26 #include "net/base/request_priority.h"
24 #include "net/http/http_server_properties.h" 27 #include "net/http/http_server_properties.h"
25 #include "net/url_request/url_request.h" 28 #include "net/url_request/url_request.h"
26 #include "net/url_request/url_request_context.h" 29 #include "net/url_request/url_request_context.h"
27 30
28 namespace content { 31 namespace content {
29 32
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 DCHECK(!ContainsKey(pointers_, request)); 299 DCHECK(!ContainsKey(pointers_, request));
297 request->set_fifo_ordering(MakeFifoOrderingId()); 300 request->set_fifo_ordering(MakeFifoOrderingId());
298 pointers_[request] = queue_.insert(request); 301 pointers_[request] = queue_.insert(request);
299 } 302 }
300 303
301 // Each client represents a tab. 304 // Each client represents a tab.
302 class ResourceScheduler::Client { 305 class ResourceScheduler::Client {
303 public: 306 public:
304 explicit Client(ResourceScheduler* scheduler, 307 explicit Client(ResourceScheduler* scheduler,
305 bool is_visible, 308 bool is_visible,
306 bool is_audible) 309 bool is_audible,
310 int fetch_mode)
307 : is_audible_(is_audible), 311 : is_audible_(is_audible),
308 is_visible_(is_visible), 312 is_visible_(is_visible),
309 is_loaded_(false), 313 is_loaded_(false),
310 is_paused_(false), 314 is_paused_(false),
311 has_body_(false), 315 has_body_(false),
312 using_spdy_proxy_(false), 316 using_spdy_proxy_(false),
313 load_started_time_(base::TimeTicks::Now()), 317 load_started_time_(base::TimeTicks::Now()),
314 scheduler_(scheduler), 318 scheduler_(scheduler),
315 in_flight_delayable_count_(0), 319 in_flight_delayable_count_(0),
316 total_layout_blocking_count_(0), 320 total_layout_blocking_count_(0),
317 throttle_state_(ResourceScheduler::THROTTLED) {} 321 throttle_state_(ResourceScheduler::THROTTLED),
322 fetch_mode_(fetch_mode) {}
318 323
319 ~Client() { 324 ~Client() {
320 // Update to default state and pause to ensure the scheduler has a 325 // Update to default state and pause to ensure the scheduler has a
321 // correct count of relevant types of clients. 326 // correct count of relevant types of clients.
322 is_visible_ = false; 327 is_visible_ = false;
323 is_audible_ = false; 328 is_audible_ = false;
324 is_paused_ = true; 329 is_paused_ = true;
325 UpdateThrottleState(); 330 UpdateThrottleState();
326 } 331 }
327 332
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 DCHECK_EQ( 622 DCHECK_EQ(
618 CountRequestsWithClassification(IN_FLIGHT_DELAYABLE_REQUEST, false), 623 CountRequestsWithClassification(IN_FLIGHT_DELAYABLE_REQUEST, false),
619 in_flight_delayable_count_); 624 in_flight_delayable_count_);
620 DCHECK_EQ(CountRequestsWithClassification(LAYOUT_BLOCKING_REQUEST, true), 625 DCHECK_EQ(CountRequestsWithClassification(LAYOUT_BLOCKING_REQUEST, true),
621 total_layout_blocking_count_); 626 total_layout_blocking_count_);
622 } 627 }
623 628
624 RequestClassification ClassifyRequest(ScheduledResourceRequest* request) { 629 RequestClassification ClassifyRequest(ScheduledResourceRequest* request) {
625 // If a request is already marked as layout-blocking make sure to keep the 630 // If a request is already marked as layout-blocking make sure to keep the
626 // classification across redirects unless the priority was lowered. 631 // classification across redirects unless the priority was lowered.
627 if (request->classification() == LAYOUT_BLOCKING_REQUEST && 632 if (fetch_mode_ == 2) {
628 request->url_request()->priority() > net::LOW) { 633 if (request->classification() == LAYOUT_BLOCKING_REQUEST &&
629 return LAYOUT_BLOCKING_REQUEST; 634 request->url_request()->priority() > net::MEDIUM) {
630 } 635 return LAYOUT_BLOCKING_REQUEST;
636 }
631 637
632 if (!has_body_ && request->url_request()->priority() > net::LOW) 638 if (!has_body_ && request->url_request()->priority() > net::MEDIUM)
633 return LAYOUT_BLOCKING_REQUEST; 639 return LAYOUT_BLOCKING_REQUEST;
634 640
635 if (request->url_request()->priority() < net::LOW) { 641 if (request->url_request()->priority() < net::MEDIUM) {
636 net::HostPortPair host_port_pair = 642 net::HostPortPair host_port_pair =
637 net::HostPortPair::FromURL(request->url_request()->url()); 643 net::HostPortPair::FromURL(request->url_request()->url());
638 net::HttpServerProperties& http_server_properties = 644 net::HttpServerProperties& http_server_properties =
639 *request->url_request()->context()->http_server_properties(); 645 *request->url_request()->context()->http_server_properties();
640 if (!http_server_properties.SupportsRequestPriority(host_port_pair) && 646 if (!http_server_properties.SupportsRequestPriority(host_port_pair) &&
641 ContainsKey(in_flight_requests_, request)) { 647 ContainsKey(in_flight_requests_, request)) {
642 return IN_FLIGHT_DELAYABLE_REQUEST; 648 return IN_FLIGHT_DELAYABLE_REQUEST;
649 }
650 }
651 } else {
652 if (request->classification() == LAYOUT_BLOCKING_REQUEST &&
653 request->url_request()->priority() > net::LOW) {
654 return LAYOUT_BLOCKING_REQUEST;
655 }
656
657 if (!has_body_ && request->url_request()->priority() > net::LOW)
658 return LAYOUT_BLOCKING_REQUEST;
659
660 if (request->url_request()->priority() < net::LOW) {
661 net::HostPortPair host_port_pair =
662 net::HostPortPair::FromURL(request->url_request()->url());
663 net::HttpServerProperties& http_server_properties =
664 *request->url_request()->context()->http_server_properties();
665 if (!http_server_properties.SupportsRequestPriority(host_port_pair) &&
666 ContainsKey(in_flight_requests_, request)) {
667 return IN_FLIGHT_DELAYABLE_REQUEST;
668 }
643 } 669 }
644 } 670 }
645 return NORMAL_REQUEST; 671 return NORMAL_REQUEST;
646 } 672 }
647 673
648 bool ShouldKeepSearching( 674 bool ShouldKeepSearching(
649 const net::HostPortPair& active_request_host) const { 675 const net::HostPortPair& active_request_host) const {
650 size_t same_host_count = 0; 676 size_t same_host_count = 0;
651 for (RequestSet::const_iterator it = in_flight_requests_.begin(); 677 for (RequestSet::const_iterator it = in_flight_requests_.begin();
652 it != in_flight_requests_.end(); ++it) { 678 it != in_flight_requests_.end(); ++it) {
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
762 } 788 }
763 789
764 if (throttle_state_ == THROTTLED && 790 if (throttle_state_ == THROTTLED &&
765 in_flight_requests_.size() >= kMaxNumThrottledRequestsPerClient) { 791 in_flight_requests_.size() >= kMaxNumThrottledRequestsPerClient) {
766 // There may still be request-priority-capable requests that should be 792 // There may still be request-priority-capable requests that should be
767 // issued. 793 // issued.
768 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING; 794 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING;
769 } 795 }
770 796
771 // High-priority and layout-blocking requests. 797 // High-priority and layout-blocking requests.
772 if (url_request.priority() >= net::LOW) { 798 if (fetch_mode_ == 2) {
773 return START_REQUEST; 799 if (url_request.priority() >= net::MEDIUM) {
800 return START_REQUEST;
801 }
802 } else {
803 if (url_request.priority() >= net::LOW) {
804 return START_REQUEST;
805 }
774 } 806 }
775 807
776 if (in_flight_delayable_count_ >= kMaxNumDelayableRequestsPerClient) { 808 if (in_flight_delayable_count_ >= kMaxNumDelayableRequestsPerClient) {
777 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; 809 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
778 } 810 }
779 811
780 if (ShouldKeepSearching(host_port_pair)) { 812 if (ShouldKeepSearching(host_port_pair)) {
781 // There may be other requests for other hosts we'd allow, 813 // There may be other requests for other hosts we'd allow,
782 // so keep checking. 814 // so keep checking.
783 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING; 815 return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING;
784 } 816 }
785 817
786 bool have_immediate_requests_in_flight = 818 if (fetch_mode_ == 2) {
787 in_flight_requests_.size() > in_flight_delayable_count_; 819 // If we are in render-blocking more make sure at least 2 requests
788 if (have_immediate_requests_in_flight && 820 // are in-flight. High priority requests would have alreay
789 (!has_body_ || total_layout_blocking_count_ != 0) && 821 // been allowed so this just restricts low-priority requests.
790 // Do not allow a low priority request through in parallel if 822 if ((!has_body_ || total_layout_blocking_count_ != 0) &&
791 // we are in a limit field trial. 823 in_flight_requests_.size() >= 2) {
Bryan McQuade 2015/07/29 17:53:47 it's hard for me to say with certainty that this i
Pat Meenan 2015/08/07 15:53:53 This has all been ripped out and replaced with fin
792 (scheduler_->limit_outstanding_requests() || 824 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
793 in_flight_delayable_count_ != 0)) { 825 }
794 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING; 826
827 // Allow 1 lower priority resource while 1 higher priority resource
828 // is pending. If more than 1 higher priority resources are in flight
829 // hold back from issuing any more lower priority requests.
830 // This balances keeping the pipe from going idle when the last high
831 // priority request completes but also limits the cases where low priority
832 // requests will be contending with them for bandwidth.
833 size_t higher_priority = 0;
Bryan McQuade 2015/07/29 17:53:47 same as above (can we test this change separately
Pat Meenan 2015/08/07 15:53:53 Also replaced and finch-controllable now.
834 size_t equal_priority = 0;
835 net::RequestPriority priority = url_request.priority();
836 for (RequestSet::const_iterator it = in_flight_requests_.begin();
837 it != in_flight_requests_.end(); ++it) {
838 net::RequestPriority pending_priority =
839 (*it)->get_request_priority_params().priority;
840 if (pending_priority > priority) {
841 higher_priority++;
842 } else if (pending_priority == priority) {
843 equal_priority++;
844 }
845 }
846 if (higher_priority > 1 || (higher_priority == 1 && equal_priority > 0)) {
847 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
848 }
849
850 } else {
851 bool have_immediate_requests_in_flight =
852 in_flight_requests_.size() > in_flight_delayable_count_;
853 if (have_immediate_requests_in_flight &&
854 (!has_body_ || total_layout_blocking_count_ != 0) &&
855 // Do not allow a low priority request through in parallel if
856 // we are in a limit field trial.
857 (scheduler_->limit_outstanding_requests() ||
858 in_flight_delayable_count_ != 0)) {
859 return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
860 }
795 } 861 }
796 862
797 return START_REQUEST; 863 return START_REQUEST;
798 } 864 }
799 865
800 void LoadAnyStartablePendingRequests() { 866 void LoadAnyStartablePendingRequests() {
801 // We iterate through all the pending requests, starting with the highest 867 // We iterate through all the pending requests, starting with the highest
802 // priority one. For each entry, one of three things can happen: 868 // priority one. For each entry, one of three things can happen:
803 // 1) We start the request, remove it from the list, and keep checking. 869 // 1) We start the request, remove it from the list, and keep checking.
804 // 2) We do NOT start the request, but ShouldStartRequest() signals us that 870 // 2) We do NOT start the request, but ShouldStartRequest() signals us that
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
844 RequestSet in_flight_requests_; 910 RequestSet in_flight_requests_;
845 base::TimeTicks load_started_time_; 911 base::TimeTicks load_started_time_;
846 // The last time the client switched state between active and background. 912 // The last time the client switched state between active and background.
847 base::TimeTicks last_active_switch_time_; 913 base::TimeTicks last_active_switch_time_;
848 ResourceScheduler* scheduler_; 914 ResourceScheduler* scheduler_;
849 // The number of delayable in-flight requests. 915 // The number of delayable in-flight requests.
850 size_t in_flight_delayable_count_; 916 size_t in_flight_delayable_count_;
851 // The number of layout-blocking in-flight requests. 917 // The number of layout-blocking in-flight requests.
852 size_t total_layout_blocking_count_; 918 size_t total_layout_blocking_count_;
853 ResourceScheduler::ClientThrottleState throttle_state_; 919 ResourceScheduler::ClientThrottleState throttle_state_;
920 int fetch_mode_;
854 }; 921 };
855 922
856 ResourceScheduler::ResourceScheduler() 923 ResourceScheduler::ResourceScheduler()
857 : should_coalesce_(false), 924 : should_coalesce_(false),
858 should_throttle_(false), 925 should_throttle_(false),
859 active_clients_loading_(0), 926 active_clients_loading_(0),
860 coalesced_clients_(0), 927 coalesced_clients_(0),
861 limit_outstanding_requests_(false), 928 limit_outstanding_requests_(false),
862 outstanding_request_limit_(0), 929 outstanding_request_limit_(0),
930 fetch_mode_(0),
863 coalescing_timer_(new base::Timer(true /* retain_user_task */, 931 coalescing_timer_(new base::Timer(true /* retain_user_task */,
864 true /* is_repeating */)) { 932 true /* is_repeating */)) {
865 std::string throttling_trial_group = 933 std::string throttling_trial_group =
866 base::FieldTrialList::FindFullName(kThrottleCoalesceFieldTrial); 934 base::FieldTrialList::FindFullName(kThrottleCoalesceFieldTrial);
867 if (throttling_trial_group == kThrottleCoalesceFieldTrialThrottle) { 935 if (throttling_trial_group == kThrottleCoalesceFieldTrialThrottle) {
868 should_throttle_ = true; 936 should_throttle_ = true;
869 } else if (throttling_trial_group == kThrottleCoalesceFieldTrialCoalesce) { 937 } else if (throttling_trial_group == kThrottleCoalesceFieldTrialCoalesce) {
870 should_coalesce_ = true; 938 should_coalesce_ = true;
871 should_throttle_ = true; 939 should_throttle_ = true;
872 } 940 }
873 941
874 std::string outstanding_limit_trial_group = 942 std::string outstanding_limit_trial_group =
875 base::FieldTrialList::FindFullName(kRequestLimitFieldTrial); 943 base::FieldTrialList::FindFullName(kRequestLimitFieldTrial);
876 std::vector<std::string> split_group( 944 std::vector<std::string> split_group(
877 base::SplitString(outstanding_limit_trial_group, "=", 945 base::SplitString(outstanding_limit_trial_group, "=",
878 base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL)); 946 base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL));
879 int outstanding_limit = 0; 947 int outstanding_limit = 0;
880 if (split_group.size() == 2 && 948 if (split_group.size() == 2 &&
881 split_group[0] == kRequestLimitFieldTrialGroupPrefix && 949 split_group[0] == kRequestLimitFieldTrialGroupPrefix &&
882 base::StringToInt(split_group[1], &outstanding_limit) && 950 base::StringToInt(split_group[1], &outstanding_limit) &&
883 outstanding_limit > 0) { 951 outstanding_limit > 0) {
884 limit_outstanding_requests_ = true; 952 limit_outstanding_requests_ = true;
885 outstanding_request_limit_ = outstanding_limit; 953 outstanding_request_limit_ = outstanding_limit;
886 } 954 }
955
956 std::string fetch_mode_cmd =
957 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
958 switches::kFetchMode);
959 if (!fetch_mode_cmd.empty()) {
960 int temp;
961 if (base::StringToInt(fetch_mode_cmd, &temp))
962 fetch_mode_ = temp;
963 }
887 } 964 }
888 965
889 ResourceScheduler::~ResourceScheduler() { 966 ResourceScheduler::~ResourceScheduler() {
890 DCHECK(unowned_requests_.empty()); 967 DCHECK(unowned_requests_.empty());
891 DCHECK(client_map_.empty()); 968 DCHECK(client_map_.empty());
892 } 969 }
893 970
894 void ResourceScheduler::SetThrottleOptionsForTesting(bool should_throttle, 971 void ResourceScheduler::SetThrottleOptionsForTesting(bool should_throttle,
895 bool should_coalesce) { 972 bool should_coalesce) {
896 should_coalesce_ = should_coalesce; 973 should_coalesce_ = should_coalesce;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
950 } 1027 }
951 1028
952 void ResourceScheduler::OnClientCreated(int child_id, 1029 void ResourceScheduler::OnClientCreated(int child_id,
953 int route_id, 1030 int route_id,
954 bool is_visible, 1031 bool is_visible,
955 bool is_audible) { 1032 bool is_audible) {
956 DCHECK(CalledOnValidThread()); 1033 DCHECK(CalledOnValidThread());
957 ClientId client_id = MakeClientId(child_id, route_id); 1034 ClientId client_id = MakeClientId(child_id, route_id);
958 DCHECK(!ContainsKey(client_map_, client_id)); 1035 DCHECK(!ContainsKey(client_map_, client_id));
959 1036
960 Client* client = new Client(this, is_visible, is_audible); 1037 Client* client = new Client(this, is_visible, is_audible, fetch_mode_);
961 client_map_[client_id] = client; 1038 client_map_[client_id] = client;
962 1039
963 client->UpdateThrottleState(); 1040 client->UpdateThrottleState();
964 } 1041 }
965 1042
966 void ResourceScheduler::OnClientDeleted(int child_id, int route_id) { 1043 void ResourceScheduler::OnClientDeleted(int child_id, int route_id) {
967 DCHECK(CalledOnValidThread()); 1044 DCHECK(CalledOnValidThread());
968 ClientId client_id = MakeClientId(child_id, route_id); 1045 ClientId client_id = MakeClientId(child_id, route_id);
969 DCHECK(ContainsKey(client_map_, client_id)); 1046 DCHECK(ContainsKey(client_map_, client_id));
970 ClientMap::iterator it = client_map_.find(client_id); 1047 ClientMap::iterator it = client_map_.find(client_id);
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
1180 NOTREACHED(); 1257 NOTREACHED();
1181 return; 1258 return;
1182 } 1259 }
1183 RequestPriorityParams new_priority_params(new_priority, 1260 RequestPriorityParams new_priority_params(new_priority,
1184 new_intra_priority_value); 1261 new_intra_priority_value);
1185 RequestPriorityParams old_priority_params = 1262 RequestPriorityParams old_priority_params =
1186 request->get_request_priority_params(); 1263 request->get_request_priority_params();
1187 1264
1188 DCHECK(old_priority_params != new_priority_params); 1265 DCHECK(old_priority_params != new_priority_params);
1189 1266
1267 // only allow priority promotions
1268 if (fetch_mode_ == 2 && old_priority_params.GreaterThan(new_priority_params))
Bryan McQuade 2015/07/29 17:53:47 are there cases where we demote priorities today?
Pat Meenan 2015/08/07 15:53:53 I'll debug this case separately and not make it pa
1269 return;
1270
1190 ClientMap::iterator client_it = client_map_.find(request->client_id()); 1271 ClientMap::iterator client_it = client_map_.find(request->client_id());
1191 if (client_it == client_map_.end()) { 1272 if (client_it == client_map_.end()) {
1192 // The client was likely deleted shortly before we received this IPC. 1273 // The client was likely deleted shortly before we received this IPC.
1193 request->url_request()->SetPriority(new_priority_params.priority); 1274 request->url_request()->SetPriority(new_priority_params.priority);
1194 request->set_request_priority_params(new_priority_params); 1275 request->set_request_priority_params(new_priority_params);
1195 return; 1276 return;
1196 } 1277 }
1197 1278
1198 if (old_priority_params == new_priority_params) 1279 if (old_priority_params == new_priority_params)
1199 return; 1280 return;
1200 1281
1201 Client *client = client_it->second; 1282 Client *client = client_it->second;
1202 client->ReprioritizeRequest( 1283 client->ReprioritizeRequest(
1203 request, old_priority_params, new_priority_params); 1284 request, old_priority_params, new_priority_params);
1204 } 1285 }
1205 1286
1206 ResourceScheduler::ClientId ResourceScheduler::MakeClientId( 1287 ResourceScheduler::ClientId ResourceScheduler::MakeClientId(
1207 int child_id, int route_id) { 1288 int child_id, int route_id) {
1208 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id; 1289 return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id;
1209 } 1290 }
1210 1291
1211 } // namespace content 1292 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/loader/resource_scheduler.h ('k') | content/public/common/content_switches.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698