1 // Copyright 2015 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.
7 #include "base/callback_forward.h"
8 #include "base/memory/weak_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "net/cookies/cookie_store.h"
15 #include "net/socket/socket_test_util.h"
16 #include "net/websockets/websocket_stream_create_test_base.h"
17 #include "net/websockets/websocket_test_util.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 #include "url/origin.h"
25 using ::testing::TestWithParam
;
26 using ::testing::ValuesIn
;
28 const char kNoCookieHeader
[] = "";
30 class TestBase
: public WebSocketStreamCreateTestBase
{
32 void CreateAndConnect(const GURL
& url
,
33 const url::Origin
& origin
,
34 const std::string
& cookie_header
,
35 const std::string
& response_body
) {
36 // We assume cookie_header ends with CRLF if not empty, as
37 // WebSocketStandardRequestWithCookies requires. Use AddCRLFIfNotEmpty
39 CHECK(cookie_header
.empty() ||
40 base::EndsWith(cookie_header
, "\r\n", base::CompareCase::SENSITIVE
));
42 url_request_context_host_
.SetExpectations(
43 WebSocketStandardRequestWithCookies(url
.path(), url
.host(), origin
,
44 cookie_header
, std::string()),
46 CreateAndConnectStream(url
.spec(), NoSubProtocols(), origin
, nullptr);
49 std::string
AddCRLFIfNotEmpty(const std::string
& s
) {
50 return s
.empty() ? s
: s
+ "\r\n";
54 struct ClientUseCookieParameter
{
55 // The URL for the WebSocket connection.
56 const char* const url
;
57 // The URL for the previously set cookies.
58 const char* const cookie_url
;
59 // The previously set cookies contents.
60 const char* const cookie_line
;
61 // The Cookie: HTTP header expected to appear in the WS request. An empty
62 // string means there is no Cookie: header.
63 const char* const cookie_header
;
66 class WebSocketStreamClientUseCookieTest
68 public TestWithParam
<ClientUseCookieParameter
> {
70 ~WebSocketStreamClientUseCookieTest() override
{
71 // Permit any endpoint locks to be released.
72 stream_request_
.reset();
74 base::RunLoop().RunUntilIdle();
77 static void SetCookieHelperFunction(const base::Closure
& task
,
78 base::WeakPtr
<bool> weak_is_called
,
79 base::WeakPtr
<bool> weak_result
,
81 *weak_is_called
= true;
82 *weak_result
= success
;
83 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
, task
);
87 struct ServerSetCookieParameter
{
88 // The URL for the WebSocket connection.
89 const char* const url
;
90 // The URL used to query cookies after the response received.
91 const char* const cookie_url
;
92 // The cookies expected to appear for |cookie_url| inquiry.
93 const char* const cookie_line
;
94 // The Set-Cookie: HTTP header attached to the response.
95 const char* const cookie_header
;
98 class WebSocketStreamServerSetCookieTest
100 public TestWithParam
<ServerSetCookieParameter
> {
102 ~WebSocketStreamServerSetCookieTest() override
{
103 // Permit any endpoint locks to be released.
104 stream_request_
.reset();
106 base::RunLoop().RunUntilIdle();
109 static void GetCookiesHelperFunction(const base::Closure
& task
,
110 base::WeakPtr
<bool> weak_is_called
,
111 base::WeakPtr
<std::string
> weak_result
,
112 const std::string
& cookies
) {
113 *weak_is_called
= true;
114 *weak_result
= cookies
;
115 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE
, task
);
119 TEST_P(WebSocketStreamClientUseCookieTest
, ClientUseCookie
) {
121 ssl_data_
.push_back(new SSLSocketDataProvider(ASYNC
, OK
));
124 url_request_context_host_
.GetURLRequestContext()->cookie_store();
126 const GURL
url(GetParam().url
);
127 const GURL
cookie_url(GetParam().cookie_url
);
128 const url::Origin
origin(GURL("http://www.example.com"));
129 const std::string
cookie_line(GetParam().cookie_line
);
130 const std::string
cookie_header(AddCRLFIfNotEmpty(GetParam().cookie_header
));
132 bool is_called
= false;
133 bool set_cookie_result
= false;
134 base::WeakPtrFactory
<bool> weak_is_called(&is_called
);
135 base::WeakPtrFactory
<bool> weak_set_cookie_result(&set_cookie_result
);
137 base::RunLoop run_loop
;
138 store
->SetCookieWithOptionsAsync(
139 cookie_url
, cookie_line
, CookieOptions(),
140 base::Bind(&SetCookieHelperFunction
, run_loop
.QuitClosure(),
141 weak_is_called
.GetWeakPtr(),
142 weak_set_cookie_result
.GetWeakPtr()));
144 ASSERT_TRUE(is_called
);
145 ASSERT_TRUE(set_cookie_result
);
147 CreateAndConnect(url
, origin
, cookie_header
, WebSocketStandardResponse(""));
148 WaitUntilConnectDone();
149 EXPECT_FALSE(has_failed());
152 TEST_P(WebSocketStreamServerSetCookieTest
, ServerSetCookie
) {
154 ssl_data_
.push_back(new SSLSocketDataProvider(ASYNC
, OK
));
156 const GURL
url(GetParam().url
);
157 const GURL
cookie_url(GetParam().cookie_url
);
158 const url::Origin
origin(GURL("http://www.example.com"));
159 const std::string
cookie_line(GetParam().cookie_line
);
160 const std::string
cookie_header(AddCRLFIfNotEmpty(GetParam().cookie_header
));
162 const std::string response
= base::StringPrintf(
163 "HTTP/1.1 101 Switching Protocols\r\n"
164 "Upgrade: websocket\r\n"
165 "Connection: Upgrade\r\n"
167 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
169 cookie_header
.c_str());
172 url_request_context_host_
.GetURLRequestContext()->cookie_store();
174 CreateAndConnect(url
, origin
, "", response
);
175 WaitUntilConnectDone();
176 EXPECT_FALSE(has_failed());
178 bool is_called
= false;
179 std::string get_cookies_result
;
180 base::WeakPtrFactory
<bool> weak_is_called(&is_called
);
181 base::WeakPtrFactory
<std::string
> weak_get_cookies_result(
182 &get_cookies_result
);
183 base::RunLoop run_loop
;
184 store
->GetCookiesWithOptionsAsync(
185 cookie_url
, CookieOptions(),
186 base::Bind(&GetCookiesHelperFunction
, run_loop
.QuitClosure(),
187 weak_is_called
.GetWeakPtr(),
188 weak_get_cookies_result
.GetWeakPtr()));
190 EXPECT_TRUE(is_called
);
191 EXPECT_EQ(cookie_line
, get_cookies_result
);
194 // Test parameters definitions follow...
196 const ClientUseCookieParameter kClientUseCookieParameters
[] = {
197 // Non-secure cookies for ws
198 {"ws://www.example.com",
199 "http://www.example.com",
201 "Cookie: test-cookie"},
203 {"ws://www.example.com",
204 "https://www.example.com",
206 "Cookie: test-cookie"},
208 {"ws://www.example.com",
209 "ws://www.example.com",
211 "Cookie: test-cookie"},
213 {"ws://www.example.com",
214 "wss://www.example.com",
216 "Cookie: test-cookie"},
218 // Non-secure cookies for wss
219 {"wss://www.example.com",
220 "http://www.example.com",
222 "Cookie: test-cookie"},
224 {"wss://www.example.com",
225 "https://www.example.com",
227 "Cookie: test-cookie"},
229 {"wss://www.example.com",
230 "ws://www.example.com",
232 "Cookie: test-cookie"},
234 {"wss://www.example.com",
235 "wss://www.example.com",
237 "Cookie: test-cookie"},
239 // Secure-cookies for ws
240 {"ws://www.example.com",
241 "https://www.example.com",
242 "test-cookie; secure",
245 {"ws://www.example.com",
246 "wss://www.example.com",
247 "test-cookie; secure",
250 // Secure-cookies for wss
251 {"wss://www.example.com",
252 "https://www.example.com",
253 "test-cookie; secure",
254 "Cookie: test-cookie"},
256 {"wss://www.example.com",
257 "wss://www.example.com",
258 "test-cookie; secure",
259 "Cookie: test-cookie"},
261 // Non-secure cookies for ws (sharing domain)
262 {"ws://www.example.com",
263 "http://www2.example.com",
264 "test-cookie; Domain=example.com",
265 "Cookie: test-cookie"},
267 {"ws://www.example.com",
268 "https://www2.example.com",
269 "test-cookie; Domain=example.com",
270 "Cookie: test-cookie"},
272 {"ws://www.example.com",
273 "ws://www2.example.com",
274 "test-cookie; Domain=example.com",
275 "Cookie: test-cookie"},
277 {"ws://www.example.com",
278 "wss://www2.example.com",
279 "test-cookie; Domain=example.com",
280 "Cookie: test-cookie"},
282 // Non-secure cookies for wss (sharing domain)
283 {"wss://www.example.com",
284 "http://www2.example.com",
285 "test-cookie; Domain=example.com",
286 "Cookie: test-cookie"},
288 {"wss://www.example.com",
289 "https://www2.example.com",
290 "test-cookie; Domain=example.com",
291 "Cookie: test-cookie"},
293 {"wss://www.example.com",
294 "ws://www2.example.com",
295 "test-cookie; Domain=example.com",
296 "Cookie: test-cookie"},
298 {"wss://www.example.com",
299 "wss://www2.example.com",
300 "test-cookie; Domain=example.com",
301 "Cookie: test-cookie"},
303 // Secure-cookies for ws (sharing domain)
304 {"ws://www.example.com",
305 "https://www2.example.com",
306 "test-cookie; Domain=example.com; secure",
309 {"ws://www.example.com",
310 "wss://www2.example.com",
311 "test-cookie; Domain=example.com; secure",
314 // Secure-cookies for wss (sharing domain)
315 {"wss://www.example.com",
316 "https://www2.example.com",
317 "test-cookie; Domain=example.com; secure",
318 "Cookie: test-cookie"},
320 {"wss://www.example.com",
321 "wss://www2.example.com",
322 "test-cookie; Domain=example.com; secure",
323 "Cookie: test-cookie"},
325 // Non-matching cookies for ws
326 {"ws://www.example.com",
327 "http://www2.example.com",
331 {"ws://www.example.com",
332 "https://www2.example.com",
336 {"ws://www.example.com",
337 "ws://www2.example.com",
341 {"ws://www.example.com",
342 "wss://www2.example.com",
346 // Non-matching cookies for wss
347 {"wss://www.example.com",
348 "http://www2.example.com",
352 {"wss://www.example.com",
353 "https://www2.example.com",
357 {"wss://www.example.com",
358 "ws://www2.example.com",
362 {"wss://www.example.com",
363 "wss://www2.example.com",
368 INSTANTIATE_TEST_CASE_P(WebSocketStreamClientUseCookieTest
,
369 WebSocketStreamClientUseCookieTest
,
370 ValuesIn(kClientUseCookieParameters
));
372 const ServerSetCookieParameter kServerSetCookieParameters
[] = {
373 // Cookies coming from ws
374 {"ws://www.example.com",
375 "http://www.example.com",
377 "Set-Cookie: test-cookie"},
379 {"ws://www.example.com",
380 "https://www.example.com",
382 "Set-Cookie: test-cookie"},
384 {"ws://www.example.com",
385 "ws://www.example.com",
387 "Set-Cookie: test-cookie"},
389 {"ws://www.example.com",
390 "wss://www.example.com",
392 "Set-Cookie: test-cookie"},
394 // Cookies coming from wss
395 {"wss://www.example.com",
396 "http://www.example.com",
398 "Set-Cookie: test-cookie"},
400 {"wss://www.example.com",
401 "https://www.example.com",
403 "Set-Cookie: test-cookie"},
405 {"wss://www.example.com",
406 "ws://www.example.com",
408 "Set-Cookie: test-cookie"},
410 {"wss://www.example.com",
411 "wss://www.example.com",
413 "Set-Cookie: test-cookie"},
415 // cookies coming from ws (sharing domain)
416 {"ws://www.example.com",
417 "http://www2.example.com",
419 "Set-Cookie: test-cookie; Domain=example.com"},
421 {"ws://www.example.com",
422 "https://www2.example.com",
424 "Set-Cookie: test-cookie; Domain=example.com"},
426 {"ws://www.example.com",
427 "ws://www2.example.com",
429 "Set-Cookie: test-cookie; Domain=example.com"},
431 {"ws://www.example.com",
432 "wss://www2.example.com",
434 "Set-Cookie: test-cookie; Domain=example.com"},
436 // cookies coming from wss (sharing domain)
437 {"wss://www.example.com",
438 "http://www2.example.com",
440 "Set-Cookie: test-cookie; Domain=example.com"},
442 {"wss://www.example.com",
443 "https://www2.example.com",
445 "Set-Cookie: test-cookie; Domain=example.com"},
447 {"wss://www.example.com",
448 "ws://www2.example.com",
450 "Set-Cookie: test-cookie; Domain=example.com"},
452 {"wss://www.example.com",
453 "wss://www2.example.com",
455 "Set-Cookie: test-cookie; Domain=example.com"},
457 // Non-matching cookies coming from ws
458 {"ws://www.example.com",
459 "http://www2.example.com",
461 "Set-Cookie: test-cookie"},
463 {"ws://www.example.com",
464 "https://www2.example.com",
466 "Set-Cookie: test-cookie"},
468 {"ws://www.example.com",
469 "ws://www2.example.com",
471 "Set-Cookie: test-cookie"},
473 {"ws://www.example.com",
474 "wss://www2.example.com",
476 "Set-Cookie: test-cookie"},
478 // Non-matching cookies coming from wss
479 {"wss://www.example.com",
480 "http://www2.example.com",
482 "Set-Cookie: test-cookie"},
484 {"wss://www.example.com",
485 "https://www2.example.com",
487 "Set-Cookie: test-cookie"},
489 {"wss://www.example.com",
490 "ws://www2.example.com",
492 "Set-Cookie: test-cookie"},
494 {"wss://www.example.com",
495 "wss://www2.example.com",
497 "Set-Cookie: test-cookie"},
500 INSTANTIATE_TEST_CASE_P(WebSocketStreamServerSetCookieTest
,
501 WebSocketStreamServerSetCookieTest
,
502 ValuesIn(kServerSetCookieParameters
));