1 // Copyright 2013 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 "net/websockets/websocket_job.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/callback.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/strings/string_split.h"
15 #include "base/strings/string_util.h"
16 #include "net/base/completion_callback.h"
17 #include "net/base/net_errors.h"
18 #include "net/base/test_completion_callback.h"
19 #include "net/cookies/cookie_store.h"
20 #include "net/cookies/cookie_store_test_helpers.h"
21 #include "net/dns/mock_host_resolver.h"
22 #include "net/http/http_transaction_factory.h"
23 #include "net/http/transport_security_state.h"
24 #include "net/proxy/proxy_service.h"
25 #include "net/socket/next_proto.h"
26 #include "net/socket/socket_test_util.h"
27 #include "net/socket_stream/socket_stream.h"
28 #include "net/spdy/spdy_session.h"
29 #include "net/spdy/spdy_websocket_test_util.h"
30 #include "net/ssl/ssl_config_service.h"
31 #include "net/url_request/url_request_context.h"
32 #include "net/websockets/websocket_throttle.h"
33 #include "testing/gmock/include/gmock/gmock.h"
34 #include "testing/gtest/include/gtest/gtest.h"
35 #include "testing/platform_test.h"
36 #include "url/gurl.h"
37
38 namespace net {
39
40 namespace {
41
42 class MockSocketStream : public SocketStream {
43 public:
MockSocketStream(const GURL & url,SocketStream::Delegate * delegate)44 MockSocketStream(const GURL& url, SocketStream::Delegate* delegate)
45 : SocketStream(url, delegate) {}
46
Connect()47 virtual void Connect() OVERRIDE {}
SendData(const char * data,int len)48 virtual bool SendData(const char* data, int len) OVERRIDE {
49 sent_data_ += std::string(data, len);
50 return true;
51 }
52
Close()53 virtual void Close() OVERRIDE {}
RestartWithAuth(const AuthCredentials & credentials)54 virtual void RestartWithAuth(
55 const AuthCredentials& credentials) OVERRIDE {
56 }
57
DetachDelegate()58 virtual void DetachDelegate() OVERRIDE {
59 delegate_ = NULL;
60 }
61
sent_data() const62 const std::string& sent_data() const {
63 return sent_data_;
64 }
65
66 protected:
~MockSocketStream()67 virtual ~MockSocketStream() {}
68
69 private:
70 std::string sent_data_;
71 };
72
73 class MockSocketStreamDelegate : public SocketStream::Delegate {
74 public:
MockSocketStreamDelegate()75 MockSocketStreamDelegate()
76 : amount_sent_(0), allow_all_cookies_(true) {}
set_allow_all_cookies(bool allow_all_cookies)77 void set_allow_all_cookies(bool allow_all_cookies) {
78 allow_all_cookies_ = allow_all_cookies;
79 }
~MockSocketStreamDelegate()80 virtual ~MockSocketStreamDelegate() {}
81
SetOnStartOpenConnection(const base::Closure & callback)82 void SetOnStartOpenConnection(const base::Closure& callback) {
83 on_start_open_connection_ = callback;
84 }
SetOnConnected(const base::Closure & callback)85 void SetOnConnected(const base::Closure& callback) {
86 on_connected_ = callback;
87 }
SetOnSentData(const base::Closure & callback)88 void SetOnSentData(const base::Closure& callback) {
89 on_sent_data_ = callback;
90 }
SetOnReceivedData(const base::Closure & callback)91 void SetOnReceivedData(const base::Closure& callback) {
92 on_received_data_ = callback;
93 }
SetOnClose(const base::Closure & callback)94 void SetOnClose(const base::Closure& callback) {
95 on_close_ = callback;
96 }
97
OnStartOpenConnection(SocketStream * socket,const CompletionCallback & callback)98 virtual int OnStartOpenConnection(
99 SocketStream* socket,
100 const CompletionCallback& callback) OVERRIDE {
101 if (!on_start_open_connection_.is_null())
102 on_start_open_connection_.Run();
103 return OK;
104 }
OnConnected(SocketStream * socket,int max_pending_send_allowed)105 virtual void OnConnected(SocketStream* socket,
106 int max_pending_send_allowed) OVERRIDE {
107 if (!on_connected_.is_null())
108 on_connected_.Run();
109 }
OnSentData(SocketStream * socket,int amount_sent)110 virtual void OnSentData(SocketStream* socket,
111 int amount_sent) OVERRIDE {
112 amount_sent_ += amount_sent;
113 if (!on_sent_data_.is_null())
114 on_sent_data_.Run();
115 }
OnReceivedData(SocketStream * socket,const char * data,int len)116 virtual void OnReceivedData(SocketStream* socket,
117 const char* data, int len) OVERRIDE {
118 received_data_ += std::string(data, len);
119 if (!on_received_data_.is_null())
120 on_received_data_.Run();
121 }
OnClose(SocketStream * socket)122 virtual void OnClose(SocketStream* socket) OVERRIDE {
123 if (!on_close_.is_null())
124 on_close_.Run();
125 }
CanGetCookies(SocketStream * socket,const GURL & url)126 virtual bool CanGetCookies(SocketStream* socket,
127 const GURL& url) OVERRIDE {
128 return allow_all_cookies_;
129 }
CanSetCookie(SocketStream * request,const GURL & url,const std::string & cookie_line,CookieOptions * options)130 virtual bool CanSetCookie(SocketStream* request,
131 const GURL& url,
132 const std::string& cookie_line,
133 CookieOptions* options) OVERRIDE {
134 return allow_all_cookies_;
135 }
136
amount_sent() const137 size_t amount_sent() const { return amount_sent_; }
received_data() const138 const std::string& received_data() const { return received_data_; }
139
140 private:
141 int amount_sent_;
142 bool allow_all_cookies_;
143 std::string received_data_;
144 base::Closure on_start_open_connection_;
145 base::Closure on_connected_;
146 base::Closure on_sent_data_;
147 base::Closure on_received_data_;
148 base::Closure on_close_;
149 };
150
151 class MockCookieStore : public CookieStore {
152 public:
153 struct Entry {
154 GURL url;
155 std::string cookie_line;
156 CookieOptions options;
157 };
158
MockCookieStore()159 MockCookieStore() {}
160
SetCookieWithOptions(const GURL & url,const std::string & cookie_line,const CookieOptions & options)161 bool SetCookieWithOptions(const GURL& url,
162 const std::string& cookie_line,
163 const CookieOptions& options) {
164 Entry entry;
165 entry.url = url;
166 entry.cookie_line = cookie_line;
167 entry.options = options;
168 entries_.push_back(entry);
169 return true;
170 }
171
GetCookiesWithOptions(const GURL & url,const CookieOptions & options)172 std::string GetCookiesWithOptions(const GURL& url,
173 const CookieOptions& options) {
174 std::string result;
175 for (size_t i = 0; i < entries_.size(); i++) {
176 Entry& entry = entries_[i];
177 if (url == entry.url) {
178 if (!result.empty()) {
179 result += "; ";
180 }
181 result += entry.cookie_line;
182 }
183 }
184 return result;
185 }
186
187 // CookieStore:
SetCookieWithOptionsAsync(const GURL & url,const std::string & cookie_line,const CookieOptions & options,const SetCookiesCallback & callback)188 virtual void SetCookieWithOptionsAsync(
189 const GURL& url,
190 const std::string& cookie_line,
191 const CookieOptions& options,
192 const SetCookiesCallback& callback) OVERRIDE {
193 bool result = SetCookieWithOptions(url, cookie_line, options);
194 if (!callback.is_null())
195 callback.Run(result);
196 }
197
GetCookiesWithOptionsAsync(const GURL & url,const CookieOptions & options,const GetCookiesCallback & callback)198 virtual void GetCookiesWithOptionsAsync(
199 const GURL& url,
200 const CookieOptions& options,
201 const GetCookiesCallback& callback) OVERRIDE {
202 if (!callback.is_null())
203 callback.Run(GetCookiesWithOptions(url, options));
204 }
205
DeleteCookieAsync(const GURL & url,const std::string & cookie_name,const base::Closure & callback)206 virtual void DeleteCookieAsync(const GURL& url,
207 const std::string& cookie_name,
208 const base::Closure& callback) OVERRIDE {
209 ADD_FAILURE();
210 }
211
DeleteAllCreatedBetweenAsync(const base::Time & delete_begin,const base::Time & delete_end,const DeleteCallback & callback)212 virtual void DeleteAllCreatedBetweenAsync(
213 const base::Time& delete_begin,
214 const base::Time& delete_end,
215 const DeleteCallback& callback) OVERRIDE {
216 ADD_FAILURE();
217 }
218
DeleteSessionCookiesAsync(const DeleteCallback &)219 virtual void DeleteSessionCookiesAsync(const DeleteCallback&) OVERRIDE {
220 ADD_FAILURE();
221 }
222
GetCookieMonster()223 virtual CookieMonster* GetCookieMonster() OVERRIDE { return NULL; }
224
entries() const225 const std::vector<Entry>& entries() const { return entries_; }
226
227 private:
228 friend class base::RefCountedThreadSafe<MockCookieStore>;
~MockCookieStore()229 virtual ~MockCookieStore() {}
230
231 std::vector<Entry> entries_;
232 };
233
234 class MockSSLConfigService : public SSLConfigService {
235 public:
GetSSLConfig(SSLConfig * config)236 virtual void GetSSLConfig(SSLConfig* config) OVERRIDE {}
237
238 protected:
~MockSSLConfigService()239 virtual ~MockSSLConfigService() {}
240 };
241
242 class MockURLRequestContext : public URLRequestContext {
243 public:
MockURLRequestContext(CookieStore * cookie_store)244 explicit MockURLRequestContext(CookieStore* cookie_store)
245 : transport_security_state_() {
246 set_cookie_store(cookie_store);
247 set_transport_security_state(&transport_security_state_);
248 base::Time expiry = base::Time::Now() + base::TimeDelta::FromDays(1000);
249 bool include_subdomains = false;
250 transport_security_state_.AddHSTS("upgrademe.com", expiry,
251 include_subdomains);
252 }
253
~MockURLRequestContext()254 virtual ~MockURLRequestContext() {}
255
256 private:
257 TransportSecurityState transport_security_state_;
258 };
259
260 class MockHttpTransactionFactory : public HttpTransactionFactory {
261 public:
MockHttpTransactionFactory(NextProto next_proto,OrderedSocketData * data)262 MockHttpTransactionFactory(NextProto next_proto, OrderedSocketData* data) {
263 data_ = data;
264 MockConnect connect_data(SYNCHRONOUS, OK);
265 data_->set_connect_data(connect_data);
266 session_deps_.reset(new SpdySessionDependencies(next_proto));
267 session_deps_->socket_factory->AddSocketDataProvider(data_);
268 http_session_ =
269 SpdySessionDependencies::SpdyCreateSession(session_deps_.get());
270 host_port_pair_.set_host("example.com");
271 host_port_pair_.set_port(80);
272 spdy_session_key_ = SpdySessionKey(host_port_pair_,
273 ProxyServer::Direct(),
274 kPrivacyModeDisabled);
275 session_ = CreateInsecureSpdySession(
276 http_session_, spdy_session_key_, BoundNetLog());
277 }
278
CreateTransaction(RequestPriority priority,scoped_ptr<HttpTransaction> * trans,HttpTransactionDelegate * delegate)279 virtual int CreateTransaction(
280 RequestPriority priority,
281 scoped_ptr<HttpTransaction>* trans,
282 HttpTransactionDelegate* delegate) OVERRIDE {
283 NOTREACHED();
284 return ERR_UNEXPECTED;
285 }
286
GetCache()287 virtual HttpCache* GetCache() OVERRIDE {
288 NOTREACHED();
289 return NULL;
290 }
291
GetSession()292 virtual HttpNetworkSession* GetSession() OVERRIDE {
293 return http_session_.get();
294 }
295
296 private:
297 OrderedSocketData* data_;
298 scoped_ptr<SpdySessionDependencies> session_deps_;
299 scoped_refptr<HttpNetworkSession> http_session_;
300 base::WeakPtr<SpdySession> session_;
301 HostPortPair host_port_pair_;
302 SpdySessionKey spdy_session_key_;
303 };
304
305 } // namespace
306
307 class WebSocketJobTest : public PlatformTest,
308 public ::testing::WithParamInterface<NextProto> {
309 public:
WebSocketJobTest()310 WebSocketJobTest() : spdy_util_(GetParam()) {}
311
SetUp()312 virtual void SetUp() OVERRIDE {
313 stream_type_ = STREAM_INVALID;
314 cookie_store_ = new MockCookieStore;
315 context_.reset(new MockURLRequestContext(cookie_store_.get()));
316 }
TearDown()317 virtual void TearDown() OVERRIDE {
318 cookie_store_ = NULL;
319 context_.reset();
320 websocket_ = NULL;
321 socket_ = NULL;
322 }
DoSendRequest()323 void DoSendRequest() {
324 EXPECT_TRUE(websocket_->SendData(kHandshakeRequestWithoutCookie,
325 kHandshakeRequestWithoutCookieLength));
326 }
DoSendData()327 void DoSendData() {
328 if (received_data().size() == kHandshakeResponseWithoutCookieLength)
329 websocket_->SendData(kDataHello, kDataHelloLength);
330 }
DoSync()331 void DoSync() {
332 sync_test_callback_.callback().Run(OK);
333 }
WaitForResult()334 int WaitForResult() {
335 return sync_test_callback_.WaitForResult();
336 }
337 protected:
338 enum StreamType {
339 STREAM_INVALID,
340 STREAM_MOCK_SOCKET,
341 STREAM_SOCKET,
342 STREAM_SPDY_WEBSOCKET,
343 };
344 enum ThrottlingOption {
345 THROTTLING_OFF,
346 THROTTLING_ON,
347 };
348 enum SpdyOption {
349 SPDY_OFF,
350 SPDY_ON,
351 };
InitWebSocketJob(const GURL & url,MockSocketStreamDelegate * delegate,StreamType stream_type)352 void InitWebSocketJob(const GURL& url,
353 MockSocketStreamDelegate* delegate,
354 StreamType stream_type) {
355 DCHECK_NE(STREAM_INVALID, stream_type);
356 stream_type_ = stream_type;
357 websocket_ = new WebSocketJob(delegate);
358
359 if (stream_type == STREAM_MOCK_SOCKET)
360 socket_ = new MockSocketStream(url, websocket_.get());
361
362 if (stream_type == STREAM_SOCKET || stream_type == STREAM_SPDY_WEBSOCKET) {
363 if (stream_type == STREAM_SPDY_WEBSOCKET) {
364 http_factory_.reset(
365 new MockHttpTransactionFactory(GetParam(), data_.get()));
366 context_->set_http_transaction_factory(http_factory_.get());
367 }
368
369 ssl_config_service_ = new MockSSLConfigService();
370 context_->set_ssl_config_service(ssl_config_service_.get());
371 proxy_service_.reset(ProxyService::CreateDirect());
372 context_->set_proxy_service(proxy_service_.get());
373 host_resolver_.reset(new MockHostResolver);
374 context_->set_host_resolver(host_resolver_.get());
375
376 socket_ = new SocketStream(url, websocket_.get());
377 socket_factory_.reset(new MockClientSocketFactory);
378 DCHECK(data_.get());
379 socket_factory_->AddSocketDataProvider(data_.get());
380 socket_->SetClientSocketFactory(socket_factory_.get());
381 }
382
383 websocket_->InitSocketStream(socket_.get());
384 websocket_->set_context(context_.get());
385 // MockHostResolver resolves all hosts to 127.0.0.1; however, when we create
386 // a WebSocketJob purely to block another one in a throttling test, we don't
387 // perform a real connect. In that case, the following address is used
388 // instead.
389 IPAddressNumber ip;
390 ParseIPLiteralToNumber("127.0.0.1", &ip);
391 websocket_->addresses_ = AddressList::CreateFromIPAddress(ip, 80);
392 }
SkipToConnecting()393 void SkipToConnecting() {
394 websocket_->state_ = WebSocketJob::CONNECTING;
395 ASSERT_TRUE(WebSocketThrottle::GetInstance()->PutInQueue(websocket_.get()));
396 }
GetWebSocketJobState()397 WebSocketJob::State GetWebSocketJobState() {
398 return websocket_->state_;
399 }
CloseWebSocketJob()400 void CloseWebSocketJob() {
401 if (websocket_->socket_.get()) {
402 websocket_->socket_->DetachDelegate();
403 WebSocketThrottle::GetInstance()->RemoveFromQueue(websocket_.get());
404 }
405 websocket_->state_ = WebSocketJob::CLOSED;
406 websocket_->delegate_ = NULL;
407 websocket_->socket_ = NULL;
408 }
GetSocket(SocketStreamJob * job)409 SocketStream* GetSocket(SocketStreamJob* job) {
410 return job->socket_.get();
411 }
sent_data() const412 const std::string& sent_data() const {
413 DCHECK_EQ(STREAM_MOCK_SOCKET, stream_type_);
414 MockSocketStream* socket =
415 static_cast<MockSocketStream*>(socket_.get());
416 DCHECK(socket);
417 return socket->sent_data();
418 }
received_data() const419 const std::string& received_data() const {
420 DCHECK_NE(STREAM_INVALID, stream_type_);
421 MockSocketStreamDelegate* delegate =
422 static_cast<MockSocketStreamDelegate*>(websocket_->delegate_);
423 DCHECK(delegate);
424 return delegate->received_data();
425 }
426
427 void TestSimpleHandshake();
428 void TestSlowHandshake();
429 void TestHandshakeWithCookie();
430 void TestHandshakeWithCookieButNotAllowed();
431 void TestHSTSUpgrade();
432 void TestInvalidSendData();
433 void TestConnectByWebSocket(ThrottlingOption throttling);
434 void TestConnectBySpdy(SpdyOption spdy, ThrottlingOption throttling);
435 void TestThrottlingLimit();
436
437 SpdyWebSocketTestUtil spdy_util_;
438 StreamType stream_type_;
439 scoped_refptr<MockCookieStore> cookie_store_;
440 scoped_ptr<MockURLRequestContext> context_;
441 scoped_refptr<WebSocketJob> websocket_;
442 scoped_refptr<SocketStream> socket_;
443 scoped_ptr<MockClientSocketFactory> socket_factory_;
444 scoped_ptr<OrderedSocketData> data_;
445 TestCompletionCallback sync_test_callback_;
446 scoped_refptr<MockSSLConfigService> ssl_config_service_;
447 scoped_ptr<ProxyService> proxy_service_;
448 scoped_ptr<MockHostResolver> host_resolver_;
449 scoped_ptr<MockHttpTransactionFactory> http_factory_;
450
451 static const char kHandshakeRequestWithoutCookie[];
452 static const char kHandshakeRequestWithCookie[];
453 static const char kHandshakeRequestWithFilteredCookie[];
454 static const char kHandshakeResponseWithoutCookie[];
455 static const char kHandshakeResponseWithCookie[];
456 static const char kDataHello[];
457 static const char kDataWorld[];
458 static const char* const kHandshakeRequestForSpdy[];
459 static const char* const kHandshakeResponseForSpdy[];
460 static const size_t kHandshakeRequestWithoutCookieLength;
461 static const size_t kHandshakeRequestWithCookieLength;
462 static const size_t kHandshakeRequestWithFilteredCookieLength;
463 static const size_t kHandshakeResponseWithoutCookieLength;
464 static const size_t kHandshakeResponseWithCookieLength;
465 static const size_t kDataHelloLength;
466 static const size_t kDataWorldLength;
467 };
468
469 const char WebSocketJobTest::kHandshakeRequestWithoutCookie[] =
470 "GET /demo HTTP/1.1\r\n"
471 "Host: example.com\r\n"
472 "Upgrade: WebSocket\r\n"
473 "Connection: Upgrade\r\n"
474 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
475 "Origin: http://example.com\r\n"
476 "Sec-WebSocket-Protocol: sample\r\n"
477 "Sec-WebSocket-Version: 13\r\n"
478 "\r\n";
479
480 const char WebSocketJobTest::kHandshakeRequestWithCookie[] =
481 "GET /demo HTTP/1.1\r\n"
482 "Host: example.com\r\n"
483 "Upgrade: WebSocket\r\n"
484 "Connection: Upgrade\r\n"
485 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
486 "Origin: http://example.com\r\n"
487 "Sec-WebSocket-Protocol: sample\r\n"
488 "Sec-WebSocket-Version: 13\r\n"
489 "Cookie: WK-test=1\r\n"
490 "\r\n";
491
492 const char WebSocketJobTest::kHandshakeRequestWithFilteredCookie[] =
493 "GET /demo HTTP/1.1\r\n"
494 "Host: example.com\r\n"
495 "Upgrade: WebSocket\r\n"
496 "Connection: Upgrade\r\n"
497 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
498 "Origin: http://example.com\r\n"
499 "Sec-WebSocket-Protocol: sample\r\n"
500 "Sec-WebSocket-Version: 13\r\n"
501 "Cookie: CR-test=1; CR-test-httponly=1\r\n"
502 "\r\n";
503
504 const char WebSocketJobTest::kHandshakeResponseWithoutCookie[] =
505 "HTTP/1.1 101 Switching Protocols\r\n"
506 "Upgrade: websocket\r\n"
507 "Connection: Upgrade\r\n"
508 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
509 "Sec-WebSocket-Protocol: sample\r\n"
510 "\r\n";
511
512 const char WebSocketJobTest::kHandshakeResponseWithCookie[] =
513 "HTTP/1.1 101 Switching Protocols\r\n"
514 "Upgrade: websocket\r\n"
515 "Connection: Upgrade\r\n"
516 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
517 "Sec-WebSocket-Protocol: sample\r\n"
518 "Set-Cookie: CR-set-test=1\r\n"
519 "\r\n";
520
521 const char WebSocketJobTest::kDataHello[] = "Hello, ";
522
523 const char WebSocketJobTest::kDataWorld[] = "World!\n";
524
525 const size_t WebSocketJobTest::kHandshakeRequestWithoutCookieLength =
526 arraysize(kHandshakeRequestWithoutCookie) - 1;
527 const size_t WebSocketJobTest::kHandshakeRequestWithCookieLength =
528 arraysize(kHandshakeRequestWithCookie) - 1;
529 const size_t WebSocketJobTest::kHandshakeRequestWithFilteredCookieLength =
530 arraysize(kHandshakeRequestWithFilteredCookie) - 1;
531 const size_t WebSocketJobTest::kHandshakeResponseWithoutCookieLength =
532 arraysize(kHandshakeResponseWithoutCookie) - 1;
533 const size_t WebSocketJobTest::kHandshakeResponseWithCookieLength =
534 arraysize(kHandshakeResponseWithCookie) - 1;
535 const size_t WebSocketJobTest::kDataHelloLength =
536 arraysize(kDataHello) - 1;
537 const size_t WebSocketJobTest::kDataWorldLength =
538 arraysize(kDataWorld) - 1;
539
TestSimpleHandshake()540 void WebSocketJobTest::TestSimpleHandshake() {
541 GURL url("ws://example.com/demo");
542 MockSocketStreamDelegate delegate;
543 InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
544 SkipToConnecting();
545
546 DoSendRequest();
547 base::MessageLoop::current()->RunUntilIdle();
548 EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
549 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
550 websocket_->OnSentData(socket_.get(),
551 kHandshakeRequestWithoutCookieLength);
552 EXPECT_EQ(kHandshakeRequestWithoutCookieLength, delegate.amount_sent());
553
554 websocket_->OnReceivedData(socket_.get(),
555 kHandshakeResponseWithoutCookie,
556 kHandshakeResponseWithoutCookieLength);
557 base::MessageLoop::current()->RunUntilIdle();
558 EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
559 EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
560 CloseWebSocketJob();
561 }
562
TestSlowHandshake()563 void WebSocketJobTest::TestSlowHandshake() {
564 GURL url("ws://example.com/demo");
565 MockSocketStreamDelegate delegate;
566 InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
567 SkipToConnecting();
568
569 DoSendRequest();
570 // We assume request is sent in one data chunk (from WebKit)
571 // We don't support streaming request.
572 base::MessageLoop::current()->RunUntilIdle();
573 EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
574 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
575 websocket_->OnSentData(socket_.get(),
576 kHandshakeRequestWithoutCookieLength);
577 EXPECT_EQ(kHandshakeRequestWithoutCookieLength, delegate.amount_sent());
578
579 std::vector<std::string> lines;
580 base::SplitString(kHandshakeResponseWithoutCookie, '\n', &lines);
581 for (size_t i = 0; i < lines.size() - 2; i++) {
582 std::string line = lines[i] + "\r\n";
583 SCOPED_TRACE("Line: " + line);
584 websocket_->OnReceivedData(socket_.get(), line.c_str(), line.size());
585 base::MessageLoop::current()->RunUntilIdle();
586 EXPECT_TRUE(delegate.received_data().empty());
587 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
588 }
589 websocket_->OnReceivedData(socket_.get(), "\r\n", 2);
590 base::MessageLoop::current()->RunUntilIdle();
591 EXPECT_FALSE(delegate.received_data().empty());
592 EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
593 EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
594 CloseWebSocketJob();
595 }
596
597 INSTANTIATE_TEST_CASE_P(
598 NextProto,
599 WebSocketJobTest,
600 testing::Values(kProtoDeprecatedSPDY2,
601 kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
602 kProtoHTTP2Draft04));
603
TEST_P(WebSocketJobTest,DelayedCookies)604 TEST_P(WebSocketJobTest, DelayedCookies) {
605 WebSocketJob::set_websocket_over_spdy_enabled(true);
606 GURL url("ws://example.com/demo");
607 GURL cookieUrl("http://example.com/demo");
608 CookieOptions cookie_options;
609 scoped_refptr<DelayedCookieMonster> cookie_store = new DelayedCookieMonster();
610 context_->set_cookie_store(cookie_store.get());
611 cookie_store->SetCookieWithOptionsAsync(cookieUrl,
612 "CR-test=1",
613 cookie_options,
614 CookieMonster::SetCookiesCallback());
615 cookie_options.set_include_httponly();
616 cookie_store->SetCookieWithOptionsAsync(
617 cookieUrl, "CR-test-httponly=1", cookie_options,
618 CookieMonster::SetCookiesCallback());
619
620 MockSocketStreamDelegate delegate;
621 InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
622 SkipToConnecting();
623
624 bool sent = websocket_->SendData(kHandshakeRequestWithCookie,
625 kHandshakeRequestWithCookieLength);
626 EXPECT_TRUE(sent);
627 base::MessageLoop::current()->RunUntilIdle();
628 EXPECT_EQ(kHandshakeRequestWithFilteredCookie, sent_data());
629 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
630 websocket_->OnSentData(socket_.get(),
631 kHandshakeRequestWithFilteredCookieLength);
632 EXPECT_EQ(kHandshakeRequestWithCookieLength,
633 delegate.amount_sent());
634
635 websocket_->OnReceivedData(socket_.get(),
636 kHandshakeResponseWithCookie,
637 kHandshakeResponseWithCookieLength);
638 base::MessageLoop::current()->RunUntilIdle();
639 EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
640 EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
641
642 CloseWebSocketJob();
643 }
644
TestHandshakeWithCookie()645 void WebSocketJobTest::TestHandshakeWithCookie() {
646 GURL url("ws://example.com/demo");
647 GURL cookieUrl("http://example.com/demo");
648 CookieOptions cookie_options;
649 cookie_store_->SetCookieWithOptions(
650 cookieUrl, "CR-test=1", cookie_options);
651 cookie_options.set_include_httponly();
652 cookie_store_->SetCookieWithOptions(
653 cookieUrl, "CR-test-httponly=1", cookie_options);
654
655 MockSocketStreamDelegate delegate;
656 InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
657 SkipToConnecting();
658
659 bool sent = websocket_->SendData(kHandshakeRequestWithCookie,
660 kHandshakeRequestWithCookieLength);
661 EXPECT_TRUE(sent);
662 base::MessageLoop::current()->RunUntilIdle();
663 EXPECT_EQ(kHandshakeRequestWithFilteredCookie, sent_data());
664 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
665 websocket_->OnSentData(socket_.get(),
666 kHandshakeRequestWithFilteredCookieLength);
667 EXPECT_EQ(kHandshakeRequestWithCookieLength,
668 delegate.amount_sent());
669
670 websocket_->OnReceivedData(socket_.get(),
671 kHandshakeResponseWithCookie,
672 kHandshakeResponseWithCookieLength);
673 base::MessageLoop::current()->RunUntilIdle();
674 EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
675 EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
676
677 EXPECT_EQ(3U, cookie_store_->entries().size());
678 EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
679 EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
680 EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
681 EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
682 EXPECT_EQ(cookieUrl, cookie_store_->entries()[2].url);
683 EXPECT_EQ("CR-set-test=1", cookie_store_->entries()[2].cookie_line);
684
685 CloseWebSocketJob();
686 }
687
TestHandshakeWithCookieButNotAllowed()688 void WebSocketJobTest::TestHandshakeWithCookieButNotAllowed() {
689 GURL url("ws://example.com/demo");
690 GURL cookieUrl("http://example.com/demo");
691 CookieOptions cookie_options;
692 cookie_store_->SetCookieWithOptions(
693 cookieUrl, "CR-test=1", cookie_options);
694 cookie_options.set_include_httponly();
695 cookie_store_->SetCookieWithOptions(
696 cookieUrl, "CR-test-httponly=1", cookie_options);
697
698 MockSocketStreamDelegate delegate;
699 delegate.set_allow_all_cookies(false);
700 InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
701 SkipToConnecting();
702
703 bool sent = websocket_->SendData(kHandshakeRequestWithCookie,
704 kHandshakeRequestWithCookieLength);
705 EXPECT_TRUE(sent);
706 base::MessageLoop::current()->RunUntilIdle();
707 EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
708 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
709 websocket_->OnSentData(socket_.get(), kHandshakeRequestWithoutCookieLength);
710 EXPECT_EQ(kHandshakeRequestWithCookieLength, delegate.amount_sent());
711
712 websocket_->OnReceivedData(socket_.get(),
713 kHandshakeResponseWithCookie,
714 kHandshakeResponseWithCookieLength);
715 base::MessageLoop::current()->RunUntilIdle();
716 EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
717 EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
718
719 EXPECT_EQ(2U, cookie_store_->entries().size());
720 EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
721 EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
722 EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
723 EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
724
725 CloseWebSocketJob();
726 }
727
TestHSTSUpgrade()728 void WebSocketJobTest::TestHSTSUpgrade() {
729 GURL url("ws://upgrademe.com/");
730 MockSocketStreamDelegate delegate;
731 scoped_refptr<SocketStreamJob> job =
732 SocketStreamJob::CreateSocketStreamJob(
733 url, &delegate, context_->transport_security_state(),
734 context_->ssl_config_service());
735 EXPECT_TRUE(GetSocket(job.get())->is_secure());
736 job->DetachDelegate();
737
738 url = GURL("ws://donotupgrademe.com/");
739 job = SocketStreamJob::CreateSocketStreamJob(
740 url, &delegate, context_->transport_security_state(),
741 context_->ssl_config_service());
742 EXPECT_FALSE(GetSocket(job.get())->is_secure());
743 job->DetachDelegate();
744 }
745
TestInvalidSendData()746 void WebSocketJobTest::TestInvalidSendData() {
747 GURL url("ws://example.com/demo");
748 MockSocketStreamDelegate delegate;
749 InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
750 SkipToConnecting();
751
752 DoSendRequest();
753 // We assume request is sent in one data chunk (from WebKit)
754 // We don't support streaming request.
755 base::MessageLoop::current()->RunUntilIdle();
756 EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
757 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
758 websocket_->OnSentData(socket_.get(),
759 kHandshakeRequestWithoutCookieLength);
760 EXPECT_EQ(kHandshakeRequestWithoutCookieLength, delegate.amount_sent());
761
762 // We could not send any data until connection is established.
763 bool sent = websocket_->SendData(kHandshakeRequestWithoutCookie,
764 kHandshakeRequestWithoutCookieLength);
765 EXPECT_FALSE(sent);
766 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
767 CloseWebSocketJob();
768 }
769
770 // Following tests verify cooperation between WebSocketJob and SocketStream.
771 // Other former tests use MockSocketStream as SocketStream, so we could not
772 // check SocketStream behavior.
773 // OrderedSocketData provide socket level verifiation by checking out-going
774 // packets in comparison with the MockWrite array and emulating in-coming
775 // packets with MockRead array.
776
TestConnectByWebSocket(ThrottlingOption throttling)777 void WebSocketJobTest::TestConnectByWebSocket(
778 ThrottlingOption throttling) {
779 // This is a test for verifying cooperation between WebSocketJob and
780 // SocketStream. If |throttling| was |THROTTLING_OFF|, it test basic
781 // situation. If |throttling| was |THROTTLING_ON|, throttling limits the
782 // latter connection.
783 MockWrite writes[] = {
784 MockWrite(ASYNC,
785 kHandshakeRequestWithoutCookie,
786 kHandshakeRequestWithoutCookieLength,
787 1),
788 MockWrite(ASYNC,
789 kDataHello,
790 kDataHelloLength,
791 3)
792 };
793 MockRead reads[] = {
794 MockRead(ASYNC,
795 kHandshakeResponseWithoutCookie,
796 kHandshakeResponseWithoutCookieLength,
797 2),
798 MockRead(ASYNC,
799 kDataWorld,
800 kDataWorldLength,
801 4),
802 MockRead(SYNCHRONOUS, 0, 5) // EOF
803 };
804 data_.reset(new OrderedSocketData(
805 reads, arraysize(reads), writes, arraysize(writes)));
806
807 GURL url("ws://example.com/demo");
808 MockSocketStreamDelegate delegate;
809 WebSocketJobTest* test = this;
810 if (throttling == THROTTLING_ON)
811 delegate.SetOnStartOpenConnection(
812 base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
813 delegate.SetOnConnected(
814 base::Bind(&WebSocketJobTest::DoSendRequest,
815 base::Unretained(test)));
816 delegate.SetOnReceivedData(
817 base::Bind(&WebSocketJobTest::DoSendData, base::Unretained(test)));
818 delegate.SetOnClose(
819 base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
820 InitWebSocketJob(url, &delegate, STREAM_SOCKET);
821
822 scoped_refptr<WebSocketJob> block_websocket;
823 if (throttling == THROTTLING_ON) {
824 // Create former WebSocket object which obstructs the latter one.
825 block_websocket = new WebSocketJob(NULL);
826 block_websocket->addresses_ = AddressList(websocket_->address_list());
827 ASSERT_TRUE(
828 WebSocketThrottle::GetInstance()->PutInQueue(block_websocket.get()));
829 }
830
831 websocket_->Connect();
832
833 if (throttling == THROTTLING_ON) {
834 EXPECT_EQ(OK, WaitForResult());
835 EXPECT_TRUE(websocket_->IsWaiting());
836
837 // Remove the former WebSocket object from throttling queue to unblock the
838 // latter.
839 block_websocket->state_ = WebSocketJob::CLOSED;
840 WebSocketThrottle::GetInstance()->RemoveFromQueue(block_websocket.get());
841 block_websocket = NULL;
842 }
843
844 EXPECT_EQ(OK, WaitForResult());
845 EXPECT_TRUE(data_->at_read_eof());
846 EXPECT_TRUE(data_->at_write_eof());
847 EXPECT_EQ(WebSocketJob::CLOSED, GetWebSocketJobState());
848 }
849
TestConnectBySpdy(SpdyOption spdy,ThrottlingOption throttling)850 void WebSocketJobTest::TestConnectBySpdy(
851 SpdyOption spdy, ThrottlingOption throttling) {
852 // This is a test for verifying cooperation between WebSocketJob and
853 // SocketStream in the situation we have SPDY session to the server. If
854 // |throttling| was |THROTTLING_ON|, throttling limits the latter connection.
855 // If you enabled spdy, you should specify |spdy| as |SPDY_ON|. Expected
856 // results depend on its configuration.
857 MockWrite writes_websocket[] = {
858 MockWrite(ASYNC,
859 kHandshakeRequestWithoutCookie,
860 kHandshakeRequestWithoutCookieLength,
861 1),
862 MockWrite(ASYNC,
863 kDataHello,
864 kDataHelloLength,
865 3)
866 };
867 MockRead reads_websocket[] = {
868 MockRead(ASYNC,
869 kHandshakeResponseWithoutCookie,
870 kHandshakeResponseWithoutCookieLength,
871 2),
872 MockRead(ASYNC,
873 kDataWorld,
874 kDataWorldLength,
875 4),
876 MockRead(SYNCHRONOUS, 0, 5) // EOF
877 };
878
879 scoped_ptr<SpdyHeaderBlock> request_headers(new SpdyHeaderBlock());
880 spdy_util_.SetHeader("path", "/demo", request_headers.get());
881 spdy_util_.SetHeader("version", "WebSocket/13", request_headers.get());
882 spdy_util_.SetHeader("scheme", "ws", request_headers.get());
883 spdy_util_.SetHeader("host", "example.com", request_headers.get());
884 spdy_util_.SetHeader("origin", "http://example.com", request_headers.get());
885 spdy_util_.SetHeader("sec-websocket-protocol", "sample",
886 request_headers.get());
887
888 scoped_ptr<SpdyHeaderBlock> response_headers(new SpdyHeaderBlock());
889 spdy_util_.SetHeader("status", "101 Switching Protocols",
890 response_headers.get());
891 spdy_util_.SetHeader("sec-websocket-protocol", "sample",
892 response_headers.get());
893
894 const SpdyStreamId kStreamId = 1;
895 scoped_ptr<SpdyFrame> request_frame(
896 spdy_util_.ConstructSpdyWebSocketHandshakeRequestFrame(
897 request_headers.Pass(),
898 kStreamId,
899 MEDIUM));
900 scoped_ptr<SpdyFrame> response_frame(
901 spdy_util_.ConstructSpdyWebSocketHandshakeResponseFrame(
902 response_headers.Pass(),
903 kStreamId,
904 MEDIUM));
905 scoped_ptr<SpdyFrame> data_hello_frame(
906 spdy_util_.ConstructSpdyWebSocketDataFrame(
907 kDataHello,
908 kDataHelloLength,
909 kStreamId,
910 false));
911 scoped_ptr<SpdyFrame> data_world_frame(
912 spdy_util_.ConstructSpdyWebSocketDataFrame(
913 kDataWorld,
914 kDataWorldLength,
915 kStreamId,
916 false));
917 MockWrite writes_spdy[] = {
918 CreateMockWrite(*request_frame.get(), 1),
919 CreateMockWrite(*data_hello_frame.get(), 3),
920 };
921 MockRead reads_spdy[] = {
922 CreateMockRead(*response_frame.get(), 2),
923 CreateMockRead(*data_world_frame.get(), 4),
924 MockRead(SYNCHRONOUS, 0, 5) // EOF
925 };
926
927 if (spdy == SPDY_ON)
928 data_.reset(new OrderedSocketData(
929 reads_spdy, arraysize(reads_spdy),
930 writes_spdy, arraysize(writes_spdy)));
931 else
932 data_.reset(new OrderedSocketData(
933 reads_websocket, arraysize(reads_websocket),
934 writes_websocket, arraysize(writes_websocket)));
935
936 GURL url("ws://example.com/demo");
937 MockSocketStreamDelegate delegate;
938 WebSocketJobTest* test = this;
939 if (throttling == THROTTLING_ON)
940 delegate.SetOnStartOpenConnection(
941 base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
942 delegate.SetOnConnected(
943 base::Bind(&WebSocketJobTest::DoSendRequest,
944 base::Unretained(test)));
945 delegate.SetOnReceivedData(
946 base::Bind(&WebSocketJobTest::DoSendData, base::Unretained(test)));
947 delegate.SetOnClose(
948 base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
949 InitWebSocketJob(url, &delegate, STREAM_SPDY_WEBSOCKET);
950
951 scoped_refptr<WebSocketJob> block_websocket;
952 if (throttling == THROTTLING_ON) {
953 // Create former WebSocket object which obstructs the latter one.
954 block_websocket = new WebSocketJob(NULL);
955 block_websocket->addresses_ = AddressList(websocket_->address_list());
956 ASSERT_TRUE(
957 WebSocketThrottle::GetInstance()->PutInQueue(block_websocket.get()));
958 }
959
960 websocket_->Connect();
961
962 if (throttling == THROTTLING_ON) {
963 EXPECT_EQ(OK, WaitForResult());
964 EXPECT_TRUE(websocket_->IsWaiting());
965
966 // Remove the former WebSocket object from throttling queue to unblock the
967 // latter.
968 block_websocket->state_ = WebSocketJob::CLOSED;
969 WebSocketThrottle::GetInstance()->RemoveFromQueue(block_websocket.get());
970 block_websocket = NULL;
971 }
972
973 EXPECT_EQ(OK, WaitForResult());
974 EXPECT_TRUE(data_->at_read_eof());
975 EXPECT_TRUE(data_->at_write_eof());
976 EXPECT_EQ(WebSocketJob::CLOSED, GetWebSocketJobState());
977 }
978
TestThrottlingLimit()979 void WebSocketJobTest::TestThrottlingLimit() {
980 std::vector<scoped_refptr<WebSocketJob> > jobs;
981 const int kMaxWebSocketJobsThrottled = 1024;
982 IPAddressNumber ip;
983 ParseIPLiteralToNumber("127.0.0.1", &ip);
984 for (int i = 0; i < kMaxWebSocketJobsThrottled + 1; ++i) {
985 scoped_refptr<WebSocketJob> job = new WebSocketJob(NULL);
986 job->addresses_ = AddressList(AddressList::CreateFromIPAddress(ip, 80));
987 if (i >= kMaxWebSocketJobsThrottled)
988 EXPECT_FALSE(WebSocketThrottle::GetInstance()->PutInQueue(job));
989 else
990 EXPECT_TRUE(WebSocketThrottle::GetInstance()->PutInQueue(job));
991 jobs.push_back(job);
992 }
993
994 // Close the jobs in reverse order. Otherwise, We need to make them prepared
995 // for Wakeup call.
996 for (std::vector<scoped_refptr<WebSocketJob> >::reverse_iterator iter =
997 jobs.rbegin();
998 iter != jobs.rend();
999 ++iter) {
1000 WebSocketJob* job = (*iter).get();
1001 job->state_ = WebSocketJob::CLOSED;
1002 WebSocketThrottle::GetInstance()->RemoveFromQueue(job);
1003 }
1004 }
1005
1006 // Execute tests in both spdy-disabled mode and spdy-enabled mode.
TEST_P(WebSocketJobTest,SimpleHandshake)1007 TEST_P(WebSocketJobTest, SimpleHandshake) {
1008 WebSocketJob::set_websocket_over_spdy_enabled(false);
1009 TestSimpleHandshake();
1010 }
1011
TEST_P(WebSocketJobTest,SlowHandshake)1012 TEST_P(WebSocketJobTest, SlowHandshake) {
1013 WebSocketJob::set_websocket_over_spdy_enabled(false);
1014 TestSlowHandshake();
1015 }
1016
TEST_P(WebSocketJobTest,HandshakeWithCookie)1017 TEST_P(WebSocketJobTest, HandshakeWithCookie) {
1018 WebSocketJob::set_websocket_over_spdy_enabled(false);
1019 TestHandshakeWithCookie();
1020 }
1021
TEST_P(WebSocketJobTest,HandshakeWithCookieButNotAllowed)1022 TEST_P(WebSocketJobTest, HandshakeWithCookieButNotAllowed) {
1023 WebSocketJob::set_websocket_over_spdy_enabled(false);
1024 TestHandshakeWithCookieButNotAllowed();
1025 }
1026
TEST_P(WebSocketJobTest,HSTSUpgrade)1027 TEST_P(WebSocketJobTest, HSTSUpgrade) {
1028 WebSocketJob::set_websocket_over_spdy_enabled(false);
1029 TestHSTSUpgrade();
1030 }
1031
TEST_P(WebSocketJobTest,InvalidSendData)1032 TEST_P(WebSocketJobTest, InvalidSendData) {
1033 WebSocketJob::set_websocket_over_spdy_enabled(false);
1034 TestInvalidSendData();
1035 }
1036
TEST_P(WebSocketJobTest,SimpleHandshakeSpdyEnabled)1037 TEST_P(WebSocketJobTest, SimpleHandshakeSpdyEnabled) {
1038 WebSocketJob::set_websocket_over_spdy_enabled(true);
1039 TestSimpleHandshake();
1040 }
1041
TEST_P(WebSocketJobTest,SlowHandshakeSpdyEnabled)1042 TEST_P(WebSocketJobTest, SlowHandshakeSpdyEnabled) {
1043 WebSocketJob::set_websocket_over_spdy_enabled(true);
1044 TestSlowHandshake();
1045 }
1046
TEST_P(WebSocketJobTest,HandshakeWithCookieSpdyEnabled)1047 TEST_P(WebSocketJobTest, HandshakeWithCookieSpdyEnabled) {
1048 WebSocketJob::set_websocket_over_spdy_enabled(true);
1049 TestHandshakeWithCookie();
1050 }
1051
TEST_P(WebSocketJobTest,HandshakeWithCookieButNotAllowedSpdyEnabled)1052 TEST_P(WebSocketJobTest, HandshakeWithCookieButNotAllowedSpdyEnabled) {
1053 WebSocketJob::set_websocket_over_spdy_enabled(true);
1054 TestHandshakeWithCookieButNotAllowed();
1055 }
1056
TEST_P(WebSocketJobTest,HSTSUpgradeSpdyEnabled)1057 TEST_P(WebSocketJobTest, HSTSUpgradeSpdyEnabled) {
1058 WebSocketJob::set_websocket_over_spdy_enabled(true);
1059 TestHSTSUpgrade();
1060 }
1061
TEST_P(WebSocketJobTest,InvalidSendDataSpdyEnabled)1062 TEST_P(WebSocketJobTest, InvalidSendDataSpdyEnabled) {
1063 WebSocketJob::set_websocket_over_spdy_enabled(true);
1064 TestInvalidSendData();
1065 }
1066
TEST_P(WebSocketJobTest,ConnectByWebSocket)1067 TEST_P(WebSocketJobTest, ConnectByWebSocket) {
1068 WebSocketJob::set_websocket_over_spdy_enabled(false);
1069 TestConnectByWebSocket(THROTTLING_OFF);
1070 }
1071
TEST_P(WebSocketJobTest,ConnectByWebSocketSpdyEnabled)1072 TEST_P(WebSocketJobTest, ConnectByWebSocketSpdyEnabled) {
1073 WebSocketJob::set_websocket_over_spdy_enabled(true);
1074 TestConnectByWebSocket(THROTTLING_OFF);
1075 }
1076
TEST_P(WebSocketJobTest,ConnectBySpdy)1077 TEST_P(WebSocketJobTest, ConnectBySpdy) {
1078 WebSocketJob::set_websocket_over_spdy_enabled(false);
1079 TestConnectBySpdy(SPDY_OFF, THROTTLING_OFF);
1080 }
1081
TEST_P(WebSocketJobTest,ConnectBySpdySpdyEnabled)1082 TEST_P(WebSocketJobTest, ConnectBySpdySpdyEnabled) {
1083 WebSocketJob::set_websocket_over_spdy_enabled(true);
1084 TestConnectBySpdy(SPDY_ON, THROTTLING_OFF);
1085 }
1086
TEST_P(WebSocketJobTest,ThrottlingWebSocket)1087 TEST_P(WebSocketJobTest, ThrottlingWebSocket) {
1088 WebSocketJob::set_websocket_over_spdy_enabled(false);
1089 TestConnectByWebSocket(THROTTLING_ON);
1090 }
1091
TEST_P(WebSocketJobTest,ThrottlingMaxNumberOfThrottledJobLimit)1092 TEST_P(WebSocketJobTest, ThrottlingMaxNumberOfThrottledJobLimit) {
1093 TestThrottlingLimit();
1094 }
1095
TEST_P(WebSocketJobTest,ThrottlingWebSocketSpdyEnabled)1096 TEST_P(WebSocketJobTest, ThrottlingWebSocketSpdyEnabled) {
1097 WebSocketJob::set_websocket_over_spdy_enabled(true);
1098 TestConnectByWebSocket(THROTTLING_ON);
1099 }
1100
TEST_P(WebSocketJobTest,ThrottlingSpdy)1101 TEST_P(WebSocketJobTest, ThrottlingSpdy) {
1102 WebSocketJob::set_websocket_over_spdy_enabled(false);
1103 TestConnectBySpdy(SPDY_OFF, THROTTLING_ON);
1104 }
1105
TEST_P(WebSocketJobTest,ThrottlingSpdySpdyEnabled)1106 TEST_P(WebSocketJobTest, ThrottlingSpdySpdyEnabled) {
1107 WebSocketJob::set_websocket_over_spdy_enabled(true);
1108 TestConnectBySpdy(SPDY_ON, THROTTLING_ON);
1109 }
1110
1111 // TODO(toyoshim): Add tests to verify throttling, SPDY stream limitation.
1112 // TODO(toyoshim,yutak): Add tests to verify closing handshake.
1113 } // namespace net
1114