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