| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2010 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 #include "chrome/browser/net/websocket_experiment/websocket_experiment_runner.h" | |
| 6 | |
| 7 #include "base/command_line.h" | |
| 8 #include "base/compiler_specific.h" | |
| 9 #include "base/message_loop.h" | |
| 10 #include "base/metrics/field_trial.h" | |
| 11 #include "base/stringprintf.h" | |
| 12 #include "base/task.h" | |
| 13 #include "chrome/common/chrome_switches.h" | |
| 14 #include "content/browser/browser_thread.h" | |
| 15 #include "net/base/host_resolver.h" | |
| 16 #include "net/base/net_errors.h" | |
| 17 #include "net/websockets/websocket.h" | |
| 18 | |
| 19 namespace chrome_browser_net_websocket_experiment { | |
| 20 | |
| 21 static const char *kExperimentHost = "websocket-experiment.chromium.org"; | |
| 22 static const int kAlternativePort = 61985; | |
| 23 | |
| 24 // Hold reference while experiment is running. | |
| 25 static scoped_refptr<WebSocketExperimentRunner> runner; | |
| 26 | |
| 27 /* static */ | |
| 28 void WebSocketExperimentRunner::Start() { | |
| 29 DCHECK(!runner.get()); | |
| 30 | |
| 31 // After June 30, 2011 builds, it will always be in default group. | |
| 32 scoped_refptr<base::FieldTrial> trial( | |
| 33 new base::FieldTrial( | |
| 34 "WebSocketExperiment", 1000, "default", 2011, 6, 30)); | |
| 35 int active = trial->AppendGroup("active", 5); // 0.5% in active group. | |
| 36 | |
| 37 bool run_experiment = (trial->group() == active); | |
| 38 #ifndef NDEBUG | |
| 39 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | |
| 40 std::string experiment_host = command_line.GetSwitchValueASCII( | |
| 41 switches::kWebSocketLiveExperimentHost); | |
| 42 if (!experiment_host.empty()) | |
| 43 run_experiment = true; | |
| 44 #else | |
| 45 run_experiment = false; | |
| 46 #endif | |
| 47 if (!run_experiment) | |
| 48 return; | |
| 49 | |
| 50 runner = new WebSocketExperimentRunner; | |
| 51 runner->Run(); | |
| 52 } | |
| 53 | |
| 54 /* static */ | |
| 55 void WebSocketExperimentRunner::Stop() { | |
| 56 if (runner.get()) | |
| 57 runner->Cancel(); | |
| 58 runner = NULL; | |
| 59 } | |
| 60 | |
| 61 WebSocketExperimentRunner::WebSocketExperimentRunner() | |
| 62 : next_state_(STATE_NONE), | |
| 63 task_state_(STATE_NONE), | |
| 64 ALLOW_THIS_IN_INITIALIZER_LIST( | |
| 65 task_callback_(this, &WebSocketExperimentRunner::OnTaskCompleted)) { | |
| 66 WebSocketExperimentTask::InitHistogram(); | |
| 67 InitConfig(); | |
| 68 } | |
| 69 | |
| 70 WebSocketExperimentRunner::~WebSocketExperimentRunner() { | |
| 71 DCHECK(!task_.get()); | |
| 72 WebSocketExperimentTask::ReleaseHistogram(); | |
| 73 } | |
| 74 | |
| 75 void WebSocketExperimentRunner::Run() { | |
| 76 DCHECK_EQ(next_state_, STATE_NONE); | |
| 77 next_state_ = STATE_RUN_WS; | |
| 78 BrowserThread::PostDelayedTask( | |
| 79 BrowserThread::IO, | |
| 80 FROM_HERE, | |
| 81 NewRunnableMethod(this, &WebSocketExperimentRunner::DoLoop), | |
| 82 config_.initial_delay_ms); | |
| 83 } | |
| 84 | |
| 85 void WebSocketExperimentRunner::Cancel() { | |
| 86 next_state_ = STATE_NONE; | |
| 87 BrowserThread::PostTask( | |
| 88 BrowserThread::IO, | |
| 89 FROM_HERE, | |
| 90 NewRunnableMethod(this, &WebSocketExperimentRunner::DoLoop)); | |
| 91 } | |
| 92 | |
| 93 void WebSocketExperimentRunner::InitConfig() { | |
| 94 config_.initial_delay_ms = 5 * 60 * 1000; // 5 mins | |
| 95 config_.next_delay_ms = 12 * 60 * 60 * 1000; // 12 hours | |
| 96 | |
| 97 std::string experiment_host = kExperimentHost; | |
| 98 #ifndef NDEBUG | |
| 99 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | |
| 100 std::string experiment_host_override = command_line.GetSwitchValueASCII( | |
| 101 switches::kWebSocketLiveExperimentHost); | |
| 102 if (!experiment_host_override.empty()) { | |
| 103 experiment_host = experiment_host_override; | |
| 104 config_.initial_delay_ms = 5 * 1000; // 5 secs. | |
| 105 } | |
| 106 #endif | |
| 107 | |
| 108 WebSocketExperimentTask::Config* config; | |
| 109 WebSocketExperimentTask::Config task_config; | |
| 110 | |
| 111 task_config.protocol_version = net::WebSocket::DEFAULT_VERSION; | |
| 112 config = &config_.ws_config[STATE_RUN_WS - STATE_RUN_WS]; | |
| 113 *config = task_config; | |
| 114 config->url = | |
| 115 GURL(base::StringPrintf("ws://%s/live_exp", experiment_host.c_str())); | |
| 116 config->ws_location = | |
| 117 base::StringPrintf("ws://%s/live_exp", experiment_host.c_str()); | |
| 118 config->http_url = | |
| 119 GURL(base::StringPrintf("http://%s/", experiment_host.c_str())); | |
| 120 | |
| 121 config = &config_.ws_config[STATE_RUN_WSS - STATE_RUN_WS]; | |
| 122 *config = task_config; | |
| 123 config->url = | |
| 124 GURL(base::StringPrintf("wss://%s/live_exp", experiment_host.c_str())); | |
| 125 config->ws_location = | |
| 126 base::StringPrintf("wss://%s/live_exp", experiment_host.c_str()); | |
| 127 config->http_url = | |
| 128 GURL(base::StringPrintf("https://%s/", experiment_host.c_str())); | |
| 129 | |
| 130 config = &config_.ws_config[STATE_RUN_WS_NODEFAULT_PORT - | |
| 131 STATE_RUN_WS]; | |
| 132 *config = task_config; | |
| 133 config->url = | |
| 134 GURL(base::StringPrintf("ws://%s:%d/live_exp", | |
| 135 experiment_host.c_str(), kAlternativePort)); | |
| 136 config->ws_location = | |
| 137 base::StringPrintf("ws://%s:%d/live_exp", | |
| 138 experiment_host.c_str(), kAlternativePort); | |
| 139 config->http_url = | |
| 140 GURL(base::StringPrintf("http://%s:%d/", | |
| 141 experiment_host.c_str(), kAlternativePort)); | |
| 142 | |
| 143 task_config.protocol_version = net::WebSocket::DRAFT75; | |
| 144 config = &config_.ws_config[STATE_RUN_WS_DRAFT75 - STATE_RUN_WS]; | |
| 145 *config = task_config; | |
| 146 config->url = | |
| 147 GURL(base::StringPrintf("ws://%s/live_exp", experiment_host.c_str())); | |
| 148 config->ws_location = | |
| 149 base::StringPrintf("ws://%s/live_exp", experiment_host.c_str()); | |
| 150 config->http_url = | |
| 151 GURL(base::StringPrintf("http://%s/", experiment_host.c_str())); | |
| 152 | |
| 153 config = &config_.ws_config[STATE_RUN_WSS_DRAFT75 - STATE_RUN_WS]; | |
| 154 *config = task_config; | |
| 155 config->url = | |
| 156 GURL(base::StringPrintf("wss://%s/live_exp", experiment_host.c_str())); | |
| 157 config->ws_location = | |
| 158 base::StringPrintf("wss://%s/live_exp", experiment_host.c_str()); | |
| 159 config->http_url = | |
| 160 GURL(base::StringPrintf("https://%s/", experiment_host.c_str())); | |
| 161 | |
| 162 config = &config_.ws_config[STATE_RUN_WS_NODEFAULT_PORT_DRAFT75 - | |
| 163 STATE_RUN_WS]; | |
| 164 *config = task_config; | |
| 165 config->url = | |
| 166 GURL(base::StringPrintf("ws://%s:%d/live_exp", | |
| 167 experiment_host.c_str(), kAlternativePort)); | |
| 168 config->ws_location = | |
| 169 base::StringPrintf("ws://%s:%d/live_exp", | |
| 170 experiment_host.c_str(), kAlternativePort); | |
| 171 config->http_url = | |
| 172 GURL(base::StringPrintf("http://%s:%d/", | |
| 173 experiment_host.c_str(), kAlternativePort)); | |
| 174 | |
| 175 } | |
| 176 | |
| 177 void WebSocketExperimentRunner::DoLoop() { | |
| 178 if (next_state_ == STATE_NONE) { | |
| 179 if (task_.get()) { | |
| 180 AddRef(); // Release in OnTaskCompleted after Cancelled. | |
| 181 task_->Cancel(); | |
| 182 } | |
| 183 return; | |
| 184 } | |
| 185 | |
| 186 State state = next_state_; | |
| 187 task_state_ = STATE_NONE; | |
| 188 next_state_ = STATE_NONE; | |
| 189 | |
| 190 switch (state) { | |
| 191 case STATE_IDLE: | |
| 192 task_.reset(); | |
| 193 next_state_ = STATE_RUN_WS; | |
| 194 BrowserThread::PostDelayedTask( | |
| 195 BrowserThread::IO, | |
| 196 FROM_HERE, | |
| 197 NewRunnableMethod(this, &WebSocketExperimentRunner::DoLoop), | |
| 198 config_.next_delay_ms); | |
| 199 break; | |
| 200 case STATE_RUN_WS: | |
| 201 case STATE_RUN_WSS: | |
| 202 case STATE_RUN_WS_NODEFAULT_PORT: | |
| 203 case STATE_RUN_WS_DRAFT75: | |
| 204 case STATE_RUN_WSS_DRAFT75: | |
| 205 case STATE_RUN_WS_NODEFAULT_PORT_DRAFT75: | |
| 206 task_.reset(new WebSocketExperimentTask( | |
| 207 config_.ws_config[state - STATE_RUN_WS], &task_callback_)); | |
| 208 task_state_ = state; | |
| 209 if (static_cast<State>(state + 1) == NUM_STATES) | |
| 210 next_state_ = STATE_IDLE; | |
| 211 else | |
| 212 next_state_ = static_cast<State>(state + 1); | |
| 213 break; | |
| 214 default: | |
| 215 NOTREACHED(); | |
| 216 break; | |
| 217 } | |
| 218 if (task_.get()) | |
| 219 task_->Run(); | |
| 220 } | |
| 221 | |
| 222 void WebSocketExperimentRunner::OnTaskCompleted(int result) { | |
| 223 if (next_state_ == STATE_NONE) { | |
| 224 task_.reset(); | |
| 225 // Task is Canceled. | |
| 226 DVLOG(1) << "WebSocketExperiment Task is canceled."; | |
| 227 Release(); | |
| 228 return; | |
| 229 } | |
| 230 task_->SaveResult(); | |
| 231 task_.reset(); | |
| 232 | |
| 233 DoLoop(); | |
| 234 } | |
| 235 | |
| 236 } // namespace chrome_browser_net_websocket_experiment | |
| OLD | NEW |