1 // Copyright (c) 2011 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 // WebSocket live experiment task. 6 // It will try the following scenario. 7 // 8 // - Fetch |http_url| within |url_fetch_deadline_ms| msec. 9 // If failed, the task is aborted (no http reachability) 10 // 11 // - Connect to |url| with WebSocket protocol within 12 // |websocket_onopen_deadline_ms| msec. 13 // Checks WebSocket connection can be established. 14 // 15 // - Send |websocket_hello_message| on the WebSocket connection and 16 // wait it from server within |websocket_hello_echoback_deadline_ms| msec. 17 // Checks message can be sent/received on the WebSocket connection. 18 // 19 // - Keep connection idle at least |websocket_idle_ms| msec. 20 // Checks WebSocket connection keep open in idle state. 21 // 22 // - Wait for some message from server within 23 // |websocket_receive_push_message_deadline_ms| msec, and echo it back. 24 // Checks server can push a message after connection has been idle. 25 // 26 // - Expect that |websocket_bye_message| message arrives within 27 // |websocket_bye_deadline_ms| msec from server. 28 // Checks previous message was sent to the server. 29 // 30 // - Close the connection and wait |websocket_close_deadline_ms| msec 31 // for onclose. 32 // Checks WebSocket connection can be closed normally. 33 34 #ifndef CHROME_BROWSER_NET_WEBSOCKET_EXPERIMENT_WEBSOCKET_EXPERIMENT_TASK_H_ 35 #define CHROME_BROWSER_NET_WEBSOCKET_EXPERIMENT_WEBSOCKET_EXPERIMENT_TASK_H_ 36 #pragma once 37 38 #include <deque> 39 #include <string> 40 41 #include "base/basictypes.h" 42 #include "base/task.h" 43 #include "base/time.h" 44 #include "chrome/common/net/url_fetcher.h" 45 #include "googleurl/src/gurl.h" 46 #include "net/base/completion_callback.h" 47 #include "net/base/net_errors.h" 48 #include "net/websockets/websocket.h" 49 50 namespace net { 51 class WebSocket; 52 } // namespace net 53 54 namespace chrome_browser_net_websocket_experiment { 55 56 class WebSocketExperimentTask : public URLFetcher::Delegate, 57 public net::WebSocketDelegate { 58 public: 59 enum State { 60 STATE_NONE, 61 STATE_URL_FETCH, 62 STATE_URL_FETCH_COMPLETE, 63 STATE_WEBSOCKET_CONNECT, 64 STATE_WEBSOCKET_CONNECT_COMPLETE, 65 STATE_WEBSOCKET_SEND_HELLO, 66 STATE_WEBSOCKET_RECV_HELLO, 67 STATE_WEBSOCKET_KEEP_IDLE, 68 STATE_WEBSOCKET_KEEP_IDLE_COMPLETE, 69 STATE_WEBSOCKET_RECV_PUSH_MESSAGE, 70 STATE_WEBSOCKET_ECHO_BACK_MESSAGE, 71 STATE_WEBSOCKET_RECV_BYE, 72 STATE_WEBSOCKET_CLOSE, 73 STATE_WEBSOCKET_CLOSE_COMPLETE, 74 NUM_STATES, 75 }; 76 77 class Config { 78 public: 79 Config(); 80 ~Config(); 81 82 GURL url; 83 std::string ws_protocol; 84 std::string ws_origin; 85 std::string ws_location; 86 net::WebSocket::ProtocolVersion protocol_version; 87 88 GURL http_url; 89 90 int64 url_fetch_deadline_ms; 91 int64 websocket_onopen_deadline_ms; 92 std::string websocket_hello_message; 93 int64 websocket_hello_echoback_deadline_ms; 94 int64 websocket_idle_ms; 95 int64 websocket_receive_push_message_deadline_ms; 96 std::string websocket_bye_message; 97 int64 websocket_bye_deadline_ms; 98 int64 websocket_close_deadline_ms; 99 }; 100 101 class Context { 102 public: 103 Context() {} 104 virtual ~Context() {} 105 106 virtual URLFetcher* CreateURLFetcher( 107 const Config& config, URLFetcher::Delegate* delegate); 108 virtual net::WebSocket* CreateWebSocket( 109 const Config& config, net::WebSocketDelegate* delegate); 110 111 private: 112 DISALLOW_COPY_AND_ASSIGN(Context); 113 }; 114 115 class Result { 116 public: 117 Result() 118 : last_result(net::OK), 119 last_state(STATE_NONE) {} 120 int last_result; 121 State last_state; 122 123 base::TimeDelta url_fetch; 124 base::TimeDelta websocket_connect; 125 base::TimeDelta websocket_echo; 126 base::TimeDelta websocket_idle; 127 base::TimeDelta websocket_total; 128 }; 129 130 // WebSocketExperimentTask will call |callback| with the last status code 131 // when the task is finished. 132 WebSocketExperimentTask(const Config& config, 133 net::CompletionCallback* callback); 134 virtual ~WebSocketExperimentTask(); 135 136 // Initializes histograms that WebSocketExperimentTask will use to save 137 // results. Must be called once before calling SaveResult(). 138 static void InitHistogram(); 139 140 // Releases histograms to store results. 141 // Must be called after all WebSocketExperimentTasks are finished. 142 static void ReleaseHistogram(); 143 144 void Run(); 145 void Cancel(); 146 void SaveResult() const; 147 148 const Config& config() const { return config_; } 149 const Result& result() const { return result_; } 150 151 // URLFetcher::Delegate method. 152 virtual void OnURLFetchComplete(const URLFetcher* source, 153 const GURL& url, 154 const net::URLRequestStatus& status, 155 int response_code, 156 const ResponseCookies& cookies, 157 const std::string& data); 158 159 // net::WebSocketDelegate methods 160 virtual void OnOpen(net::WebSocket* websocket); 161 virtual void OnMessage(net::WebSocket* websocket, const std::string& msg); 162 virtual void OnError(net::WebSocket* websocket); 163 virtual void OnClose(net::WebSocket* websocket, bool was_clean); 164 virtual void OnSocketError(const net::WebSocket* websocket, int error); 165 166 void SetContext(Context* context); 167 168 private: 169 void OnTimedOut(); 170 171 void DoLoop(int result); 172 173 int DoURLFetch(); 174 int DoURLFetchComplete(int result); 175 int DoWebSocketConnect(); 176 int DoWebSocketConnectComplete(int result); 177 int DoWebSocketSendHello(); 178 int DoWebSocketReceiveHello(int result); 179 int DoWebSocketKeepIdle(); 180 int DoWebSocketKeepIdleComplete(int result); 181 int DoWebSocketReceivePushMessage(int result); 182 int DoWebSocketEchoBackMessage(); 183 int DoWebSocketReceiveBye(int result); 184 int DoWebSocketClose(); 185 int DoWebSocketCloseComplete(int result); 186 void SetTimeout(int64 deadline_ms); 187 void RevokeTimeoutTimer(); 188 void Finish(int result); 189 190 Config config_; 191 scoped_ptr<Context> context_; 192 Result result_; 193 194 ScopedRunnableMethodFactory<WebSocketExperimentTask> method_factory_; 195 net::CompletionCallback* callback_; 196 State next_state_; 197 198 scoped_ptr<URLFetcher> url_fetcher_; 199 base::TimeTicks url_fetch_start_time_; 200 201 scoped_refptr<net::WebSocket> websocket_; 202 int last_websocket_error_; 203 std::deque<std::string> received_messages_; 204 std::string push_message_; 205 base::TimeTicks websocket_connect_start_time_; 206 base::TimeTicks websocket_echo_start_time_; 207 base::TimeTicks websocket_idle_start_time_; 208 209 DISALLOW_COPY_AND_ASSIGN(WebSocketExperimentTask); 210 }; 211 212 } // namespace chrome_browser_net 213 214 #endif // CHROME_BROWSER_NET_WEBSOCKET_EXPERIMENT_WEBSOCKET_EXPERIMENT_TASK_H_ 215