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

Side by Side 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, 9 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <string>
6 #include <vector>
7
8 #include "base/ref_counted.h"
9 #include "googleurl/src/gurl.h"
10 #include "net/base/cookie_policy.h"
11 #include "net/base/cookie_store.h"
12 #include "net/base/net_errors.h"
13 #include "net/socket_stream/socket_stream.h"
14 #include "net/url_request/url_request_context.h"
15 #include "net/websockets/websocket_job.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/platform_test.h"
19
20 namespace net {
21
22 class MockSocketStream : public SocketStream {
23 public:
24 MockSocketStream(const GURL& url, SocketStream::Delegate* delegate)
25 : SocketStream(url, delegate) {}
26 virtual ~MockSocketStream() {}
27
28 virtual void Connect() {}
29 virtual bool SendData(const char* data, int len) {
30 sent_data_ += std::string(data, len);
31 return true;
32 }
33
34 virtual void Close() {}
35 virtual void RestartWithAuth(
36 const std::wstring& username, std::wstring& password) {}
37 virtual void DetachDelegate() {
38 delegate_ = NULL;
39 }
40
41 const std::string& sent_data() const {
42 return sent_data_;
43 }
44
45 private:
46 std::string sent_data_;
47 };
48
49 class MockSocketStreamDelegate : public SocketStream::Delegate {
50 public:
51 MockSocketStreamDelegate()
52 : amount_sent_(0) {}
53 virtual ~MockSocketStreamDelegate() {}
54
55 virtual void OnConnected(SocketStream* socket, int max_pending_send_allowed) {
56 }
57 virtual void OnSentData(SocketStream* socket, int amount_sent) {
58 amount_sent_ += amount_sent;
59 }
60 virtual void OnReceivedData(SocketStream* socket,
61 const char* data, int len) {
62 received_data_ += std::string(data, len);
63 }
64 virtual void OnClose(SocketStream* socket) {
65 }
66
67 size_t amount_sent() const { return amount_sent_; }
68 const std::string& received_data() const { return received_data_; }
69
70 private:
71 int amount_sent_;
72 std::string received_data_;
73 };
74
75 class MockCookieStore : public CookieStore {
76 public:
77 struct Entry {
78 GURL url;
79 std::string cookie_line;
80 CookieOptions options;
81 };
82 MockCookieStore() {}
83
84 virtual bool SetCookieWithOptions(const GURL& url,
85 const std::string& cookie_line,
86 const CookieOptions& options) {
87 Entry entry;
88 entry.url = url;
89 entry.cookie_line = cookie_line;
90 entry.options = options;
91 entries_.push_back(entry);
92 return true;
93 }
94 virtual std::string GetCookiesWithOptions(const GURL& url,
95 const CookieOptions& options) {
96 std::string result;
97 for (size_t i = 0; i < entries_.size(); i++) {
98 Entry &entry = entries_[i];
99 if (url == entry.url) {
100 if (!result.empty()) {
101 result += "; ";
102 }
103 result += entry.cookie_line;
104 }
105 }
106 return result;
107 }
108 virtual void DeleteCookie(const GURL& url,
109 const std::string& cookie_name) {}
110 virtual CookieMonster* GetCookieMonster() { return NULL; }
111
112 const std::vector<Entry>& entries() const { return entries_; }
113
114 private:
115 friend class base::RefCountedThreadSafe<MockCookieStore>;
116 virtual ~MockCookieStore() {}
117
118 std::vector<Entry> entries_;
119 };
120
121 class MockCookiePolicy : public CookiePolicy,
122 public base::RefCountedThreadSafe<MockCookiePolicy> {
123 public:
124 MockCookiePolicy() : allow_all_cookies_(true), callback_(NULL) {}
125
126 void set_allow_all_cookies(bool allow_all_cookies) {
127 allow_all_cookies_ = allow_all_cookies;
128 }
129
130 virtual int CanGetCookies(const GURL& url,
131 const GURL& first_party_for_cookies,
132 CompletionCallback* callback) {
133 DCHECK(!callback_);
134 callback_ = callback;
135 MessageLoop::current()->PostTask(
136 FROM_HERE, NewRunnableMethod(this, &MockCookiePolicy::OnCanGetCookies));
137 return ERR_IO_PENDING;
138 }
139
140 virtual int CanSetCookie(const GURL& url,
141 const GURL& first_party_for_cookies,
142 const std::string& cookie_line,
143 CompletionCallback* callback) {
144 DCHECK(!callback_);
145 callback_ = callback;
146 MessageLoop::current()->PostTask(
147 FROM_HERE, NewRunnableMethod(this, &MockCookiePolicy::OnCanSetCookie));
148 return ERR_IO_PENDING;
149 }
150
151 private:
152 friend class base::RefCountedThreadSafe<MockCookiePolicy>;
153 virtual ~MockCookiePolicy() {}
154
155 void OnCanGetCookies() {
156 CompletionCallback* callback = callback_;
157 callback_ = NULL;
158 if (allow_all_cookies_)
159 callback->Run(OK);
160 else
161 callback->Run(ERR_ACCESS_DENIED);
162 }
163 void OnCanSetCookie() {
164 CompletionCallback* callback = callback_;
165 callback_ = NULL;
166 if (allow_all_cookies_)
167 callback->Run(OK);
168 else
169 callback->Run(ERR_ACCESS_DENIED);
170 }
171
172 bool allow_all_cookies_;
173 CompletionCallback* callback_;
174 };
175
176 class MockURLRequestContext : public URLRequestContext {
177 public:
178 MockURLRequestContext(CookieStore* cookie_store,
179 CookiePolicy* cookie_policy) {
180 cookie_store_ = cookie_store;
181 cookie_policy_ = cookie_policy;
182 }
183
184 private:
185 friend class base::RefCountedThreadSafe<MockURLRequestContext>;
186 virtual ~MockURLRequestContext() {}
187 };
188
189 class WebSocketJobTest : public PlatformTest {
190 public:
191 virtual void SetUp() {
192 cookie_store_ = new MockCookieStore;
193 cookie_policy_ = new MockCookiePolicy;
194 context_ = new MockURLRequestContext(
195 cookie_store_.get(), cookie_policy_.get());
196 }
197 virtual void TearDown() {
198 cookie_store_ = NULL;
199 cookie_policy_ = NULL;
200 context_ = NULL;
201 websocket_ = NULL;
202 socket_ = NULL;
203 }
204 protected:
205 void InitWebSocketJob(const GURL& url, MockSocketStreamDelegate* delegate) {
206 websocket_ = new WebSocketJob(delegate);
207 socket_ = new MockSocketStream(url, websocket_.get());
208 websocket_->InitSocketStream(socket_.get());
209 websocket_->state_ = WebSocketJob::CONNECTING;
210 websocket_->set_context(context_.get());
211 }
212 WebSocketJob::State GetWebSocketJobState() {
213 return websocket_->state_;
214 }
215 void CloseWebSocketJob() {
216 if (websocket_->socket_)
217 websocket_->socket_->DetachDelegate();
218 websocket_->state_ = WebSocketJob::CLOSED;
219 websocket_->delegate_ = NULL;
220 websocket_->socket_ = NULL;
221 }
222
223 scoped_refptr<MockCookieStore> cookie_store_;
224 scoped_refptr<MockCookiePolicy> cookie_policy_;
225 scoped_refptr<MockURLRequestContext> context_;
226 scoped_refptr<WebSocketJob> websocket_;
227 scoped_refptr<MockSocketStream> socket_;
228 };
229
230 TEST_F(WebSocketJobTest, SimpleHandshake) {
231 GURL url("ws://example.com/demo");
232 MockSocketStreamDelegate delegate;
233 InitWebSocketJob(url, &delegate);
234
235 static const char* kHandshakeRequestMessage =
236 "GET /demo HTTP/1.1\r\n"
237 "Upgrade: WebSocket\r\n"
238 "Connection: Upgrade\r\n"
239 "Host: example.com\r\n"
240 "Origin: http://example.com\r\n"
241 "WebSocket-Protocol: sample\r\n"
242 "\r\n";
243
244 bool sent = websocket_->SendData(kHandshakeRequestMessage,
245 strlen(kHandshakeRequestMessage));
246 EXPECT_EQ(true, sent);
247 MessageLoop::current()->RunAllPending();
248 EXPECT_EQ(kHandshakeRequestMessage, socket_->sent_data());
249 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
250 websocket_->OnSentData(socket_.get(), strlen(kHandshakeRequestMessage));
251 EXPECT_EQ(strlen(kHandshakeRequestMessage), delegate.amount_sent());
252
253 static const char* kHandshakeResponseMessage =
254 "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
255 "Upgrade: WebSocket\r\n"
256 "Connection: Upgrade\r\n"
257 "WebSocket-Origin: http://example.com\r\n"
258 "WebSocket-Location: ws://example.com/demo\r\n"
259 "WebSocket-Protocol: sample\r\n"
260 "\r\n";
261
262 websocket_->OnReceivedData(socket_.get(),
263 kHandshakeResponseMessage,
264 strlen(kHandshakeResponseMessage));
265 MessageLoop::current()->RunAllPending();
266 EXPECT_EQ(kHandshakeResponseMessage, delegate.received_data());
267 EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
268 CloseWebSocketJob();
269 }
270
271 TEST_F(WebSocketJobTest, SlowHandshake) {
272 GURL url("ws://example.com/demo");
273 MockSocketStreamDelegate delegate;
274 InitWebSocketJob(url, &delegate);
275
276 static const char* kHandshakeRequestMessage =
277 "GET /demo HTTP/1.1\r\n"
278 "Upgrade: WebSocket\r\n"
279 "Connection: Upgrade\r\n"
280 "Host: example.com\r\n"
281 "Origin: http://example.com\r\n"
282 "WebSocket-Protocol: sample\r\n"
283 "\r\n";
284 std::vector<std::string> lines;
285 SplitString(kHandshakeRequestMessage, '\n', &lines);
286 for (size_t i = 0; i < lines.size() - 2; i++) {
287 std::string line = lines[i] + "\r\n";
288 SCOPED_TRACE("Line: " + line);
289 bool sent = websocket_->SendData(line.c_str(), line.size());
290 EXPECT_EQ(true, sent);
291 MessageLoop::current()->RunAllPending();
292 EXPECT_TRUE(socket_->sent_data().empty());
293 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
294 }
295 bool sent = websocket_->SendData("\r\n", 2);
296 EXPECT_EQ(true, sent);
297 MessageLoop::current()->RunAllPending();
298 EXPECT_EQ(kHandshakeRequestMessage, socket_->sent_data());
299 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
300
301 for (size_t i = 0; i < lines.size() - 2; i++) {
302 std::string line = lines[i] + "\r\n";
303 SCOPED_TRACE("Line: " + line);
304 websocket_->OnSentData(socket_.get(), line.size());
305 EXPECT_EQ(0U, delegate.amount_sent());
306 }
307 websocket_->OnSentData(socket_.get(), 2); // \r\n
308 EXPECT_EQ(strlen(kHandshakeRequestMessage), delegate.amount_sent());
309 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
310
311 static const char* kHandshakeResponseMessage =
312 "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
313 "Upgrade: WebSocket\r\n"
314 "Connection: Upgrade\r\n"
315 "WebSocket-Origin: http://example.com\r\n"
316 "WebSocket-Location: ws://example.com/demo\r\n"
317 "WebSocket-Protocol: sample\r\n"
318 "\r\n";
319
320 lines.clear();
321 SplitString(kHandshakeResponseMessage, '\n', &lines);
322 for (size_t i = 0; i < lines.size() - 2; i++) {
323 std::string line = lines[i] + "\r\n";
324 SCOPED_TRACE("Line: " + line);
325 websocket_->OnReceivedData(socket_,
326 line.c_str(),
327 line.size());
328 MessageLoop::current()->RunAllPending();
329 EXPECT_TRUE(delegate.received_data().empty());
330 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
331 }
332 websocket_->OnReceivedData(socket_.get(), "\r\n", 2);
333 MessageLoop::current()->RunAllPending();
334 EXPECT_EQ(kHandshakeResponseMessage, delegate.received_data());
335 EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
336 CloseWebSocketJob();
337 }
338
339 TEST_F(WebSocketJobTest, HandshakeWithCookie) {
340 GURL url("ws://example.com/demo");
341 GURL cookieUrl("http://example.com/demo");
342 CookieOptions cookie_options;
343 cookie_store_->SetCookieWithOptions(
344 cookieUrl, "CR-test=1", cookie_options);
345 cookie_options.set_include_httponly();
346 cookie_store_->SetCookieWithOptions(
347 cookieUrl, "CR-test-httponly=1", cookie_options);
348
349 MockSocketStreamDelegate delegate;
350 InitWebSocketJob(url, &delegate);
351
352 static const char* kHandshakeRequestMessage =
353 "GET /demo HTTP/1.1\r\n"
354 "Upgrade: WebSocket\r\n"
355 "Connection: Upgrade\r\n"
356 "Host: example.com\r\n"
357 "Origin: http://example.com\r\n"
358 "WebSocket-Protocol: sample\r\n"
359 "Cookie: WK-test=1\r\n"
360 "\r\n";
361
362 static const char* kHandshakeRequestExpected =
363 "GET /demo HTTP/1.1\r\n"
364 "Upgrade: WebSocket\r\n"
365 "Connection: Upgrade\r\n"
366 "Host: example.com\r\n"
367 "Origin: http://example.com\r\n"
368 "WebSocket-Protocol: sample\r\n"
369 "Cookie: CR-test=1; CR-test-httponly=1\r\n"
370 "\r\n";
371
372 bool sent = websocket_->SendData(kHandshakeRequestMessage,
373 strlen(kHandshakeRequestMessage));
374 EXPECT_EQ(true, sent);
375 MessageLoop::current()->RunAllPending();
376 EXPECT_EQ(kHandshakeRequestExpected, socket_->sent_data());
377 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
378 websocket_->OnSentData(socket_, strlen(kHandshakeRequestExpected));
379 EXPECT_EQ(strlen(kHandshakeRequestMessage), delegate.amount_sent());
380
381 static const char* kHandshakeResponseMessage =
382 "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
383 "Upgrade: WebSocket\r\n"
384 "Connection: Upgrade\r\n"
385 "WebSocket-Origin: http://example.com\r\n"
386 "WebSocket-Location: ws://example.com/demo\r\n"
387 "WebSocket-Protocol: sample\r\n"
388 "Set-Cookie: CR-set-test=1\r\n"
389 "\r\n";
390
391 static const char* kHandshakeResponseExpected =
392 "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
393 "Upgrade: WebSocket\r\n"
394 "Connection: Upgrade\r\n"
395 "WebSocket-Origin: http://example.com\r\n"
396 "WebSocket-Location: ws://example.com/demo\r\n"
397 "WebSocket-Protocol: sample\r\n"
398 "\r\n";
399
400 websocket_->OnReceivedData(socket_.get(),
401 kHandshakeResponseMessage,
402 strlen(kHandshakeResponseMessage));
403 MessageLoop::current()->RunAllPending();
404 EXPECT_EQ(kHandshakeResponseExpected, delegate.received_data());
405 EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
406
407 EXPECT_EQ(3U, cookie_store_->entries().size());
408 EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
409 EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
410 EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
411 EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
412 EXPECT_EQ(cookieUrl, cookie_store_->entries()[2].url);
413 EXPECT_EQ("CR-set-test=1", cookie_store_->entries()[2].cookie_line);
414
415 CloseWebSocketJob();
416 }
417
418 TEST_F(WebSocketJobTest, HandshakeWithCookieButNotAllowed) {
419 GURL url("ws://example.com/demo");
420 GURL cookieUrl("http://example.com/demo");
421 CookieOptions cookie_options;
422 cookie_store_->SetCookieWithOptions(
423 cookieUrl, "CR-test=1", cookie_options);
424 cookie_options.set_include_httponly();
425 cookie_store_->SetCookieWithOptions(
426 cookieUrl, "CR-test-httponly=1", cookie_options);
427 cookie_policy_->set_allow_all_cookies(false);
428
429 MockSocketStreamDelegate delegate;
430 InitWebSocketJob(url, &delegate);
431
432 static const char* kHandshakeRequestMessage =
433 "GET /demo HTTP/1.1\r\n"
434 "Upgrade: WebSocket\r\n"
435 "Connection: Upgrade\r\n"
436 "Host: example.com\r\n"
437 "Origin: http://example.com\r\n"
438 "WebSocket-Protocol: sample\r\n"
439 "Cookie: WK-test=1\r\n"
440 "\r\n";
441
442 static const char* kHandshakeRequestExpected =
443 "GET /demo HTTP/1.1\r\n"
444 "Upgrade: WebSocket\r\n"
445 "Connection: Upgrade\r\n"
446 "Host: example.com\r\n"
447 "Origin: http://example.com\r\n"
448 "WebSocket-Protocol: sample\r\n"
449 "\r\n";
450
451 bool sent = websocket_->SendData(kHandshakeRequestMessage,
452 strlen(kHandshakeRequestMessage));
453 EXPECT_EQ(true, sent);
454 MessageLoop::current()->RunAllPending();
455 EXPECT_EQ(kHandshakeRequestExpected, socket_->sent_data());
456 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
457 websocket_->OnSentData(socket_, strlen(kHandshakeRequestExpected));
458 EXPECT_EQ(strlen(kHandshakeRequestMessage), delegate.amount_sent());
459
460 static const char* kHandshakeResponseMessage =
461 "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
462 "Upgrade: WebSocket\r\n"
463 "Connection: Upgrade\r\n"
464 "WebSocket-Origin: http://example.com\r\n"
465 "WebSocket-Location: ws://example.com/demo\r\n"
466 "WebSocket-Protocol: sample\r\n"
467 "Set-Cookie: CR-set-test=1\r\n"
468 "\r\n";
469
470 static const char* kHandshakeResponseExpected =
471 "HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
472 "Upgrade: WebSocket\r\n"
473 "Connection: Upgrade\r\n"
474 "WebSocket-Origin: http://example.com\r\n"
475 "WebSocket-Location: ws://example.com/demo\r\n"
476 "WebSocket-Protocol: sample\r\n"
477 "\r\n";
478
479 websocket_->OnReceivedData(socket_.get(),
480 kHandshakeResponseMessage,
481 strlen(kHandshakeResponseMessage));
482 MessageLoop::current()->RunAllPending();
483 EXPECT_EQ(kHandshakeResponseExpected, delegate.received_data());
484 EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
485
486 EXPECT_EQ(2U, cookie_store_->entries().size());
487 EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
488 EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
489 EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
490 EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
491
492 CloseWebSocketJob();
493 }
494
495 } // namespace net
OLDNEW
« 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