|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef NET_HTTP_HTTP_NETWORK_TRANSACTION_H_ | 
|  | #define NET_HTTP_HTTP_NETWORK_TRANSACTION_H_ | 
|  |  | 
|  | #include <string> | 
|  |  | 
|  | #include "base/basictypes.h" | 
|  | #include "base/gtest_prod_util.h" | 
|  | #include "base/memory/ref_counted.h" | 
|  | #include "base/memory/scoped_ptr.h" | 
|  | #include "base/time.h" | 
|  | #include "net/base/net_log.h" | 
|  | #include "net/base/request_priority.h" | 
|  | #include "net/base/ssl_config_service.h" | 
|  | #include "net/http/http_auth.h" | 
|  | #include "net/http/http_request_headers.h" | 
|  | #include "net/http/http_response_info.h" | 
|  | #include "net/http/http_stream_factory.h" | 
|  | #include "net/http/http_transaction.h" | 
|  | #include "net/proxy/proxy_service.h" | 
|  |  | 
|  | namespace net { | 
|  |  | 
|  | class HttpAuthController; | 
|  | class HttpNetworkSession; | 
|  | class HttpStreamBase; | 
|  | class HttpStreamRequest; | 
|  | class IOBuffer; | 
|  | struct HttpRequestInfo; | 
|  |  | 
|  | class NET_EXPORT_PRIVATE HttpNetworkTransaction | 
|  | : public HttpTransaction, | 
|  | public HttpStreamRequest::Delegate { | 
|  | public: | 
|  | explicit HttpNetworkTransaction(HttpNetworkSession* session); | 
|  |  | 
|  | virtual ~HttpNetworkTransaction(); | 
|  |  | 
|  | // HttpTransaction methods: | 
|  | virtual int Start(const HttpRequestInfo* request_info, | 
|  | const CompletionCallback& callback, | 
|  | const BoundNetLog& net_log) OVERRIDE; | 
|  | virtual int RestartIgnoringLastError( | 
|  | const CompletionCallback& callback) OVERRIDE; | 
|  | virtual int RestartWithCertificate( | 
|  | X509Certificate* client_cert, | 
|  | const CompletionCallback& callback) OVERRIDE; | 
|  | virtual int RestartWithAuth(const AuthCredentials& credentials, | 
|  | const CompletionCallback& callback) OVERRIDE; | 
|  | virtual bool IsReadyToRestartForAuth() OVERRIDE; | 
|  |  | 
|  | virtual int Read(IOBuffer* buf, | 
|  | int buf_len, | 
|  | const CompletionCallback& callback) OVERRIDE; | 
|  | virtual void StopCaching() OVERRIDE {} | 
|  | virtual void DoneReading() OVERRIDE {} | 
|  | virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE; | 
|  | virtual LoadState GetLoadState() const OVERRIDE; | 
|  | virtual UploadProgress GetUploadProgress() const OVERRIDE; | 
|  |  | 
|  | // HttpStreamRequest::Delegate methods: | 
|  | virtual void OnStreamReady(const SSLConfig& used_ssl_config, | 
|  | const ProxyInfo& used_proxy_info, | 
|  | HttpStreamBase* stream) OVERRIDE; | 
|  | virtual void OnStreamFailed(int status, | 
|  | const SSLConfig& used_ssl_config) OVERRIDE; | 
|  | virtual void OnCertificateError(int status, | 
|  | const SSLConfig& used_ssl_config, | 
|  | const SSLInfo& ssl_info) OVERRIDE; | 
|  | virtual void OnNeedsProxyAuth( | 
|  | const HttpResponseInfo& response_info, | 
|  | const SSLConfig& used_ssl_config, | 
|  | const ProxyInfo& used_proxy_info, | 
|  | HttpAuthController* auth_controller) OVERRIDE; | 
|  | virtual void OnNeedsClientAuth(const SSLConfig& used_ssl_config, | 
|  | SSLCertRequestInfo* cert_info) OVERRIDE; | 
|  | virtual void OnHttpsProxyTunnelResponse(const HttpResponseInfo& response_info, | 
|  | const SSLConfig& used_ssl_config, | 
|  | const ProxyInfo& used_proxy_info, | 
|  | HttpStreamBase* stream) OVERRIDE; | 
|  |  | 
|  | private: | 
|  | FRIEND_TEST_ALL_PREFIXES(HttpNetworkTransactionSpdy2Test, | 
|  | ResetStateForRestart); | 
|  | FRIEND_TEST_ALL_PREFIXES(HttpNetworkTransactionSpdy3Test, | 
|  | ResetStateForRestart); | 
|  | FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionSpdy2Test, | 
|  | WindowUpdateReceived); | 
|  | FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionSpdy2Test, | 
|  | WindowUpdateSent); | 
|  | FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionSpdy2Test, | 
|  | WindowUpdateOverflow); | 
|  | FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionSpdy2Test, | 
|  | FlowControlStallResume); | 
|  | FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionSpdy3Test, | 
|  | WindowUpdateReceived); | 
|  | FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionSpdy3Test, | 
|  | WindowUpdateSent); | 
|  | FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionSpdy3Test, | 
|  | WindowUpdateOverflow); | 
|  | FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionSpdy3Test, | 
|  | FlowControlStallResume); | 
|  | FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionSpdy3Test, | 
|  | FlowControlStallResumeAfterSettings); | 
|  | FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionSpdy3Test, | 
|  | FlowControlNegativeSendWindowSize); | 
|  |  | 
|  | enum State { | 
|  | STATE_CREATE_STREAM, | 
|  | STATE_CREATE_STREAM_COMPLETE, | 
|  | STATE_INIT_STREAM, | 
|  | STATE_INIT_STREAM_COMPLETE, | 
|  | STATE_GENERATE_PROXY_AUTH_TOKEN, | 
|  | STATE_GENERATE_PROXY_AUTH_TOKEN_COMPLETE, | 
|  | STATE_GENERATE_SERVER_AUTH_TOKEN, | 
|  | STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE, | 
|  | STATE_INIT_REQUEST_BODY, | 
|  | STATE_INIT_REQUEST_BODY_COMPLETE, | 
|  | STATE_BUILD_REQUEST, | 
|  | STATE_BUILD_REQUEST_COMPLETE, | 
|  | STATE_SEND_REQUEST, | 
|  | STATE_SEND_REQUEST_COMPLETE, | 
|  | STATE_READ_HEADERS, | 
|  | STATE_READ_HEADERS_COMPLETE, | 
|  | STATE_READ_BODY, | 
|  | STATE_READ_BODY_COMPLETE, | 
|  | STATE_DRAIN_BODY_FOR_AUTH_RESTART, | 
|  | STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE, | 
|  | STATE_NONE | 
|  | }; | 
|  |  | 
|  | bool is_https_request() const; | 
|  |  | 
|  | void DoCallback(int result); | 
|  | void OnIOComplete(int result); | 
|  |  | 
|  | // Runs the state transition loop. | 
|  | int DoLoop(int result); | 
|  |  | 
|  | // Each of these methods corresponds to a State value.  Those with an input | 
|  | // argument receive the result from the previous state.  If a method returns | 
|  | // ERR_IO_PENDING, then the result from OnIOComplete will be passed to the | 
|  | // next state method as the result arg. | 
|  | int DoCreateStream(); | 
|  | int DoCreateStreamComplete(int result); | 
|  | int DoInitStream(); | 
|  | int DoInitStreamComplete(int result); | 
|  | int DoGenerateProxyAuthToken(); | 
|  | int DoGenerateProxyAuthTokenComplete(int result); | 
|  | int DoGenerateServerAuthToken(); | 
|  | int DoGenerateServerAuthTokenComplete(int result); | 
|  | int DoInitRequestBody(); | 
|  | int DoInitRequestBodyComplete(int result); | 
|  | int DoBuildRequest(); | 
|  | int DoBuildRequestComplete(int result); | 
|  | int DoSendRequest(); | 
|  | int DoSendRequestComplete(int result); | 
|  | int DoReadHeaders(); | 
|  | int DoReadHeadersComplete(int result); | 
|  | int DoReadBody(); | 
|  | int DoReadBodyComplete(int result); | 
|  | int DoDrainBodyForAuthRestart(); | 
|  | int DoDrainBodyForAuthRestartComplete(int result); | 
|  |  | 
|  | void BuildRequestHeaders(bool using_proxy); | 
|  |  | 
|  | // Record histogram of time until first byte of header is received. | 
|  | void LogTransactionConnectedMetrics(); | 
|  |  | 
|  | // Record histogram of latency (durations until last byte received). | 
|  | void LogTransactionMetrics() const; | 
|  |  | 
|  | // Writes a log message to help debugging in the field when we block a proxy | 
|  | // response to a CONNECT request. | 
|  | void LogBlockedTunnelResponse(int response_code) const; | 
|  |  | 
|  | // Called to handle a client certificate request. | 
|  | int HandleCertificateRequest(int error); | 
|  |  | 
|  | // Called to possibly recover from an SSL handshake error.  Sets next_state_ | 
|  | // and returns OK if recovering from the error.  Otherwise, the same error | 
|  | // code is returned. | 
|  | int HandleSSLHandshakeError(int error); | 
|  |  | 
|  | // Called to possibly recover from the given error.  Sets next_state_ and | 
|  | // returns OK if recovering from the error.  Otherwise, the same error code | 
|  | // is returned. | 
|  | int HandleIOError(int error); | 
|  |  | 
|  | // Gets the response headers from the HttpStream. | 
|  | HttpResponseHeaders* GetResponseHeaders() const; | 
|  |  | 
|  | // Called when we reached EOF or got an error.  Returns true if we should | 
|  | // resend the request.  |error| is OK when we reached EOF. | 
|  | bool ShouldResendRequest(int error) const; | 
|  |  | 
|  | // Resets the connection and the request headers for resend.  Called when | 
|  | // ShouldResendRequest() is true. | 
|  | void ResetConnectionAndRequestForResend(); | 
|  |  | 
|  | // Decides the policy when the connection is closed before the end of headers | 
|  | // has been read. This only applies to reading responses, and not writing | 
|  | // requests. | 
|  | int HandleConnectionClosedBeforeEndOfHeaders(); | 
|  |  | 
|  | // Sets up the state machine to restart the transaction with auth. | 
|  | void PrepareForAuthRestart(HttpAuth::Target target); | 
|  |  | 
|  | // Called when we don't need to drain the response body or have drained it. | 
|  | // Resets |connection_| unless |keep_alive| is true, then calls | 
|  | // ResetStateForRestart.  Sets |next_state_| appropriately. | 
|  | void DidDrainBodyForAuthRestart(bool keep_alive); | 
|  |  | 
|  | // Resets the members of the transaction so it can be restarted. | 
|  | void ResetStateForRestart(); | 
|  |  | 
|  | // Resets the members of the transaction, except |stream_|, which needs | 
|  | // to be maintained for multi-round auth. | 
|  | void ResetStateForAuthRestart(); | 
|  |  | 
|  | // Returns true if we should try to add a Proxy-Authorization header | 
|  | bool ShouldApplyProxyAuth() const; | 
|  |  | 
|  | // Returns true if we should try to add an Authorization header. | 
|  | bool ShouldApplyServerAuth() const; | 
|  |  | 
|  | // Handles HTTP status code 401 or 407. | 
|  | // HandleAuthChallenge() returns a network error code, or OK on success. | 
|  | // May update |pending_auth_target_| or |response_.auth_challenge|. | 
|  | int HandleAuthChallenge(); | 
|  |  | 
|  | // Returns true if we have auth credentials for the given target. | 
|  | bool HaveAuth(HttpAuth::Target target) const; | 
|  |  | 
|  | // Get the {scheme, host, path, port} for the authentication target | 
|  | GURL AuthURL(HttpAuth::Target target) const; | 
|  |  | 
|  | // Debug helper. | 
|  | static std::string DescribeState(State state); | 
|  |  | 
|  | scoped_refptr<HttpAuthController> | 
|  | auth_controllers_[HttpAuth::AUTH_NUM_TARGETS]; | 
|  |  | 
|  | // Whether this transaction is waiting for proxy auth, server auth, or is | 
|  | // not waiting for any auth at all. |pending_auth_target_| is read and | 
|  | // cleared by RestartWithAuth(). | 
|  | HttpAuth::Target pending_auth_target_; | 
|  |  | 
|  | CompletionCallback io_callback_; | 
|  | CompletionCallback callback_; | 
|  |  | 
|  | scoped_refptr<HttpNetworkSession> session_; | 
|  |  | 
|  | BoundNetLog net_log_; | 
|  | const HttpRequestInfo* request_; | 
|  | HttpResponseInfo response_; | 
|  |  | 
|  | // |proxy_info_| is the ProxyInfo used by the HttpStreamRequest. | 
|  | ProxyInfo proxy_info_; | 
|  |  | 
|  | scoped_ptr<HttpStreamRequest> stream_request_; | 
|  | scoped_ptr<HttpStreamBase> stream_; | 
|  |  | 
|  | // True if we've validated the headers that the stream parser has returned. | 
|  | bool headers_valid_; | 
|  |  | 
|  | // True if we've logged the time of the first response byte.  Used to | 
|  | // prevent logging across authentication activity where we see multiple | 
|  | // responses. | 
|  | bool logged_response_time_; | 
|  |  | 
|  | SSLConfig server_ssl_config_; | 
|  | SSLConfig proxy_ssl_config_; | 
|  |  | 
|  | HttpRequestHeaders request_headers_; | 
|  |  | 
|  | // The size in bytes of the buffer we use to drain the response body that | 
|  | // we want to throw away.  The response body is typically a small error | 
|  | // page just a few hundred bytes long. | 
|  | static const int kDrainBodyBufferSize = 1024; | 
|  |  | 
|  | // User buffer and length passed to the Read method. | 
|  | scoped_refptr<IOBuffer> read_buf_; | 
|  | int read_buf_len_; | 
|  |  | 
|  | // The time the Start method was called. | 
|  | base::Time start_time_; | 
|  |  | 
|  | // The next state in the state machine. | 
|  | State next_state_; | 
|  |  | 
|  | // True when the tunnel is in the process of being established - we can't | 
|  | // read from the socket until the tunnel is done. | 
|  | bool establishing_tunnel_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(HttpNetworkTransaction); | 
|  | }; | 
|  |  | 
|  | }  // namespace net | 
|  |  | 
|  | #endif  // NET_HTTP_HTTP_NETWORK_TRANSACTION_H_ |