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(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
    601                     kProtoHTTP2Draft04));
    602 
    603 TEST_P(WebSocketJobTest, DelayedCookies) {
    604   WebSocketJob::set_websocket_over_spdy_enabled(true);
    605   GURL url("ws://example.com/demo");
    606   GURL cookieUrl("http://example.com/demo");
    607   CookieOptions cookie_options;
    608   scoped_refptr<DelayedCookieMonster> cookie_store = new DelayedCookieMonster();
    609   context_->set_cookie_store(cookie_store.get());
    610   cookie_store->SetCookieWithOptionsAsync(cookieUrl,
    611                                           "CR-test=1",
    612                                           cookie_options,
    613                                           CookieMonster::SetCookiesCallback());
    614   cookie_options.set_include_httponly();
    615   cookie_store->SetCookieWithOptionsAsync(
    616       cookieUrl, "CR-test-httponly=1", cookie_options,
    617       CookieMonster::SetCookiesCallback());
    618 
    619   MockSocketStreamDelegate delegate;
    620   InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
    621   SkipToConnecting();
    622 
    623   bool sent = websocket_->SendData(kHandshakeRequestWithCookie,
    624                                    kHandshakeRequestWithCookieLength);
    625   EXPECT_TRUE(sent);
    626   base::MessageLoop::current()->RunUntilIdle();
    627   EXPECT_EQ(kHandshakeRequestWithFilteredCookie, sent_data());
    628   EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
    629   websocket_->OnSentData(socket_.get(),
    630                          kHandshakeRequestWithFilteredCookieLength);
    631   EXPECT_EQ(kHandshakeRequestWithCookieLength,
    632             delegate.amount_sent());
    633 
    634   websocket_->OnReceivedData(socket_.get(),
    635                              kHandshakeResponseWithCookie,
    636                              kHandshakeResponseWithCookieLength);
    637   base::MessageLoop::current()->RunUntilIdle();
    638   EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
    639   EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
    640 
    641   CloseWebSocketJob();
    642 }
    643 
    644 void WebSocketJobTest::TestHandshakeWithCookie() {
    645   GURL url("ws://example.com/demo");
    646   GURL cookieUrl("http://example.com/demo");
    647   CookieOptions cookie_options;
    648   cookie_store_->SetCookieWithOptions(
    649       cookieUrl, "CR-test=1", cookie_options);
    650   cookie_options.set_include_httponly();
    651   cookie_store_->SetCookieWithOptions(
    652       cookieUrl, "CR-test-httponly=1", cookie_options);
    653 
    654   MockSocketStreamDelegate delegate;
    655   InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
    656   SkipToConnecting();
    657 
    658   bool sent = websocket_->SendData(kHandshakeRequestWithCookie,
    659                                    kHandshakeRequestWithCookieLength);
    660   EXPECT_TRUE(sent);
    661   base::MessageLoop::current()->RunUntilIdle();
    662   EXPECT_EQ(kHandshakeRequestWithFilteredCookie, sent_data());
    663   EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
    664   websocket_->OnSentData(socket_.get(),
    665                          kHandshakeRequestWithFilteredCookieLength);
    666   EXPECT_EQ(kHandshakeRequestWithCookieLength,
    667             delegate.amount_sent());
    668 
    669   websocket_->OnReceivedData(socket_.get(),
    670                              kHandshakeResponseWithCookie,
    671                              kHandshakeResponseWithCookieLength);
    672   base::MessageLoop::current()->RunUntilIdle();
    673   EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
    674   EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
    675 
    676   EXPECT_EQ(3U, cookie_store_->entries().size());
    677   EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
    678   EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
    679   EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
    680   EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
    681   EXPECT_EQ(cookieUrl, cookie_store_->entries()[2].url);
    682   EXPECT_EQ("CR-set-test=1", cookie_store_->entries()[2].cookie_line);
    683 
    684   CloseWebSocketJob();
    685 }
    686 
    687 void WebSocketJobTest::TestHandshakeWithCookieButNotAllowed() {
    688   GURL url("ws://example.com/demo");
    689   GURL cookieUrl("http://example.com/demo");
    690   CookieOptions cookie_options;
    691   cookie_store_->SetCookieWithOptions(
    692       cookieUrl, "CR-test=1", cookie_options);
    693   cookie_options.set_include_httponly();
    694   cookie_store_->SetCookieWithOptions(
    695       cookieUrl, "CR-test-httponly=1", cookie_options);
    696 
    697   MockSocketStreamDelegate delegate;
    698   delegate.set_allow_all_cookies(false);
    699   InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
    700   SkipToConnecting();
    701 
    702   bool sent = websocket_->SendData(kHandshakeRequestWithCookie,
    703                                    kHandshakeRequestWithCookieLength);
    704   EXPECT_TRUE(sent);
    705   base::MessageLoop::current()->RunUntilIdle();
    706   EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
    707   EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
    708   websocket_->OnSentData(socket_.get(), kHandshakeRequestWithoutCookieLength);
    709   EXPECT_EQ(kHandshakeRequestWithCookieLength, delegate.amount_sent());
    710 
    711   websocket_->OnReceivedData(socket_.get(),
    712                              kHandshakeResponseWithCookie,
    713                              kHandshakeResponseWithCookieLength);
    714   base::MessageLoop::current()->RunUntilIdle();
    715   EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
    716   EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
    717 
    718   EXPECT_EQ(2U, cookie_store_->entries().size());
    719   EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
    720   EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
    721   EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
    722   EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
    723 
    724   CloseWebSocketJob();
    725 }
    726 
    727 void WebSocketJobTest::TestHSTSUpgrade() {
    728   GURL url("ws://upgrademe.com/");
    729   MockSocketStreamDelegate delegate;
    730   scoped_refptr<SocketStreamJob> job =
    731       SocketStreamJob::CreateSocketStreamJob(
    732           url, &delegate, context_->transport_security_state(),
    733           context_->ssl_config_service());
    734   EXPECT_TRUE(GetSocket(job.get())->is_secure());
    735   job->DetachDelegate();
    736 
    737   url = GURL("ws://donotupgrademe.com/");
    738   job = SocketStreamJob::CreateSocketStreamJob(
    739       url, &delegate, context_->transport_security_state(),
    740       context_->ssl_config_service());
    741   EXPECT_FALSE(GetSocket(job.get())->is_secure());
    742   job->DetachDelegate();
    743 }
    744 
    745 void WebSocketJobTest::TestInvalidSendData() {
    746   GURL url("ws://example.com/demo");
    747   MockSocketStreamDelegate delegate;
    748   InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
    749   SkipToConnecting();
    750 
    751   DoSendRequest();
    752   // We assume request is sent in one data chunk (from WebKit)
    753   // We don't support streaming request.
    754   base::MessageLoop::current()->RunUntilIdle();
    755   EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
    756   EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
    757   websocket_->OnSentData(socket_.get(),
    758                          kHandshakeRequestWithoutCookieLength);
    759   EXPECT_EQ(kHandshakeRequestWithoutCookieLength, delegate.amount_sent());
    760 
    761   // We could not send any data until connection is established.
    762   bool sent = websocket_->SendData(kHandshakeRequestWithoutCookie,
    763                                    kHandshakeRequestWithoutCookieLength);
    764   EXPECT_FALSE(sent);
    765   EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
    766   CloseWebSocketJob();
    767 }
    768 
    769 // Following tests verify cooperation between WebSocketJob and SocketStream.
    770 // Other former tests use MockSocketStream as SocketStream, so we could not
    771 // check SocketStream behavior.
    772 // OrderedSocketData provide socket level verifiation by checking out-going
    773 // packets in comparison with the MockWrite array and emulating in-coming
    774 // packets with MockRead array.
    775 
    776 void WebSocketJobTest::TestConnectByWebSocket(
    777     ThrottlingOption throttling) {
    778   // This is a test for verifying cooperation between WebSocketJob and
    779   // SocketStream. If |throttling| was |THROTTLING_OFF|, it test basic
    780   // situation. If |throttling| was |THROTTLING_ON|, throttling limits the
    781   // latter connection.
    782   MockWrite writes[] = {
    783     MockWrite(ASYNC,
    784               kHandshakeRequestWithoutCookie,
    785               kHandshakeRequestWithoutCookieLength,
    786               1),
    787     MockWrite(ASYNC,
    788               kDataHello,
    789               kDataHelloLength,
    790               3)
    791   };
    792   MockRead reads[] = {
    793     MockRead(ASYNC,
    794              kHandshakeResponseWithoutCookie,
    795              kHandshakeResponseWithoutCookieLength,
    796              2),
    797     MockRead(ASYNC,
    798              kDataWorld,
    799              kDataWorldLength,
    800              4),
    801     MockRead(SYNCHRONOUS, 0, 5)  // EOF
    802   };
    803   data_.reset(new OrderedSocketData(
    804       reads, arraysize(reads), writes, arraysize(writes)));
    805 
    806   GURL url("ws://example.com/demo");
    807   MockSocketStreamDelegate delegate;
    808   WebSocketJobTest* test = this;
    809   if (throttling == THROTTLING_ON)
    810     delegate.SetOnStartOpenConnection(
    811         base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
    812   delegate.SetOnConnected(
    813       base::Bind(&WebSocketJobTest::DoSendRequest,
    814                  base::Unretained(test)));
    815   delegate.SetOnReceivedData(
    816       base::Bind(&WebSocketJobTest::DoSendData, base::Unretained(test)));
    817   delegate.SetOnClose(
    818       base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
    819   InitWebSocketJob(url, &delegate, STREAM_SOCKET);
    820 
    821   scoped_refptr<WebSocketJob> block_websocket;
    822   if (throttling == THROTTLING_ON) {
    823     // Create former WebSocket object which obstructs the latter one.
    824     block_websocket = new WebSocketJob(NULL);
    825     block_websocket->addresses_ = AddressList(websocket_->address_list());
    826     ASSERT_TRUE(
    827         WebSocketThrottle::GetInstance()->PutInQueue(block_websocket.get()));
    828   }
    829 
    830   websocket_->Connect();
    831 
    832   if (throttling == THROTTLING_ON) {
    833     EXPECT_EQ(OK, WaitForResult());
    834     EXPECT_TRUE(websocket_->IsWaiting());
    835 
    836     // Remove the former WebSocket object from throttling queue to unblock the
    837     // latter.
    838     block_websocket->state_ = WebSocketJob::CLOSED;
    839     WebSocketThrottle::GetInstance()->RemoveFromQueue(block_websocket.get());
    840     block_websocket = NULL;
    841   }
    842 
    843   EXPECT_EQ(OK, WaitForResult());
    844   EXPECT_TRUE(data_->at_read_eof());
    845   EXPECT_TRUE(data_->at_write_eof());
    846   EXPECT_EQ(WebSocketJob::CLOSED, GetWebSocketJobState());
    847 }
    848 
    849 void WebSocketJobTest::TestConnectBySpdy(
    850     SpdyOption spdy, ThrottlingOption throttling) {
    851   // This is a test for verifying cooperation between WebSocketJob and
    852   // SocketStream in the situation we have SPDY session to the server. If
    853   // |throttling| was |THROTTLING_ON|, throttling limits the latter connection.
    854   // If you enabled spdy, you should specify |spdy| as |SPDY_ON|. Expected
    855   // results depend on its configuration.
    856   MockWrite writes_websocket[] = {
    857     MockWrite(ASYNC,
    858               kHandshakeRequestWithoutCookie,
    859               kHandshakeRequestWithoutCookieLength,
    860               1),
    861     MockWrite(ASYNC,
    862               kDataHello,
    863               kDataHelloLength,
    864               3)
    865   };
    866   MockRead reads_websocket[] = {
    867     MockRead(ASYNC,
    868              kHandshakeResponseWithoutCookie,
    869              kHandshakeResponseWithoutCookieLength,
    870              2),
    871     MockRead(ASYNC,
    872              kDataWorld,
    873              kDataWorldLength,
    874              4),
    875     MockRead(SYNCHRONOUS, 0, 5)  // EOF
    876   };
    877 
    878   scoped_ptr<SpdyHeaderBlock> request_headers(new SpdyHeaderBlock());
    879   spdy_util_.SetHeader("path", "/demo", request_headers.get());
    880   spdy_util_.SetHeader("version", "WebSocket/13", request_headers.get());
    881   spdy_util_.SetHeader("scheme", "ws", request_headers.get());
    882   spdy_util_.SetHeader("host", "example.com", request_headers.get());
    883   spdy_util_.SetHeader("origin", "http://example.com", request_headers.get());
    884   spdy_util_.SetHeader("sec-websocket-protocol", "sample",
    885                        request_headers.get());
    886 
    887   scoped_ptr<SpdyHeaderBlock> response_headers(new SpdyHeaderBlock());
    888   spdy_util_.SetHeader("status", "101 Switching Protocols",
    889                        response_headers.get());
    890   spdy_util_.SetHeader("sec-websocket-protocol", "sample",
    891                        response_headers.get());
    892 
    893   const SpdyStreamId kStreamId = 1;
    894   scoped_ptr<SpdyFrame> request_frame(
    895       spdy_util_.ConstructSpdyWebSocketHandshakeRequestFrame(
    896           request_headers.Pass(),
    897           kStreamId,
    898           MEDIUM));
    899   scoped_ptr<SpdyFrame> response_frame(
    900       spdy_util_.ConstructSpdyWebSocketHandshakeResponseFrame(
    901           response_headers.Pass(),
    902           kStreamId,
    903           MEDIUM));
    904   scoped_ptr<SpdyFrame> data_hello_frame(
    905       spdy_util_.ConstructSpdyWebSocketDataFrame(
    906           kDataHello,
    907           kDataHelloLength,
    908           kStreamId,
    909           false));
    910   scoped_ptr<SpdyFrame> data_world_frame(
    911       spdy_util_.ConstructSpdyWebSocketDataFrame(
    912           kDataWorld,
    913           kDataWorldLength,
    914           kStreamId,
    915           false));
    916   MockWrite writes_spdy[] = {
    917     CreateMockWrite(*request_frame.get(), 1),
    918     CreateMockWrite(*data_hello_frame.get(), 3),
    919   };
    920   MockRead reads_spdy[] = {
    921     CreateMockRead(*response_frame.get(), 2),
    922     CreateMockRead(*data_world_frame.get(), 4),
    923     MockRead(SYNCHRONOUS, 0, 5)  // EOF
    924   };
    925 
    926   if (spdy == SPDY_ON)
    927     data_.reset(new OrderedSocketData(
    928         reads_spdy, arraysize(reads_spdy),
    929         writes_spdy, arraysize(writes_spdy)));
    930   else
    931     data_.reset(new OrderedSocketData(
    932         reads_websocket, arraysize(reads_websocket),
    933         writes_websocket, arraysize(writes_websocket)));
    934 
    935   GURL url("ws://example.com/demo");
    936   MockSocketStreamDelegate delegate;
    937   WebSocketJobTest* test = this;
    938   if (throttling == THROTTLING_ON)
    939     delegate.SetOnStartOpenConnection(
    940         base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
    941   delegate.SetOnConnected(
    942       base::Bind(&WebSocketJobTest::DoSendRequest,
    943                  base::Unretained(test)));
    944   delegate.SetOnReceivedData(
    945       base::Bind(&WebSocketJobTest::DoSendData, base::Unretained(test)));
    946   delegate.SetOnClose(
    947       base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
    948   InitWebSocketJob(url, &delegate, STREAM_SPDY_WEBSOCKET);
    949 
    950   scoped_refptr<WebSocketJob> block_websocket;
    951   if (throttling == THROTTLING_ON) {
    952     // Create former WebSocket object which obstructs the latter one.
    953     block_websocket = new WebSocketJob(NULL);
    954     block_websocket->addresses_ = AddressList(websocket_->address_list());
    955     ASSERT_TRUE(
    956         WebSocketThrottle::GetInstance()->PutInQueue(block_websocket.get()));
    957   }
    958 
    959   websocket_->Connect();
    960 
    961   if (throttling == THROTTLING_ON) {
    962     EXPECT_EQ(OK, WaitForResult());
    963     EXPECT_TRUE(websocket_->IsWaiting());
    964 
    965     // Remove the former WebSocket object from throttling queue to unblock the
    966     // latter.
    967     block_websocket->state_ = WebSocketJob::CLOSED;
    968     WebSocketThrottle::GetInstance()->RemoveFromQueue(block_websocket.get());
    969     block_websocket = NULL;
    970   }
    971 
    972   EXPECT_EQ(OK, WaitForResult());
    973   EXPECT_TRUE(data_->at_read_eof());
    974   EXPECT_TRUE(data_->at_write_eof());
    975   EXPECT_EQ(WebSocketJob::CLOSED, GetWebSocketJobState());
    976 }
    977 
    978 void WebSocketJobTest::TestThrottlingLimit() {
    979   std::vector<scoped_refptr<WebSocketJob> > jobs;
    980   const int kMaxWebSocketJobsThrottled = 1024;
    981   IPAddressNumber ip;
    982   ParseIPLiteralToNumber("127.0.0.1", &ip);
    983   for (int i = 0; i < kMaxWebSocketJobsThrottled + 1; ++i) {
    984     scoped_refptr<WebSocketJob> job = new WebSocketJob(NULL);
    985     job->addresses_ = AddressList(AddressList::CreateFromIPAddress(ip, 80));
    986     if (i >= kMaxWebSocketJobsThrottled)
    987       EXPECT_FALSE(WebSocketThrottle::GetInstance()->PutInQueue(job));
    988     else
    989       EXPECT_TRUE(WebSocketThrottle::GetInstance()->PutInQueue(job));
    990     jobs.push_back(job);
    991   }
    992 
    993   // Close the jobs in reverse order. Otherwise, We need to make them prepared
    994   // for Wakeup call.
    995   for (std::vector<scoped_refptr<WebSocketJob> >::reverse_iterator iter =
    996            jobs.rbegin();
    997        iter != jobs.rend();
    998        ++iter) {
    999     WebSocketJob* job = (*iter).get();
   1000     job->state_ = WebSocketJob::CLOSED;
   1001     WebSocketThrottle::GetInstance()->RemoveFromQueue(job);
   1002   }
   1003 }
   1004 
   1005 // Execute tests in both spdy-disabled mode and spdy-enabled mode.
   1006 TEST_P(WebSocketJobTest, SimpleHandshake) {
   1007   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1008   TestSimpleHandshake();
   1009 }
   1010 
   1011 TEST_P(WebSocketJobTest, SlowHandshake) {
   1012   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1013   TestSlowHandshake();
   1014 }
   1015 
   1016 TEST_P(WebSocketJobTest, HandshakeWithCookie) {
   1017   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1018   TestHandshakeWithCookie();
   1019 }
   1020 
   1021 TEST_P(WebSocketJobTest, HandshakeWithCookieButNotAllowed) {
   1022   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1023   TestHandshakeWithCookieButNotAllowed();
   1024 }
   1025 
   1026 TEST_P(WebSocketJobTest, HSTSUpgrade) {
   1027   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1028   TestHSTSUpgrade();
   1029 }
   1030 
   1031 TEST_P(WebSocketJobTest, InvalidSendData) {
   1032   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1033   TestInvalidSendData();
   1034 }
   1035 
   1036 TEST_P(WebSocketJobTest, SimpleHandshakeSpdyEnabled) {
   1037   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1038   TestSimpleHandshake();
   1039 }
   1040 
   1041 TEST_P(WebSocketJobTest, SlowHandshakeSpdyEnabled) {
   1042   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1043   TestSlowHandshake();
   1044 }
   1045 
   1046 TEST_P(WebSocketJobTest, HandshakeWithCookieSpdyEnabled) {
   1047   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1048   TestHandshakeWithCookie();
   1049 }
   1050 
   1051 TEST_P(WebSocketJobTest, HandshakeWithCookieButNotAllowedSpdyEnabled) {
   1052   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1053   TestHandshakeWithCookieButNotAllowed();
   1054 }
   1055 
   1056 TEST_P(WebSocketJobTest, HSTSUpgradeSpdyEnabled) {
   1057   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1058   TestHSTSUpgrade();
   1059 }
   1060 
   1061 TEST_P(WebSocketJobTest, InvalidSendDataSpdyEnabled) {
   1062   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1063   TestInvalidSendData();
   1064 }
   1065 
   1066 TEST_P(WebSocketJobTest, ConnectByWebSocket) {
   1067   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1068   TestConnectByWebSocket(THROTTLING_OFF);
   1069 }
   1070 
   1071 TEST_P(WebSocketJobTest, ConnectByWebSocketSpdyEnabled) {
   1072   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1073   TestConnectByWebSocket(THROTTLING_OFF);
   1074 }
   1075 
   1076 TEST_P(WebSocketJobTest, ConnectBySpdy) {
   1077   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1078   TestConnectBySpdy(SPDY_OFF, THROTTLING_OFF);
   1079 }
   1080 
   1081 TEST_P(WebSocketJobTest, ConnectBySpdySpdyEnabled) {
   1082   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1083   TestConnectBySpdy(SPDY_ON, THROTTLING_OFF);
   1084 }
   1085 
   1086 TEST_P(WebSocketJobTest, ThrottlingWebSocket) {
   1087   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1088   TestConnectByWebSocket(THROTTLING_ON);
   1089 }
   1090 
   1091 TEST_P(WebSocketJobTest, ThrottlingMaxNumberOfThrottledJobLimit) {
   1092   TestThrottlingLimit();
   1093 }
   1094 
   1095 TEST_P(WebSocketJobTest, ThrottlingWebSocketSpdyEnabled) {
   1096   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1097   TestConnectByWebSocket(THROTTLING_ON);
   1098 }
   1099 
   1100 TEST_P(WebSocketJobTest, ThrottlingSpdy) {
   1101   WebSocketJob::set_websocket_over_spdy_enabled(false);
   1102   TestConnectBySpdy(SPDY_OFF, THROTTLING_ON);
   1103 }
   1104 
   1105 TEST_P(WebSocketJobTest, ThrottlingSpdySpdyEnabled) {
   1106   WebSocketJob::set_websocket_over_spdy_enabled(true);
   1107   TestConnectBySpdy(SPDY_ON, THROTTLING_ON);
   1108 }
   1109 
   1110 // TODO(toyoshim): Add tests to verify throttling, SPDY stream limitation.
   1111 // TODO(toyoshim,yutak): Add tests to verify closing handshake.
   1112 }  // namespace net
   1113