Home | History | Annotate | Download | only in websocket_experiment
      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