Home | History | Annotate | Download | only in websockets
      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:
     44   MockSocketStream(const GURL& url, SocketStream::Delegate* delegate)
     45       : SocketStream(url, delegate) {}
     46 
     47   virtual void Connect() OVERRIDE {}
     48   virtual bool SendData(const char* data, int len) OVERRIDE {
     49     sent_data_ += std::string(data, len);
     50     return true;
     51   }
     52 
     53   virtual void Close() OVERRIDE {}
     54   virtual void RestartWithAuth(
     55       const AuthCredentials& credentials) OVERRIDE {
     56   }
     57 
     58   virtual void DetachDelegate() OVERRIDE {
     59     delegate_ = NULL;
     60   }
     61 
     62   const std::string& sent_data() const {
     63     return sent_data_;
     64   }
     65 
     66  protected:
     67   virtual ~MockSocketStream() {}
     68 
     69  private:
     70   std::string sent_data_;
     71 };
     72 
     73 class MockSocketStreamDelegate : public SocketStream::Delegate {
     74  public:
     75   MockSocketStreamDelegate()
     76       : amount_sent_(0), allow_all_cookies_(true) {}
     77   void set_allow_all_cookies(bool allow_all_cookies) {
     78     allow_all_cookies_ = allow_all_cookies;
     79   }
     80   virtual ~MockSocketStreamDelegate() {}
     81 
     82   void SetOnStartOpenConnection(const base::Closure& callback) {
     83     on_start_open_connection_ = callback;
     84   }
     85   void SetOnConnected(const base::Closure& callback) {
     86     on_connected_ = callback;
     87   }
     88   void SetOnSentData(const base::Closure& callback) {
     89     on_sent_data_ = callback;
     90   }
     91   void SetOnReceivedData(const base::Closure& callback) {
     92     on_received_data_ = callback;
     93   }
     94   void SetOnClose(const base::Closure& callback) {
     95     on_close_ = callback;
     96   }
     97 
     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   }
    105   virtual void OnConnected(SocketStream* socket,
    106                            int max_pending_send_allowed) OVERRIDE {
    107     if (!on_connected_.is_null())
    108       on_connected_.Run();
    109   }
    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   }
    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   }
    122   virtual void OnClose(SocketStream* socket) OVERRIDE {
    123     if (!on_close_.is_null())
    124       on_close_.Run();
    125   }
    126   virtual bool CanGetCookies(SocketStream* socket,
    127                              const GURL& url) OVERRIDE {
    128     return allow_all_cookies_;
    129   }
    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 
    137   size_t amount_sent() const { return amount_sent_; }
    138   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 
    159   MockCookieStore() {}
    160 
    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 
    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:
    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 
    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 
    206   virtual void DeleteCookieAsync(const GURL& url,
    207                                  const std::string& cookie_name,
    208                                  const base::Closure& callback) OVERRIDE {
    209     ADD_FAILURE();
    210   }
    211 
    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 
    219   virtual void DeleteSessionCookiesAsync(const DeleteCallback&) OVERRIDE {
    220     ADD_FAILURE();
    221   }
    222 
    223   virtual CookieMonster* GetCookieMonster() OVERRIDE { return NULL; }
    224 
    225   const std::vector<Entry>& entries() const { return entries_; }
    226 
    227  private:
    228   friend class base::RefCountedThreadSafe<MockCookieStore>;
    229   virtual ~MockCookieStore() {}
    230 
    231   std::vector<Entry> entries_;
    232 };
    233 
    234 class MockSSLConfigService : public SSLConfigService {
    235  public:
    236   virtual void GetSSLConfig(SSLConfig* config) OVERRIDE {}
    237 
    238  protected:
    239   virtual ~MockSSLConfigService() {}
    240 };
    241 
    242 class MockURLRequestContext : public URLRequestContext {
    243  public:
    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 
    254   virtual ~MockURLRequestContext() {}
    255 
    256  private:
    257   TransportSecurityState transport_security_state_;
    258 };
    259 
    260 class MockHttpTransactionFactory : public HttpTransactionFactory {
    261  public:
    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 
    279   virtual int CreateTransaction(
    280       RequestPriority priority,
    281       scoped_ptr<HttpTransaction>* trans,
    282       HttpTransactionDelegate* delegate) OVERRIDE {
    283     NOTREACHED();
    284     return ERR_UNEXPECTED;
    285   }
    286 
    287   virtual HttpCache* GetCache() OVERRIDE {
    288     NOTREACHED();
    289     return NULL;
    290   }
    291 
    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:
    310   WebSocketJobTest() : spdy_util_(GetParam()) {}
    311 
    312   virtual void SetUp() OVERRIDE {
    313     stream_type_ = STREAM_INVALID;
    314     cookie_store_ = new MockCookieStore;
    315     context_.reset(new MockURLRequestContext(cookie_store_.get()));
    316   }
    317   virtual void TearDown() OVERRIDE {
    318     cookie_store_ = NULL;
    319     context_.reset();
    320     websocket_ = NULL;
    321     socket_ = NULL;
    322   }
    323   void DoSendRequest() {
    324     EXPECT_TRUE(websocket_->SendData(kHandshakeRequestWithoutCookie,
    325                                      kHandshakeRequestWithoutCookieLength));
    326   }
    327   void DoSendData() {
    328     if (received_data().size() == kHandshakeResponseWithoutCookieLength)
    329       websocket_->SendData(kDataHello, kDataHelloLength);
    330   }
    331   void DoSync() {
    332     sync_test_callback_.callback().Run(OK);
    333   }
    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   };
    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   }
    393   void SkipToConnecting() {
    394     websocket_->state_ = WebSocketJob::CONNECTING;
    395     ASSERT_TRUE(WebSocketThrottle::GetInstance()->PutInQueue(websocket_.get()));
    396   }
    397   WebSocketJob::State GetWebSocketJobState() {
    398     return websocket_->state_;
    399   }
    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   }
    409   SocketStream* GetSocket(SocketStreamJob* job) {
    410     return job->socket_.get();
    411   }
    412   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   }
    419   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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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.
   1007 TEST_P(WebSocketJobTest, SimpleHandshake) {
   1008   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1009   TestSimpleHandshake();
   1010 }
   1011 
   1012 TEST_P(WebSocketJobTest, SlowHandshake) {
   1013   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1014   TestSlowHandshake();
   1015 }
   1016 
   1017 TEST_P(WebSocketJobTest, HandshakeWithCookie) {
   1018   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1019   TestHandshakeWithCookie();
   1020 }
   1021 
   1022 TEST_P(WebSocketJobTest, HandshakeWithCookieButNotAllowed) {
   1023   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1024   TestHandshakeWithCookieButNotAllowed();
   1025 }
   1026 
   1027 TEST_P(WebSocketJobTest, HSTSUpgrade) {
   1028   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1029   TestHSTSUpgrade();
   1030 }
   1031 
   1032 TEST_P(WebSocketJobTest, InvalidSendData) {
   1033   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1034   TestInvalidSendData();
   1035 }
   1036 
   1037 TEST_P(WebSocketJobTest, SimpleHandshakeSpdyEnabled) {
   1038   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1039   TestSimpleHandshake();
   1040 }
   1041 
   1042 TEST_P(WebSocketJobTest, SlowHandshakeSpdyEnabled) {
   1043   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1044   TestSlowHandshake();
   1045 }
   1046 
   1047 TEST_P(WebSocketJobTest, HandshakeWithCookieSpdyEnabled) {
   1048   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1049   TestHandshakeWithCookie();
   1050 }
   1051 
   1052 TEST_P(WebSocketJobTest, HandshakeWithCookieButNotAllowedSpdyEnabled) {
   1053   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1054   TestHandshakeWithCookieButNotAllowed();
   1055 }
   1056 
   1057 TEST_P(WebSocketJobTest, HSTSUpgradeSpdyEnabled) {
   1058   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1059   TestHSTSUpgrade();
   1060 }
   1061 
   1062 TEST_P(WebSocketJobTest, InvalidSendDataSpdyEnabled) {
   1063   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1064   TestInvalidSendData();
   1065 }
   1066 
   1067 TEST_P(WebSocketJobTest, ConnectByWebSocket) {
   1068   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1069   TestConnectByWebSocket(THROTTLING_OFF);
   1070 }
   1071 
   1072 TEST_P(WebSocketJobTest, ConnectByWebSocketSpdyEnabled) {
   1073   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1074   TestConnectByWebSocket(THROTTLING_OFF);
   1075 }
   1076 
   1077 TEST_P(WebSocketJobTest, ConnectBySpdy) {
   1078   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1079   TestConnectBySpdy(SPDY_OFF, THROTTLING_OFF);
   1080 }
   1081 
   1082 TEST_P(WebSocketJobTest, ConnectBySpdySpdyEnabled) {
   1083   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1084   TestConnectBySpdy(SPDY_ON, THROTTLING_OFF);
   1085 }
   1086 
   1087 TEST_P(WebSocketJobTest, ThrottlingWebSocket) {
   1088   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1089   TestConnectByWebSocket(THROTTLING_ON);
   1090 }
   1091 
   1092 TEST_P(WebSocketJobTest, ThrottlingMaxNumberOfThrottledJobLimit) {
   1093   TestThrottlingLimit();
   1094 }
   1095 
   1096 TEST_P(WebSocketJobTest, ThrottlingWebSocketSpdyEnabled) {
   1097   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1098   TestConnectByWebSocket(THROTTLING_ON);
   1099 }
   1100 
   1101 TEST_P(WebSocketJobTest, ThrottlingSpdy) {
   1102   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1103   TestConnectBySpdy(SPDY_OFF, THROTTLING_ON);
   1104 }
   1105 
   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