1 // Copyright 2016 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_HTTP_HTTP_STREAM_FACTORY_JOB_CONTROLLER_H_ 6 #define NET_HTTP_HTTP_STREAM_FACTORY_JOB_CONTROLLER_H_ 7 8 #include <memory> 9 #include <string> 10 #include <vector> 11 12 #include "base/cancelable_callback.h" 13 #include "base/memory/raw_ptr.h" 14 #include "base/time/time.h" 15 #include "net/base/host_port_pair.h" 16 #include "net/base/net_errors.h" 17 #include "net/http/http_stream_factory_job.h" 18 #include "net/http/http_stream_request.h" 19 #include "net/spdy/spdy_session_pool.h" 20 #include "net/ssl/ssl_config.h" 21 #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" 22 23 namespace net { 24 25 class ProxyResolutionRequest; 26 27 namespace test { 28 29 class JobControllerPeer; 30 31 } // namespace test 32 33 // HttpStreamFactory::JobController manages Request and Job(s). 34 class HttpStreamFactory::JobController 35 : public HttpStreamFactory::Job::Delegate, 36 public HttpStreamRequest::Helper { 37 public: 38 JobController(HttpStreamFactory* factory, 39 HttpStreamRequest::Delegate* delegate, 40 HttpNetworkSession* session, 41 JobFactory* job_factory, 42 const HttpRequestInfo& http_request_info, 43 bool is_preconnect, 44 bool is_websocket, 45 bool enable_ip_based_pooling, 46 bool enable_alternative_services, 47 bool delay_main_job_with_available_spdy_session, 48 const std::vector<SSLConfig::CertAndStatus>& allowed_bad_certs); 49 50 ~JobController() override; 51 52 // Used in tests only for verification purpose. main_job()53 const Job* main_job() const { return main_job_.get(); } alternative_job()54 const Job* alternative_job() const { return alternative_job_.get(); } dns_alpn_h3_job()55 const Job* dns_alpn_h3_job() const { return dns_alpn_h3_job_.get(); } 56 57 // Modifies `url` in-place, applying any applicable HostMappingRules of 58 // `session_` to it. 59 void RewriteUrlWithHostMappingRules(GURL& url) const; 60 61 // Same as RewriteUrlWithHostMappingRules(), but duplicates `url` instead of 62 // modifying it. 63 GURL DuplicateUrlWithHostMappingRules(const GURL& url) const; 64 65 // Methods below are called by HttpStreamFactory only. 66 // Creates request and hands out to HttpStreamFactory, this will also create 67 // Job(s) and start serving the created request. 68 std::unique_ptr<HttpStreamRequest> Start( 69 HttpStreamRequest::Delegate* delegate, 70 WebSocketHandshakeStreamBase::CreateHelper* 71 websocket_handshake_stream_create_helper, 72 const NetLogWithSource& source_net_log, 73 HttpStreamRequest::StreamType stream_type, 74 RequestPriority priority); 75 76 void Preconnect(int num_streams); 77 78 // From HttpStreamRequest::Helper. 79 // Returns the LoadState for Request. 80 LoadState GetLoadState() const override; 81 82 // Called when Request is destructed. Job(s) associated with but not bound to 83 // |request_| will be deleted. |request_| and |bound_job_| will be nulled if 84 // ever set. 85 void OnRequestComplete() override; 86 87 // Called to resume the HttpStream creation process when necessary 88 // Proxy authentication credentials are collected. 89 int RestartTunnelWithProxyAuth() override; 90 91 // Called when the priority of transaction changes. 92 void SetPriority(RequestPriority priority) override; 93 94 // From HttpStreamFactory::Job::Delegate. 95 // Invoked when |job| has an HttpStream ready. 96 void OnStreamReady(Job* job) override; 97 98 // Invoked when |job| has a BidirectionalStream ready. 99 void OnBidirectionalStreamImplReady( 100 Job* job, 101 const ProxyInfo& used_proxy_info) override; 102 103 // Invoked when |job| has a WebSocketHandshakeStream ready. 104 void OnWebSocketHandshakeStreamReady( 105 Job* job, 106 const ProxyInfo& used_proxy_info, 107 std::unique_ptr<WebSocketHandshakeStreamBase> stream) override; 108 109 // Invoked when a QUIC job finished a DNS resolution. 110 void OnQuicHostResolution(const url::SchemeHostPort& destination, 111 base::TimeTicks dns_resolution_start_time, 112 base::TimeTicks dns_resolution_end_time) override; 113 114 // Invoked when |job| fails to create a stream. 115 void OnStreamFailed(Job* job, int status) override; 116 117 // Invoked when |job| fails on the default network. 118 void OnFailedOnDefaultNetwork(Job* job) override; 119 120 // Invoked when |job| has a certificate error for the Request. 121 void OnCertificateError(Job* job, 122 int status, 123 const SSLInfo& ssl_info) override; 124 125 // Invoked when |job| raises failure for SSL Client Auth. 126 void OnNeedsClientAuth(Job* job, SSLCertRequestInfo* cert_info) override; 127 128 // Invoked when |job| needs proxy authentication. 129 void OnNeedsProxyAuth(Job* job, 130 const HttpResponseInfo& proxy_response, 131 const ProxyInfo& used_proxy_info, 132 HttpAuthController* auth_controller) override; 133 134 // Invoked when the |job| finishes pre-connecting sockets. 135 void OnPreconnectsComplete(Job* job, int result) override; 136 137 // Invoked to record connection attempts made by the socket layer to 138 // Request if |job| is associated with Request. 139 void AddConnectionAttemptsToRequest( 140 Job* job, 141 const ConnectionAttempts& attempts) override; 142 143 // Invoked when |job| finishes initiating a connection. 144 // Resume the other job if there's an error raised. 145 void OnConnectionInitialized(Job* job, int rv) override; 146 147 // Return false if |job| can advance to the next state. Otherwise, |job| 148 // will wait for Job::Resume() to be called before advancing. 149 bool ShouldWait(Job* job) override; 150 151 const NetLogWithSource* GetNetLog() const override; 152 153 void MaybeSetWaitTimeForMainJob(const base::TimeDelta& delay) override; 154 155 WebSocketHandshakeStreamBase::CreateHelper* 156 websocket_handshake_stream_create_helper() override; 157 is_preconnect()158 bool is_preconnect() const { return is_preconnect_; } 159 160 // Returns true if |this| has a pending request that is not completed. HasPendingRequest()161 bool HasPendingRequest() const { return request_ != nullptr; } 162 163 // Returns true if |this| has a pending main job that is not completed. 164 bool HasPendingMainJob() const; 165 166 // Returns true if |this| has a pending alternative job that is not completed. 167 bool HasPendingAltJob() const; 168 get_main_job_wait_time_for_tests()169 base::TimeDelta get_main_job_wait_time_for_tests() { 170 return main_job_wait_time_; 171 } 172 173 private: 174 friend class test::JobControllerPeer; 175 176 enum State { 177 STATE_RESOLVE_PROXY, 178 STATE_RESOLVE_PROXY_COMPLETE, 179 STATE_CREATE_JOBS, 180 STATE_NONE 181 }; 182 183 void OnIOComplete(int result); 184 185 void RunLoop(int result); 186 int DoLoop(int result); 187 int DoResolveProxy(); 188 int DoResolveProxyComplete(int result); 189 // Creates Job(s) for |request_info_|. Job(s) will be owned by |this|. 190 int DoCreateJobs(); 191 192 // Called to bind |job| to the |request_| and orphan all other jobs that are 193 // still associated with |request_|. 194 void BindJob(Job* job); 195 196 // Called after BindJob() to notify the unbound job that its result should be 197 // ignored by JobController. The unbound job can be canceled or continue until 198 // completion. 199 void OrphanUnboundJob(); 200 201 // Invoked when the orphaned |job| finishes. 202 void OnOrphanedJobComplete(const Job* job); 203 204 // Called when a Job succeeds. 205 void OnJobSucceeded(Job* job); 206 207 // Clears inappropriate jobs before starting them. 208 void ClearInappropriateJobs(); 209 210 // Marks completion of the |request_|. 211 void MarkRequestComplete(Job* job); 212 213 // Called when all Jobs complete. Reports alternative service brokenness to 214 // HttpServerProperties if apply and resets net errors afterwards: 215 // - report broken if the main job has no error and the alternative job has an 216 // error; 217 // - report broken until default network change if the main job has no error, 218 // the alternative job has no error, but the alternative job failed on the 219 // default network. 220 void MaybeReportBrokenAlternativeService( 221 const AlternativeService& alt_service, 222 int alt_job_net_error, 223 bool alt_job_failed_on_default_network, 224 const std::string& histogram_name_for_failure); 225 226 void MaybeNotifyFactoryOfCompletion(); 227 228 void NotifyRequestFailed(int rv); 229 230 // Called to resume the main job with delay. Main job is resumed only when 231 // |alternative_job_| has failed or |main_job_wait_time_| elapsed. 232 void MaybeResumeMainJob(Job* job, const base::TimeDelta& delay); 233 234 // Posts a task to resume the main job after |delay|. 235 void ResumeMainJobLater(const base::TimeDelta& delay); 236 237 // Resumes the main job immediately. 238 void ResumeMainJob(); 239 240 // Reset error status to default value for Jobs: 241 // - reset |main_job_net_error_| and |alternative_job_net_error_| and 242 // |dns_alpn_h3_job_net_error_| to OK; 243 // - reset |alternative_job_failed_on_default_network_| and 244 // |dns_alpn_h3_job_failed_on_default_network_| to false. 245 void ResetErrorStatusForJobs(); 246 247 AlternativeServiceInfo GetAlternativeServiceInfoFor( 248 const GURL& http_request_info_url, 249 const StreamRequestInfo& request_info, 250 HttpStreamRequest::Delegate* delegate, 251 HttpStreamRequest::StreamType stream_type); 252 253 AlternativeServiceInfo GetAlternativeServiceInfoInternal( 254 const GURL& http_request_info_url, 255 const StreamRequestInfo& request_info, 256 HttpStreamRequest::Delegate* delegate, 257 HttpStreamRequest::StreamType stream_type); 258 259 // Just calls QuicContext::SelectQuicVersion(). 260 quic::ParsedQuicVersion SelectQuicVersion( 261 const quic::ParsedQuicVersionVector& advertised_versions); 262 263 // Records histogram metrics for the usage of alternative protocol. Must be 264 // called when |job| has succeeded and the other job will be orphaned. 265 void ReportAlternateProtocolUsage( 266 AlternateProtocolUsage alternate_protocol_usage, 267 bool is_google_host) const; 268 269 // Returns whether |job| is an orphaned job. 270 bool IsJobOrphaned(Job* job) const; 271 272 // Calculates why Chrome uses a specific transport protocol for HTTP semantics 273 // and returns it as an enum. 274 // This returns ALTERNATE_PROTOCOL_USAGE_UNSPECIFIED_REASON as a default value 275 // when the reason is unknown. 276 AlternateProtocolUsage CalculateAlternateProtocolUsage(Job* job) const; 277 278 // Called when a Job encountered a network error that could be resolved by 279 // trying a new proxy configuration. If there is another proxy configuration 280 // to try then this method sets |next_state_| appropriately and returns either 281 // OK or ERR_IO_PENDING depending on whether or not the new proxy 282 // configuration is available synchronously or asynchronously. Otherwise, the 283 // given error code is simply returned. 284 int ReconsiderProxyAfterError(Job* job, int error); 285 286 // Returns true if QUIC is allowed for |host|. 287 bool IsQuicAllowedForHost(const std::string& host); 288 GetJobCount()289 int GetJobCount() const { 290 return (main_job_ ? 1 : 0) + (alternative_job_ ? 1 : 0) + 291 (dns_alpn_h3_job_ ? 1 : 0); 292 } 293 294 // Called when the request needs to use the HttpStreamPool instead of `this`. 295 // Call site of Start() should destroy the current HttpStreamRequest and 296 // switch to the HttpStreamPool. `this` will be destroyed when `request_` is 297 // destroyed. 298 void SwitchToHttpStreamPool(); 299 300 // Called when `this` asked the HttpStreamPool to handle a preconnect and 301 // the preconnect completed. Used to notify the factory of completion. 302 void OnPoolPreconnectsComplete(int rv); 303 304 // Used to call HttpStreamRequest::OnSwitchesToHttpStreamPool() later. 305 void CallOnSwitchesToHttpStreamPool(HttpStreamPoolRequestInfo request_info); 306 307 const raw_ptr<HttpStreamFactory> factory_; 308 const raw_ptr<HttpNetworkSession> session_; 309 const raw_ptr<JobFactory> job_factory_; 310 311 // Request will be handed out to factory once created. This just keeps an 312 // reference and is safe as |request_| will notify |this| JobController 313 // when it's destructed by calling OnRequestComplete(), which nulls 314 // |request_|. 315 raw_ptr<HttpStreamRequest> request_ = nullptr; 316 317 raw_ptr<HttpStreamRequest::Delegate> delegate_; 318 319 // True if this JobController is used to preconnect streams. 320 const bool is_preconnect_; 321 322 // True if request is for Websocket. 323 const bool is_websocket_; 324 325 // Enable pooling to a SpdySession with matching IP and certificate even if 326 // the SpdySessionKey is different. 327 const bool enable_ip_based_pooling_; 328 329 // Enable using alternative services for the request. If false, the 330 // JobController will only create a |main_job_|. 331 const bool enable_alternative_services_; 332 333 // For normal (non-preconnect) job, |main_job_| is a job waiting to see if 334 // |alternative_job_| or |dns_alpn_h3_job_| can reuse a connection. If both 335 // |alternative_job_| and |dns_alpn_h3_job_| are unable to do so, |this| will 336 // notify |main_job_| to proceed and then race the two jobs. 337 // For preconnect job, |main_job_| is started first, and if it fails with 338 // ERR_DNS_NO_MATCHING_SUPPORTED_ALPN, |preconnect_backup_job_| will be 339 // started. 340 std::unique_ptr<Job> main_job_; 341 std::unique_ptr<Job> alternative_job_; 342 std::unique_ptr<Job> dns_alpn_h3_job_; 343 344 std::unique_ptr<Job> preconnect_backup_job_; 345 346 // The alternative service used by |alternative_job_| 347 // (or by |main_job_| if |is_preconnect_|.) 348 AlternativeServiceInfo alternative_service_info_; 349 350 // Error status used for alternative service brokenness reporting. 351 // Net error code of the main job. Set to OK by default. 352 int main_job_net_error_ = OK; 353 // Net error code of the alternative job. Set to OK by default. 354 int alternative_job_net_error_ = OK; 355 // Set to true if the alternative job failed on the default network. 356 bool alternative_job_failed_on_default_network_ = false; 357 // Net error code of the DNS HTTPS ALPN job. Set to OK by default. 358 int dns_alpn_h3_job_net_error_ = OK; 359 // Set to true if the DNS HTTPS ALPN job failed on the default network. 360 bool dns_alpn_h3_job_failed_on_default_network_ = false; 361 362 // True if a Job has ever been bound to the |request_|. 363 bool job_bound_ = false; 364 365 // True if the main job has to wait for the alternative job: i.e., the main 366 // job must not create a connection until it is resumed. 367 bool main_job_is_blocked_ = false; 368 369 // Handle for cancelling any posted delayed ResumeMainJob() task. 370 base::CancelableOnceClosure resume_main_job_callback_; 371 // True if the main job was blocked and has been resumed in ResumeMainJob(). 372 bool main_job_is_resumed_ = false; 373 374 // If true, delay main job even the request can be sent immediately on an 375 // available SPDY session. 376 bool delay_main_job_with_available_spdy_session_; 377 378 // Set to true when `this` asked the request to use HttpStreamPool instead 379 // of `this`. 380 bool switched_to_http_stream_pool_ = false; 381 382 // Waiting time for the main job before it is resumed. 383 base::TimeDelta main_job_wait_time_; 384 385 // At the point where a Job is irrevocably tied to |request_|, we set this. 386 // It will be nulled when the |request_| is finished. 387 raw_ptr<Job> bound_job_ = nullptr; 388 389 State next_state_ = STATE_RESOLVE_PROXY; 390 std::unique_ptr<ProxyResolutionRequest> proxy_resolve_request_; 391 // The URL from the input `http_request_info`. 392 // TODO(https://crbug.com/332724851): Remove this, and update code to use 393 // `origin_url_`. 394 const GURL http_request_info_url_; 395 // The same as `request_info_url_`, but with any applicable rules in 396 // HostMappingRules applied to it. 397 // TODO: Make this use SchemeHostPort instead, and rename it. 398 const GURL origin_url_; 399 const StreamRequestInfo request_info_; 400 ProxyInfo proxy_info_; 401 const std::vector<SSLConfig::CertAndStatus> allowed_bad_certs_; 402 int num_streams_ = 0; 403 HttpStreamRequest::StreamType stream_type_; 404 RequestPriority priority_ = IDLE; 405 const NetLogWithSource net_log_; 406 407 base::WeakPtrFactory<JobController> ptr_factory_{this}; 408 }; 409 410 } // namespace net 411 412 #endif // NET_HTTP_HTTP_STREAM_FACTORY_JOB_CONTROLLER_H_ 413