Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4584)

Unified Diff: chrome/browser/net/websocket_experiment/websocket_experiment_task.cc

Issue 333045: WIP: websocket live experiment (Closed)
Patch Set: fix comment Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/net/websocket_experiment/websocket_experiment_task.h ('k') | chrome/chrome.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/net/websocket_experiment/websocket_experiment_task.cc
diff --git a/chrome/browser/net/websocket_experiment/websocket_experiment_task.cc b/chrome/browser/net/websocket_experiment/websocket_experiment_task.cc
new file mode 100644
index 0000000000000000000000000000000000000000..94e0f502a3f60f7747d9ba280cf75c44beebe862
--- /dev/null
+++ b/chrome/browser/net/websocket_experiment/websocket_experiment_task.cc
@@ -0,0 +1,345 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/net/websocket_experiment/websocket_experiment_task.h"
+
+#include "base/message_loop.h"
+#include "chrome/browser/net/url_request_context_getter.h"
+#include "chrome/browser/profile.h"
+#include "net/websockets/websocket.h"
+
+namespace chrome_browser_net_websocket_experiment {
+
+URLFetcher* WebSocketExperimentTask::Context::CreateURLFetcher() {
+ return new URLFetcher(config_.http_url, URLFetcher::HEAD, task_);
+}
+
+net::WebSocket* WebSocketExperimentTask::Context::CreateWebSocket() {
+ URLRequestContextGetter* getter =
+ Profile::GetDefaultRequestContext();
+ DCHECK(getter);
+ net::WebSocket::Request* request(
+ new net::WebSocket::Request(config_.url,
+ config_.ws_protocol,
+ config_.ws_origin,
+ config_.ws_location,
+ getter->GetURLRequestContext()));
+ return new net::WebSocket(request, task_);
+}
+
+WebSocketExperimentTask::WebSocketExperimentTask(
+ const Config& config,
+ net::CompletionCallback* callback)
+ : config_(config),
+ context_(ALLOW_THIS_IN_INITIALIZER_LIST(new Context(config, this))),
+ message_loop_(MessageLoopForIO::current()),
+ method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
+ callback_(callback),
+ next_state_(STATE_NONE) {
+ DCHECK(message_loop_);
+}
+
+WebSocketExperimentTask::~WebSocketExperimentTask() {
+ DCHECK(!websocket_);
+}
+
+void WebSocketExperimentTask::Run() {
+ next_state_ = STATE_URL_FETCH;
+ DoLoop(net::OK);
+}
+
+// URLFetcher::Delegate method.
+void WebSocketExperimentTask::OnURLFetchComplete(
+ const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data) {
+ result_.url_fetch = base::TimeTicks::Now() - url_fetch_start_time_;
+ RevokeTimeoutTimer();
+ int result = net::ERR_FAILED;
+ if (next_state_ != STATE_URL_FETCH_COMPLETE)
+ result = net::ERR_UNEXPECTED;
+ else if (response_code == 200)
+ result = net::OK;
+ DoLoop(result);
+}
+
+// net::WebSocketDelegate
+void WebSocketExperimentTask::OnOpen(net::WebSocket* websocket) {
+ result_.websocket_connect =
+ base::TimeTicks::Now() - websocket_connect_start_time_;
+ RevokeTimeoutTimer();
+ if (next_state_ == STATE_WEBSOCKET_CONNECT_COMPLETE)
+ DoLoop(net::OK);
+ else
+ DoLoop(net::ERR_UNEXPECTED);
+}
+
+void WebSocketExperimentTask::OnMessage(
+ net::WebSocket* websocket, const std::string& msg) {
+ if (!result_.websocket_echo.ToInternalValue())
+ result_.websocket_echo =
+ base::TimeTicks::Now() - websocket_echo_start_time_;
+ if (!websocket_idle_start_time_.is_null() &&
+ !result_.websocket_idle.ToInternalValue())
+ result_.websocket_idle =
+ base::TimeTicks::Now() - websocket_idle_start_time_;
+ RevokeTimeoutTimer();
+ received_messages_.push_back(msg);
+ int result = net::ERR_UNEXPECTED;
+ switch (next_state_) {
+ case STATE_WEBSOCKET_RECV_HELLO:
+ case STATE_WEBSOCKET_RECV_PUSH_MESSAGE:
+ case STATE_WEBSOCKET_RECV_BYE:
+ result = net::OK;
+ break;
+ default:
+ break;
+ }
+ DoLoop(result);
+}
+
+void WebSocketExperimentTask::OnClose(net::WebSocket* websocket) {
+ RevokeTimeoutTimer();
+ int result = net::ERR_CONNECTION_CLOSED;
+ if (next_state_ == STATE_WEBSOCKET_CLOSE_COMPLETE)
+ result = net::OK;
+ DoLoop(result);
+}
+
+void WebSocketExperimentTask::SetContext(Context* context) {
+ context_.reset(context);
+}
+
+void WebSocketExperimentTask::OnTimedOut() {
+ RevokeTimeoutTimer();
+ DoLoop(net::ERR_TIMED_OUT);
+}
+
+void WebSocketExperimentTask::DoLoop(int result) {
+ do {
+ State state = next_state_;
+ next_state_ = STATE_NONE;
+ switch (state) {
+ case STATE_URL_FETCH:
+ result = DoURLFetch();
+ break;
+ case STATE_URL_FETCH_COMPLETE:
+ result = DoURLFetchComplete(result);
+ break;
+ case STATE_WEBSOCKET_CONNECT:
+ result = DoWebSocketConnect();
+ break;
+ case STATE_WEBSOCKET_CONNECT_COMPLETE:
+ result = DoWebSocketConnectComplete(result);
+ break;
+ case STATE_WEBSOCKET_SEND_HELLO:
+ result = DoWebSocketSendHello();
+ break;
+ case STATE_WEBSOCKET_RECV_HELLO:
+ result = DoWebSocketReceiveHello(result);
+ break;
+ case STATE_WEBSOCKET_KEEP_IDLE:
+ result = DoWebSocketKeepIdle();
+ break;
+ case STATE_WEBSOCKET_KEEP_IDLE_COMPLETE:
+ result = DoWebSocketKeepIdleComplete(result);
+ break;
+ case STATE_WEBSOCKET_RECV_PUSH_MESSAGE:
+ result = DoWebSocketReceivePushMessage(result);
+ break;
+ case STATE_WEBSOCKET_ECHO_BACK_MESSAGE:
+ result = DoWebSocketEchoBackMessage();
+ break;
+ case STATE_WEBSOCKET_RECV_BYE:
+ result = DoWebSocketReceiveBye(result);
+ break;
+ case STATE_WEBSOCKET_CLOSE:
+ result = DoWebSocketClose();
+ break;
+ case STATE_WEBSOCKET_CLOSE_COMPLETE:
+ result = DoWebSocketCloseComplete(result);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ } while (result != net::ERR_IO_PENDING && next_state_ != STATE_NONE);
+
+ if (result != net::ERR_IO_PENDING)
+ Finish(result);
+}
+
+int WebSocketExperimentTask::DoURLFetch() {
+ next_state_ = STATE_URL_FETCH_COMPLETE;
+ DCHECK(!url_fetcher_.get());
+
+ url_fetcher_.reset(context_->CreateURLFetcher());
+ url_fetch_start_time_ = base::TimeTicks::Now();
+ url_fetcher_->Start();
+
+ SetTimeout(config_.url_fetch_deadline_ms);
+ return net::ERR_IO_PENDING;
+}
+
+int WebSocketExperimentTask::DoURLFetchComplete(int result) {
+ url_fetcher_.reset();
+
+ if (result < 0)
+ return result;
+
+ next_state_ = STATE_WEBSOCKET_CONNECT;
+ return net::OK;
+}
+
+int WebSocketExperimentTask::DoWebSocketConnect() {
+ DCHECK(!websocket_);
+
+ next_state_ = STATE_WEBSOCKET_CONNECT_COMPLETE;
+ websocket_ = context_->CreateWebSocket();
+ websocket_connect_start_time_ = base::TimeTicks::Now();
+ websocket_->Connect();
+
+ SetTimeout(config_.websocket_onopen_deadline_ms);
+ return net::ERR_IO_PENDING;
+}
+
+int WebSocketExperimentTask::DoWebSocketConnectComplete(int result) {
+ if (result < 0)
+ return result;
+ DCHECK(websocket_);
+
+ next_state_ = STATE_WEBSOCKET_SEND_HELLO;
+ return net::OK;
+}
+
+int WebSocketExperimentTask::DoWebSocketSendHello() {
+ DCHECK(websocket_);
+
+ next_state_ = STATE_WEBSOCKET_RECV_HELLO;
+
+ websocket_echo_start_time_ = base::TimeTicks::Now();
+ websocket_->Send(config_.websocket_hello_message);
+ SetTimeout(config_.websocket_hello_echoback_deadline_ms);
+ return net::ERR_IO_PENDING;
+}
+
+int WebSocketExperimentTask::DoWebSocketReceiveHello(int result) {
+ if (result < 0)
+ return result;
+
+ DCHECK(websocket_);
+
+ if (received_messages_.size() != 1)
+ return net::ERR_INVALID_RESPONSE;
+
+ std::string msg = received_messages_.front();
+ received_messages_.pop_front();
+ if (msg != config_.websocket_hello_message)
+ return net::ERR_INVALID_RESPONSE;
+
+ next_state_ = STATE_WEBSOCKET_KEEP_IDLE;
+ return net::OK;
+}
+
+int WebSocketExperimentTask::DoWebSocketKeepIdle() {
+ DCHECK(websocket_);
+
+ next_state_ = STATE_WEBSOCKET_KEEP_IDLE_COMPLETE;
+ websocket_idle_start_time_ = base::TimeTicks::Now();
+ SetTimeout(config_.websocket_idle_ms);
+ return net::ERR_IO_PENDING;
+}
+
+int WebSocketExperimentTask::DoWebSocketKeepIdleComplete(int result) {
+ if (result != net::ERR_TIMED_OUT) {
+ // Server sends back too early, or unexpected close?
+ if (result == net::OK)
+ result = net::ERR_UNEXPECTED;
+ return result;
+ }
+
+ DCHECK(websocket_);
+
+ next_state_ = STATE_WEBSOCKET_RECV_PUSH_MESSAGE;
+ SetTimeout(config_.websocket_receive_push_message_deadline_ms);
+ return net::ERR_IO_PENDING;
+}
+
+int WebSocketExperimentTask::DoWebSocketReceivePushMessage(int result) {
+ if (result < 0)
+ return result;
+
+ DCHECK(websocket_);
+ if (received_messages_.size() != 1)
+ return net::ERR_INVALID_RESPONSE;
+
+ push_message_ = received_messages_.front();
+ received_messages_.pop_front();
+
+ next_state_ = STATE_WEBSOCKET_ECHO_BACK_MESSAGE;
+ return net::OK;
+}
+
+int WebSocketExperimentTask::DoWebSocketEchoBackMessage() {
+ DCHECK(websocket_);
+ DCHECK(!push_message_.empty());
+
+ next_state_ = STATE_WEBSOCKET_RECV_BYE;
+ websocket_->Send(push_message_);
+ SetTimeout(config_.websocket_bye_deadline_ms);
+ return net::ERR_IO_PENDING;
+}
+
+int WebSocketExperimentTask::DoWebSocketReceiveBye(int result) {
+ if (result < 0)
+ return result;
+
+ DCHECK(websocket_);
+
+ if (received_messages_.size() != 1)
+ return net::ERR_INVALID_RESPONSE;
+
+ std::string bye = received_messages_.front();
+ received_messages_.pop_front();
+
+ if (bye != config_.websocket_bye_message)
+ return net::ERR_INVALID_RESPONSE;
+
+ next_state_ = STATE_WEBSOCKET_CLOSE;
+ return net::OK;
+}
+
+int WebSocketExperimentTask::DoWebSocketClose() {
+ DCHECK(websocket_);
+
+ next_state_ = STATE_WEBSOCKET_CLOSE_COMPLETE;
+ websocket_->Close();
+ SetTimeout(config_.websocket_close_deadline_ms);
+ return net::ERR_IO_PENDING;
+}
+
+int WebSocketExperimentTask::DoWebSocketCloseComplete(int result) {
+ websocket_ = NULL;
+ return result;
+}
+
+void WebSocketExperimentTask::SetTimeout(int64 deadline_ms) {
+ message_loop_->PostDelayedTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(&WebSocketExperimentTask::OnTimedOut),
+ deadline_ms);
+}
+
+void WebSocketExperimentTask::RevokeTimeoutTimer() {
+ method_factory_.RevokeAll();
+}
+
+void WebSocketExperimentTask::Finish(int result) {
+ callback_->Run(result);
+}
+
+} // namespace chrome_browser_net
« no previous file with comments | « chrome/browser/net/websocket_experiment/websocket_experiment_task.h ('k') | chrome/chrome.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698