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
3// found in the LICENSE file.
4
5#ifndef NET_WEBSOCKETS_WEBSOCKET_JOB_H_
6#define NET_WEBSOCKETS_WEBSOCKET_JOB_H_
7
8#include <deque>
9#include <string>
10#include <vector>
11
12#include "base/memory/weak_ptr.h"
13#include "net/base/address_list.h"
14#include "net/base/completion_callback.h"
15#include "net/socket_stream/socket_stream_job.h"
16#include "net/spdy/spdy_header_block.h"
17#include "net/spdy/spdy_websocket_stream.h"
18
19class GURL;
20
21namespace net {
22
23class DrainableIOBuffer;
24class SSLInfo;
25class WebSocketHandshakeRequestHandler;
26class WebSocketHandshakeResponseHandler;
27
28// WebSocket protocol specific job on SocketStream.
29// It captures WebSocket handshake message and handles cookie operations.
30// Chrome security policy doesn't allow renderer process (except dev tools)
31// see HttpOnly cookies, so it injects cookie header in handshake request and
32// strips set-cookie headers in handshake response.
33// TODO(ukai): refactor websocket.cc to use this.
34class NET_EXPORT WebSocketJob
35    : public SocketStreamJob,
36      public SocketStream::Delegate,
37      public SpdyWebSocketStream::Delegate {
38 public:
39  // This is state of WebSocket, not SocketStream.
40  enum State {
41    INITIALIZED = -1,
42    CONNECTING = 0,
43    OPEN = 1,
44    CLOSING = 2,
45    CLOSED = 3,
46  };
47
48  explicit WebSocketJob(SocketStream::Delegate* delegate);
49
50  static void EnsureInit();
51
52  State state() const { return state_; }
53  virtual void Connect() OVERRIDE;
54  virtual bool SendData(const char* data, int len) OVERRIDE;
55  virtual void Close() OVERRIDE;
56  virtual void RestartWithAuth(const AuthCredentials& credentials) OVERRIDE;
57  virtual void DetachDelegate() OVERRIDE;
58
59  // SocketStream::Delegate methods.
60  virtual int OnStartOpenConnection(
61      SocketStream* socket, const CompletionCallback& callback) OVERRIDE;
62  virtual void OnConnected(SocketStream* socket,
63                           int max_pending_send_allowed) OVERRIDE;
64  virtual void OnSentData(SocketStream* socket, int amount_sent) OVERRIDE;
65  virtual void OnReceivedData(SocketStream* socket,
66                              const char* data,
67                              int len) OVERRIDE;
68  virtual void OnClose(SocketStream* socket) OVERRIDE;
69  virtual void OnAuthRequired(
70      SocketStream* socket, AuthChallengeInfo* auth_info) OVERRIDE;
71  virtual void OnSSLCertificateError(SocketStream* socket,
72                                     const SSLInfo& ssl_info,
73                                     bool fatal) OVERRIDE;
74  virtual void OnError(const SocketStream* socket, int error) OVERRIDE;
75
76  // SpdyWebSocketStream::Delegate methods.
77  virtual void OnCreatedSpdyStream(int status) OVERRIDE;
78  virtual void OnSentSpdyHeaders() OVERRIDE;
79  virtual void OnSpdyResponseHeadersUpdated(
80      const SpdyHeaderBlock& response_headers) OVERRIDE;
81  virtual void OnSentSpdyData(size_t bytes_sent) OVERRIDE;
82  virtual void OnReceivedSpdyData(scoped_ptr<SpdyBuffer> buffer) OVERRIDE;
83  virtual void OnCloseSpdyStream() OVERRIDE;
84
85 private:
86  friend class WebSocketThrottle;
87  friend class WebSocketJobTest;
88  virtual ~WebSocketJob();
89
90  bool SendHandshakeRequest(const char* data, int len);
91  void AddCookieHeaderAndSend();
92  void LoadCookieCallback(const std::string& cookie);
93
94  void OnSentHandshakeRequest(SocketStream* socket, int amount_sent);
95  // Parses received data into handshake_response_. When finished receiving the
96  // response, calls SaveCookiesAndNotifyHeadersComplete().
97  void OnReceivedHandshakeResponse(
98      SocketStream* socket, const char* data, int len);
99  // Saves received cookies to the cookie store, and then notifies the
100  // delegate_ of completion of handshake.
101  void SaveCookiesAndNotifyHeadersComplete();
102  void SaveNextCookie();
103  void OnCookieSaved(bool cookie_status);
104  // Clears variables for handling cookies, rebuilds handshake string excluding
105  // cookies, and then pass the handshake string to delegate_.
106  void NotifyHeadersComplete();
107  void DoSendData();
108
109  GURL GetURLForCookies() const;
110
111  const AddressList& address_list() const;
112  int TrySpdyStream();
113  void SetWaiting();
114  bool IsWaiting() const;
115  void Wakeup();
116  void RetryPendingIO();
117  void CompleteIO(int result);
118
119  bool SendDataInternal(const char* data, int length);
120  void CloseInternal();
121  void SendPending();
122
123  SocketStream::Delegate* delegate_;
124  State state_;
125  bool waiting_;
126  AddressList addresses_;
127  CompletionCallback callback_;  // for throttling.
128
129  scoped_ptr<WebSocketHandshakeRequestHandler> handshake_request_;
130  scoped_ptr<WebSocketHandshakeResponseHandler> handshake_response_;
131
132  bool started_to_send_handshake_request_;
133  size_t handshake_request_sent_;
134
135  std::vector<std::string> response_cookies_;
136  size_t response_cookies_save_index_;
137
138  std::deque<scoped_refptr<IOBufferWithSize> > send_buffer_queue_;
139  scoped_refptr<DrainableIOBuffer> current_send_buffer_;
140  std::vector<char> received_data_after_handshake_;
141
142  int spdy_protocol_version_;
143  scoped_ptr<SpdyWebSocketStream> spdy_websocket_stream_;
144  std::string challenge_;
145
146  bool save_next_cookie_running_;
147  bool callback_pending_;
148
149  base::WeakPtrFactory<WebSocketJob> weak_ptr_factory_;
150  base::WeakPtrFactory<WebSocketJob> weak_ptr_factory_for_send_pending_;
151
152  DISALLOW_COPY_AND_ASSIGN(WebSocketJob);
153};
154
155}  // namespace
156
157#endif  // NET_WEBSOCKETS_WEBSOCKET_JOB_H_
158