13f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// Copyright (c) 2011 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_ 363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <deque> 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/basictypes.h" 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/task.h" 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/time.h" 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/net/url_fetcher.h" 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h" 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/completion_callback.h" 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_errors.h" 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/websockets/websocket.h" 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net { 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WebSocket; 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace net 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace chrome_browser_net_websocket_experiment { 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WebSocketExperimentTask : public URLFetcher::Delegate, 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public net::WebSocketDelegate { 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch enum State { 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STATE_NONE, 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STATE_URL_FETCH, 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STATE_URL_FETCH_COMPLETE, 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STATE_WEBSOCKET_CONNECT, 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STATE_WEBSOCKET_CONNECT_COMPLETE, 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STATE_WEBSOCKET_SEND_HELLO, 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STATE_WEBSOCKET_RECV_HELLO, 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STATE_WEBSOCKET_KEEP_IDLE, 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STATE_WEBSOCKET_KEEP_IDLE_COMPLETE, 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STATE_WEBSOCKET_RECV_PUSH_MESSAGE, 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STATE_WEBSOCKET_ECHO_BACK_MESSAGE, 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STATE_WEBSOCKET_RECV_BYE, 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STATE_WEBSOCKET_CLOSE, 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STATE_WEBSOCKET_CLOSE_COMPLETE, 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NUM_STATES, 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch class Config { 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Config(); 8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ~Config(); 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url; 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string ws_protocol; 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string ws_origin; 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string ws_location; 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::WebSocket::ProtocolVersion protocol_version; 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL http_url; 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 url_fetch_deadline_ms; 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 websocket_onopen_deadline_ms; 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string websocket_hello_message; 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 websocket_hello_echoback_deadline_ms; 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 websocket_idle_ms; 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 websocket_receive_push_message_deadline_ms; 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string websocket_bye_message; 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 websocket_bye_deadline_ms; 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 websocket_close_deadline_ms; 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 10072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch class Context { 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Context() {} 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual ~Context() {} 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual URLFetcher* CreateURLFetcher( 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const Config& config, URLFetcher::Delegate* delegate); 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual net::WebSocket* CreateWebSocket( 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const Config& config, net::WebSocketDelegate* delegate); 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(Context); 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch class Result { 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Result() 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : last_result(net::OK), 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch last_state(STATE_NONE) {} 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int last_result; 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch State last_state; 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeDelta url_fetch; 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeDelta websocket_connect; 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeDelta websocket_echo; 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeDelta websocket_idle; 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeDelta websocket_total; 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // WebSocketExperimentTask will call |callback| with the last status code 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // when the task is finished. 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebSocketExperimentTask(const Config& config, 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::CompletionCallback* callback); 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual ~WebSocketExperimentTask(); 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Initializes histograms that WebSocketExperimentTask will use to save 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // results. Must be called once before calling SaveResult(). 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static void InitHistogram(); 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Releases histograms to store results. 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Must be called after all WebSocketExperimentTasks are finished. 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static void ReleaseHistogram(); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Run(); 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Cancel(); 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void SaveResult() const; 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const Config& config() const { return config_; } 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const Result& result() const { return result_; } 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // URLFetcher::Delegate method. 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnURLFetchComplete(const URLFetcher* source, 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url, 1543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen const net::URLRequestStatus& status, 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int response_code, 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ResponseCookies& cookies, 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& data); 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // net::WebSocketDelegate methods 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnOpen(net::WebSocket* websocket); 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnMessage(net::WebSocket* websocket, const std::string& msg); 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnError(net::WebSocket* websocket); 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnClose(net::WebSocket* websocket, bool was_clean); 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnSocketError(const net::WebSocket* websocket, int error); 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void SetContext(Context* context); 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OnTimedOut(); 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void DoLoop(int result); 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int DoURLFetch(); 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int DoURLFetchComplete(int result); 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int DoWebSocketConnect(); 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int DoWebSocketConnectComplete(int result); 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int DoWebSocketSendHello(); 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int DoWebSocketReceiveHello(int result); 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int DoWebSocketKeepIdle(); 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int DoWebSocketKeepIdleComplete(int result); 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int DoWebSocketReceivePushMessage(int result); 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int DoWebSocketEchoBackMessage(); 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int DoWebSocketReceiveBye(int result); 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int DoWebSocketClose(); 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int DoWebSocketCloseComplete(int result); 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void SetTimeout(int64 deadline_ms); 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void RevokeTimeoutTimer(); 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Finish(int result); 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Config config_; 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<Context> context_; 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Result result_; 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedRunnableMethodFactory<WebSocketExperimentTask> method_factory_; 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::CompletionCallback* callback_; 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch State next_state_; 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<URLFetcher> url_fetcher_; 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeTicks url_fetch_start_time_; 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<net::WebSocket> websocket_; 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int last_websocket_error_; 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::deque<std::string> received_messages_; 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string push_message_; 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeTicks websocket_connect_start_time_; 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeTicks websocket_echo_start_time_; 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeTicks websocket_idle_start_time_; 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(WebSocketExperimentTask); 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace chrome_browser_net 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // CHROME_BROWSER_NET_WEBSOCKET_EXPERIMENT_WEBSOCKET_EXPERIMENT_TASK_H_ 215