172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector>
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/ref_counted.h"
93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_split.h"
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_util.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/cookie_policy.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/cookie_store.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_errors.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/sys_addrinfo.h"
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/transport_security_state.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/socket_stream/socket_stream.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/url_request/url_request_context.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/websockets/websocket_job.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/websockets/websocket_throttle.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/gtest/include/gtest/gtest.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/gmock/include/gmock/gmock.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "testing/platform_test.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net {
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass MockSocketStream : public SocketStream {
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockSocketStream(const GURL& url, SocketStream::Delegate* delegate)
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : SocketStream(url, delegate) {}
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual ~MockSocketStream() {}
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void Connect() {}
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool SendData(const char* data, int len) {
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    sent_data_ += std::string(data, len);
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void Close() {}
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void RestartWithAuth(
413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const string16& username, const string16& password) {}
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void DetachDelegate() {
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delegate_ = NULL;
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const std::string& sent_data() const {
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return sent_data_;
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string sent_data_;
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass MockSocketStreamDelegate : public SocketStream::Delegate {
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockSocketStreamDelegate()
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : amount_sent_(0) {}
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual ~MockSocketStreamDelegate() {}
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnConnected(SocketStream* socket, int max_pending_send_allowed) {
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnSentData(SocketStream* socket, int amount_sent) {
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    amount_sent_ += amount_sent;
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnReceivedData(SocketStream* socket,
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              const char* data, int len) {
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    received_data_ += std::string(data, len);
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnClose(SocketStream* socket) {
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size_t amount_sent() const { return amount_sent_; }
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const std::string& received_data() const { return received_data_; }
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int amount_sent_;
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string received_data_;
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass MockCookieStore : public CookieStore {
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct Entry {
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GURL url;
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string cookie_line;
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CookieOptions options;
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockCookieStore() {}
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool SetCookieWithOptions(const GURL& url,
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    const std::string& cookie_line,
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    const CookieOptions& options) {
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Entry entry;
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    entry.url = url;
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    entry.cookie_line = cookie_line;
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    entry.options = options;
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    entries_.push_back(entry);
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual std::string GetCookiesWithOptions(const GURL& url,
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            const CookieOptions& options) {
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string result;
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (size_t i = 0; i < entries_.size(); i++) {
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Entry &entry = entries_[i];
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (url == entry.url) {
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (!result.empty()) {
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          result += "; ";
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        result += entry.cookie_line;
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return result;
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void DeleteCookie(const GURL& url,
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            const std::string& cookie_name) {}
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual CookieMonster* GetCookieMonster() { return NULL; }
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const std::vector<Entry>& entries() const { return entries_; }
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  friend class base::RefCountedThreadSafe<MockCookieStore>;
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual ~MockCookieStore() {}
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<Entry> entries_;
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass MockCookiePolicy : public CookiePolicy {
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MockCookiePolicy() : allow_all_cookies_(true) {}
129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual ~MockCookiePolicy() {}
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void set_allow_all_cookies(bool allow_all_cookies) {
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    allow_all_cookies_ = allow_all_cookies;
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual int CanGetCookies(const GURL& url,
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            const GURL& first_party_for_cookies) const {
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (allow_all_cookies_)
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return OK;
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return ERR_ACCESS_DENIED;
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual int CanSetCookie(const GURL& url,
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           const GURL& first_party_for_cookies,
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                           const std::string& cookie_line) const {
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (allow_all_cookies_)
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return OK;
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return ERR_ACCESS_DENIED;
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private:
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool allow_all_cookies_;
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass MockURLRequestContext : public URLRequestContext {
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockURLRequestContext(CookieStore* cookie_store,
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        CookiePolicy* cookie_policy) {
158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    set_cookie_store(cookie_store);
159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    set_cookie_policy(cookie_policy);
160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    transport_security_state_ = new TransportSecurityState();
161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    set_transport_security_state(transport_security_state_.get());
162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    TransportSecurityState::DomainState state;
163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    state.expiry = base::Time::Now() + base::TimeDelta::FromSeconds(1000);
164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    transport_security_state_->EnableHost("upgrademe.com", state);
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  friend class base::RefCountedThreadSafe<MockURLRequestContext>;
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual ~MockURLRequestContext() {}
170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_refptr<TransportSecurityState> transport_security_state_;
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WebSocketJobTest : public PlatformTest {
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void SetUp() {
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cookie_store_ = new MockCookieStore;
178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    cookie_policy_.reset(new MockCookiePolicy);
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    context_ = new MockURLRequestContext(
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        cookie_store_.get(), cookie_policy_.get());
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void TearDown() {
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cookie_store_ = NULL;
184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    cookie_policy_.reset();
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    context_ = NULL;
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    websocket_ = NULL;
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    socket_ = NULL;
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch protected:
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void InitWebSocketJob(const GURL& url, MockSocketStreamDelegate* delegate) {
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    websocket_ = new WebSocketJob(delegate);
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    socket_ = new MockSocketStream(url, websocket_.get());
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    websocket_->InitSocketStream(socket_.get());
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    websocket_->set_context(context_.get());
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    websocket_->state_ = WebSocketJob::CONNECTING;
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    struct addrinfo addr;
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    memset(&addr, 0, sizeof(struct addrinfo));
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    addr.ai_family = AF_INET;
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    addr.ai_addrlen = sizeof(struct sockaddr_in);
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    struct sockaddr_in sa_in;
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    memset(&sa_in, 0, sizeof(struct sockaddr_in));
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    memcpy(&sa_in.sin_addr, "\x7f\0\0\1", 4);
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    addr.ai_addr = reinterpret_cast<sockaddr*>(&sa_in);
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    addr.ai_next = NULL;
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    websocket_->addresses_.Copy(&addr, true);
20621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    WebSocketThrottle::GetInstance()->PutInQueue(websocket_);
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebSocketJob::State GetWebSocketJobState() {
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return websocket_->state_;
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void CloseWebSocketJob() {
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (websocket_->socket_) {
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      websocket_->socket_->DetachDelegate();
21421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      WebSocketThrottle::GetInstance()->RemoveFromQueue(websocket_);
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    websocket_->state_ = WebSocketJob::CLOSED;
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    websocket_->delegate_ = NULL;
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    websocket_->socket_ = NULL;
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SocketStream* GetSocket(SocketStreamJob* job) {
221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return job->socket_.get();
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<MockCookieStore> cookie_store_;
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_ptr<MockCookiePolicy> cookie_policy_;
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<MockURLRequestContext> context_;
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<WebSocketJob> websocket_;
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<MockSocketStream> socket_;
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(WebSocketJobTest, SimpleHandshake) {
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL url("ws://example.com/demo");
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockSocketStreamDelegate delegate;
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InitWebSocketJob(url, &delegate);
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char* kHandshakeRequestMessage =
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "GET /demo HTTP/1.1\r\n"
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Host: example.com\r\n"
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Connection: Upgrade\r\n"
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Protocol: sample\r\n"
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Upgrade: WebSocket\r\n"
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Origin: http://example.com\r\n"
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "\r\n"
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "^n:ds[4U";
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool sent = websocket_->SendData(kHandshakeRequestMessage,
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   strlen(kHandshakeRequestMessage));
25072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_TRUE(sent);
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(kHandshakeRequestMessage, socket_->sent_data());
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  websocket_->OnSentData(socket_.get(), strlen(kHandshakeRequestMessage));
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(strlen(kHandshakeRequestMessage), delegate.amount_sent());
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char kHandshakeResponseMessage[] =
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Upgrade: WebSocket\r\n"
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Connection: Upgrade\r\n"
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Origin: http://example.com\r\n"
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Location: ws://example.com/demo\r\n"
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Protocol: sample\r\n"
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "\r\n"
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "8jKS'y:G*Co,Wxa-";
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  websocket_->OnReceivedData(socket_.get(),
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             kHandshakeResponseMessage,
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             strlen(kHandshakeResponseMessage));
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(kHandshakeResponseMessage, delegate.received_data());
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CloseWebSocketJob();
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(WebSocketJobTest, SlowHandshake) {
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL url("ws://example.com/demo");
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockSocketStreamDelegate delegate;
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InitWebSocketJob(url, &delegate);
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char* kHandshakeRequestMessage =
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "GET /demo HTTP/1.1\r\n"
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Host: example.com\r\n"
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Connection: Upgrade\r\n"
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Protocol: sample\r\n"
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Upgrade: WebSocket\r\n"
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Origin: http://example.com\r\n"
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "\r\n"
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "^n:ds[4U";
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool sent = websocket_->SendData(kHandshakeRequestMessage,
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   strlen(kHandshakeRequestMessage));
29572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_TRUE(sent);
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We assume request is sent in one data chunk (from WebKit)
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We don't support streaming request.
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(kHandshakeRequestMessage, socket_->sent_data());
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  websocket_->OnSentData(socket_.get(), strlen(kHandshakeRequestMessage));
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(strlen(kHandshakeRequestMessage), delegate.amount_sent());
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char kHandshakeResponseMessage[] =
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Upgrade: WebSocket\r\n"
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Connection: Upgrade\r\n"
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Origin: http://example.com\r\n"
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Location: ws://example.com/demo\r\n"
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Protocol: sample\r\n"
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "\r\n"
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "8jKS'y:G*Co,Wxa-";
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<std::string> lines;
315731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  base::SplitString(kHandshakeResponseMessage, '\n', &lines);
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < lines.size() - 2; i++) {
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string line = lines[i] + "\r\n";
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SCOPED_TRACE("Line: " + line);
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    websocket_->OnReceivedData(socket_,
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               line.c_str(),
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               line.size());
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MessageLoop::current()->RunAllPending();
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_TRUE(delegate.received_data().empty());
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  websocket_->OnReceivedData(socket_.get(), "\r\n", 2);
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_TRUE(delegate.received_data().empty());
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  websocket_->OnReceivedData(socket_.get(), "8jKS'y:G*Co,Wxa-", 16);
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(kHandshakeResponseMessage, delegate.received_data());
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CloseWebSocketJob();
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(WebSocketJobTest, HandshakeWithCookie) {
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL url("ws://example.com/demo");
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL cookieUrl("http://example.com/demo");
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CookieOptions cookie_options;
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cookie_store_->SetCookieWithOptions(
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      cookieUrl, "CR-test=1", cookie_options);
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cookie_options.set_include_httponly();
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cookie_store_->SetCookieWithOptions(
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      cookieUrl, "CR-test-httponly=1", cookie_options);
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockSocketStreamDelegate delegate;
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InitWebSocketJob(url, &delegate);
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char* kHandshakeRequestMessage =
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "GET /demo HTTP/1.1\r\n"
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Host: example.com\r\n"
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Connection: Upgrade\r\n"
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Protocol: sample\r\n"
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Upgrade: WebSocket\r\n"
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Origin: http://example.com\r\n"
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Cookie: WK-test=1\r\n"
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "\r\n"
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "^n:ds[4U";
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char* kHandshakeRequestExpected =
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "GET /demo HTTP/1.1\r\n"
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Host: example.com\r\n"
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Connection: Upgrade\r\n"
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Protocol: sample\r\n"
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Upgrade: WebSocket\r\n"
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Origin: http://example.com\r\n"
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Cookie: CR-test=1; CR-test-httponly=1\r\n"
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "\r\n"
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "^n:ds[4U";
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool sent = websocket_->SendData(kHandshakeRequestMessage,
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   strlen(kHandshakeRequestMessage));
37772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_TRUE(sent);
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(kHandshakeRequestExpected, socket_->sent_data());
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  websocket_->OnSentData(socket_, strlen(kHandshakeRequestExpected));
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(strlen(kHandshakeRequestMessage), delegate.amount_sent());
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char kHandshakeResponseMessage[] =
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Upgrade: WebSocket\r\n"
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Connection: Upgrade\r\n"
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Origin: http://example.com\r\n"
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Location: ws://example.com/demo\r\n"
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Protocol: sample\r\n"
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Set-Cookie: CR-set-test=1\r\n"
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "\r\n"
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "8jKS'y:G*Co,Wxa-";
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char* kHandshakeResponseExpected =
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Upgrade: WebSocket\r\n"
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Connection: Upgrade\r\n"
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Origin: http://example.com\r\n"
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Location: ws://example.com/demo\r\n"
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Protocol: sample\r\n"
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "\r\n"
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "8jKS'y:G*Co,Wxa-";
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  websocket_->OnReceivedData(socket_.get(),
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             kHandshakeResponseMessage,
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             strlen(kHandshakeResponseMessage));
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(kHandshakeResponseExpected, delegate.received_data());
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(3U, cookie_store_->entries().size());
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(cookieUrl, cookie_store_->entries()[2].url);
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("CR-set-test=1", cookie_store_->entries()[2].cookie_line);
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CloseWebSocketJob();
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(WebSocketJobTest, HandshakeWithCookieButNotAllowed) {
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL url("ws://example.com/demo");
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL cookieUrl("http://example.com/demo");
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CookieOptions cookie_options;
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cookie_store_->SetCookieWithOptions(
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      cookieUrl, "CR-test=1", cookie_options);
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cookie_options.set_include_httponly();
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cookie_store_->SetCookieWithOptions(
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      cookieUrl, "CR-test-httponly=1", cookie_options);
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cookie_policy_->set_allow_all_cookies(false);
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockSocketStreamDelegate delegate;
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InitWebSocketJob(url, &delegate);
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char* kHandshakeRequestMessage =
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "GET /demo HTTP/1.1\r\n"
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Host: example.com\r\n"
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Connection: Upgrade\r\n"
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Protocol: sample\r\n"
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Upgrade: WebSocket\r\n"
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Origin: http://example.com\r\n"
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Cookie: WK-test=1\r\n"
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "\r\n"
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "^n:ds[4U";
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char* kHandshakeRequestExpected =
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "GET /demo HTTP/1.1\r\n"
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Host: example.com\r\n"
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Connection: Upgrade\r\n"
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00\r\n"
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Protocol: sample\r\n"
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Upgrade: WebSocket\r\n"
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5\r\n"
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Origin: http://example.com\r\n"
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "\r\n"
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "^n:ds[4U";
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool sent = websocket_->SendData(kHandshakeRequestMessage,
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   strlen(kHandshakeRequestMessage));
46472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EXPECT_TRUE(sent);
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(kHandshakeRequestExpected, socket_->sent_data());
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  websocket_->OnSentData(socket_, strlen(kHandshakeRequestExpected));
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(strlen(kHandshakeRequestMessage), delegate.amount_sent());
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char kHandshakeResponseMessage[] =
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Upgrade: WebSocket\r\n"
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Connection: Upgrade\r\n"
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Origin: http://example.com\r\n"
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Location: ws://example.com/demo\r\n"
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Protocol: sample\r\n"
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Set-Cookie: CR-set-test=1\r\n"
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "\r\n"
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "8jKS'y:G*Co,Wxa-";
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char* kHandshakeResponseExpected =
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Upgrade: WebSocket\r\n"
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Connection: Upgrade\r\n"
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Origin: http://example.com\r\n"
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Location: ws://example.com/demo\r\n"
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "Sec-WebSocket-Protocol: sample\r\n"
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "\r\n"
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      "8jKS'y:G*Co,Wxa-";
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  websocket_->OnReceivedData(socket_.get(),
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             kHandshakeResponseMessage,
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             strlen(kHandshakeResponseMessage));
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->RunAllPending();
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(kHandshakeResponseExpected, delegate.received_data());
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(2U, cookie_store_->entries().size());
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CloseWebSocketJob();
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
508ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenTEST_F(WebSocketJobTest, HSTSUpgrade) {
509ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  GURL url("ws://upgrademe.com/");
510ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  MockSocketStreamDelegate delegate;
511ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_refptr<SocketStreamJob> job = SocketStreamJob::CreateSocketStreamJob(
512ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      url, &delegate, *context_.get());
513ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_TRUE(GetSocket(job.get())->is_secure());
514ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  job->DetachDelegate();
515ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
516ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  url = GURL("ws://donotupgrademe.com/");
517ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  job = SocketStreamJob::CreateSocketStreamJob(
518ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      url, &delegate, *context_.get());
519ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  EXPECT_FALSE(GetSocket(job.get())->is_secure());
520ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  job->DetachDelegate();
521ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
522ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace net
524