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

Side by Side Diff: net/http/http_stream_factory_impl_job_controller.cc

Issue 2260623002: Race TCP connection to proxies with QUIC connections (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 4 years, 3 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
OLDNEW
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2016 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 "net/http/http_stream_factory_impl_job_controller.h" 5 #include "net/http/http_stream_factory_impl_job_controller.h"
6 6
7 #include "base/metrics/histogram_macros.h" 7 #include "base/metrics/histogram_macros.h"
8 #include "base/strings/string_number_conversions.h" 8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_util.h" 9 #include "base/strings/string_util.h"
10 #include "base/values.h" 10 #include "base/values.h"
11 #include "net/base/host_mapping_rules.h" 11 #include "net/base/host_mapping_rules.h"
12 #include "net/base/proxy_delegate.h"
12 #include "net/http/bidirectional_stream_impl.h" 13 #include "net/http/bidirectional_stream_impl.h"
13 #include "net/http/transport_security_state.h" 14 #include "net/http/transport_security_state.h"
15 #include "net/proxy/proxy_server.h"
14 #include "net/spdy/spdy_session.h" 16 #include "net/spdy/spdy_session.h"
15 17
16 namespace net { 18 namespace net {
17 19
18 // Returns parameters associated with the delay of the HTTP stream job. 20 // Returns parameters associated with the delay of the HTTP stream job.
19 std::unique_ptr<base::Value> NetLogHttpStreamJobDelayCallback( 21 std::unique_ptr<base::Value> NetLogHttpStreamJobDelayCallback(
20 base::TimeDelta delay, 22 base::TimeDelta delay,
21 NetLogCaptureMode /* capture_mode */) { 23 NetLogCaptureMode /* capture_mode */) {
22 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); 24 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
23 dict->SetInteger("resume_after_ms", static_cast<int>(delay.InMilliseconds())); 25 dict->SetInteger("resume_after_ms", static_cast<int>(delay.InMilliseconds()));
24 return std::move(dict); 26 return std::move(dict);
25 } 27 }
26 28
27 HttpStreamFactoryImpl::JobController::JobController( 29 HttpStreamFactoryImpl::JobController::JobController(
28 HttpStreamFactoryImpl* factory, 30 HttpStreamFactoryImpl* factory,
29 HttpStreamRequest::Delegate* delegate, 31 HttpStreamRequest::Delegate* delegate,
30 HttpNetworkSession* session, 32 HttpNetworkSession* session,
31 JobFactory* job_factory) 33 JobFactory* job_factory)
32 : factory_(factory), 34 : factory_(factory),
33 session_(session), 35 session_(session),
34 job_factory_(job_factory), 36 job_factory_(job_factory),
35 request_(nullptr), 37 request_(nullptr),
36 delegate_(delegate), 38 delegate_(delegate),
37 is_preconnect_(false), 39 is_preconnect_(false),
38 job_bound_(false), 40 job_bound_(false),
39 main_job_is_blocked_(false), 41 main_job_is_blocked_(false),
40 bound_job_(nullptr), 42 bound_job_(nullptr),
43 can_start_alternative_proxy_job_(false),
41 ptr_factory_(this) { 44 ptr_factory_(this) {
42 DCHECK(factory); 45 DCHECK(factory);
43 } 46 }
44 47
45 HttpStreamFactoryImpl::JobController::~JobController() { 48 HttpStreamFactoryImpl::JobController::~JobController() {
46 main_job_.reset(); 49 main_job_.reset();
47 alternative_job_.reset(); 50 alternative_job_.reset();
48 bound_job_ = nullptr; 51 bound_job_ = nullptr;
49 } 52 }
50 53
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 } 351 }
349 352
350 if (!request_) 353 if (!request_)
351 return; 354 return;
352 if (!bound_job_) 355 if (!bound_job_)
353 BindJob(job); 356 BindJob(job);
354 request_->OnNeedsProxyAuth(proxy_response, used_ssl_config, used_proxy_info, 357 request_->OnNeedsProxyAuth(proxy_response, used_ssl_config, used_proxy_info,
355 auth_controller); 358 auth_controller);
356 } 359 }
357 360
361 void HttpStreamFactoryImpl::JobController::OnResolveProxyComplete(
362 Job* job,
363 const HttpRequestInfo& request_info,
364 RequestPriority priority,
365 const SSLConfig& server_ssl_config,
366 const SSLConfig& proxy_ssl_config,
367 HttpStreamRequest::StreamType stream_type) {
368 DCHECK(job);
369
370 ProxyServer alternative_proxy_server;
371 if (!ShouldCreateAlternativeProxyServerJob(job, job->proxy_info(),
372 request_info.url,
373 &alternative_proxy_server)) {
374 return;
375 }
376
377 DCHECK(main_job_);
378 DCHECK_EQ(MAIN, job->job_type());
379 DCHECK(!alternative_job_);
380 DCHECK(!main_job_is_blocked_);
381
382 HostPortPair destination(HostPortPair::FromURL(request_info.url));
383 GURL origin_url = ApplyHostMappingRules(request_info.url, &destination);
384
385 alternative_job_.reset(job_factory_->CreateJob(
386 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config,
387 proxy_ssl_config, destination, origin_url, alternative_proxy_server,
388 job->net_log().net_log()));
389 AttachJob(alternative_job_.get());
390
391 can_start_alternative_proxy_job_ = false;
392 main_job_is_blocked_ = true;
393
394 base::ThreadTaskRunnerHandle::Get()->PostTask(
395 FROM_HERE, base::Bind(&HttpStreamFactoryImpl::Job::Start,
396 base::Unretained(alternative_job_.get()),
397 request_->stream_type()));
398 }
399
358 void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady( 400 void HttpStreamFactoryImpl::JobController::OnNewSpdySessionReady(
359 Job* job, 401 Job* job,
360 const base::WeakPtr<SpdySession>& spdy_session, 402 const base::WeakPtr<SpdySession>& spdy_session,
361 bool direct) { 403 bool direct) {
362 DCHECK(job); 404 DCHECK(job);
363 DCHECK(job->using_spdy()); 405 DCHECK(job->using_spdy());
364 406
365 bool is_job_orphaned = job_bound_ && bound_job_ != job; 407 bool is_job_orphaned = job_bound_ && bound_job_ != job;
366 408
367 // Cache these values in case the job gets deleted. 409 // Cache these values in case the job gets deleted.
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 ApplyHostMappingRules(request_info.url, &alternative_destination)); 642 ApplyHostMappingRules(request_info.url, &alternative_destination));
601 643
602 alternative_job_.reset(job_factory_->CreateJob( 644 alternative_job_.reset(job_factory_->CreateJob(
603 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config, 645 this, ALTERNATIVE, session_, request_info, priority, server_ssl_config,
604 proxy_ssl_config, alternative_destination, origin_url, 646 proxy_ssl_config, alternative_destination, origin_url,
605 alternative_service, net_log.net_log())); 647 alternative_service, net_log.net_log()));
606 AttachJob(alternative_job_.get()); 648 AttachJob(alternative_job_.get());
607 649
608 main_job_is_blocked_ = true; 650 main_job_is_blocked_ = true;
609 alternative_job_->Start(request_->stream_type()); 651 alternative_job_->Start(request_->stream_type());
652 } else {
653 can_start_alternative_proxy_job_ = true;
610 } 654 }
611 // Even if |alternative_job| has already finished, it will not have notified 655 // Even if |alternative_job| has already finished, it will not have notified
612 // the request yet, since we defer that to the next iteration of the 656 // the request yet, since we defer that to the next iteration of the
613 // MessageLoop, so starting |main_job_| is always safe. 657 // MessageLoop, so starting |main_job_| is always safe.
614 main_job_->Start(request_->stream_type()); 658 main_job_->Start(request_->stream_type());
615 } 659 }
616 660
617 void HttpStreamFactoryImpl::JobController::AttachJob(Job* job) { 661 void HttpStreamFactoryImpl::JobController::AttachJob(Job* job) {
618 DCHECK(job); 662 DCHECK(job);
619 factory_->request_map_[job] = request_; 663 factory_->request_map_[job] = request_;
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
888 if (first_alternative_service.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) 932 if (first_alternative_service.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL)
889 first_alternative_service = alternative_service; 933 first_alternative_service = alternative_service;
890 } 934 }
891 935
892 // Ask delegate to mark QUIC as broken for the origin. 936 // Ask delegate to mark QUIC as broken for the origin.
893 if (quic_advertised && quic_all_broken && delegate != nullptr) 937 if (quic_advertised && quic_all_broken && delegate != nullptr)
894 delegate->OnQuicBroken(); 938 delegate->OnQuicBroken();
895 939
896 return first_alternative_service; 940 return first_alternative_service;
897 } 941 }
942
943 bool HttpStreamFactoryImpl::JobController::
944 ShouldCreateAlternativeProxyServerJob(
945 Job* job,
946 const ProxyInfo& proxy_info,
947 const GURL& url,
948 ProxyServer* alternative_proxy_server) const {
949 DCHECK(!alternative_proxy_server->is_valid());
950 if (!can_start_alternative_proxy_job_) {
951 // Either an alternative service job or an alternative proxy server job has
952 // already been started.
953 return false;
954 }
955
956 if (job->job_type() == ALTERNATIVE) {
957 // If |job| is using alternative service, then alternative proxy server
958 // should not be used.
959 return false;
960 }
961
962 if (job->job_type() == PRECONNECT) {
963 // Preconnects should be fetched using only the main job to keep the
964 // resource utilization down.
965 return false;
966 }
967
968 if (proxy_info.is_empty() || proxy_info.is_direct() || proxy_info.is_quic()) {
969 // Alternative proxy server job can be created only if |job| fetches the
970 // |request_| through a non-QUIC proxy.
971 return false;
972 }
973
974 if (!url.SchemeIs(url::kHttpScheme)) {
975 // Only HTTP URLs can be fetched through alternative proxy server, since the
976 // alternative proxy server may not support fetching of URLs with other
977 // schemes.
978 return false;
979 }
980
981 ProxyDelegate* proxy_delegate = session_->params().proxy_delegate;
982 if (!proxy_delegate)
983 return false;
984
985 proxy_delegate->GetAlternativeProxy(url, proxy_info.proxy_server(),
986 alternative_proxy_server);
987
988 if (!alternative_proxy_server->is_valid())
989 return false;
990
991 DCHECK(!(*alternative_proxy_server == proxy_info.proxy_server()));
992
993 if (!alternative_proxy_server->is_https() &&
994 !alternative_proxy_server->is_quic()) {
995 // Alternative proxy server should be a secure server.
996 return false;
997 }
998
999 if (alternative_proxy_server->is_quic()) {
1000 // Check that QUIC is enabled globally, and it is not disabled on
1001 // the specified port.
1002 if (!session_->params().enable_quic ||
1003 session_->quic_stream_factory()->IsQuicDisabled(
1004 alternative_proxy_server->host_port_pair().port())) {
1005 return false;
1006 }
1007 }
1008
1009 return true;
898 } 1010 }
1011 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698