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 |