Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(902)

Unified Diff: net/websockets/websocket_job_unittest.cc

Issue 601077: Support HttpOnly cookie on Web Socket (Closed)
Patch Set: fix darin's comment Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/websockets/websocket_job.cc ('k') | webkit/tools/layout_tests/test_expectations.txt » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/websockets/websocket_job_unittest.cc
diff --git a/net/websockets/websocket_job_unittest.cc b/net/websockets/websocket_job_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..de96a323f56b8bd69130ea715a1d71b20fdf5aae
--- /dev/null
+++ b/net/websockets/websocket_job_unittest.cc
@@ -0,0 +1,495 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+#include <vector>
+
+#include "base/ref_counted.h"
+#include "googleurl/src/gurl.h"
+#include "net/base/cookie_policy.h"
+#include "net/base/cookie_store.h"
+#include "net/base/net_errors.h"
+#include "net/socket_stream/socket_stream.h"
+#include "net/url_request/url_request_context.h"
+#include "net/websockets/websocket_job.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/platform_test.h"
+
+namespace net {
+
+class MockSocketStream : public SocketStream {
+ public:
+ MockSocketStream(const GURL& url, SocketStream::Delegate* delegate)
+ : SocketStream(url, delegate) {}
+ virtual ~MockSocketStream() {}
+
+ virtual void Connect() {}
+ virtual bool SendData(const char* data, int len) {
+ sent_data_ += std::string(data, len);
+ return true;
+ }
+
+ virtual void Close() {}
+ virtual void RestartWithAuth(
+ const std::wstring& username, std::wstring& password) {}
+ virtual void DetachDelegate() {
+ delegate_ = NULL;
+ }
+
+ const std::string& sent_data() const {
+ return sent_data_;
+ }
+
+ private:
+ std::string sent_data_;
+};
+
+class MockSocketStreamDelegate : public SocketStream::Delegate {
+ public:
+ MockSocketStreamDelegate()
+ : amount_sent_(0) {}
+ virtual ~MockSocketStreamDelegate() {}
+
+ virtual void OnConnected(SocketStream* socket, int max_pending_send_allowed) {
+ }
+ virtual void OnSentData(SocketStream* socket, int amount_sent) {
+ amount_sent_ += amount_sent;
+ }
+ virtual void OnReceivedData(SocketStream* socket,
+ const char* data, int len) {
+ received_data_ += std::string(data, len);
+ }
+ virtual void OnClose(SocketStream* socket) {
+ }
+
+ size_t amount_sent() const { return amount_sent_; }
+ const std::string& received_data() const { return received_data_; }
+
+ private:
+ int amount_sent_;
+ std::string received_data_;
+};
+
+class MockCookieStore : public CookieStore {
+ public:
+ struct Entry {
+ GURL url;
+ std::string cookie_line;
+ CookieOptions options;
+ };
+ MockCookieStore() {}
+
+ virtual bool SetCookieWithOptions(const GURL& url,
+ const std::string& cookie_line,
+ const CookieOptions& options) {
+ Entry entry;
+ entry.url = url;
+ entry.cookie_line = cookie_line;
+ entry.options = options;
+ entries_.push_back(entry);
+ return true;
+ }
+ virtual std::string GetCookiesWithOptions(const GURL& url,
+ const CookieOptions& options) {
+ std::string result;
+ for (size_t i = 0; i < entries_.size(); i++) {
+ Entry &entry = entries_[i];
+ if (url == entry.url) {
+ if (!result.empty()) {
+ result += "; ";
+ }
+ result += entry.cookie_line;
+ }
+ }
+ return result;
+ }
+ virtual void DeleteCookie(const GURL& url,
+ const std::string& cookie_name) {}
+ virtual CookieMonster* GetCookieMonster() { return NULL; }
+
+ const std::vector<Entry>& entries() const { return entries_; }
+
+ private:
+ friend class base::RefCountedThreadSafe<MockCookieStore>;
+ virtual ~MockCookieStore() {}
+
+ std::vector<Entry> entries_;
+};
+
+class MockCookiePolicy : public CookiePolicy,
+ public base::RefCountedThreadSafe<MockCookiePolicy> {
+ public:
+ MockCookiePolicy() : allow_all_cookies_(true), callback_(NULL) {}
+
+ void set_allow_all_cookies(bool allow_all_cookies) {
+ allow_all_cookies_ = allow_all_cookies;
+ }
+
+ virtual int CanGetCookies(const GURL& url,
+ const GURL& first_party_for_cookies,
+ CompletionCallback* callback) {
+ DCHECK(!callback_);
+ callback_ = callback;
+ MessageLoop::current()->PostTask(
+ FROM_HERE, NewRunnableMethod(this, &MockCookiePolicy::OnCanGetCookies));
+ return ERR_IO_PENDING;
+ }
+
+ virtual int CanSetCookie(const GURL& url,
+ const GURL& first_party_for_cookies,
+ const std::string& cookie_line,
+ CompletionCallback* callback) {
+ DCHECK(!callback_);
+ callback_ = callback;
+ MessageLoop::current()->PostTask(
+ FROM_HERE, NewRunnableMethod(this, &MockCookiePolicy::OnCanSetCookie));
+ return ERR_IO_PENDING;
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<MockCookiePolicy>;
+ virtual ~MockCookiePolicy() {}
+
+ void OnCanGetCookies() {
+ CompletionCallback* callback = callback_;
+ callback_ = NULL;
+ if (allow_all_cookies_)
+ callback->Run(OK);
+ else
+ callback->Run(ERR_ACCESS_DENIED);
+ }
+ void OnCanSetCookie() {
+ CompletionCallback* callback = callback_;
+ callback_ = NULL;
+ if (allow_all_cookies_)
+ callback->Run(OK);
+ else
+ callback->Run(ERR_ACCESS_DENIED);
+ }
+
+ bool allow_all_cookies_;
+ CompletionCallback* callback_;
+};
+
+class MockURLRequestContext : public URLRequestContext {
+ public:
+ MockURLRequestContext(CookieStore* cookie_store,
+ CookiePolicy* cookie_policy) {
+ cookie_store_ = cookie_store;
+ cookie_policy_ = cookie_policy;
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<MockURLRequestContext>;
+ virtual ~MockURLRequestContext() {}
+};
+
+class WebSocketJobTest : public PlatformTest {
+ public:
+ virtual void SetUp() {
+ cookie_store_ = new MockCookieStore;
+ cookie_policy_ = new MockCookiePolicy;
+ context_ = new MockURLRequestContext(
+ cookie_store_.get(), cookie_policy_.get());
+ }
+ virtual void TearDown() {
+ cookie_store_ = NULL;
+ cookie_policy_ = NULL;
+ context_ = NULL;
+ websocket_ = NULL;
+ socket_ = NULL;
+ }
+ protected:
+ void InitWebSocketJob(const GURL& url, MockSocketStreamDelegate* delegate) {
+ websocket_ = new WebSocketJob(delegate);
+ socket_ = new MockSocketStream(url, websocket_.get());
+ websocket_->InitSocketStream(socket_.get());
+ websocket_->state_ = WebSocketJob::CONNECTING;
+ websocket_->set_context(context_.get());
+ }
+ WebSocketJob::State GetWebSocketJobState() {
+ return websocket_->state_;
+ }
+ void CloseWebSocketJob() {
+ if (websocket_->socket_)
+ websocket_->socket_->DetachDelegate();
+ websocket_->state_ = WebSocketJob::CLOSED;
+ websocket_->delegate_ = NULL;
+ websocket_->socket_ = NULL;
+ }
+
+ scoped_refptr<MockCookieStore> cookie_store_;
+ scoped_refptr<MockCookiePolicy> cookie_policy_;
+ scoped_refptr<MockURLRequestContext> context_;
+ scoped_refptr<WebSocketJob> websocket_;
+ scoped_refptr<MockSocketStream> socket_;
+};
+
+TEST_F(WebSocketJobTest, SimpleHandshake) {
+ GURL url("ws://example.com/demo");
+ MockSocketStreamDelegate delegate;
+ InitWebSocketJob(url, &delegate);
+
+ static const char* kHandshakeRequestMessage =
+ "GET /demo HTTP/1.1\r\n"
+ "Upgrade: WebSocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Host: example.com\r\n"
+ "Origin: http://example.com\r\n"
+ "WebSocket-Protocol: sample\r\n"
+ "\r\n";
+
+ bool sent = websocket_->SendData(kHandshakeRequestMessage,
+ strlen(kHandshakeRequestMessage));
+ EXPECT_EQ(true, sent);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(kHandshakeRequestMessage, socket_->sent_data());
+ EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
+ websocket_->OnSentData(socket_.get(), strlen(kHandshakeRequestMessage));
+ EXPECT_EQ(strlen(kHandshakeRequestMessage), delegate.amount_sent());
+
+ static const char* kHandshakeResponseMessage =
+ "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
+ "Upgrade: WebSocket\r\n"
+ "Connection: Upgrade\r\n"
+ "WebSocket-Origin: http://example.com\r\n"
+ "WebSocket-Location: ws://example.com/demo\r\n"
+ "WebSocket-Protocol: sample\r\n"
+ "\r\n";
+
+ websocket_->OnReceivedData(socket_.get(),
+ kHandshakeResponseMessage,
+ strlen(kHandshakeResponseMessage));
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(kHandshakeResponseMessage, delegate.received_data());
+ EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
+ CloseWebSocketJob();
+}
+
+TEST_F(WebSocketJobTest, SlowHandshake) {
+ GURL url("ws://example.com/demo");
+ MockSocketStreamDelegate delegate;
+ InitWebSocketJob(url, &delegate);
+
+ static const char* kHandshakeRequestMessage =
+ "GET /demo HTTP/1.1\r\n"
+ "Upgrade: WebSocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Host: example.com\r\n"
+ "Origin: http://example.com\r\n"
+ "WebSocket-Protocol: sample\r\n"
+ "\r\n";
+ std::vector<std::string> lines;
+ SplitString(kHandshakeRequestMessage, '\n', &lines);
+ for (size_t i = 0; i < lines.size() - 2; i++) {
+ std::string line = lines[i] + "\r\n";
+ SCOPED_TRACE("Line: " + line);
+ bool sent = websocket_->SendData(line.c_str(), line.size());
+ EXPECT_EQ(true, sent);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_TRUE(socket_->sent_data().empty());
+ EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
+ }
+ bool sent = websocket_->SendData("\r\n", 2);
+ EXPECT_EQ(true, sent);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(kHandshakeRequestMessage, socket_->sent_data());
+ EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
+
+ for (size_t i = 0; i < lines.size() - 2; i++) {
+ std::string line = lines[i] + "\r\n";
+ SCOPED_TRACE("Line: " + line);
+ websocket_->OnSentData(socket_.get(), line.size());
+ EXPECT_EQ(0U, delegate.amount_sent());
+ }
+ websocket_->OnSentData(socket_.get(), 2); // \r\n
+ EXPECT_EQ(strlen(kHandshakeRequestMessage), delegate.amount_sent());
+ EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
+
+ static const char* kHandshakeResponseMessage =
+ "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
+ "Upgrade: WebSocket\r\n"
+ "Connection: Upgrade\r\n"
+ "WebSocket-Origin: http://example.com\r\n"
+ "WebSocket-Location: ws://example.com/demo\r\n"
+ "WebSocket-Protocol: sample\r\n"
+ "\r\n";
+
+ lines.clear();
+ SplitString(kHandshakeResponseMessage, '\n', &lines);
+ for (size_t i = 0; i < lines.size() - 2; i++) {
+ std::string line = lines[i] + "\r\n";
+ SCOPED_TRACE("Line: " + line);
+ websocket_->OnReceivedData(socket_,
+ line.c_str(),
+ line.size());
+ MessageLoop::current()->RunAllPending();
+ EXPECT_TRUE(delegate.received_data().empty());
+ EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
+ }
+ websocket_->OnReceivedData(socket_.get(), "\r\n", 2);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(kHandshakeResponseMessage, delegate.received_data());
+ EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
+ CloseWebSocketJob();
+}
+
+TEST_F(WebSocketJobTest, HandshakeWithCookie) {
+ GURL url("ws://example.com/demo");
+ GURL cookieUrl("http://example.com/demo");
+ CookieOptions cookie_options;
+ cookie_store_->SetCookieWithOptions(
+ cookieUrl, "CR-test=1", cookie_options);
+ cookie_options.set_include_httponly();
+ cookie_store_->SetCookieWithOptions(
+ cookieUrl, "CR-test-httponly=1", cookie_options);
+
+ MockSocketStreamDelegate delegate;
+ InitWebSocketJob(url, &delegate);
+
+ static const char* kHandshakeRequestMessage =
+ "GET /demo HTTP/1.1\r\n"
+ "Upgrade: WebSocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Host: example.com\r\n"
+ "Origin: http://example.com\r\n"
+ "WebSocket-Protocol: sample\r\n"
+ "Cookie: WK-test=1\r\n"
+ "\r\n";
+
+ static const char* kHandshakeRequestExpected =
+ "GET /demo HTTP/1.1\r\n"
+ "Upgrade: WebSocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Host: example.com\r\n"
+ "Origin: http://example.com\r\n"
+ "WebSocket-Protocol: sample\r\n"
+ "Cookie: CR-test=1; CR-test-httponly=1\r\n"
+ "\r\n";
+
+ bool sent = websocket_->SendData(kHandshakeRequestMessage,
+ strlen(kHandshakeRequestMessage));
+ EXPECT_EQ(true, sent);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(kHandshakeRequestExpected, socket_->sent_data());
+ EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
+ websocket_->OnSentData(socket_, strlen(kHandshakeRequestExpected));
+ EXPECT_EQ(strlen(kHandshakeRequestMessage), delegate.amount_sent());
+
+ static const char* kHandshakeResponseMessage =
+ "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
+ "Upgrade: WebSocket\r\n"
+ "Connection: Upgrade\r\n"
+ "WebSocket-Origin: http://example.com\r\n"
+ "WebSocket-Location: ws://example.com/demo\r\n"
+ "WebSocket-Protocol: sample\r\n"
+ "Set-Cookie: CR-set-test=1\r\n"
+ "\r\n";
+
+ static const char* kHandshakeResponseExpected =
+ "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
+ "Upgrade: WebSocket\r\n"
+ "Connection: Upgrade\r\n"
+ "WebSocket-Origin: http://example.com\r\n"
+ "WebSocket-Location: ws://example.com/demo\r\n"
+ "WebSocket-Protocol: sample\r\n"
+ "\r\n";
+
+ websocket_->OnReceivedData(socket_.get(),
+ kHandshakeResponseMessage,
+ strlen(kHandshakeResponseMessage));
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(kHandshakeResponseExpected, delegate.received_data());
+ EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
+
+ EXPECT_EQ(3U, cookie_store_->entries().size());
+ EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
+ EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
+ EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
+ EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
+ EXPECT_EQ(cookieUrl, cookie_store_->entries()[2].url);
+ EXPECT_EQ("CR-set-test=1", cookie_store_->entries()[2].cookie_line);
+
+ CloseWebSocketJob();
+}
+
+TEST_F(WebSocketJobTest, HandshakeWithCookieButNotAllowed) {
+ GURL url("ws://example.com/demo");
+ GURL cookieUrl("http://example.com/demo");
+ CookieOptions cookie_options;
+ cookie_store_->SetCookieWithOptions(
+ cookieUrl, "CR-test=1", cookie_options);
+ cookie_options.set_include_httponly();
+ cookie_store_->SetCookieWithOptions(
+ cookieUrl, "CR-test-httponly=1", cookie_options);
+ cookie_policy_->set_allow_all_cookies(false);
+
+ MockSocketStreamDelegate delegate;
+ InitWebSocketJob(url, &delegate);
+
+ static const char* kHandshakeRequestMessage =
+ "GET /demo HTTP/1.1\r\n"
+ "Upgrade: WebSocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Host: example.com\r\n"
+ "Origin: http://example.com\r\n"
+ "WebSocket-Protocol: sample\r\n"
+ "Cookie: WK-test=1\r\n"
+ "\r\n";
+
+ static const char* kHandshakeRequestExpected =
+ "GET /demo HTTP/1.1\r\n"
+ "Upgrade: WebSocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Host: example.com\r\n"
+ "Origin: http://example.com\r\n"
+ "WebSocket-Protocol: sample\r\n"
+ "\r\n";
+
+ bool sent = websocket_->SendData(kHandshakeRequestMessage,
+ strlen(kHandshakeRequestMessage));
+ EXPECT_EQ(true, sent);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(kHandshakeRequestExpected, socket_->sent_data());
+ EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
+ websocket_->OnSentData(socket_, strlen(kHandshakeRequestExpected));
+ EXPECT_EQ(strlen(kHandshakeRequestMessage), delegate.amount_sent());
+
+ static const char* kHandshakeResponseMessage =
+ "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
+ "Upgrade: WebSocket\r\n"
+ "Connection: Upgrade\r\n"
+ "WebSocket-Origin: http://example.com\r\n"
+ "WebSocket-Location: ws://example.com/demo\r\n"
+ "WebSocket-Protocol: sample\r\n"
+ "Set-Cookie: CR-set-test=1\r\n"
+ "\r\n";
+
+ static const char* kHandshakeResponseExpected =
+ "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
+ "Upgrade: WebSocket\r\n"
+ "Connection: Upgrade\r\n"
+ "WebSocket-Origin: http://example.com\r\n"
+ "WebSocket-Location: ws://example.com/demo\r\n"
+ "WebSocket-Protocol: sample\r\n"
+ "\r\n";
+
+ websocket_->OnReceivedData(socket_.get(),
+ kHandshakeResponseMessage,
+ strlen(kHandshakeResponseMessage));
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(kHandshakeResponseExpected, delegate.received_data());
+ EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
+
+ EXPECT_EQ(2U, cookie_store_->entries().size());
+ EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
+ EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
+ EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
+ EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
+
+ CloseWebSocketJob();
+}
+
+} // namespace net
« no previous file with comments | « net/websockets/websocket_job.cc ('k') | webkit/tools/layout_tests/test_expectations.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698