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 19 class GURL; 20 21 namespace net { 22 23 class DrainableIOBuffer; 24 class SSLInfo; 25 class WebSocketHandshakeRequestHandler; 26 class 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. 34 class 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 // Enable or Disable WebSocket over SPDY feature. 53 // This function is intended to be called before I/O thread starts. 54 static void set_websocket_over_spdy_enabled(bool enabled); 55 56 State state() const { return state_; } 57 virtual void Connect() OVERRIDE; 58 virtual bool SendData(const char* data, int len) OVERRIDE; 59 virtual void Close() OVERRIDE; 60 virtual void RestartWithAuth(const AuthCredentials& credentials) OVERRIDE; 61 virtual void DetachDelegate() OVERRIDE; 62 63 // SocketStream::Delegate methods. 64 virtual int OnStartOpenConnection( 65 SocketStream* socket, const CompletionCallback& callback) OVERRIDE; 66 virtual void OnConnected(SocketStream* socket, 67 int max_pending_send_allowed) OVERRIDE; 68 virtual void OnSentData(SocketStream* socket, int amount_sent) OVERRIDE; 69 virtual void OnReceivedData(SocketStream* socket, 70 const char* data, 71 int len) OVERRIDE; 72 virtual void OnClose(SocketStream* socket) OVERRIDE; 73 virtual void OnAuthRequired( 74 SocketStream* socket, AuthChallengeInfo* auth_info) OVERRIDE; 75 virtual void OnSSLCertificateError(SocketStream* socket, 76 const SSLInfo& ssl_info, 77 bool fatal) OVERRIDE; 78 virtual void OnError(const SocketStream* socket, int error) OVERRIDE; 79 80 // SpdyWebSocketStream::Delegate methods. 81 virtual void OnCreatedSpdyStream(int status) OVERRIDE; 82 virtual void OnSentSpdyHeaders() OVERRIDE; 83 virtual void OnSpdyResponseHeadersUpdated( 84 const SpdyHeaderBlock& response_headers) OVERRIDE; 85 virtual void OnSentSpdyData(size_t bytes_sent) OVERRIDE; 86 virtual void OnReceivedSpdyData(scoped_ptr<SpdyBuffer> buffer) OVERRIDE; 87 virtual void OnCloseSpdyStream() OVERRIDE; 88 89 private: 90 friend class WebSocketThrottle; 91 friend class WebSocketJobTest; 92 virtual ~WebSocketJob(); 93 94 bool SendHandshakeRequest(const char* data, int len); 95 void AddCookieHeaderAndSend(); 96 void LoadCookieCallback(const std::string& cookie); 97 98 void OnSentHandshakeRequest(SocketStream* socket, int amount_sent); 99 // Parses received data into handshake_response_. When finished receiving the 100 // response, calls SaveCookiesAndNotifyHeadersComplete(). 101 void OnReceivedHandshakeResponse( 102 SocketStream* socket, const char* data, int len); 103 // Saves received cookies to the cookie store, and then notifies the 104 // delegate_ of completion of handshake. 105 void SaveCookiesAndNotifyHeadersComplete(); 106 void SaveNextCookie(); 107 void OnCookieSaved(bool cookie_status); 108 // Clears variables for handling cookies, rebuilds handshake string excluding 109 // cookies, and then pass the handshake string to delegate_. 110 void NotifyHeadersComplete(); 111 void DoSendData(); 112 113 GURL GetURLForCookies() const; 114 115 const AddressList& address_list() const; 116 int TrySpdyStream(); 117 void SetWaiting(); 118 bool IsWaiting() const; 119 void Wakeup(); 120 void RetryPendingIO(); 121 void CompleteIO(int result); 122 123 bool SendDataInternal(const char* data, int length); 124 void CloseInternal(); 125 void SendPending(); 126 127 static bool websocket_over_spdy_enabled_; 128 129 SocketStream::Delegate* delegate_; 130 State state_; 131 bool waiting_; 132 AddressList addresses_; 133 CompletionCallback callback_; // for throttling. 134 135 scoped_ptr<WebSocketHandshakeRequestHandler> handshake_request_; 136 scoped_ptr<WebSocketHandshakeResponseHandler> handshake_response_; 137 138 bool started_to_send_handshake_request_; 139 size_t handshake_request_sent_; 140 141 std::vector<std::string> response_cookies_; 142 size_t response_cookies_save_index_; 143 144 std::deque<scoped_refptr<IOBufferWithSize> > send_buffer_queue_; 145 scoped_refptr<DrainableIOBuffer> current_send_buffer_; 146 std::vector<char> received_data_after_handshake_; 147 148 int spdy_protocol_version_; 149 scoped_ptr<SpdyWebSocketStream> spdy_websocket_stream_; 150 std::string challenge_; 151 152 bool save_next_cookie_running_; 153 bool callback_pending_; 154 155 base::WeakPtrFactory<WebSocketJob> weak_ptr_factory_; 156 base::WeakPtrFactory<WebSocketJob> weak_ptr_factory_for_send_pending_; 157 158 DISALLOW_COPY_AND_ASSIGN(WebSocketJob); 159 }; 160 161 } // namespace 162 163 #endif // NET_WEBSOCKETS_WEBSOCKET_JOB_H_ 164