• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
Context()103     Context() {}
~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:
Result()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 
config()148   const Config& config() const { return config_; }
result()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