summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorukai@chromium.org <ukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-11 06:59:38 +0000
committerukai@chromium.org <ukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-11 06:59:38 +0000
commit7c7377aa746c05b3cfd0cb4b61c3514b7ea38d0f (patch)
tree783a06a8981cb80103c26cc36366a15d49f5f2f1
parent6a781684b760689def3447b084493ca7e1877a82 (diff)
downloadchromium_src-7c7377aa746c05b3cfd0cb4b61c3514b7ea38d0f.zip
chromium_src-7c7377aa746c05b3cfd0cb4b61c3514b7ea38d0f.tar.gz
chromium_src-7c7377aa746c05b3cfd0cb4b61c3514b7ea38d0f.tar.bz2
WebSocket Live Experiment
BUG=none TEST=none Review URL: http://codereview.chromium.org/369002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@31653 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/browser_main.cc4
-rw-r--r--chrome/browser/net/websocket_experiment/websocket_experiment_runner.cc332
-rw-r--r--chrome/browser/net/websocket_experiment/websocket_experiment_runner.h81
-rw-r--r--chrome/browser/net/websocket_experiment/websocket_experiment_task.cc101
-rw-r--r--chrome/browser/net/websocket_experiment/websocket_experiment_task.h28
-rwxr-xr-xchrome/chrome.gyp2
6 files changed, 511 insertions, 37 deletions
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc
index 6475c88..78e35dc 100644
--- a/chrome/browser/browser_main.cc
+++ b/chrome/browser/browser_main.cc
@@ -39,6 +39,7 @@
#include "chrome/browser/net/dns_global.h"
#include "chrome/browser/net/metadata_url_request.h"
#include "chrome/browser/net/sdch_dictionary_fetcher.h"
+#include "chrome/browser/net/websocket_experiment/websocket_experiment_runner.h"
#include "chrome/browser/plugin_service.h"
#include "chrome/browser/process_singleton.h"
#include "chrome/browser/profile_manager.h"
@@ -831,7 +832,9 @@ int BrowserMain(const MainFunctionParams& parameters) {
if (enabled)
metrics->Start();
}
+ chrome_browser_net_websocket_experiment::WebSocketExperimentRunner::Start();
}
+
InstallJankometer(parsed_command_line);
#if defined(OS_WIN) && !defined(GOOGLE_CHROME_BUILD)
@@ -877,6 +880,7 @@ int BrowserMain(const MainFunctionParams& parameters) {
RunUIMessageLoop(browser_process.get());
}
}
+ chrome_browser_net_websocket_experiment::WebSocketExperimentRunner::Stop();
process_singleton.Cleanup();
diff --git a/chrome/browser/net/websocket_experiment/websocket_experiment_runner.cc b/chrome/browser/net/websocket_experiment/websocket_experiment_runner.cc
new file mode 100644
index 0000000..43981b0
--- /dev/null
+++ b/chrome/browser/net/websocket_experiment/websocket_experiment_runner.cc
@@ -0,0 +1,332 @@
+// 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_runner.h"
+
+#include "base/compiler_specific.h"
+#include "base/histogram.h"
+#include "base/message_loop.h"
+#include "base/task.h"
+#include "chrome/browser/chrome_thread.h"
+#include "net/base/net_errors.h"
+
+namespace chrome_browser_net_websocket_experiment {
+
+static const char *kExperimentHost = "websocket-experiment.chromium.org";
+static const int kAlternativePort = 61985;
+
+static const char kLastStateName[] = "LastState";
+static const char kUrlFetchName[] = "UrlFetch";
+static const char kWebSocketConnectName[] = "WebSocketConnect";
+static const char kWebSocketEchoName[] = "WebSocketEcho";
+static const char kWebSocketIdleName[] = "WebSocketIdle";
+static const char kWebSocketTotalName[] = "WebSocketTotal";
+static const int kUrlFetchDeadlineSec = 10;
+static const int kWebSocketConnectDeadlineSec = 10;
+static const int kWebSocketEchoDeadlineSec = 5;
+static const int kWebSocketIdleSec = 1;
+static const int kWebSocketPushDeadlineSec = 1;
+static const int kWebSocketByeDeadlineSec = 10;
+static const int kWebSocketCloseDeadlineSec = 5;
+static const int kWebSocketTimeSec = 10;
+
+// Hold reference while experiment is running.
+static scoped_refptr<WebSocketExperimentRunner> runner;
+
+/* static */
+void WebSocketExperimentRunner::Start() {
+ DCHECK(!runner.get());
+ runner = new WebSocketExperimentRunner;
+ runner->Run();
+}
+
+/* static */
+void WebSocketExperimentRunner::Stop() {
+ if (runner.get())
+ runner->Cancel();
+ runner = NULL;
+}
+
+WebSocketExperimentRunner::WebSocketExperimentRunner()
+ : next_state_(STATE_NONE),
+ task_state_(STATE_NONE),
+ ALLOW_THIS_IN_INITIALIZER_LIST(
+ task_callback_(this, &WebSocketExperimentRunner::OnTaskCompleted)) {
+ InitConfig();
+ InitHistograms();
+}
+
+WebSocketExperimentRunner::~WebSocketExperimentRunner() {
+ DLOG(INFO) << "WebSocketExperimentRunner deleted";
+ DCHECK(!task_.get());
+}
+
+void WebSocketExperimentRunner::Run() {
+ DCHECK_EQ(next_state_, STATE_NONE);
+ next_state_ = STATE_RUN_WS;
+ ChromeThread::PostDelayedTask(
+ ChromeThread::IO,
+ FROM_HERE,
+ NewRunnableMethod(this, &WebSocketExperimentRunner::DoLoop),
+ config_.initial_delay_ms);
+}
+
+void WebSocketExperimentRunner::Cancel() {
+ next_state_ = STATE_NONE;
+ ChromeThread::PostTask(
+ ChromeThread::IO,
+ FROM_HERE,
+ NewRunnableMethod(this, &WebSocketExperimentRunner::DoLoop));
+}
+
+void WebSocketExperimentRunner::InitConfig() {
+ config_.initial_delay_ms = 5 * 60 * 1000; // 5 mins
+ config_.next_delay_ms = 12 * 60 * 60 * 1000; // 12 hours
+
+ WebSocketExperimentTask::Config task_config;
+ task_config.ws_protocol = "google-websocket-liveexperiment";
+ task_config.ws_origin = "http://dev.chromium.org/";
+ task_config.url_fetch_deadline_ms = kUrlFetchDeadlineSec * 1000;
+ task_config.websocket_onopen_deadline_ms =
+ kWebSocketConnectDeadlineSec * 1000;
+ task_config.websocket_hello_message = "Hello";
+ task_config.websocket_hello_echoback_deadline_ms =
+ kWebSocketEchoDeadlineSec * 1000;
+ // Note: wait 1.5 sec in websocket_experiment_def.txt
+ task_config.websocket_idle_ms = kWebSocketIdleSec * 1000;
+ task_config.websocket_receive_push_message_deadline_ms =
+ kWebSocketPushDeadlineSec * 1000;
+ task_config.websocket_bye_message = "Bye";
+ task_config.websocket_bye_deadline_ms =
+ kWebSocketByeDeadlineSec * 1000;
+ task_config.websocket_close_deadline_ms =
+ kWebSocketCloseDeadlineSec * 1000;
+
+ config_.ws_config = task_config;
+ config_.ws_config.url =
+ GURL(StringPrintf("ws://%s/live_exp", kExperimentHost));
+ config_.ws_config.ws_location =
+ StringPrintf("ws://%s/live_exp", kExperimentHost);
+ config_.ws_config.http_url =
+ GURL(StringPrintf("http://%s/", kExperimentHost));
+
+ config_.wss_config = task_config;
+ config_.wss_config.url =
+ GURL(StringPrintf("wss://%s/live_exp", kExperimentHost));
+ config_.wss_config.ws_location =
+ StringPrintf("wss://%s/live_exp", kExperimentHost);
+ config_.wss_config.http_url =
+ GURL(StringPrintf("https://%s/", kExperimentHost));
+
+ config_.ws_nondefault_config = task_config;
+ config_.ws_nondefault_config.url =
+ GURL(StringPrintf("ws://%s:%d/live_exp",
+ kExperimentHost, kAlternativePort));
+ config_.ws_nondefault_config.ws_location =
+ StringPrintf("ws://%s:%d/live_exp",
+ kExperimentHost, kAlternativePort);
+ config_.ws_nondefault_config.http_url =
+ GURL(StringPrintf("http://%s:%d/",
+ kExperimentHost, kAlternativePort));
+}
+
+void WebSocketExperimentRunner::InitHistograms() {
+ InitHistogram<LinearHistogram, Histogram::Sample>(
+ kLastStateName, 1, WebSocketExperimentTask::NUM_STATES,
+ WebSocketExperimentTask::NUM_STATES + 1);
+
+ InitHistogram<Histogram, base::TimeDelta>(
+ kUrlFetchName, base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromSeconds(kUrlFetchDeadlineSec), 50);
+
+ InitHistogram<Histogram, base::TimeDelta>(
+ kWebSocketConnectName, base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromSeconds(kWebSocketConnectDeadlineSec), 50);
+
+ InitHistogram<Histogram, base::TimeDelta>(
+ kWebSocketEchoName, base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromSeconds(kWebSocketEchoDeadlineSec), 50);
+
+ InitHistogram<Histogram, base::TimeDelta>(
+ kWebSocketIdleName, base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromSeconds(
+ kWebSocketIdleSec + kWebSocketPushDeadlineSec), 50);
+
+ InitHistogram<Histogram, base::TimeDelta>(
+ kWebSocketTotalName, base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromSeconds(kWebSocketTimeSec), 50);
+}
+
+void WebSocketExperimentRunner::DoLoop() {
+ if (next_state_ == STATE_NONE) {
+ if (task_.get()) {
+ AddRef(); // Release in OnTaskCompleted.
+ task_->Cancel();
+ }
+ return;
+ }
+
+ State state = next_state_;
+ task_state_ = STATE_NONE;
+ next_state_ = STATE_NONE;
+
+ DLOG(INFO) << "WebSocketExperiment state=" << state;
+ switch (state) {
+ case STATE_IDLE:
+ task_.reset();
+ next_state_ = STATE_RUN_WS;
+ ChromeThread::PostDelayedTask(
+ ChromeThread::IO,
+ FROM_HERE,
+ NewRunnableMethod(this, &WebSocketExperimentRunner::DoLoop),
+ config_.next_delay_ms);
+ break;
+ case STATE_RUN_WS:
+ task_.reset(new WebSocketExperimentTask(config_.ws_config,
+ &task_callback_));
+ task_state_ = STATE_RUN_WS;
+ next_state_ = STATE_RUN_WSS;
+ break;
+ case STATE_RUN_WSS:
+ task_.reset(new WebSocketExperimentTask(config_.wss_config,
+ &task_callback_));
+ task_state_ = STATE_RUN_WSS;
+ next_state_ = STATE_RUN_WS_NODEFAULT_PORT;
+ break;
+ case STATE_RUN_WS_NODEFAULT_PORT:
+ task_.reset(new WebSocketExperimentTask(config_.ws_nondefault_config,
+ &task_callback_));
+ task_state_ = STATE_RUN_WS_NODEFAULT_PORT;
+ next_state_ = STATE_IDLE;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ if (task_.get())
+ task_->Run();
+}
+
+void WebSocketExperimentRunner::OnTaskCompleted(int result) {
+ DLOG(INFO) << "WebSocketExperiment TaskCompleted result="
+ << net::ErrorToString(result);
+ if (result == net::ERR_ABORTED) {
+ task_.reset();
+ // Task is Canceled.
+ Release();
+ return;
+ }
+ UpdateTaskResultHistogram(task_.get());
+ task_.reset();
+
+ DoLoop();
+}
+
+void WebSocketExperimentRunner::UpdateTaskResultHistogram(
+ const WebSocketExperimentTask* task) {
+ DCHECK(task);
+ const WebSocketExperimentTask::Config& task_config = task->config();
+ const WebSocketExperimentTask::Result& task_result = task->result();
+ DLOG(INFO) << "Result for url=" << task_config.url
+ << " last_result="
+ << net::ErrorToString(task_result.last_result)
+ << " last_state=" << task_result.last_state
+ << " url_fetch=" << task_result.url_fetch.InSecondsF()
+ << " websocket_connect="
+ << task_result.websocket_connect.InSecondsF()
+ << " websocket_echo="
+ << task_result.websocket_echo.InSecondsF()
+ << " websocket_idle="
+ << task_result.websocket_idle.InSecondsF()
+ << " websocket_total="
+ << task_result.websocket_total.InSecondsF();
+
+
+ Histogram* last_state = GetHistogram(kLastStateName);
+ DCHECK(last_state);
+ last_state->Add(task_result.last_state);
+
+ Histogram* url_fetch = GetHistogram(kUrlFetchName);
+ DCHECK(url_fetch);
+ url_fetch->AddTime(task_result.url_fetch);
+
+ if (task_result.last_state <
+ WebSocketExperimentTask::STATE_WEBSOCKET_CONNECT_COMPLETE)
+ return;
+
+ Histogram* websocket_connect = GetHistogram(kWebSocketConnectName);
+ DCHECK(websocket_connect);
+ websocket_connect->AddTime(task_result.websocket_connect);
+
+ if (task_result.last_state <
+ WebSocketExperimentTask::STATE_WEBSOCKET_RECV_HELLO)
+ return;
+
+ Histogram* websocket_echo = GetHistogram(kWebSocketEchoName);
+ DCHECK(websocket_echo);
+ websocket_echo->AddTime(task_result.websocket_echo);
+
+ if (task_result.last_state <
+ WebSocketExperimentTask::STATE_WEBSOCKET_KEEP_IDLE)
+ return;
+
+ Histogram* websocket_idle = GetHistogram(kWebSocketIdleName);
+ DCHECK(websocket_idle);
+ websocket_idle->AddTime(task_result.websocket_idle);
+
+ if (task_result.last_state <
+ WebSocketExperimentTask::STATE_WEBSOCKET_CLOSE_COMPLETE)
+ return;
+
+ Histogram* websocket_total = GetHistogram(kWebSocketTotalName);
+ DCHECK(websocket_total);
+ websocket_total->AddTime(task_result.websocket_total);
+}
+
+template<class HistogramType, typename HistogramSample>
+void WebSocketExperimentRunner::InitHistogram(
+ const char* type_name,
+ HistogramSample min, HistogramSample max, size_t bucket_count) {
+ static std::string name = StringPrintf(
+ "WebSocketExperiment.Basic.%s", type_name);
+ HistogramType* counter = new HistogramType(name.c_str(),
+ min, max, bucket_count);
+ counter->SetFlags(kUmaTargetedHistogramFlag);
+ ws_histograms_[type_name] = linked_ptr<Histogram>(counter);
+
+ name = StringPrintf("WebSocketExperiment.Secure.%s", type_name);
+ counter = new HistogramType(name.c_str(), min, max, bucket_count);
+ counter->SetFlags(kUmaTargetedHistogramFlag);
+ wss_histograms_[type_name] = linked_ptr<Histogram>(counter);
+
+ name = StringPrintf("WebSocketExperiment.NoDefaultPort.%s", type_name);
+ counter = new HistogramType(name.c_str(), min, max, bucket_count);
+ counter->SetFlags(kUmaTargetedHistogramFlag);
+ ws_nondefault_histograms_[type_name] = linked_ptr<Histogram>(counter);
+}
+
+Histogram* WebSocketExperimentRunner::GetHistogram(
+ const std::string& type_name) const {
+ const HistogramMap* histogram_map = NULL;
+ switch (task_state_) {
+ case STATE_RUN_WS:
+ histogram_map = &ws_histograms_;
+ break;
+ case STATE_RUN_WSS:
+ histogram_map = &wss_histograms_;
+ break;
+ case STATE_RUN_WS_NODEFAULT_PORT:
+ histogram_map = &ws_nondefault_histograms_;
+ break;
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+ DCHECK(histogram_map);
+ HistogramMap::const_iterator found = histogram_map->find(type_name);
+ DCHECK(found != histogram_map->end());
+ return found->second.get();
+}
+
+} // namespace chrome_browser_net_websocket_experiment
diff --git a/chrome/browser/net/websocket_experiment/websocket_experiment_runner.h b/chrome/browser/net/websocket_experiment/websocket_experiment_runner.h
new file mode 100644
index 0000000..efc5da2
--- /dev/null
+++ b/chrome/browser/net/websocket_experiment/websocket_experiment_runner.h
@@ -0,0 +1,81 @@
+// 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.
+
+#ifndef CHROME_BROWSER_NET_WEBSOCKET_EXPERIMENT_WEBSOCKET_EXPERIMENT_RUNNER_H_
+#define CHROME_BROWSER_NET_WEBSOCKET_EXPERIMENT_WEBSOCKET_EXPERIMENT_RUNNER_H_
+
+#include "base/basictypes.h"
+#include "base/histogram.h"
+#include "base/linked_ptr.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/net/websocket_experiment/websocket_experiment_task.h"
+#include "net/base/completion_callback.h"
+
+namespace chrome_browser_net_websocket_experiment {
+
+class WebSocketExperimentRunner
+ : public base::RefCountedThreadSafe<WebSocketExperimentRunner> {
+ public:
+ class Config {
+ public:
+ Config()
+ : initial_delay_ms(0),
+ next_delay_ms(0) {}
+
+ int64 initial_delay_ms;
+ int64 next_delay_ms;
+ WebSocketExperimentTask::Config ws_config;
+ WebSocketExperimentTask::Config wss_config;
+ WebSocketExperimentTask::Config ws_nondefault_config;
+ };
+ static void Start();
+ static void Stop();
+
+ void Run();
+ void Cancel();
+
+ private:
+ typedef std::map<std::string, linked_ptr<Histogram> > HistogramMap;
+
+ enum State {
+ STATE_NONE,
+ STATE_IDLE,
+ STATE_RUN_WS,
+ STATE_RUN_WSS,
+ STATE_RUN_WS_NODEFAULT_PORT,
+ };
+ WebSocketExperimentRunner();
+ virtual ~WebSocketExperimentRunner();
+ friend class base::RefCountedThreadSafe<WebSocketExperimentRunner>;
+
+ void InitConfig();
+ void InitHistograms();
+ void DoLoop();
+ void OnTaskCompleted(int result);
+ void UpdateTaskResultHistogram(const WebSocketExperimentTask* task);
+
+ template<class HistogramType, typename HistogramSample>
+ void InitHistogram(const char* type_name,
+ HistogramSample min, HistogramSample max,
+ size_t bucket_count);
+
+ Histogram* GetHistogram(const std::string& type_name) const;
+
+ Config config_;
+ State next_state_;
+ State task_state_;
+ scoped_ptr<WebSocketExperimentTask> task_;
+ net::CompletionCallbackImpl<WebSocketExperimentRunner> task_callback_;
+
+ HistogramMap ws_histograms_;
+ HistogramMap wss_histograms_;
+ HistogramMap ws_nondefault_histograms_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketExperimentRunner);
+};
+
+} // namespace chrome_browser_net_websocket_experiment
+
+#endif // CHROME_BROWSER_NET_WEBSOCKET_EXPERIMENT_WEBSOCKET_EXPERIMENT_RUNNER_H_
diff --git a/chrome/browser/net/websocket_experiment/websocket_experiment_task.cc b/chrome/browser/net/websocket_experiment/websocket_experiment_task.cc
index 94e0f50..a988008 100644
--- a/chrome/browser/net/websocket_experiment/websocket_experiment_task.cc
+++ b/chrome/browser/net/websocket_experiment/websocket_experiment_task.cc
@@ -4,43 +4,57 @@
#include "chrome/browser/net/websocket_experiment/websocket_experiment_task.h"
-#include "base/message_loop.h"
+#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/net/url_request_context_getter.h"
#include "chrome/browser/profile.h"
+#include "net/base/load_flags.h"
+#include "net/base/net_errors.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_);
+URLFetcher* WebSocketExperimentTask::Context::CreateURLFetcher(
+ const Config& config, URLFetcher::Delegate* delegate) {
+ URLRequestContextGetter* getter =
+ Profile::GetDefaultRequestContext();
+ DCHECK(getter);
+ DLOG(INFO) << "url=" << config.http_url;
+ URLFetcher* fetcher =
+ new URLFetcher(config.http_url, URLFetcher::GET, delegate);
+ fetcher->set_request_context(getter);
+ fetcher->set_load_flags(
+ net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE |
+ net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SEND_AUTH_DATA);
+ return fetcher;
}
-net::WebSocket* WebSocketExperimentTask::Context::CreateWebSocket() {
+net::WebSocket* WebSocketExperimentTask::Context::CreateWebSocket(
+ const Config& config, net::WebSocketDelegate* delegate) {
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,
+ new net::WebSocket::Request(config.url,
+ config.ws_protocol,
+ config.ws_origin,
+ config.ws_location,
getter->GetURLRequestContext()));
- return new net::WebSocket(request, task_);
+ return new net::WebSocket(request, delegate);
}
WebSocketExperimentTask::WebSocketExperimentTask(
const Config& config,
net::CompletionCallback* callback)
: config_(config),
- context_(ALLOW_THIS_IN_INITIALIZER_LIST(new Context(config, this))),
- message_loop_(MessageLoopForIO::current()),
+ context_(ALLOW_THIS_IN_INITIALIZER_LIST(new Context())),
method_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
callback_(callback),
- next_state_(STATE_NONE) {
- DCHECK(message_loop_);
+ next_state_(STATE_NONE),
+ last_websocket_error_(net::OK) {
}
WebSocketExperimentTask::~WebSocketExperimentTask() {
+ DLOG(INFO) << "WebSocketExperimentTask finished";
DCHECK(!websocket_);
}
@@ -49,6 +63,11 @@ void WebSocketExperimentTask::Run() {
DoLoop(net::OK);
}
+void WebSocketExperimentTask::Cancel() {
+ next_state_ = STATE_NONE;
+ DoLoop(net::OK);
+}
+
// URLFetcher::Delegate method.
void WebSocketExperimentTask::OnURLFetchComplete(
const URLFetcher* source,
@@ -59,10 +78,12 @@ void WebSocketExperimentTask::OnURLFetchComplete(
const std::string& data) {
result_.url_fetch = base::TimeTicks::Now() - url_fetch_start_time_;
RevokeTimeoutTimer();
+ DLOG(INFO) << "OnURLFetchCompleted";
int result = net::ERR_FAILED;
- if (next_state_ != STATE_URL_FETCH_COMPLETE)
+ if (next_state_ != STATE_URL_FETCH_COMPLETE) {
+ DLOG(INFO) << "unexpected state=" << next_state_;
result = net::ERR_UNEXPECTED;
- else if (response_code == 200)
+ } else if (response_code == 200 || response_code == 304)
result = net::OK;
DoLoop(result);
}
@@ -72,10 +93,12 @@ void WebSocketExperimentTask::OnOpen(net::WebSocket* websocket) {
result_.websocket_connect =
base::TimeTicks::Now() - websocket_connect_start_time_;
RevokeTimeoutTimer();
+ int result = net::ERR_UNEXPECTED;
if (next_state_ == STATE_WEBSOCKET_CONNECT_COMPLETE)
- DoLoop(net::OK);
+ result = net::OK;
else
- DoLoop(net::ERR_UNEXPECTED);
+ DLOG(INFO) << "unexpected state=" << next_state_;
+ DoLoop(result);
}
void WebSocketExperimentTask::OnMessage(
@@ -88,6 +111,7 @@ void WebSocketExperimentTask::OnMessage(
result_.websocket_idle =
base::TimeTicks::Now() - websocket_idle_start_time_;
RevokeTimeoutTimer();
+ DLOG(INFO) << "OnMessage msg=" << msg;
received_messages_.push_back(msg);
int result = net::ERR_UNEXPECTED;
switch (next_state_) {
@@ -97,6 +121,7 @@ void WebSocketExperimentTask::OnMessage(
result = net::OK;
break;
default:
+ DLOG(INFO) << "unexpected state=" << next_state_;
break;
}
DoLoop(result);
@@ -104,25 +129,42 @@ void WebSocketExperimentTask::OnMessage(
void WebSocketExperimentTask::OnClose(net::WebSocket* websocket) {
RevokeTimeoutTimer();
+ websocket_ = NULL;
+ result_.websocket_total =
+ base::TimeTicks::Now() - websocket_connect_start_time_;
int result = net::ERR_CONNECTION_CLOSED;
+ if (last_websocket_error_ != net::OK)
+ result = last_websocket_error_;
if (next_state_ == STATE_WEBSOCKET_CLOSE_COMPLETE)
result = net::OK;
DoLoop(result);
}
+void WebSocketExperimentTask::OnError(
+ const net::WebSocket* websocket, int error) {
+ DLOG(INFO) << "WebSocket error=" << net::ErrorToString(error);
+ last_websocket_error_ = error;
+}
+
void WebSocketExperimentTask::SetContext(Context* context) {
context_.reset(context);
}
void WebSocketExperimentTask::OnTimedOut() {
+ DLOG(INFO) << "OnTimedOut";
RevokeTimeoutTimer();
DoLoop(net::ERR_TIMED_OUT);
}
void WebSocketExperimentTask::DoLoop(int result) {
+ if (next_state_ == STATE_NONE) {
+ Finish(net::ERR_ABORTED);
+ return;
+ }
do {
State state = next_state_;
next_state_ = STATE_NONE;
+ DLOG(INFO) << "WebSocketExperimentTask state=" << state;
switch (state) {
case STATE_URL_FETCH:
result = DoURLFetch();
@@ -167,8 +209,11 @@ void WebSocketExperimentTask::DoLoop(int result) {
NOTREACHED();
break;
}
+ result_.last_state = state;
} while (result != net::ERR_IO_PENDING && next_state_ != STATE_NONE);
+ DLOG(INFO) << "WebSocketExperiemntTask Loop done next_state=" << next_state_
+ << " result=" << net::ErrorToString(result);
if (result != net::ERR_IO_PENDING)
Finish(result);
}
@@ -177,15 +222,17 @@ int WebSocketExperimentTask::DoURLFetch() {
next_state_ = STATE_URL_FETCH_COMPLETE;
DCHECK(!url_fetcher_.get());
- url_fetcher_.reset(context_->CreateURLFetcher());
+ url_fetcher_.reset(context_->CreateURLFetcher(config_, this));
+ SetTimeout(config_.url_fetch_deadline_ms);
+ DLOG(INFO) << "URLFetch url=" << url_fetcher_->url()
+ << " timeout=" << config_.url_fetch_deadline_ms;
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) {
+ DLOG(INFO) << "DoURLFetchComplete result=" << result;
url_fetcher_.reset();
if (result < 0)
@@ -199,7 +246,7 @@ int WebSocketExperimentTask::DoWebSocketConnect() {
DCHECK(!websocket_);
next_state_ = STATE_WEBSOCKET_CONNECT_COMPLETE;
- websocket_ = context_->CreateWebSocket();
+ websocket_ = context_->CreateWebSocket(config_, this);
websocket_connect_start_time_ = base::TimeTicks::Now();
websocket_->Connect();
@@ -328,10 +375,12 @@ int WebSocketExperimentTask::DoWebSocketCloseComplete(int result) {
}
void WebSocketExperimentTask::SetTimeout(int64 deadline_ms) {
- message_loop_->PostDelayedTask(
+ bool r = ChromeThread::PostDelayedTask(
+ ChromeThread::IO,
FROM_HERE,
method_factory_.NewRunnableMethod(&WebSocketExperimentTask::OnTimedOut),
deadline_ms);
+ DCHECK(r) << "No IO thread running?";
}
void WebSocketExperimentTask::RevokeTimeoutTimer() {
@@ -339,7 +388,15 @@ void WebSocketExperimentTask::RevokeTimeoutTimer() {
}
void WebSocketExperimentTask::Finish(int result) {
+ DLOG(INFO) << "Finish Task for " << config_.url
+ << " next_state=" << next_state_
+ << " result=" << net::ErrorToString(result);
+ url_fetcher_.reset();
+ scoped_refptr<net::WebSocket> websocket = websocket_;
+ websocket_ = NULL;
callback_->Run(result);
+ if (websocket)
+ websocket->DetachDelegate();
}
} // namespace chrome_browser_net
diff --git a/chrome/browser/net/websocket_experiment/websocket_experiment_task.h b/chrome/browser/net/websocket_experiment/websocket_experiment_task.h
index 7bf3fdd..eeab4a7 100644
--- a/chrome/browser/net/websocket_experiment/websocket_experiment_task.h
+++ b/chrome/browser/net/websocket_experiment/websocket_experiment_task.h
@@ -46,8 +46,6 @@
#include "net/base/net_errors.h"
#include "net/websockets/websocket.h"
-class MessageLoop;
-
namespace net {
class WebSocket;
} // namespace net
@@ -72,6 +70,7 @@ class WebSocketExperimentTask : public URLFetcher::Delegate,
STATE_WEBSOCKET_RECV_BYE,
STATE_WEBSOCKET_CLOSE,
STATE_WEBSOCKET_CLOSE_COMPLETE,
+ NUM_STATES,
};
class Config {
public:
@@ -102,16 +101,13 @@ class WebSocketExperimentTask : public URLFetcher::Delegate,
};
class Context {
public:
- Context(const Config& config, WebSocketExperimentTask* task)
- : config_(config), task_(task) {}
+ Context() {}
virtual ~Context() {}
- virtual URLFetcher* CreateURLFetcher();
- virtual net::WebSocket* CreateWebSocket();
-
- protected:
- const Config& config_;
- WebSocketExperimentTask* task_;
+ virtual URLFetcher* CreateURLFetcher(
+ const Config& config, URLFetcher::Delegate* delegate);
+ virtual net::WebSocket* CreateWebSocket(
+ const Config& config, net::WebSocketDelegate* delegate);
private:
DISALLOW_COPY_AND_ASSIGN(Context);
@@ -119,7 +115,7 @@ class WebSocketExperimentTask : public URLFetcher::Delegate,
class Result {
public:
Result()
- : last_result(net::ERR_UNEXPECTED),
+ : last_result(net::OK),
last_state(STATE_NONE) {}
int last_result;
State last_state;
@@ -128,6 +124,7 @@ class WebSocketExperimentTask : public URLFetcher::Delegate,
base::TimeDelta websocket_connect;
base::TimeDelta websocket_echo;
base::TimeDelta websocket_idle;
+ base::TimeDelta websocket_total;
};
// WebSocketExperimentTask will call |callback| with the last status code
@@ -137,10 +134,10 @@ class WebSocketExperimentTask : public URLFetcher::Delegate,
virtual ~WebSocketExperimentTask();
void Run();
+ void Cancel();
- const Result& GetResult() const {
- return result_;
- }
+ const Config& config() const { return config_; }
+ const Result& result() const { return result_; }
// URLFetcher::Delegate method.
virtual void OnURLFetchComplete(const URLFetcher* source,
@@ -154,6 +151,7 @@ class WebSocketExperimentTask : public URLFetcher::Delegate,
virtual void OnOpen(net::WebSocket* websocket);
virtual void OnMessage(net::WebSocket* websocket, const std::string& msg);
virtual void OnClose(net::WebSocket* websocket);
+ virtual void OnError(const net::WebSocket* websocket, int error);
void SetContext(Context* context);
@@ -183,7 +181,6 @@ class WebSocketExperimentTask : public URLFetcher::Delegate,
scoped_ptr<Context> context_;
Result result_;
- MessageLoop* message_loop_;
ScopedRunnableMethodFactory<WebSocketExperimentTask> method_factory_;
net::CompletionCallback* callback_;
State next_state_;
@@ -192,6 +189,7 @@ class WebSocketExperimentTask : public URLFetcher::Delegate,
base::TimeTicks url_fetch_start_time_;
scoped_refptr<net::WebSocket> websocket_;
+ int last_websocket_error_;
std::deque<std::string> received_messages_;
std::string push_message_;
base::TimeTicks websocket_connect_start_time_;
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index bc4711d..9e1b50f 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -1854,6 +1854,8 @@
'browser/net/url_request_slow_http_job.h',
'browser/net/url_request_tracking.cc',
'browser/net/url_request_tracking.h',
+ 'browser/net/websocket_experiment/websocket_experiment_runner.cc',
+ 'browser/net/websocket_experiment/websocket_experiment_runner.h',
'browser/net/websocket_experiment/websocket_experiment_task.cc',
'browser/net/websocket_experiment/websocket_experiment_task.h',
'browser/notifications/balloon.cc',