summaryrefslogtreecommitdiffstats
path: root/net/http/http_stream_request.h
blob: 62ba5d86493079713eb23da8b89837f5ee0d84c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
// Copyright (c) 2010 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_STREAM_REQUEST_H_
#define NET_HTTP_HTTP_STREAM_REQUEST_H_

#include "base/scoped_ptr.h"
#include "base/task.h"
#include "net/base/completion_callback.h"
#include "net/base/host_mapping_rules.h"
#include "net/base/ssl_config_service.h"
#include "net/http/http_auth.h"
#include "net/http/http_auth_controller.h"
#include "net/http/http_alternate_protocols.h"
#include "net/http/stream_factory.h"
#include "net/proxy/proxy_service.h"
#include "net/socket/client_socket_handle.h"

namespace net {

class ClientSocketHandle;
class HttpAuthController;
class HttpNetworkSession;
class HttpProxySocketParams;
class SOCKSSocketParams;
class SSLSocketParams;
class StreamRequestDelegate;
class TCPSocketParams;
struct HttpRequestInfo;

// An HttpStreamRequest exists for each stream which is in progress of being
// created for the StreamFactory.
class HttpStreamRequest : public StreamRequest {
 public:
  class PreconnectDelegate {
   public:
    virtual ~PreconnectDelegate() {}

    virtual void OnPreconnectsComplete(HttpStreamRequest* request,
                                       int result) = 0;
  };

  HttpStreamRequest(StreamFactory* factory,
                    HttpNetworkSession* session);
  virtual ~HttpStreamRequest();

  // Start initiates the process of creating a new HttpStream.
  // 3 parameters are passed in by reference.  The caller asserts that the
  // lifecycle of these parameters will remain valid until the stream is
  // created, failed, or destroyed.  In the first two cases, the delegate will
  // be called to notify completion of the request.
  void Start(const HttpRequestInfo* request_info,
             SSLConfig* ssl_config,
             ProxyInfo* proxy_info,
             Delegate* delegate,
             const BoundNetLog& net_log);

  int Preconnect(int num_streams,
                 const HttpRequestInfo* request_info,
                 SSLConfig* ssl_config,
                 ProxyInfo* proxy_info,
                 PreconnectDelegate* delegate,
                 const BoundNetLog& net_log);

  // StreamRequest interface
  virtual int RestartWithCertificate(X509Certificate* client_cert);
  virtual int RestartTunnelWithProxyAuth(const string16& username,
                                         const string16& password);
  virtual LoadState GetLoadState() const;

  virtual bool was_alternate_protocol_available() const;
  virtual bool was_npn_negotiated() const;
  virtual bool using_spdy() const;

 private:
  enum AlternateProtocolMode {
    kUnspecified,  // Unspecified, check HttpAlternateProtocols
    kUsingAlternateProtocol,  // Using an alternate protocol
    kDoNotUseAlternateProtocol,  // Failed to connect once, do not try again.
  };

  enum State {
    STATE_RESOLVE_PROXY,
    STATE_RESOLVE_PROXY_COMPLETE,
    STATE_INIT_CONNECTION,
    STATE_INIT_CONNECTION_COMPLETE,
    STATE_WAITING_USER_ACTION,
    STATE_RESTART_TUNNEL_AUTH,
    STATE_RESTART_TUNNEL_AUTH_COMPLETE,
    STATE_CREATE_STREAM,
    STATE_CREATE_STREAM_COMPLETE,
    STATE_DRAIN_BODY_FOR_AUTH_RESTART,
    STATE_DRAIN_BODY_FOR_AUTH_RESTART_COMPLETE,
    STATE_DONE,
    STATE_NONE
  };

  const HttpRequestInfo& request_info() const;
  ProxyInfo* proxy_info() const;
  SSLConfig* ssl_config() const;

  // Callbacks to the delegate.
  void OnStreamReadyCallback();
  void OnStreamFailedCallback(int result);
  void OnCertificateErrorCallback(int result, const SSLInfo& ssl_info);
  void OnNeedsProxyAuthCallback(const HttpResponseInfo& response_info,
                                HttpAuthController* auth_controller);
  void OnNeedsClientAuthCallback(SSLCertRequestInfo* cert_info);
  void OnHttpsProxyTunnelResponseCallback(const HttpResponseInfo& response_info,
                                          HttpStream* stream);
  void OnPreconnectsComplete(int result);

  void OnIOComplete(int result);
  int RunLoop(int result);
  int DoLoop(int result);
  int StartInternal(const HttpRequestInfo* request_info,
                    SSLConfig* ssl_config,
                    ProxyInfo* proxy_info,
                    const BoundNetLog& net_log);

  // 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 DoResolveProxy();
  int DoResolveProxyComplete(int result);
  int DoInitConnection();
  int DoInitConnectionComplete(int result);
  int DoWaitingUserAction(int result);
  int DoCreateStream();
  int DoCreateStreamComplete(int result);
  int DoRestartTunnelAuth();
  int DoRestartTunnelAuthComplete(int result);

  // Set the motivation for this request onto the underlying socket.
  void SetSocketMotivation();

  bool IsHttpsProxyAndHttpUrl();

  // Returns a newly create SSLSocketParams, and sets several
  // fields of ssl_config_.
  scoped_refptr<SSLSocketParams> GenerateSSLParams(
      scoped_refptr<TCPSocketParams> tcp_params,
      scoped_refptr<HttpProxySocketParams> http_proxy_params,
      scoped_refptr<SOCKSSocketParams> socks_params,
      ProxyServer::Scheme proxy_scheme,
      const HostPortPair& host_and_port,
      bool want_spdy_over_npn);

  // AlternateProtocol API
  void MarkBrokenAlternateProtocolAndFallback();

  // Retrieve SSLInfo from our SSL Socket.
  // This must only be called when we are using an SSLSocket.
  // After calling, the caller can use ssl_info_.
  void GetSSLInfo();

  // Called when we encounter a network error that could be resolved by trying
  // a new proxy configuration.  If there is another proxy configuration to try
  // then this method sets next_state_ appropriately and returns either OK or
  // ERR_IO_PENDING depending on whether or not the new proxy configuration is
  // available synchronously or asynchronously.  Otherwise, the given error
  // code is simply returned.
  int ReconsiderProxyAfterError(int error);

  // Called to handle a certificate error.  Stores the certificate in the
  // allowed_bad_certs list, and checks if the error can be ignored.  Returns
  // OK if it can be ignored, or the error code otherwise.
  int HandleCertificateError(int error);

  // 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);

  // Moves this stream request into SPDY mode.
  void SwitchToSpdyMode();

  // Should we force SPDY to run over SSL for this stream request.
  bool ShouldForceSpdySSL();

  // Should we force SPDY to run without SSL for this stream request.
  bool ShouldForceSpdyWithoutSSL();

  // Record histograms of latency until Connect() completes.
  static void LogHttpConnectedMetrics(const ClientSocketHandle& handle);

  const HttpRequestInfo* request_info_;  // Use request_info().
  ProxyInfo* proxy_info_;  // Use proxy_info().
  SSLConfig* ssl_config_;  // Use ssl_config().

  scoped_refptr<HttpNetworkSession> session_;
  CompletionCallbackImpl<HttpStreamRequest> io_callback_;
  scoped_ptr<ClientSocketHandle> connection_;
  StreamFactory* const factory_;
  Delegate* delegate_;
  BoundNetLog net_log_;
  State next_state_;
  ProxyService::PacRequest* pac_request_;
  SSLInfo ssl_info_;
  // The hostname and port of the endpoint.  This is not necessarily the one
  // specified by the URL, due to Alternate-Protocol or fixed testing ports.
  HostPortPair endpoint_;

  // True if handling a HTTPS request, or using SPDY with SSL
  bool using_ssl_;

  // True if this network transaction is using SPDY instead of HTTP.
  bool using_spdy_;

  // Force spdy for all connections.
  bool force_spdy_always_;

  // Force spdy only for SSL connections.
  bool force_spdy_over_ssl_;

  // The certificate error while using SPDY over SSL for insecure URLs.
  int spdy_certificate_error_;

  scoped_refptr<HttpAuthController>
    auth_controllers_[HttpAuth::AUTH_NUM_TARGETS];

  AlternateProtocolMode alternate_protocol_mode_;

  // Only valid if |alternate_protocol_mode_| == kUsingAlternateProtocol.
  HttpAlternateProtocols::Protocol alternate_protocol_;

  // 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_;

  scoped_ptr<HttpStream> stream_;

  // True if finding the connection for this request found an alternate
  // protocol was available.
  bool was_alternate_protocol_available_;

  // True if we negotiated NPN.
  bool was_npn_negotiated_;

  PreconnectDelegate* preconnect_delegate_;

  // Only used if |preconnect_delegate_| is non-NULL.
  int num_streams_;

  ScopedRunnableMethodFactory<HttpStreamRequest> method_factory_;

  DISALLOW_COPY_AND_ASSIGN(HttpStreamRequest);
};

}  // namespace net

#endif  // NET_HTTP_HTTP_STREAM_REQUEST_H_