1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/websockets/websocket_job.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/string_util.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/completion_callback.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/test_completion_callback.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/cookies/cookie_store.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/cookies/cookie_store_test_helpers.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/dns/mock_host_resolver.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_transaction_factory.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/transport_security_state.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_service.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/socket/next_proto.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/socket_test_util.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket_stream/socket_stream.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_session.h"
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/spdy/spdy_websocket_test_util.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_config_service.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/websockets/websocket_throttle.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/platform_test.h"
367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace net {
39b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class MockSocketStream : public SocketStream {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MockSocketStream(const GURL& url, SocketStream::Delegate* delegate,
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   URLRequestContext* context, CookieStore* cookie_store)
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : SocketStream(url, delegate, context, cookie_store) {}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Connect() OVERRIDE {}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool SendData(const char* data, int len) OVERRIDE {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sent_data_ += std::string(data, len);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Close() OVERRIDE {}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RestartWithAuth(
56b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      const AuthCredentials& credentials) OVERRIDE {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DetachDelegate() OVERRIDE {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_ = NULL;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& sent_data() const {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sent_data_;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MockSocketStream() {}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string sent_data_;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
74b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class MockSocketStreamDelegate : public SocketStream::Delegate {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockSocketStreamDelegate()
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : amount_sent_(0), allow_all_cookies_(true) {}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_allow_all_cookies(bool allow_all_cookies) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allow_all_cookies_ = allow_all_cookies;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MockSocketStreamDelegate() {}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnStartOpenConnection(const base::Closure& callback) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_start_open_connection_ = callback;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnConnected(const base::Closure& callback) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_connected_ = callback;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnSentData(const base::Closure& callback) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_sent_data_ = callback;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnReceivedData(const base::Closure& callback) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_received_data_ = callback;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetOnClose(const base::Closure& callback) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    on_close_ = callback;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int OnStartOpenConnection(
100b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      SocketStream* socket,
101b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      const CompletionCallback& callback) OVERRIDE {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_start_open_connection_.is_null())
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_start_open_connection_.Run();
104b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return OK;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
106b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  virtual void OnConnected(SocketStream* socket,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int max_pending_send_allowed) OVERRIDE {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_connected_.is_null())
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_connected_.Run();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
111b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  virtual void OnSentData(SocketStream* socket,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          int amount_sent) OVERRIDE {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    amount_sent_ += amount_sent;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_sent_data_.is_null())
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_sent_data_.Run();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
117b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  virtual void OnReceivedData(SocketStream* socket,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const char* data, int len) OVERRIDE {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    received_data_ += std::string(data, len);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_received_data_.is_null())
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_received_data_.Run();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
123b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  virtual void OnClose(SocketStream* socket) OVERRIDE {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!on_close_.is_null())
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      on_close_.Run();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
127b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  virtual bool CanGetCookies(SocketStream* socket,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const GURL& url) OVERRIDE {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return allow_all_cookies_;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
131b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  virtual bool CanSetCookie(SocketStream* request,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const GURL& url,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const std::string& cookie_line,
134b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                            CookieOptions* options) OVERRIDE {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return allow_all_cookies_;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t amount_sent() const { return amount_sent_; }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& received_data() const { return received_data_; }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int amount_sent_;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool allow_all_cookies_;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string received_data_;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure on_start_open_connection_;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure on_connected_;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure on_sent_data_;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure on_received_data_;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Closure on_close_;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
152b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class MockCookieStore : public CookieStore {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct Entry {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL url;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string cookie_line;
157b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    CookieOptions options;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockCookieStore() {}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool SetCookieWithOptions(const GURL& url,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const std::string& cookie_line,
164b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                            const CookieOptions& options) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Entry entry;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.url = url;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.cookie_line = cookie_line;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry.options = options;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entries_.push_back(entry);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string GetCookiesWithOptions(const GURL& url,
174b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                    const CookieOptions& options) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string result;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < entries_.size(); i++) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Entry& entry = entries_[i];
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (url == entry.url) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!result.empty()) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          result += "; ";
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result += entry.cookie_line;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CookieStore:
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetCookieWithOptionsAsync(
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& url,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& cookie_line,
192b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      const CookieOptions& options,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const SetCookiesCallback& callback) OVERRIDE {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool result = SetCookieWithOptions(url, cookie_line, options);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback.is_null())
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.Run(result);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void GetCookiesWithOptionsAsync(
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& url,
201b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      const CookieOptions& options,
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GetCookiesCallback& callback) OVERRIDE {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback.is_null())
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.Run(GetCookiesWithOptions(url, options));
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
207effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  virtual void GetAllCookiesForURLAsync(
208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      const GURL& url,
209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      const GetCookieListCallback& callback) OVERRIDE {
210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    ADD_FAILURE();
211effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DeleteCookieAsync(const GURL& url,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const std::string& cookie_name,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const base::Closure& callback) OVERRIDE {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ADD_FAILURE();
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DeleteAllCreatedBetweenAsync(
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::Time& delete_begin,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const base::Time& delete_end,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const DeleteCallback& callback) OVERRIDE {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ADD_FAILURE();
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void DeleteAllCreatedBetweenForHostAsync(
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const base::Time delete_begin,
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const base::Time delete_end,
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const GURL& url,
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      const DeleteCallback& callback) OVERRIDE {
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ADD_FAILURE();
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DeleteSessionCookiesAsync(const DeleteCallback&) OVERRIDE {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ADD_FAILURE();
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
238b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  virtual CookieMonster* GetCookieMonster() OVERRIDE { return NULL; }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<Entry>& entries() const { return entries_; }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<MockCookieStore>;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MockCookieStore() {}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Entry> entries_;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
249b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class MockSSLConfigService : public SSLConfigService {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
251b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  virtual void GetSSLConfig(SSLConfig* config) OVERRIDE {}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MockSSLConfigService() {}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
257b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class MockURLRequestContext : public URLRequestContext {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
259b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  explicit MockURLRequestContext(CookieStore* cookie_store)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : transport_security_state_() {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_cookie_store(cookie_store);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_transport_security_state(&transport_security_state_);
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::Time expiry = base::Time::Now() + base::TimeDelta::FromDays(1000);
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool include_subdomains = false;
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    transport_security_state_.AddHSTS("upgrademe.com", expiry,
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      include_subdomains);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual ~MockURLRequestContext() {
2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    AssertNoURLRequests();
2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
274b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  TransportSecurityState transport_security_state_;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
277b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class MockHttpTransactionFactory : public HttpTransactionFactory {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
27946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  MockHttpTransactionFactory(NextProto next_proto,
28046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                             OrderedSocketData* data,
28146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                             bool enable_websocket_over_spdy) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_ = data;
283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    MockConnect connect_data(SYNCHRONOUS, OK);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_->set_connect_data(connect_data);
285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    session_deps_.reset(new SpdySessionDependencies(next_proto));
28646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    session_deps_->enable_websocket_over_spdy = enable_websocket_over_spdy;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_deps_->socket_factory->AddSocketDataProvider(data_);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    http_session_ =
289b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        SpdySessionDependencies::SpdyCreateSession(session_deps_.get());
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_port_pair_.set_host("example.com");
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_port_pair_.set_port(80);
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    spdy_session_key_ = SpdySessionKey(host_port_pair_,
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                            ProxyServer::Direct(),
294e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                                            PRIVACY_MODE_DISABLED);
2957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    session_ = CreateInsecureSpdySession(
2967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        http_session_, spdy_session_key_, BoundNetLog());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int CreateTransaction(
300b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      RequestPriority priority,
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      scoped_ptr<HttpTransaction>* trans) OVERRIDE {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
303b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return ERR_UNEXPECTED;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
306b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  virtual HttpCache* GetCache() OVERRIDE {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
311b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  virtual HttpNetworkSession* GetSession() OVERRIDE {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return http_session_.get();
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
316b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  OrderedSocketData* data_;
317b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<SpdySessionDependencies> session_deps_;
318b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_refptr<HttpNetworkSession> http_session_;
319ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::WeakPtr<SpdySession> session_;
320b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  HostPortPair host_port_pair_;
32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SpdySessionKey spdy_session_key_;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
324c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass DeletingSocketStreamDelegate : public SocketStream::Delegate {
325c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public:
326c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DeletingSocketStreamDelegate()
327c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      : delete_next_(false) {}
328c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
329c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Since this class needs to be able to delete |job_|, it must be the only
330c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // reference holder (except for temporary references). Provide access to the
331c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // pointer for tests to use.
332c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  WebSocketJob* job() { return job_.get(); }
333c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
334c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void set_job(WebSocketJob* job) { job_ = job; }
335c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
336c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // After calling this, the next call to a method on this delegate will delete
337c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // the WebSocketJob object.
338c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void set_delete_next(bool delete_next) { delete_next_ = delete_next; }
339c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
340c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void DeleteJobMaybe() {
341c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (delete_next_) {
342c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      job_->DetachContext();
343c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      job_->DetachDelegate();
344c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      job_ = NULL;
345c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
346c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
347c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
348c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // SocketStream::Delegate implementation
349c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
350c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // OnStartOpenConnection() is not implemented by SocketStreamDispatcherHost
351c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
352c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void OnConnected(SocketStream* socket,
353c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                           int max_pending_send_allowed) OVERRIDE {
354c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    DeleteJobMaybe();
355c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
356c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
357c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void OnSentData(SocketStream* socket, int amount_sent) OVERRIDE {
358c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    DeleteJobMaybe();
359c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
360c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
361c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void OnReceivedData(SocketStream* socket,
362c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                              const char* data,
363c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                              int len) OVERRIDE {
364c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    DeleteJobMaybe();
365c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
366c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
367c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void OnClose(SocketStream* socket) OVERRIDE { DeleteJobMaybe(); }
368c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
369c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void OnAuthRequired(SocketStream* socket,
370c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                              AuthChallengeInfo* auth_info) OVERRIDE {
371c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    DeleteJobMaybe();
372c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
373c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
374c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void OnSSLCertificateError(SocketStream* socket,
375c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                     const SSLInfo& ssl_info,
376c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                     bool fatal) OVERRIDE {
377c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    DeleteJobMaybe();
378c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
379c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
380c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void OnError(const SocketStream* socket, int error) OVERRIDE {
381c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    DeleteJobMaybe();
382c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
383c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
384c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // CanGetCookies() and CanSetCookies() do not appear to be able to delete the
385c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // WebSocketJob object.
386c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
387c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch private:
388c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_refptr<WebSocketJob> job_;
389c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool delete_next_;
390c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch};
391c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass WebSocketJobTest : public PlatformTest,
395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                         public ::testing::WithParamInterface<NextProto> {
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
39746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  WebSocketJobTest()
39846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      : spdy_util_(GetParam()),
39946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        enable_websocket_over_spdy_(false) {}
400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stream_type_ = STREAM_INVALID;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cookie_store_ = new MockCookieStore;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_.reset(new MockURLRequestContext(cookie_store_.get()));
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cookie_store_ = NULL;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_.reset();
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    websocket_ = NULL;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    socket_ = NULL;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoSendRequest() {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(websocket_->SendData(kHandshakeRequestWithoutCookie,
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     kHandshakeRequestWithoutCookieLength));
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoSendData() {
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (received_data().size() == kHandshakeResponseWithoutCookieLength)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      websocket_->SendData(kDataHello, kDataHelloLength);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoSync() {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sync_test_callback_.callback().Run(OK);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int WaitForResult() {
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sync_test_callback_.WaitForResult();
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
42646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum StreamType {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STREAM_INVALID,
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STREAM_MOCK_SOCKET,
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STREAM_SOCKET,
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STREAM_SPDY_WEBSOCKET,
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum ThrottlingOption {
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    THROTTLING_OFF,
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    THROTTLING_ON,
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum SpdyOption {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SPDY_OFF,
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SPDY_ON,
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InitWebSocketJob(const GURL& url,
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        MockSocketStreamDelegate* delegate,
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        StreamType stream_type) {
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(STREAM_INVALID, stream_type);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stream_type_ = stream_type;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    websocket_ = new WebSocketJob(delegate);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (stream_type == STREAM_MOCK_SOCKET)
450a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      socket_ = new MockSocketStream(url, websocket_.get(), context_.get(),
451a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     NULL);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (stream_type == STREAM_SOCKET || stream_type == STREAM_SPDY_WEBSOCKET) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (stream_type == STREAM_SPDY_WEBSOCKET) {
45546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        http_factory_.reset(new MockHttpTransactionFactory(
45646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            GetParam(), data_.get(), enable_websocket_over_spdy_));
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        context_->set_http_transaction_factory(http_factory_.get());
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_config_service_ = new MockSSLConfigService();
461868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      context_->set_ssl_config_service(ssl_config_service_.get());
462b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      proxy_service_.reset(ProxyService::CreateDirect());
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->set_proxy_service(proxy_service_.get());
464b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      host_resolver_.reset(new MockHostResolver);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_->set_host_resolver(host_resolver_.get());
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
467a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      socket_ = new SocketStream(url, websocket_.get(), context_.get(), NULL);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      socket_factory_.reset(new MockClientSocketFactory);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(data_.get());
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      socket_factory_->AddSocketDataProvider(data_.get());
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      socket_->SetClientSocketFactory(socket_factory_.get());
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    websocket_->InitSocketStream(socket_.get());
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // MockHostResolver resolves all hosts to 127.0.0.1; however, when we create
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // a WebSocketJob purely to block another one in a throttling test, we don't
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // perform a real connect. In that case, the following address is used
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // instead.
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPAddressNumber ip;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ParseIPLiteralToNumber("127.0.0.1", &ip);
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    websocket_->addresses_ = AddressList::CreateFromIPAddress(ip, 80);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SkipToConnecting() {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    websocket_->state_ = WebSocketJob::CONNECTING;
485ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ASSERT_TRUE(WebSocketThrottle::GetInstance()->PutInQueue(websocket_.get()));
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketJob::State GetWebSocketJobState() {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return websocket_->state_;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CloseWebSocketJob() {
491868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (websocket_->socket_.get()) {
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      websocket_->socket_->DetachDelegate();
493868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      WebSocketThrottle::GetInstance()->RemoveFromQueue(websocket_.get());
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    websocket_->state_ = WebSocketJob::CLOSED;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    websocket_->delegate_ = NULL;
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    websocket_->socket_ = NULL;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SocketStream* GetSocket(SocketStreamJob* job) {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return job->socket_.get();
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& sent_data() const {
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(STREAM_MOCK_SOCKET, stream_type_);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockSocketStream* socket =
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<MockSocketStream*>(socket_.get());
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(socket);
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return socket->sent_data();
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& received_data() const {
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(STREAM_INVALID, stream_type_);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockSocketStreamDelegate* delegate =
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<MockSocketStreamDelegate*>(websocket_->delegate_);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(delegate);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return delegate->received_data();
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TestSimpleHandshake();
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TestSlowHandshake();
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TestHandshakeWithCookie();
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TestHandshakeWithCookieButNotAllowed();
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TestHSTSUpgrade();
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TestInvalidSendData();
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TestConnectByWebSocket(ThrottlingOption throttling);
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TestConnectBySpdy(SpdyOption spdy, ThrottlingOption throttling);
525ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  void TestThrottlingLimit();
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
527eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SpdyWebSocketTestUtil spdy_util_;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StreamType stream_type_;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<MockCookieStore> cookie_store_;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MockURLRequestContext> context_;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<WebSocketJob> websocket_;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> socket_;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MockClientSocketFactory> socket_factory_;
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<OrderedSocketData> data_;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback sync_test_callback_;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<MockSSLConfigService> ssl_config_service_;
537b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<ProxyService> proxy_service_;
538b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<MockHostResolver> host_resolver_;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MockHttpTransactionFactory> http_factory_;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Must be set before call to enable_websocket_over_spdy, defaults to false.
54246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bool enable_websocket_over_spdy_;
54346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kHandshakeRequestWithoutCookie[];
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kHandshakeRequestWithCookie[];
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kHandshakeRequestWithFilteredCookie[];
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kHandshakeResponseWithoutCookie[];
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kHandshakeResponseWithCookie[];
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kDataHello[];
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kDataWorld[];
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* const kHandshakeRequestForSpdy[];
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* const kHandshakeResponseForSpdy[];
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t kHandshakeRequestWithoutCookieLength;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t kHandshakeRequestWithCookieLength;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t kHandshakeRequestWithFilteredCookieLength;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t kHandshakeResponseWithoutCookieLength;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t kHandshakeResponseWithCookieLength;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t kDataHelloLength;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const size_t kDataWorldLength;
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
562c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Tests using this fixture verify that the WebSocketJob can handle being
563c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// deleted while calling back to the delegate correctly. These tests need to be
564c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// run under AddressSanitizer or other systems for detecting use-after-free
565c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// errors in order to find problems.
566c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass WebSocketJobDeleteTest : public ::testing::Test {
567c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch protected:
568c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  WebSocketJobDeleteTest()
569c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      : delegate_(new DeletingSocketStreamDelegate),
570c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        cookie_store_(new MockCookieStore),
571c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        context_(new MockURLRequestContext(cookie_store_.get())) {
572c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    WebSocketJob* websocket = new WebSocketJob(delegate_.get());
573c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    delegate_->set_job(websocket);
574c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
575c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    socket_ = new MockSocketStream(
576c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        GURL("ws://127.0.0.1/"), websocket, context_.get(), NULL);
577c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
578c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    websocket->InitSocketStream(socket_.get());
579c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
580c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
581c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  void SetDeleteNext() { return delegate_->set_delete_next(true); }
582c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  WebSocketJob* job() { return delegate_->job(); }
583c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
584c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_ptr<DeletingSocketStreamDelegate> delegate_;
585c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_refptr<MockCookieStore> cookie_store_;
586c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_ptr<MockURLRequestContext> context_;
587c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_refptr<SocketStream> socket_;
588c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch};
589c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
590eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst char WebSocketJobTest::kHandshakeRequestWithoutCookie[] =
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "GET /demo HTTP/1.1\r\n"
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Host: example.com\r\n"
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Upgrade: WebSocket\r\n"
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Connection: Upgrade\r\n"
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Origin: http://example.com\r\n"
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Protocol: sample\r\n"
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Version: 13\r\n"
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\r\n";
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
601eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst char WebSocketJobTest::kHandshakeRequestWithCookie[] =
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "GET /demo HTTP/1.1\r\n"
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Host: example.com\r\n"
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Upgrade: WebSocket\r\n"
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Connection: Upgrade\r\n"
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Origin: http://example.com\r\n"
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Protocol: sample\r\n"
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Version: 13\r\n"
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Cookie: WK-test=1\r\n"
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\r\n";
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
613eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst char WebSocketJobTest::kHandshakeRequestWithFilteredCookie[] =
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "GET /demo HTTP/1.1\r\n"
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Host: example.com\r\n"
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Upgrade: WebSocket\r\n"
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Connection: Upgrade\r\n"
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Origin: http://example.com\r\n"
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Protocol: sample\r\n"
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Version: 13\r\n"
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Cookie: CR-test=1; CR-test-httponly=1\r\n"
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\r\n";
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst char WebSocketJobTest::kHandshakeResponseWithoutCookie[] =
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "HTTP/1.1 101 Switching Protocols\r\n"
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Upgrade: websocket\r\n"
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Connection: Upgrade\r\n"
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Protocol: sample\r\n"
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\r\n";
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
633eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst char WebSocketJobTest::kHandshakeResponseWithCookie[] =
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "HTTP/1.1 101 Switching Protocols\r\n"
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Upgrade: websocket\r\n"
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Connection: Upgrade\r\n"
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Sec-WebSocket-Protocol: sample\r\n"
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Set-Cookie: CR-set-test=1\r\n"
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\r\n";
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst char WebSocketJobTest::kDataHello[] = "Hello, ";
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst char WebSocketJobTest::kDataWorld[] = "World!\n";
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
646eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst size_t WebSocketJobTest::kHandshakeRequestWithoutCookieLength =
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arraysize(kHandshakeRequestWithoutCookie) - 1;
648eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst size_t WebSocketJobTest::kHandshakeRequestWithCookieLength =
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arraysize(kHandshakeRequestWithCookie) - 1;
650eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst size_t WebSocketJobTest::kHandshakeRequestWithFilteredCookieLength =
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arraysize(kHandshakeRequestWithFilteredCookie) - 1;
652eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst size_t WebSocketJobTest::kHandshakeResponseWithoutCookieLength =
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arraysize(kHandshakeResponseWithoutCookie) - 1;
654eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst size_t WebSocketJobTest::kHandshakeResponseWithCookieLength =
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arraysize(kHandshakeResponseWithCookie) - 1;
656eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst size_t WebSocketJobTest::kDataHelloLength =
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arraysize(kDataHello) - 1;
658eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst size_t WebSocketJobTest::kDataWorldLength =
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arraysize(kDataWorld) - 1;
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
661eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid WebSocketJobTest::TestSimpleHandshake() {
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url("ws://example.com/demo");
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockSocketStreamDelegate delegate;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkipToConnecting();
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoSendRequest();
66890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket_->OnSentData(socket_.get(),
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kHandshakeRequestWithoutCookieLength);
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeRequestWithoutCookieLength, delegate.amount_sent());
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket_->OnReceivedData(socket_.get(),
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kHandshakeResponseWithoutCookie,
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kHandshakeResponseWithoutCookieLength);
67890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseWebSocketJob();
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid WebSocketJobTest::TestSlowHandshake() {
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url("ws://example.com/demo");
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockSocketStreamDelegate delegate;
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkipToConnecting();
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoSendRequest();
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We assume request is sent in one data chunk (from WebKit)
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't support streaming request.
69390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket_->OnSentData(socket_.get(),
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kHandshakeRequestWithoutCookieLength);
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeRequestWithoutCookieLength, delegate.amount_sent());
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> lines;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SplitString(kHandshakeResponseWithoutCookie, '\n', &lines);
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < lines.size() - 2; i++) {
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string line = lines[i] + "\r\n";
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE("Line: " + line);
705868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    websocket_->OnReceivedData(socket_.get(), line.c_str(), line.size());
70690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->RunUntilIdle();
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(delegate.received_data().empty());
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket_->OnReceivedData(socket_.get(), "\r\n", 2);
71190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(delegate.received_data().empty());
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseWebSocketJob();
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
718eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochINSTANTIATE_TEST_CASE_P(
719eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    NextProto,
720eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    WebSocketJobTest,
7214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    testing::Values(kProtoDeprecatedSPDY2,
722a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                    kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
723eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
724eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, DelayedCookies) {
72546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  enable_websocket_over_spdy_ = true;
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url("ws://example.com/demo");
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL cookieUrl("http://example.com/demo");
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CookieOptions cookie_options;
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<DelayedCookieMonster> cookie_store = new DelayedCookieMonster();
730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  context_->set_cookie_store(cookie_store.get());
731868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  cookie_store->SetCookieWithOptionsAsync(cookieUrl,
732868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          "CR-test=1",
733868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          cookie_options,
734868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                          CookieMonster::SetCookiesCallback());
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cookie_options.set_include_httponly();
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cookie_store->SetCookieWithOptionsAsync(
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cookieUrl, "CR-test-httponly=1", cookie_options,
738b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      CookieMonster::SetCookiesCallback());
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockSocketStreamDelegate delegate;
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkipToConnecting();
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool sent = websocket_->SendData(kHandshakeRequestWithCookie,
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   kHandshakeRequestWithCookieLength);
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sent);
74790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeRequestWithFilteredCookie, sent_data());
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
750868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  websocket_->OnSentData(socket_.get(),
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kHandshakeRequestWithFilteredCookieLength);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeRequestWithCookieLength,
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            delegate.amount_sent());
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket_->OnReceivedData(socket_.get(),
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kHandshakeResponseWithCookie,
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kHandshakeResponseWithCookieLength);
75890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseWebSocketJob();
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid WebSocketJobTest::TestHandshakeWithCookie() {
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url("ws://example.com/demo");
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL cookieUrl("http://example.com/demo");
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CookieOptions cookie_options;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cookie_store_->SetCookieWithOptions(
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cookieUrl, "CR-test=1", cookie_options);
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cookie_options.set_include_httponly();
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cookie_store_->SetCookieWithOptions(
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cookieUrl, "CR-test-httponly=1", cookie_options);
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockSocketStreamDelegate delegate;
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkipToConnecting();
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool sent = websocket_->SendData(kHandshakeRequestWithCookie,
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   kHandshakeRequestWithCookieLength);
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sent);
78290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeRequestWithFilteredCookie, sent_data());
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
785868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  websocket_->OnSentData(socket_.get(),
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kHandshakeRequestWithFilteredCookieLength);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeRequestWithCookieLength,
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            delegate.amount_sent());
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket_->OnReceivedData(socket_.get(),
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kHandshakeResponseWithCookie,
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kHandshakeResponseWithCookieLength);
79390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(3U, cookie_store_->entries().size());
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(cookieUrl, cookie_store_->entries()[2].url);
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("CR-set-test=1", cookie_store_->entries()[2].cookie_line);
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseWebSocketJob();
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
808eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid WebSocketJobTest::TestHandshakeWithCookieButNotAllowed() {
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url("ws://example.com/demo");
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL cookieUrl("http://example.com/demo");
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CookieOptions cookie_options;
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cookie_store_->SetCookieWithOptions(
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cookieUrl, "CR-test=1", cookie_options);
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cookie_options.set_include_httponly();
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cookie_store_->SetCookieWithOptions(
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cookieUrl, "CR-test-httponly=1", cookie_options);
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockSocketStreamDelegate delegate;
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate.set_allow_all_cookies(false);
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkipToConnecting();
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool sent = websocket_->SendData(kHandshakeRequestWithCookie,
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   kHandshakeRequestWithCookieLength);
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sent);
82690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
829868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  websocket_->OnSentData(socket_.get(), kHandshakeRequestWithoutCookieLength);
830868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(kHandshakeRequestWithCookieLength, delegate.amount_sent());
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket_->OnReceivedData(socket_.get(),
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kHandshakeResponseWithCookie,
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kHandshakeResponseWithCookieLength);
83590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2U, cookie_store_->entries().size());
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseWebSocketJob();
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
848eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid WebSocketJobTest::TestHSTSUpgrade() {
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url("ws://upgrademe.com/");
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockSocketStreamDelegate delegate;
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStreamJob> job =
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SocketStreamJob::CreateSocketStreamJob(
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          url, &delegate, context_->transport_security_state(),
854a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          context_->ssl_config_service(), NULL, NULL);
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(GetSocket(job.get())->is_secure());
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  job->DetachDelegate();
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url = GURL("ws://donotupgrademe.com/");
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  job = SocketStreamJob::CreateSocketStreamJob(
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url, &delegate, context_->transport_security_state(),
861a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      context_->ssl_config_service(), NULL, NULL);
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(GetSocket(job.get())->is_secure());
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  job->DetachDelegate();
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
866eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid WebSocketJobTest::TestInvalidSendData() {
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url("ws://example.com/demo");
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockSocketStreamDelegate delegate;
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkipToConnecting();
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoSendRequest();
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We assume request is sent in one data chunk (from WebKit)
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't support streaming request.
87590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop::current()->RunUntilIdle();
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket_->OnSentData(socket_.get(),
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kHandshakeRequestWithoutCookieLength);
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kHandshakeRequestWithoutCookieLength, delegate.amount_sent());
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We could not send any data until connection is established.
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool sent = websocket_->SendData(kHandshakeRequestWithoutCookie,
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   kHandshakeRequestWithoutCookieLength);
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(sent);
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseWebSocketJob();
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Following tests verify cooperation between WebSocketJob and SocketStream.
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Other former tests use MockSocketStream as SocketStream, so we could not
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// check SocketStream behavior.
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OrderedSocketData provide socket level verifiation by checking out-going
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// packets in comparison with the MockWrite array and emulating in-coming
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// packets with MockRead array.
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
897eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid WebSocketJobTest::TestConnectByWebSocket(
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ThrottlingOption throttling) {
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is a test for verifying cooperation between WebSocketJob and
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SocketStream. If |throttling| was |THROTTLING_OFF|, it test basic
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // situation. If |throttling| was |THROTTLING_ON|, throttling limits the
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // latter connection.
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes[] = {
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC,
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              kHandshakeRequestWithoutCookie,
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              kHandshakeRequestWithoutCookieLength,
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              1),
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC,
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              kDataHello,
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              kDataHelloLength,
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              3)
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads[] = {
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC,
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             kHandshakeResponseWithoutCookie,
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             kHandshakeResponseWithoutCookieLength,
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             2),
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC,
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             kDataWorld,
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             kDataWorldLength,
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             4),
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(SYNCHRONOUS, 0, 5)  // EOF
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_.reset(new OrderedSocketData(
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reads, arraysize(reads), writes, arraysize(writes)));
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url("ws://example.com/demo");
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockSocketStreamDelegate delegate;
929eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  WebSocketJobTest* test = this;
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (throttling == THROTTLING_ON)
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate.SetOnStartOpenConnection(
932eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate.SetOnConnected(
934eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&WebSocketJobTest::DoSendRequest,
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(test)));
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate.SetOnReceivedData(
937eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&WebSocketJobTest::DoSendData, base::Unretained(test)));
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate.SetOnClose(
939eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitWebSocketJob(url, &delegate, STREAM_SOCKET);
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<WebSocketJob> block_websocket;
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (throttling == THROTTLING_ON) {
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create former WebSocket object which obstructs the latter one.
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    block_websocket = new WebSocketJob(NULL);
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    block_websocket->addresses_ = AddressList(websocket_->address_list());
947ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ASSERT_TRUE(
948ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        WebSocketThrottle::GetInstance()->PutInQueue(block_websocket.get()));
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket_->Connect();
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (throttling == THROTTLING_ON) {
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, WaitForResult());
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(websocket_->IsWaiting());
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Remove the former WebSocket object from throttling queue to unblock the
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // latter.
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    block_websocket->state_ = WebSocketJob::CLOSED;
960ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    WebSocketThrottle::GetInstance()->RemoveFromQueue(block_websocket.get());
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    block_websocket = NULL;
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, WaitForResult());
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(data_->at_read_eof());
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(data_->at_write_eof());
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WebSocketJob::CLOSED, GetWebSocketJobState());
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
970eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid WebSocketJobTest::TestConnectBySpdy(
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpdyOption spdy, ThrottlingOption throttling) {
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is a test for verifying cooperation between WebSocketJob and
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SocketStream in the situation we have SPDY session to the server. If
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |throttling| was |THROTTLING_ON|, throttling limits the latter connection.
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If you enabled spdy, you should specify |spdy| as |SPDY_ON|. Expected
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // results depend on its configuration.
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes_websocket[] = {
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC,
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              kHandshakeRequestWithoutCookie,
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              kHandshakeRequestWithoutCookieLength,
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              1),
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite(ASYNC,
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              kDataHello,
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              kDataHelloLength,
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              3)
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads_websocket[] = {
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC,
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             kHandshakeResponseWithoutCookie,
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             kHandshakeResponseWithoutCookieLength,
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             2),
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(ASYNC,
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             kDataWorld,
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             kDataWorldLength,
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             4),
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(SYNCHRONOUS, 0, 5)  // EOF
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
999eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> request_headers(new SpdyHeaderBlock());
1000eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_util_.SetHeader("path", "/demo", request_headers.get());
1001eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_util_.SetHeader("version", "WebSocket/13", request_headers.get());
1002eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_util_.SetHeader("scheme", "ws", request_headers.get());
1003eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_util_.SetHeader("host", "example.com", request_headers.get());
1004eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_util_.SetHeader("origin", "http://example.com", request_headers.get());
1005eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_util_.SetHeader("sec-websocket-protocol", "sample",
1006eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       request_headers.get());
1007eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1008eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<SpdyHeaderBlock> response_headers(new SpdyHeaderBlock());
1009eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_util_.SetHeader("status", "101 Switching Protocols",
1010eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       response_headers.get());
1011eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  spdy_util_.SetHeader("sec-websocket-protocol", "sample",
1012eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       response_headers.get());
1013eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SpdyStreamId kStreamId = 1;
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> request_frame(
1016eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWebSocketHandshakeRequestFrame(
1017eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          request_headers.Pass(),
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kStreamId,
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          MEDIUM));
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> response_frame(
1021eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWebSocketHandshakeResponseFrame(
1022eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          response_headers.Pass(),
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kStreamId,
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          MEDIUM));
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_hello_frame(
1026eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWebSocketDataFrame(
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kDataHello,
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kDataHelloLength,
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kStreamId,
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          false));
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpdyFrame> data_world_frame(
1032eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      spdy_util_.ConstructSpdyWebSocketDataFrame(
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kDataWorld,
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kDataWorldLength,
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kStreamId,
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          false));
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite writes_spdy[] = {
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*request_frame.get(), 1),
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockWrite(*data_hello_frame.get(), 3),
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead reads_spdy[] = {
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*response_frame.get(), 2),
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CreateMockRead(*data_world_frame.get(), 4),
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead(SYNCHRONOUS, 0, 5)  // EOF
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (spdy == SPDY_ON)
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_.reset(new OrderedSocketData(
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reads_spdy, arraysize(reads_spdy),
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        writes_spdy, arraysize(writes_spdy)));
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_.reset(new OrderedSocketData(
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reads_websocket, arraysize(reads_websocket),
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        writes_websocket, arraysize(writes_websocket)));
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url("ws://example.com/demo");
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockSocketStreamDelegate delegate;
1058eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  WebSocketJobTest* test = this;
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (throttling == THROTTLING_ON)
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate.SetOnStartOpenConnection(
1061eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate.SetOnConnected(
1063eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&WebSocketJobTest::DoSendRequest,
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(test)));
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate.SetOnReceivedData(
1066eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&WebSocketJobTest::DoSendData, base::Unretained(test)));
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate.SetOnClose(
1068eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitWebSocketJob(url, &delegate, STREAM_SPDY_WEBSOCKET);
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<WebSocketJob> block_websocket;
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (throttling == THROTTLING_ON) {
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create former WebSocket object which obstructs the latter one.
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    block_websocket = new WebSocketJob(NULL);
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    block_websocket->addresses_ = AddressList(websocket_->address_list());
1076ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ASSERT_TRUE(
1077ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        WebSocketThrottle::GetInstance()->PutInQueue(block_websocket.get()));
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  websocket_->Connect();
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (throttling == THROTTLING_ON) {
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, WaitForResult());
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(websocket_->IsWaiting());
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Remove the former WebSocket object from throttling queue to unblock the
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // latter.
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    block_websocket->state_ = WebSocketJob::CLOSED;
1089ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    WebSocketThrottle::GetInstance()->RemoveFromQueue(block_websocket.get());
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    block_websocket = NULL;
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, WaitForResult());
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(data_->at_read_eof());
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(data_->at_write_eof());
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WebSocketJob::CLOSED, GetWebSocketJobState());
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1099ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid WebSocketJobTest::TestThrottlingLimit() {
1100ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  std::vector<scoped_refptr<WebSocketJob> > jobs;
1101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const int kMaxWebSocketJobsThrottled = 1024;
1102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  IPAddressNumber ip;
1103ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ParseIPLiteralToNumber("127.0.0.1", &ip);
1104ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  for (int i = 0; i < kMaxWebSocketJobsThrottled + 1; ++i) {
1105ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    scoped_refptr<WebSocketJob> job = new WebSocketJob(NULL);
1106ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    job->addresses_ = AddressList(AddressList::CreateFromIPAddress(ip, 80));
1107ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (i >= kMaxWebSocketJobsThrottled)
11081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      EXPECT_FALSE(WebSocketThrottle::GetInstance()->PutInQueue(job.get()));
1109ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    else
11101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      EXPECT_TRUE(WebSocketThrottle::GetInstance()->PutInQueue(job.get()));
1111ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    jobs.push_back(job);
1112ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
1113ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1114ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Close the jobs in reverse order. Otherwise, We need to make them prepared
1115ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // for Wakeup call.
1116ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  for (std::vector<scoped_refptr<WebSocketJob> >::reverse_iterator iter =
1117ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch           jobs.rbegin();
1118ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch       iter != jobs.rend();
1119ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch       ++iter) {
1120ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    WebSocketJob* job = (*iter).get();
1121ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    job->state_ = WebSocketJob::CLOSED;
1122ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    WebSocketThrottle::GetInstance()->RemoveFromQueue(job);
1123ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
1124ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1125ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Execute tests in both spdy-disabled mode and spdy-enabled mode.
1127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, SimpleHandshake) {
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSimpleHandshake();
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, SlowHandshake) {
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSlowHandshake();
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, HandshakeWithCookie) {
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHandshakeWithCookie();
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, HandshakeWithCookieButNotAllowed) {
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHandshakeWithCookieButNotAllowed();
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, HSTSUpgrade) {
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHSTSUpgrade();
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, InvalidSendData) {
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestInvalidSendData();
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, SimpleHandshakeSpdyEnabled) {
115246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  enable_websocket_over_spdy_ = true;
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSimpleHandshake();
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, SlowHandshakeSpdyEnabled) {
115746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  enable_websocket_over_spdy_ = true;
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSlowHandshake();
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, HandshakeWithCookieSpdyEnabled) {
116246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  enable_websocket_over_spdy_ = true;
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHandshakeWithCookie();
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, HandshakeWithCookieButNotAllowedSpdyEnabled) {
116746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  enable_websocket_over_spdy_ = true;
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHandshakeWithCookieButNotAllowed();
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, HSTSUpgradeSpdyEnabled) {
117246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  enable_websocket_over_spdy_ = true;
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHSTSUpgrade();
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, InvalidSendDataSpdyEnabled) {
117746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  enable_websocket_over_spdy_ = true;
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestInvalidSendData();
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, ConnectByWebSocket) {
118246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  enable_websocket_over_spdy_ = true;
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestConnectByWebSocket(THROTTLING_OFF);
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, ConnectByWebSocketSpdyEnabled) {
118746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  enable_websocket_over_spdy_ = true;
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestConnectByWebSocket(THROTTLING_OFF);
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, ConnectBySpdy) {
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestConnectBySpdy(SPDY_OFF, THROTTLING_OFF);
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, ConnectBySpdySpdyEnabled) {
119646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  enable_websocket_over_spdy_ = true;
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestConnectBySpdy(SPDY_ON, THROTTLING_OFF);
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, ThrottlingWebSocket) {
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestConnectByWebSocket(THROTTLING_ON);
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1204ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTEST_P(WebSocketJobTest, ThrottlingMaxNumberOfThrottledJobLimit) {
1205ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  TestThrottlingLimit();
1206ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
1207ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
1208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, ThrottlingWebSocketSpdyEnabled) {
120946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  enable_websocket_over_spdy_ = true;
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestConnectByWebSocket(THROTTLING_ON);
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, ThrottlingSpdy) {
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestConnectBySpdy(SPDY_OFF, THROTTLING_ON);
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochTEST_P(WebSocketJobTest, ThrottlingSpdySpdyEnabled) {
121846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  enable_websocket_over_spdy_ = true;
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestConnectBySpdy(SPDY_ON, THROTTLING_ON);
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1222c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(WebSocketJobDeleteTest, OnClose) {
1223c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SetDeleteNext();
1224c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  job()->OnClose(socket_.get());
1225c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // OnClose() sets WebSocketJob::_socket to NULL before we can detach it, so
1226c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // socket_->delegate is still set at this point. Clear it to avoid hitting
1227c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // DCHECK(!delegate_) in the SocketStream destructor. SocketStream::Finish()
1228c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // is the only caller of this method in real code, and it also sets delegate_
1229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // to NULL.
1230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  socket_->DetachDelegate();
1231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_FALSE(job());
1232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(WebSocketJobDeleteTest, OnAuthRequired) {
1235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SetDeleteNext();
1236c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  job()->OnAuthRequired(socket_.get(), NULL);
1237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_FALSE(job());
1238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1239c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(WebSocketJobDeleteTest, OnSSLCertificateError) {
1241c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SSLInfo ssl_info;
1242c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SetDeleteNext();
1243c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  job()->OnSSLCertificateError(socket_.get(), ssl_info, true);
1244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_FALSE(job());
1245c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1246c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1247c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(WebSocketJobDeleteTest, OnError) {
1248c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SetDeleteNext();
1249c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  job()->OnError(socket_.get(), ERR_CONNECTION_RESET);
1250c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_FALSE(job());
1251c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1252c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1253c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(WebSocketJobDeleteTest, OnSentSpdyHeaders) {
1254c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  job()->Connect();
1255c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SetDeleteNext();
1256c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  job()->OnSentSpdyHeaders();
1257c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_FALSE(job());
1258c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1259c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1260c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(WebSocketJobDeleteTest, OnSentHandshakeRequest) {
1261c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  static const char kMinimalRequest[] =
1262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      "GET /demo HTTP/1.1\r\n"
1263c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      "Host: example.com\r\n"
1264c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      "Upgrade: WebSocket\r\n"
1265c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      "Connection: Upgrade\r\n"
1266c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
1267c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      "Origin: http://example.com\r\n"
1268c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      "Sec-WebSocket-Version: 13\r\n"
1269c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      "\r\n";
1270c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const size_t kMinimalRequestSize = arraysize(kMinimalRequest) - 1;
1271c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  job()->Connect();
1272c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  job()->SendData(kMinimalRequest, kMinimalRequestSize);
1273c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SetDeleteNext();
1274c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  job()->OnSentData(socket_.get(), kMinimalRequestSize);
1275c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_FALSE(job());
1276c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1277c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1278c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochTEST_F(WebSocketJobDeleteTest, NotifyHeadersComplete) {
1279c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  static const char kMinimalResponse[] =
1280c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      "HTTP/1.1 101 Switching Protocols\r\n"
1281c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      "Upgrade: websocket\r\n"
1282c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      "Connection: Upgrade\r\n"
1283c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
1284c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      "\r\n";
1285c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  job()->Connect();
1286c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SetDeleteNext();
1287c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  job()->OnReceivedData(
1288c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      socket_.get(), kMinimalResponse, arraysize(kMinimalResponse) - 1);
1289c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_FALSE(job());
1290c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
1291c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(toyoshim): Add tests to verify throttling, SPDY stream limitation.
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(toyoshim,yutak): Add tests to verify closing handshake.
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
1295