1 // Copyright 2013 The Chromium Authors
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 "net/websockets/websocket_channel.h"
6
7 #include <stddef.h>
8 #include <string.h>
9
10 #include <algorithm>
11 #include <iostream>
12 #include <iterator>
13 #include <string>
14 #include <tuple>
15 #include <utility>
16 #include <vector>
17
18 #include "base/check.h"
19 #include "base/dcheck_is_on.h"
20 #include "base/functional/bind.h"
21 #include "base/functional/callback.h"
22 #include "base/location.h"
23 #include "base/memory/raw_ptr.h"
24 #include "base/memory/weak_ptr.h"
25 #include "base/ranges/algorithm.h"
26 #include "base/run_loop.h"
27 #include "base/strings/string_piece.h"
28 #include "base/task/single_thread_task_runner.h"
29 #include "base/time/time.h"
30 #include "net/base/auth.h"
31 #include "net/base/completion_once_callback.h"
32 #include "net/base/io_buffer.h"
33 #include "net/base/ip_address.h"
34 #include "net/base/ip_endpoint.h"
35 #include "net/base/isolation_info.h"
36 #include "net/base/net_errors.h"
37 #include "net/base/test_completion_callback.h"
38 #include "net/cookies/site_for_cookies.h"
39 #include "net/http/http_request_headers.h"
40 #include "net/http/http_response_headers.h"
41 #include "net/log/net_log_with_source.h"
42 #include "net/ssl/ssl_info.h"
43 #include "net/test/test_with_task_environment.h"
44 #include "net/traffic_annotation/network_traffic_annotation.h"
45 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
46 #include "net/url_request/url_request_context.h"
47 #include "net/url_request/url_request_context_builder.h"
48 #include "net/url_request/url_request_test_util.h"
49 #include "net/websockets/websocket_errors.h"
50 #include "net/websockets/websocket_event_interface.h"
51 #include "net/websockets/websocket_handshake_request_info.h"
52 #include "net/websockets/websocket_handshake_response_info.h"
53 #include "testing/gmock/include/gmock/gmock.h"
54 #include "testing/gtest/include/gtest/gtest.h"
55 #include "url/gurl.h"
56 #include "url/origin.h"
57
58 // Hacky macros to construct the body of a Close message from a code and a
59 // string, while ensuring the result is a compile-time constant string.
60 // Use like CLOSE_DATA(NORMAL_CLOSURE, "Explanation String")
61 #define CLOSE_DATA(code, string) WEBSOCKET_CLOSE_CODE_AS_STRING_##code string
62 #define WEBSOCKET_CLOSE_CODE_AS_STRING_NORMAL_CLOSURE "\x03\xe8"
63 #define WEBSOCKET_CLOSE_CODE_AS_STRING_GOING_AWAY "\x03\xe9"
64 #define WEBSOCKET_CLOSE_CODE_AS_STRING_PROTOCOL_ERROR "\x03\xea"
65 #define WEBSOCKET_CLOSE_CODE_AS_STRING_ABNORMAL_CLOSURE "\x03\xee"
66 #define WEBSOCKET_CLOSE_CODE_AS_STRING_SERVER_ERROR "\x03\xf3"
67
68 namespace net {
69
70 class WebSocketBasicHandshakeStream;
71 class WebSocketHttp2HandshakeStream;
72
73 // Printing helpers to allow GoogleMock to print frames. These are explicitly
74 // designed to look like the static initialisation format we use in these
75 // tests. They have to live in the net namespace in order to be found by
76 // GoogleMock; a nested anonymous namespace will not work.
77
operator <<(std::ostream & os,const WebSocketFrameHeader & header)78 std::ostream& operator<<(std::ostream& os, const WebSocketFrameHeader& header) {
79 return os << (header.final ? "FINAL_FRAME" : "NOT_FINAL_FRAME") << ", "
80 << header.opcode << ", "
81 << (header.masked ? "MASKED" : "NOT_MASKED");
82 }
83
operator <<(std::ostream & os,const WebSocketFrame & frame)84 std::ostream& operator<<(std::ostream& os, const WebSocketFrame& frame) {
85 os << "{" << frame.header << ", ";
86 if (frame.payload) {
87 return os << "\""
88 << base::StringPiece(frame.payload, frame.header.payload_length)
89 << "\"}";
90 }
91 return os << "NULL}";
92 }
93
operator <<(std::ostream & os,const std::vector<std::unique_ptr<WebSocketFrame>> & frames)94 std::ostream& operator<<(
95 std::ostream& os,
96 const std::vector<std::unique_ptr<WebSocketFrame>>& frames) {
97 os << "{";
98 bool first = true;
99 for (const auto& frame : frames) {
100 if (!first) {
101 os << ",\n";
102 } else {
103 first = false;
104 }
105 os << *frame;
106 }
107 return os << "}";
108 }
109
operator <<(std::ostream & os,const std::vector<std::unique_ptr<WebSocketFrame>> * vector)110 std::ostream& operator<<(
111 std::ostream& os,
112 const std::vector<std::unique_ptr<WebSocketFrame>>* vector) {
113 return os << '&' << *vector;
114 }
115
116 namespace {
117
118 using ::base::TimeDelta;
119
120 using ::testing::_;
121 using ::testing::AnyNumber;
122 using ::testing::DefaultValue;
123 using ::testing::DoAll;
124 using ::testing::InSequence;
125 using ::testing::MockFunction;
126 using ::testing::NotNull;
127 using ::testing::Return;
128 using ::testing::ReturnRef;
129 using ::testing::SaveArg;
130 using ::testing::StrictMock;
131
132 // A selection of characters that have traditionally been mangled in some
133 // environment or other, for testing 8-bit cleanliness.
134 const char kBinaryBlob[] = {'\n', '\r', // BACKWARDS CRNL
135 '\0', // nul
136 '\x7F', // DEL
137 '\x80', '\xFF', // NOT VALID UTF-8
138 '\x1A', // Control-Z, EOF on DOS
139 '\x03', // Control-C
140 '\x04', // EOT, special for Unix terms
141 '\x1B', // ESC, often special
142 '\b', // backspace
143 '\'', // single-quote, special in PHP
144 };
145 const size_t kBinaryBlobSize = std::size(kBinaryBlob);
146
147 const int kVeryBigTimeoutMillis = 60 * 60 * 24 * 1000;
148
149 // TestTimeouts::tiny_timeout() is 100ms! I could run halfway around the world
150 // in that time! I would like my tests to run a bit quicker.
151 const int kVeryTinyTimeoutMillis = 1;
152
153 using ChannelState = WebSocketChannel::ChannelState;
154 constexpr ChannelState CHANNEL_ALIVE = WebSocketChannel::CHANNEL_ALIVE;
155 constexpr ChannelState CHANNEL_DELETED = WebSocketChannel::CHANNEL_DELETED;
156
157 // This typedef mainly exists to avoid having to repeat the "NOLINT" incantation
158 // all over the place.
159 typedef StrictMock< MockFunction<void(int)> > Checkpoint; // NOLINT
160
161 // This mock is for testing expectations about how the EventInterface is used.
162 class MockWebSocketEventInterface : public WebSocketEventInterface {
163 public:
164 MockWebSocketEventInterface() = default;
165
OnDataFrame(bool fin,WebSocketMessageType type,base::span<const char> payload)166 void OnDataFrame(bool fin,
167 WebSocketMessageType type,
168 base::span<const char> payload) override {
169 return OnDataFrameVector(fin, type,
170 std::vector<char>(payload.begin(), payload.end()));
171 }
172
173 MOCK_METHOD1(OnCreateURLRequest, void(URLRequest*));
174 MOCK_METHOD3(OnAddChannelResponse,
175 void(std::unique_ptr<WebSocketHandshakeResponseInfo> response,
176 const std::string&,
177 const std::string&)); // NOLINT
178 MOCK_METHOD3(OnDataFrameVector,
179 void(bool,
180 WebSocketMessageType,
181 const std::vector<char>&)); // NOLINT
182 MOCK_METHOD0(HasPendingDataFrames, bool(void)); // NOLINT
183 MOCK_METHOD0(OnSendDataFrameDone, void(void)); // NOLINT
184 MOCK_METHOD0(OnClosingHandshake, void(void)); // NOLINT
185 MOCK_METHOD3(OnFailChannel,
186 void(const std::string&, int, absl::optional<int>)); // NOLINT
187 MOCK_METHOD3(OnDropChannel,
188 void(bool, uint16_t, const std::string&)); // NOLINT
189
190 // We can't use GMock with std::unique_ptr.
OnStartOpeningHandshake(std::unique_ptr<WebSocketHandshakeRequestInfo>)191 void OnStartOpeningHandshake(
192 std::unique_ptr<WebSocketHandshakeRequestInfo>) override {
193 OnStartOpeningHandshakeCalled();
194 }
OnSSLCertificateError(std::unique_ptr<SSLErrorCallbacks> ssl_error_callbacks,const GURL & url,int net_error,const SSLInfo & ssl_info,bool fatal)195 void OnSSLCertificateError(
196 std::unique_ptr<SSLErrorCallbacks> ssl_error_callbacks,
197 const GURL& url,
198 int net_error,
199 const SSLInfo& ssl_info,
200 bool fatal) override {
201 OnSSLCertificateErrorCalled(
202 ssl_error_callbacks.get(), url, ssl_info, fatal);
203 }
OnAuthRequired(const AuthChallengeInfo & auth_info,scoped_refptr<HttpResponseHeaders> response_headers,const IPEndPoint & remote_endpoint,base::OnceCallback<void (const AuthCredentials *)> callback,absl::optional<AuthCredentials> * credentials)204 int OnAuthRequired(const AuthChallengeInfo& auth_info,
205 scoped_refptr<HttpResponseHeaders> response_headers,
206 const IPEndPoint& remote_endpoint,
207 base::OnceCallback<void(const AuthCredentials*)> callback,
208 absl::optional<AuthCredentials>* credentials) override {
209 return OnAuthRequiredCalled(std::move(auth_info),
210 std::move(response_headers), remote_endpoint,
211 credentials);
212 }
213
214 MOCK_METHOD0(OnStartOpeningHandshakeCalled, void()); // NOLINT
215 MOCK_METHOD4(
216 OnSSLCertificateErrorCalled,
217 void(SSLErrorCallbacks*, const GURL&, const SSLInfo&, bool)); // NOLINT
218 MOCK_METHOD4(OnAuthRequiredCalled,
219 int(const AuthChallengeInfo&,
220 scoped_refptr<HttpResponseHeaders>,
221 const IPEndPoint&,
222 absl::optional<AuthCredentials>*));
223 };
224
225 // This fake EventInterface is for tests which need a WebSocketEventInterface
226 // implementation but are not verifying how it is used.
227 class FakeWebSocketEventInterface : public WebSocketEventInterface {
OnCreateURLRequest(URLRequest * request)228 void OnCreateURLRequest(URLRequest* request) override {}
OnAddChannelResponse(std::unique_ptr<WebSocketHandshakeResponseInfo> response,const std::string & selected_protocol,const std::string & extensions)229 void OnAddChannelResponse(
230 std::unique_ptr<WebSocketHandshakeResponseInfo> response,
231 const std::string& selected_protocol,
232 const std::string& extensions) override {}
OnDataFrame(bool fin,WebSocketMessageType type,base::span<const char> data_span)233 void OnDataFrame(bool fin,
234 WebSocketMessageType type,
235 base::span<const char> data_span) override {}
OnSendDataFrameDone()236 void OnSendDataFrameDone() override {}
HasPendingDataFrames()237 bool HasPendingDataFrames() override { return false; }
OnClosingHandshake()238 void OnClosingHandshake() override {}
OnFailChannel(const std::string & message,int net_error,absl::optional<int> response_code)239 void OnFailChannel(const std::string& message,
240 int net_error,
241 absl::optional<int> response_code) override {}
OnDropChannel(bool was_clean,uint16_t code,const std::string & reason)242 void OnDropChannel(bool was_clean,
243 uint16_t code,
244 const std::string& reason) override {}
OnStartOpeningHandshake(std::unique_ptr<WebSocketHandshakeRequestInfo> request)245 void OnStartOpeningHandshake(
246 std::unique_ptr<WebSocketHandshakeRequestInfo> request) override {}
OnSSLCertificateError(std::unique_ptr<SSLErrorCallbacks> ssl_error_callbacks,const GURL & url,int net_error,const SSLInfo & ssl_info,bool fatal)247 void OnSSLCertificateError(
248 std::unique_ptr<SSLErrorCallbacks> ssl_error_callbacks,
249 const GURL& url,
250 int net_error,
251 const SSLInfo& ssl_info,
252 bool fatal) override {}
OnAuthRequired(const AuthChallengeInfo & auth_info,scoped_refptr<HttpResponseHeaders> response_headers,const IPEndPoint & remote_endpoint,base::OnceCallback<void (const AuthCredentials *)> callback,absl::optional<AuthCredentials> * credentials)253 int OnAuthRequired(const AuthChallengeInfo& auth_info,
254 scoped_refptr<HttpResponseHeaders> response_headers,
255 const IPEndPoint& remote_endpoint,
256 base::OnceCallback<void(const AuthCredentials*)> callback,
257 absl::optional<AuthCredentials>* credentials) override {
258 *credentials = absl::nullopt;
259 return OK;
260 }
261 };
262
263 // This fake WebSocketStream is for tests that require a WebSocketStream but are
264 // not testing the way it is used. It has minimal functionality to return
265 // the |protocol| and |extensions| that it was constructed with.
266 class FakeWebSocketStream : public WebSocketStream {
267 public:
268 // Constructs with empty protocol and extensions.
269 FakeWebSocketStream() = default;
270
271 // Constructs with specified protocol and extensions.
FakeWebSocketStream(const std::string & protocol,const std::string & extensions)272 FakeWebSocketStream(const std::string& protocol,
273 const std::string& extensions)
274 : protocol_(protocol), extensions_(extensions) {}
275
ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>> * frames,CompletionOnceCallback callback)276 int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
277 CompletionOnceCallback callback) override {
278 return ERR_IO_PENDING;
279 }
280
WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>> * frames,CompletionOnceCallback callback)281 int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
282 CompletionOnceCallback callback) override {
283 return ERR_IO_PENDING;
284 }
285
Close()286 void Close() override {}
287
288 // Returns the string passed to the constructor.
GetSubProtocol() const289 std::string GetSubProtocol() const override { return protocol_; }
290
291 // Returns the string passed to the constructor.
GetExtensions() const292 std::string GetExtensions() const override { return extensions_; }
293
GetNetLogWithSource() const294 const NetLogWithSource& GetNetLogWithSource() const override {
295 return net_log_;
296 }
297
298 private:
299 // The string to return from GetSubProtocol().
300 std::string protocol_;
301
302 // The string to return from GetExtensions().
303 std::string extensions_;
304
305 NetLogWithSource net_log_;
306 };
307
308 // To make the static initialisers easier to read, we use enums rather than
309 // bools.
310 enum IsFinal { NOT_FINAL_FRAME, FINAL_FRAME };
311
312 enum IsMasked { NOT_MASKED, MASKED };
313
314 // This is used to initialise a WebSocketFrame but is statically initialisable.
315 struct InitFrame {
316 IsFinal final;
317 // Reserved fields omitted for now. Add them if you need them.
318 WebSocketFrameHeader::OpCode opcode;
319 IsMasked masked;
320
321 // Will be used to create the IOBuffer member. Can be null for null data. Is a
322 // nul-terminated string for ease-of-use. |header.payload_length| is
323 // initialised from |strlen(data)|. This means it is not 8-bit clean, but this
324 // is not an issue for test data.
325 const char* const data;
326 };
327
328 // For GoogleMock
operator <<(std::ostream & os,const InitFrame & frame)329 std::ostream& operator<<(std::ostream& os, const InitFrame& frame) {
330 os << "{" << (frame.final == FINAL_FRAME ? "FINAL_FRAME" : "NOT_FINAL_FRAME")
331 << ", " << frame.opcode << ", "
332 << (frame.masked == MASKED ? "MASKED" : "NOT_MASKED") << ", ";
333 if (frame.data) {
334 return os << "\"" << frame.data << "\"}";
335 }
336 return os << "NULL}";
337 }
338
339 template <size_t N>
operator <<(std::ostream & os,const InitFrame (& frames)[N])340 std::ostream& operator<<(std::ostream& os, const InitFrame (&frames)[N]) {
341 os << "{";
342 bool first = true;
343 for (size_t i = 0; i < N; ++i) {
344 if (!first) {
345 os << ",\n";
346 } else {
347 first = false;
348 }
349 os << frames[i];
350 }
351 return os << "}";
352 }
353
354 // Convert a const array of InitFrame structs to the format used at
355 // runtime. Templated on the size of the array to save typing.
356 template <size_t N>
CreateFrameVector(const InitFrame (& source_frames)[N],std::vector<scoped_refptr<IOBuffer>> * result_frame_data)357 std::vector<std::unique_ptr<WebSocketFrame>> CreateFrameVector(
358 const InitFrame (&source_frames)[N],
359 std::vector<scoped_refptr<IOBuffer>>* result_frame_data) {
360 std::vector<std::unique_ptr<WebSocketFrame>> result_frames;
361 result_frames.reserve(N);
362 for (size_t i = 0; i < N; ++i) {
363 const InitFrame& source_frame = source_frames[i];
364 auto result_frame = std::make_unique<WebSocketFrame>(source_frame.opcode);
365 size_t frame_length = source_frame.data ? strlen(source_frame.data) : 0;
366 WebSocketFrameHeader& result_header = result_frame->header;
367 result_header.final = (source_frame.final == FINAL_FRAME);
368 result_header.masked = (source_frame.masked == MASKED);
369 result_header.payload_length = frame_length;
370 if (source_frame.data) {
371 auto buffer = base::MakeRefCounted<IOBufferWithSize>(frame_length);
372 result_frame_data->push_back(buffer);
373 std::copy(source_frame.data, source_frame.data + frame_length,
374 buffer->data());
375 result_frame->payload = buffer->data();
376 }
377 result_frames.push_back(std::move(result_frame));
378 }
379 return result_frames;
380 }
381
382 // A GoogleMock action which can be used to respond to call to ReadFrames with
383 // some frames. Use like ReadFrames(_, _).WillOnce(ReturnFrames(&frames,
384 // &result_frame_data_)); |frames| is an array of InitFrame. |frames| needs to
385 // be passed by pointer because otherwise it will be treated as a pointer and
386 // the array size information will be lost.
ACTION_P2(ReturnFrames,source_frames,result_frame_data)387 ACTION_P2(ReturnFrames, source_frames, result_frame_data) {
388 *arg0 = CreateFrameVector(*source_frames, result_frame_data);
389 return OK;
390 }
391
392 // The implementation of a GoogleMock matcher which can be used to compare a
393 // std::vector<std::unique_ptr<WebSocketFrame>>* against an expectation defined
394 // as an
395 // array of InitFrame objects. Although it is possible to compose built-in
396 // GoogleMock matchers to check the contents of a WebSocketFrame, the results
397 // are so unreadable that it is better to use this matcher.
398 template <size_t N>
399 class EqualsFramesMatcher : public ::testing::MatcherInterface<
400 std::vector<std::unique_ptr<WebSocketFrame>>*> {
401 public:
EqualsFramesMatcher(const InitFrame (* expect_frames)[N])402 explicit EqualsFramesMatcher(const InitFrame (*expect_frames)[N])
403 : expect_frames_(expect_frames) {}
404
MatchAndExplain(std::vector<std::unique_ptr<WebSocketFrame>> * actual_frames,::testing::MatchResultListener * listener) const405 bool MatchAndExplain(
406 std::vector<std::unique_ptr<WebSocketFrame>>* actual_frames,
407 ::testing::MatchResultListener* listener) const override {
408 if (actual_frames->size() != N) {
409 *listener << "the vector size is " << actual_frames->size();
410 return false;
411 }
412 for (size_t i = 0; i < N; ++i) {
413 const WebSocketFrame& actual_frame = *(*actual_frames)[i];
414 const InitFrame& expected_frame = (*expect_frames_)[i];
415 if (actual_frame.header.final != (expected_frame.final == FINAL_FRAME)) {
416 *listener << "the frame is marked as "
417 << (actual_frame.header.final ? "" : "not ") << "final";
418 return false;
419 }
420 if (actual_frame.header.opcode != expected_frame.opcode) {
421 *listener << "the opcode is " << actual_frame.header.opcode;
422 return false;
423 }
424 if (actual_frame.header.masked != (expected_frame.masked == MASKED)) {
425 *listener << "the frame is "
426 << (actual_frame.header.masked ? "masked" : "not masked");
427 return false;
428 }
429 const size_t expected_length =
430 expected_frame.data ? strlen(expected_frame.data) : 0;
431 if (actual_frame.header.payload_length != expected_length) {
432 *listener << "the payload length is "
433 << actual_frame.header.payload_length;
434 return false;
435 }
436 if (expected_length != 0 &&
437 memcmp(actual_frame.payload, expected_frame.data,
438 actual_frame.header.payload_length) != 0) {
439 *listener << "the data content differs";
440 return false;
441 }
442 }
443 return true;
444 }
445
DescribeTo(std::ostream * os) const446 void DescribeTo(std::ostream* os) const override {
447 *os << "matches " << *expect_frames_;
448 }
449
DescribeNegationTo(std::ostream * os) const450 void DescribeNegationTo(std::ostream* os) const override {
451 *os << "does not match " << *expect_frames_;
452 }
453
454 private:
455 const InitFrame (*expect_frames_)[N];
456 };
457
458 // The definition of EqualsFrames GoogleMock matcher. Unlike the ReturnFrames
459 // action, this can take the array by reference.
460 template <size_t N>
EqualsFrames(const InitFrame (& frames)[N])461 ::testing::Matcher<std::vector<std::unique_ptr<WebSocketFrame>>*> EqualsFrames(
462 const InitFrame (&frames)[N]) {
463 return ::testing::MakeMatcher(new EqualsFramesMatcher<N>(&frames));
464 }
465
466 // A GoogleMock action to run a Closure.
ACTION_P(InvokeClosure,test_closure)467 ACTION_P(InvokeClosure, test_closure) {
468 test_closure->closure().Run();
469 }
470
471 // A FakeWebSocketStream whose ReadFrames() function returns data.
472 class ReadableFakeWebSocketStream : public FakeWebSocketStream {
473 public:
474 enum IsSync { SYNC, ASYNC };
475
476 // After constructing the object, call PrepareReadFrames() once for each
477 // time you wish it to return from the test.
478 ReadableFakeWebSocketStream() = default;
479
480 // Check that all the prepared responses have been consumed.
~ReadableFakeWebSocketStream()481 ~ReadableFakeWebSocketStream() override {
482 CHECK(index_ >= responses_.size());
483 CHECK(!read_frames_pending_);
484 }
485
486 // Prepares a fake response. Fake responses will be returned from ReadFrames()
487 // in the same order they were prepared with PrepareReadFrames() and
488 // PrepareReadFramesError(). If |async| is ASYNC, then ReadFrames() will
489 // return ERR_IO_PENDING and the callback will be scheduled to run on the
490 // message loop. This requires the test case to run the message loop. If
491 // |async| is SYNC, the response will be returned synchronously. |error| is
492 // returned directly from ReadFrames() in the synchronous case, or passed to
493 // the callback in the asynchronous case. |frames| will be converted to a
494 // std::vector<std::unique_ptr<WebSocketFrame>> and copied to the pointer that
495 // was
496 // passed to ReadFrames().
497 template <size_t N>
PrepareReadFrames(IsSync async,int error,const InitFrame (& frames)[N])498 void PrepareReadFrames(IsSync async,
499 int error,
500 const InitFrame (&frames)[N]) {
501 responses_.push_back(std::make_unique<Response>(
502 async, error, CreateFrameVector(frames, &result_frame_data_)));
503 }
504
505 // An alternate version of PrepareReadFrames for when we need to construct
506 // the frames manually.
PrepareRawReadFrames(IsSync async,int error,std::vector<std::unique_ptr<WebSocketFrame>> frames)507 void PrepareRawReadFrames(
508 IsSync async,
509 int error,
510 std::vector<std::unique_ptr<WebSocketFrame>> frames) {
511 responses_.push_back(
512 std::make_unique<Response>(async, error, std::move(frames)));
513 }
514
515 // Prepares a fake error response (ie. there is no data).
PrepareReadFramesError(IsSync async,int error)516 void PrepareReadFramesError(IsSync async, int error) {
517 responses_.push_back(std::make_unique<Response>(
518 async, error, std::vector<std::unique_ptr<WebSocketFrame>>()));
519 }
520
ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>> * frames,CompletionOnceCallback callback)521 int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
522 CompletionOnceCallback callback) override {
523 CHECK(!read_frames_pending_);
524 if (index_ >= responses_.size())
525 return ERR_IO_PENDING;
526 if (responses_[index_]->async == ASYNC) {
527 read_frames_pending_ = true;
528 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
529 FROM_HERE,
530 base::BindOnce(&ReadableFakeWebSocketStream::DoCallback,
531 base::Unretained(this), frames, std::move(callback)));
532 return ERR_IO_PENDING;
533 } else {
534 frames->swap(responses_[index_]->frames);
535 return responses_[index_++]->error;
536 }
537 }
538
539 private:
DoCallback(std::vector<std::unique_ptr<WebSocketFrame>> * frames,CompletionOnceCallback callback)540 void DoCallback(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
541 CompletionOnceCallback callback) {
542 read_frames_pending_ = false;
543 frames->swap(responses_[index_]->frames);
544 std::move(callback).Run(responses_[index_++]->error);
545 return;
546 }
547
548 struct Response {
Responsenet::__anon82a82a100111::ReadableFakeWebSocketStream::Response549 Response(IsSync async,
550 int error,
551 std::vector<std::unique_ptr<WebSocketFrame>> frames)
552 : async(async), error(error), frames(std::move(frames)) {}
553
554 // Bad things will happen if we attempt to copy or assign |frames|.
555 Response(const Response&) = delete;
556 Response& operator=(const Response&) = delete;
557
558 IsSync async;
559 int error;
560 std::vector<std::unique_ptr<WebSocketFrame>> frames;
561 };
562 std::vector<std::unique_ptr<Response>> responses_;
563
564 // The index into the responses_ array of the next response to be returned.
565 size_t index_ = 0;
566
567 // True when an async response from ReadFrames() is pending. This only applies
568 // to "real" async responses. Once all the prepared responses have been
569 // returned, ReadFrames() returns ERR_IO_PENDING but read_frames_pending_ is
570 // not set to true.
571 bool read_frames_pending_ = false;
572
573 std::vector<scoped_refptr<IOBuffer>> result_frame_data_;
574 };
575
576 // A FakeWebSocketStream where writes always complete successfully and
577 // synchronously.
578 class WriteableFakeWebSocketStream : public FakeWebSocketStream {
579 public:
WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>> * frames,CompletionOnceCallback callback)580 int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
581 CompletionOnceCallback callback) override {
582 return OK;
583 }
584 };
585
586 // A FakeWebSocketStream where writes always fail.
587 class UnWriteableFakeWebSocketStream : public FakeWebSocketStream {
588 public:
WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>> * frames,CompletionOnceCallback callback)589 int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
590 CompletionOnceCallback callback) override {
591 return ERR_CONNECTION_RESET;
592 }
593 };
594
595 // A FakeWebSocketStream which echoes any frames written back. Clears the
596 // "masked" header bit, but makes no other checks for validity. Tests using this
597 // must run the MessageLoop to receive the callback(s). If a message with opcode
598 // Close is echoed, then an ERR_CONNECTION_CLOSED is returned in the next
599 // callback. The test must do something to cause WriteFrames() to be called,
600 // otherwise the ReadFrames() callback will never be called.
601 class EchoeyFakeWebSocketStream : public FakeWebSocketStream {
602 public:
603 EchoeyFakeWebSocketStream() = default;
604
WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>> * frames,CompletionOnceCallback callback)605 int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
606 CompletionOnceCallback callback) override {
607 for (const auto& frame : *frames) {
608 auto buffer = base::MakeRefCounted<IOBufferWithSize>(
609 static_cast<size_t>(frame->header.payload_length));
610 std::copy(frame->payload, frame->payload + frame->header.payload_length,
611 buffer->data());
612 frame->payload = buffer->data();
613 buffers_.push_back(buffer);
614 }
615 stored_frames_.insert(stored_frames_.end(),
616 std::make_move_iterator(frames->begin()),
617 std::make_move_iterator(frames->end()));
618 frames->clear();
619 // Users of WebSocketStream will not expect the ReadFrames() callback to be
620 // called from within WriteFrames(), so post it to the message loop instead.
621 PostCallback();
622 return OK;
623 }
624
ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>> * frames,CompletionOnceCallback callback)625 int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
626 CompletionOnceCallback callback) override {
627 read_callback_ = std::move(callback);
628 read_frames_ = frames;
629 if (done_)
630 PostCallback();
631 return ERR_IO_PENDING;
632 }
633
634 private:
PostCallback()635 void PostCallback() {
636 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
637 FROM_HERE, base::BindOnce(&EchoeyFakeWebSocketStream::DoCallback,
638 base::Unretained(this)));
639 }
640
DoCallback()641 void DoCallback() {
642 if (done_) {
643 std::move(read_callback_).Run(ERR_CONNECTION_CLOSED);
644 } else if (!stored_frames_.empty()) {
645 done_ = MoveFrames(read_frames_);
646 read_frames_ = nullptr;
647 std::move(read_callback_).Run(OK);
648 }
649 }
650
651 // Copy the frames stored in stored_frames_ to |out|, while clearing the
652 // "masked" header bit. Returns true if a Close Frame was seen, false
653 // otherwise.
MoveFrames(std::vector<std::unique_ptr<WebSocketFrame>> * out)654 bool MoveFrames(std::vector<std::unique_ptr<WebSocketFrame>>* out) {
655 bool seen_close = false;
656 *out = std::move(stored_frames_);
657 for (const auto& frame : *out) {
658 WebSocketFrameHeader& header = frame->header;
659 header.masked = false;
660 if (header.opcode == WebSocketFrameHeader::kOpCodeClose)
661 seen_close = true;
662 }
663 return seen_close;
664 }
665
666 std::vector<std::unique_ptr<WebSocketFrame>> stored_frames_;
667 CompletionOnceCallback read_callback_;
668 // Owned by the caller of ReadFrames().
669 raw_ptr<std::vector<std::unique_ptr<WebSocketFrame>>> read_frames_ = nullptr;
670 std::vector<scoped_refptr<IOBuffer>> buffers_;
671 // True if we should close the connection.
672 bool done_ = false;
673 };
674
675 // A FakeWebSocketStream where writes trigger a connection reset.
676 // This differs from UnWriteableFakeWebSocketStream in that it is asynchronous
677 // and triggers ReadFrames to return a reset as well. Tests using this need to
678 // run the message loop. There are two tricky parts here:
679 // 1. Calling the write callback may call Close(), after which the read callback
680 // should not be called.
681 // 2. Calling either callback may delete the stream altogether.
682 class ResetOnWriteFakeWebSocketStream : public FakeWebSocketStream {
683 public:
684 ResetOnWriteFakeWebSocketStream() = default;
685
WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>> * frames,CompletionOnceCallback callback)686 int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
687 CompletionOnceCallback callback) override {
688 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
689 FROM_HERE,
690 base::BindOnce(
691 &ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed,
692 weak_ptr_factory_.GetWeakPtr(), std::move(callback),
693 ERR_CONNECTION_RESET));
694 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
695 FROM_HERE,
696 base::BindOnce(
697 &ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed,
698 weak_ptr_factory_.GetWeakPtr(), std::move(read_callback_),
699 ERR_CONNECTION_RESET));
700 return ERR_IO_PENDING;
701 }
702
ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>> * frames,CompletionOnceCallback callback)703 int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
704 CompletionOnceCallback callback) override {
705 read_callback_ = std::move(callback);
706 return ERR_IO_PENDING;
707 }
708
Close()709 void Close() override { closed_ = true; }
710
711 private:
CallCallbackUnlessClosed(CompletionOnceCallback callback,int value)712 void CallCallbackUnlessClosed(CompletionOnceCallback callback, int value) {
713 if (!closed_)
714 std::move(callback).Run(value);
715 }
716
717 CompletionOnceCallback read_callback_;
718 bool closed_ = false;
719 // An IO error can result in the socket being deleted, so we use weak pointers
720 // to ensure correct behaviour in that case.
721 base::WeakPtrFactory<ResetOnWriteFakeWebSocketStream> weak_ptr_factory_{this};
722 };
723
724 // This mock is for verifying that WebSocket protocol semantics are obeyed (to
725 // the extent that they are implemented in WebSocketCommon).
726 class MockWebSocketStream : public WebSocketStream {
727 public:
728 MOCK_METHOD2(ReadFrames,
729 int(std::vector<std::unique_ptr<WebSocketFrame>>*,
730 CompletionOnceCallback));
731 MOCK_METHOD2(WriteFrames,
732 int(std::vector<std::unique_ptr<WebSocketFrame>>*,
733 CompletionOnceCallback));
734
735 MOCK_METHOD0(Close, void());
736 MOCK_CONST_METHOD0(GetSubProtocol, std::string());
737 MOCK_CONST_METHOD0(GetExtensions, std::string());
738 MOCK_CONST_METHOD0(GetNetLogWithSource, NetLogWithSource&());
739 MOCK_METHOD0(AsWebSocketStream, WebSocketStream*());
740 };
741
742 class MockWebSocketStreamRequest : public WebSocketStreamRequest {
743 public:
744 MOCK_METHOD1(OnBasicHandshakeStreamCreated,
745 void(WebSocketBasicHandshakeStream* handshake_stream));
746 MOCK_METHOD1(OnHttp2HandshakeStreamCreated,
747 void(WebSocketHttp2HandshakeStream* handshake_stream));
748 MOCK_METHOD1(OnFailure, void(const std::string& message));
749 };
750
751 struct WebSocketStreamCreationCallbackArgumentSaver {
Createnet::__anon82a82a100111::WebSocketStreamCreationCallbackArgumentSaver752 std::unique_ptr<WebSocketStreamRequest> Create(
753 const GURL& new_socket_url,
754 const std::vector<std::string>& requested_subprotocols,
755 const url::Origin& new_origin,
756 const SiteForCookies& new_site_for_cookies,
757 bool new_has_storage_access,
758 const IsolationInfo& new_isolation_info,
759 const HttpRequestHeaders& additional_headers,
760 URLRequestContext* new_url_request_context,
761 const NetLogWithSource& net_log,
762 NetworkTrafficAnnotationTag traffic_annotation,
763 std::unique_ptr<WebSocketStream::ConnectDelegate> new_connect_delegate) {
764 socket_url = new_socket_url;
765 origin = new_origin;
766 site_for_cookies = new_site_for_cookies;
767 has_storage_access = new_has_storage_access;
768 isolation_info = new_isolation_info;
769 url_request_context = new_url_request_context;
770 connect_delegate = std::move(new_connect_delegate);
771 return std::make_unique<MockWebSocketStreamRequest>();
772 }
773
774 GURL socket_url;
775 url::Origin origin;
776 SiteForCookies site_for_cookies;
777 bool has_storage_access;
778 IsolationInfo isolation_info;
779 raw_ptr<URLRequestContext> url_request_context;
780 std::unique_ptr<WebSocketStream::ConnectDelegate> connect_delegate;
781 };
782
AsVector(base::StringPiece s)783 std::vector<char> AsVector(base::StringPiece s) {
784 return std::vector<char>(s.begin(), s.end());
785 }
786
787 // Converts a base::StringPiece to a IOBuffer. For test purposes, it is
788 // convenient to be able to specify data as a string, but the
789 // WebSocketEventInterface requires the IOBuffer type.
AsIOBuffer(base::StringPiece s)790 scoped_refptr<IOBuffer> AsIOBuffer(base::StringPiece s) {
791 auto buffer = base::MakeRefCounted<IOBufferWithSize>(s.size());
792 base::ranges::copy(s, buffer->data());
793 return buffer;
794 }
795
796 class FakeSSLErrorCallbacks
797 : public WebSocketEventInterface::SSLErrorCallbacks {
798 public:
CancelSSLRequest(int error,const SSLInfo * ssl_info)799 void CancelSSLRequest(int error, const SSLInfo* ssl_info) override {}
ContinueSSLRequest()800 void ContinueSSLRequest() override {}
801 };
802
803 // Base class for all test fixtures.
804 class WebSocketChannelTest : public TestWithTaskEnvironment {
805 protected:
WebSocketChannelTest()806 WebSocketChannelTest() : stream_(std::make_unique<FakeWebSocketStream>()) {}
807
808 // Creates a new WebSocketChannel and connects it, using the settings stored
809 // in |connect_data_|.
CreateChannelAndConnect()810 void CreateChannelAndConnect() {
811 channel_ = std::make_unique<WebSocketChannel>(
812 CreateEventInterface(), connect_data_.url_request_context.get());
813 channel_->SendAddChannelRequestForTesting(
814 connect_data_.socket_url, connect_data_.requested_subprotocols,
815 connect_data_.origin, connect_data_.site_for_cookies,
816 /*has_storage_access=*/false, connect_data_.isolation_info,
817 HttpRequestHeaders(), TRAFFIC_ANNOTATION_FOR_TESTS,
818 base::BindOnce(&WebSocketStreamCreationCallbackArgumentSaver::Create,
819 base::Unretained(&connect_data_.argument_saver)));
820 }
821
822 // Same as CreateChannelAndConnect(), but calls the on_success callback as
823 // well. This method is virtual so that subclasses can also set the stream.
CreateChannelAndConnectSuccessfully()824 virtual void CreateChannelAndConnectSuccessfully() {
825 CreateChannelAndConnect();
826 connect_data_.argument_saver.connect_delegate->OnSuccess(
827 std::move(stream_), std::make_unique<WebSocketHandshakeResponseInfo>(
828 GURL(), nullptr, IPEndPoint(), base::Time()));
829 std::ignore = channel_->ReadFrames();
830 }
831
832 // Returns a WebSocketEventInterface to be passed to the WebSocketChannel.
833 // This implementation returns a newly-created fake. Subclasses may return a
834 // mock instead.
CreateEventInterface()835 virtual std::unique_ptr<WebSocketEventInterface> CreateEventInterface() {
836 return std::make_unique<FakeWebSocketEventInterface>();
837 }
838
839 // This method serves no other purpose than to provide a nice syntax for
840 // assigning to stream_. class T must be a subclass of WebSocketStream or you
841 // will have unpleasant compile errors.
842 template <class T>
set_stream(std::unique_ptr<T> stream)843 void set_stream(std::unique_ptr<T> stream) {
844 stream_ = std::move(stream);
845 }
846
847 // A struct containing the data that will be used to connect the channel.
848 // Grouped for readability.
849 struct ConnectData {
ConnectDatanet::__anon82a82a100111::WebSocketChannelTest::ConnectData850 ConnectData()
851 : url_request_context(CreateTestURLRequestContextBuilder()->Build()),
852 socket_url("ws://ws/"),
853 origin(url::Origin::Create(GURL("http://ws"))),
854 site_for_cookies(SiteForCookies::FromUrl(GURL("http://ws/"))),
855 has_storage_access(false) {
856 this->isolation_info =
857 IsolationInfo::Create(IsolationInfo::RequestType::kOther, origin,
858 origin, SiteForCookies::FromOrigin(origin));
859 }
860
861 // URLRequestContext object.
862 std::unique_ptr<URLRequestContext> url_request_context;
863
864 // URL to (pretend to) connect to.
865 GURL socket_url;
866 // Requested protocols for the request.
867 std::vector<std::string> requested_subprotocols;
868 // Origin of the request
869 url::Origin origin;
870 // First party for cookies for the request.
871 net::SiteForCookies site_for_cookies;
872 // Whether the calling context has opted into the Storage Access API.
873 bool has_storage_access;
874 // IsolationInfo created from the origin.
875 net::IsolationInfo isolation_info;
876
877 WebSocketStreamCreationCallbackArgumentSaver argument_saver;
878 };
879 ConnectData connect_data_;
880
881 // The channel we are testing. Not initialised until SetChannel() is called.
882 std::unique_ptr<WebSocketChannel> channel_;
883
884 // A mock or fake stream for tests that need one.
885 std::unique_ptr<WebSocketStream> stream_;
886
887 std::vector<scoped_refptr<IOBuffer>> result_frame_data_;
888 };
889
890 // enum of WebSocketEventInterface calls. These are intended to be or'd together
891 // in order to instruct WebSocketChannelDeletingTest when it should fail.
892 enum EventInterfaceCall {
893 EVENT_ON_ADD_CHANNEL_RESPONSE = 0x1,
894 EVENT_ON_DATA_FRAME = 0x2,
895 EVENT_ON_FLOW_CONTROL = 0x4,
896 EVENT_ON_CLOSING_HANDSHAKE = 0x8,
897 EVENT_ON_FAIL_CHANNEL = 0x10,
898 EVENT_ON_DROP_CHANNEL = 0x20,
899 EVENT_ON_START_OPENING_HANDSHAKE = 0x40,
900 EVENT_ON_FINISH_OPENING_HANDSHAKE = 0x80,
901 EVENT_ON_SSL_CERTIFICATE_ERROR = 0x100,
902 };
903
904 // Base class for tests which verify that EventInterface methods are called
905 // appropriately.
906 class WebSocketChannelEventInterfaceTest : public WebSocketChannelTest {
907 public:
SetUp()908 void SetUp() override {
909 EXPECT_CALL(*event_interface_, HasPendingDataFrames()).Times(AnyNumber());
910 }
911
912 protected:
WebSocketChannelEventInterfaceTest()913 WebSocketChannelEventInterfaceTest()
914 : event_interface_(
915 std::make_unique<StrictMock<MockWebSocketEventInterface>>()) {
916 }
917
918 ~WebSocketChannelEventInterfaceTest() override = default;
919
920 // Tests using this fixture must set expectations on the event_interface_ mock
921 // object before calling CreateChannelAndConnect() or
922 // CreateChannelAndConnectSuccessfully(). This will only work once per test
923 // case, but once should be enough.
CreateEventInterface()924 std::unique_ptr<WebSocketEventInterface> CreateEventInterface() override {
925 return std::move(event_interface_);
926 }
927
928 std::unique_ptr<MockWebSocketEventInterface> event_interface_;
929 };
930
931 // Base class for tests which verify that WebSocketStream methods are called
932 // appropriately by using a MockWebSocketStream.
933 class WebSocketChannelStreamTest : public WebSocketChannelEventInterfaceTest {
934 public:
SetUp()935 void SetUp() override {
936 WebSocketChannelEventInterfaceTest::SetUp();
937 // For the purpose of the tests using this fixture, it doesn't matter
938 // whether these methods are called or not.
939 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
940 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
941 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _))
942 .Times(AnyNumber());
943 EXPECT_CALL(*event_interface_, OnDataFrameVector(_, _, _))
944 .Times(AnyNumber());
945 EXPECT_CALL(*event_interface_, OnClosingHandshake()).Times(AnyNumber());
946 EXPECT_CALL(*event_interface_, OnSendDataFrameDone()).Times(AnyNumber());
947 EXPECT_CALL(*event_interface_, OnFailChannel(_, _, _)).Times(AnyNumber());
948 EXPECT_CALL(*event_interface_, OnDropChannel(_, _, _)).Times(AnyNumber());
949 }
950
951 protected:
WebSocketChannelStreamTest()952 WebSocketChannelStreamTest()
953 : mock_stream_(std::make_unique<StrictMock<MockWebSocketStream>>()) {}
954
CreateChannelAndConnectSuccessfully()955 void CreateChannelAndConnectSuccessfully() override {
956 set_stream(std::move(mock_stream_));
957 WebSocketChannelTest::CreateChannelAndConnectSuccessfully();
958 }
959
960 std::unique_ptr<MockWebSocketStream> mock_stream_;
961 };
962
963 // Fixture for tests which test UTF-8 validation of sent Text frames via the
964 // EventInterface.
965 class WebSocketChannelSendUtf8Test
966 : public WebSocketChannelEventInterfaceTest {
967 public:
SetUp()968 void SetUp() override {
969 WebSocketChannelEventInterfaceTest::SetUp();
970 set_stream(std::make_unique<WriteableFakeWebSocketStream>());
971 // For the purpose of the tests using this fixture, it doesn't matter
972 // whether these methods are called or not.
973 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _))
974 .Times(AnyNumber());
975 EXPECT_CALL(*event_interface_, OnSendDataFrameDone()).Times(AnyNumber());
976 }
977 };
978
979 // Fixture for tests which test UTF-8 validation of received Text frames using a
980 // mock WebSocketStream.
981 class WebSocketChannelReceiveUtf8Test : public WebSocketChannelStreamTest {
982 public:
SetUp()983 void SetUp() override {
984 WebSocketChannelStreamTest::SetUp();
985 // For the purpose of the tests using this fixture, it doesn't matter
986 // whether these methods are called or not.
987 }
988 };
989
990 // Simple test that everything that should be passed to the stream creation
991 // callback is passed to the argument saver.
TEST_F(WebSocketChannelTest,EverythingIsPassedToTheCreatorFunction)992 TEST_F(WebSocketChannelTest, EverythingIsPassedToTheCreatorFunction) {
993 connect_data_.socket_url = GURL("ws://example.com/test");
994 connect_data_.origin = url::Origin::Create(GURL("http://example.com"));
995 connect_data_.site_for_cookies =
996 SiteForCookies::FromUrl(GURL("http://example.com/"));
997 connect_data_.isolation_info = net::IsolationInfo::Create(
998 IsolationInfo::RequestType::kOther, connect_data_.origin,
999 connect_data_.origin, SiteForCookies::FromOrigin(connect_data_.origin));
1000 connect_data_.requested_subprotocols.push_back("Sinbad");
1001
1002 CreateChannelAndConnect();
1003
1004 const WebSocketStreamCreationCallbackArgumentSaver& actual =
1005 connect_data_.argument_saver;
1006
1007 EXPECT_EQ(connect_data_.url_request_context.get(),
1008 actual.url_request_context);
1009
1010 EXPECT_EQ(connect_data_.socket_url, actual.socket_url);
1011 EXPECT_EQ(connect_data_.origin.Serialize(), actual.origin.Serialize());
1012 EXPECT_TRUE(
1013 connect_data_.site_for_cookies.IsEquivalent(actual.site_for_cookies));
1014 EXPECT_EQ(connect_data_.has_storage_access, actual.has_storage_access);
1015 EXPECT_TRUE(
1016 connect_data_.isolation_info.IsEqualForTesting(actual.isolation_info));
1017 }
1018
TEST_F(WebSocketChannelEventInterfaceTest,ConnectSuccessReported)1019 TEST_F(WebSocketChannelEventInterfaceTest, ConnectSuccessReported) {
1020 // false means success.
1021 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, "", ""));
1022
1023 CreateChannelAndConnect();
1024
1025 connect_data_.argument_saver.connect_delegate->OnSuccess(
1026 std::move(stream_), std::make_unique<WebSocketHandshakeResponseInfo>(
1027 GURL(), nullptr, IPEndPoint(), base::Time()));
1028 std::ignore = channel_->ReadFrames();
1029 }
1030
TEST_F(WebSocketChannelEventInterfaceTest,ConnectFailureReported)1031 TEST_F(WebSocketChannelEventInterfaceTest, ConnectFailureReported) {
1032 EXPECT_CALL(*event_interface_, OnFailChannel("hello", ERR_FAILED, _));
1033
1034 CreateChannelAndConnect();
1035
1036 connect_data_.argument_saver.connect_delegate->OnFailure("hello", ERR_FAILED,
1037 absl::nullopt);
1038 }
1039
TEST_F(WebSocketChannelEventInterfaceTest,NonWebSocketSchemeRejected)1040 TEST_F(WebSocketChannelEventInterfaceTest, NonWebSocketSchemeRejected) {
1041 EXPECT_CALL(*event_interface_, OnFailChannel("Invalid scheme", _, _));
1042 connect_data_.socket_url = GURL("http://www.google.com/");
1043 CreateChannelAndConnect();
1044 }
1045
TEST_F(WebSocketChannelEventInterfaceTest,ProtocolPassed)1046 TEST_F(WebSocketChannelEventInterfaceTest, ProtocolPassed) {
1047 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, "Bob", ""));
1048
1049 CreateChannelAndConnect();
1050
1051 connect_data_.argument_saver.connect_delegate->OnSuccess(
1052 std::make_unique<FakeWebSocketStream>("Bob", ""),
1053 std::make_unique<WebSocketHandshakeResponseInfo>(
1054 GURL(), nullptr, IPEndPoint(), base::Time()));
1055 std::ignore = channel_->ReadFrames();
1056 }
1057
TEST_F(WebSocketChannelEventInterfaceTest,ExtensionsPassed)1058 TEST_F(WebSocketChannelEventInterfaceTest, ExtensionsPassed) {
1059 EXPECT_CALL(*event_interface_,
1060 OnAddChannelResponse(_, "", "extension1, extension2"));
1061
1062 CreateChannelAndConnect();
1063
1064 connect_data_.argument_saver.connect_delegate->OnSuccess(
1065 std::make_unique<FakeWebSocketStream>("", "extension1, extension2"),
1066 std::make_unique<WebSocketHandshakeResponseInfo>(
1067 GURL(), nullptr, IPEndPoint(), base::Time()));
1068 std::ignore = channel_->ReadFrames();
1069 }
1070
1071 // The first frames from the server can arrive together with the handshake, in
1072 // which case they will be available as soon as ReadFrames() is called the first
1073 // time.
TEST_F(WebSocketChannelEventInterfaceTest,DataLeftFromHandshake)1074 TEST_F(WebSocketChannelEventInterfaceTest, DataLeftFromHandshake) {
1075 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1076 static const InitFrame frames[] = {
1077 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1078 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1079 set_stream(std::move(stream));
1080 {
1081 InSequence s;
1082 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1083 EXPECT_CALL(*event_interface_,
1084 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
1085 AsVector("HELLO")));
1086 }
1087
1088 CreateChannelAndConnectSuccessfully();
1089 }
1090
1091 // A remote server could accept the handshake, but then immediately send a
1092 // Close frame.
TEST_F(WebSocketChannelEventInterfaceTest,CloseAfterHandshake)1093 TEST_F(WebSocketChannelEventInterfaceTest, CloseAfterHandshake) {
1094 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1095 static const InitFrame frames[] = {
1096 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1097 NOT_MASKED, CLOSE_DATA(SERVER_ERROR, "Internal Server Error")}};
1098 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1099 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1100 ERR_CONNECTION_CLOSED);
1101 set_stream(std::move(stream));
1102 {
1103 InSequence s;
1104 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1105 EXPECT_CALL(*event_interface_, OnClosingHandshake());
1106 EXPECT_CALL(
1107 *event_interface_,
1108 OnDropChannel(
1109 true, kWebSocketErrorInternalServerError, "Internal Server Error"));
1110 }
1111
1112 CreateChannelAndConnectSuccessfully();
1113 }
1114
1115 // Do not close until browser has sent all pending frames.
TEST_F(WebSocketChannelEventInterfaceTest,ShouldCloseWhileNoDataFrames)1116 TEST_F(WebSocketChannelEventInterfaceTest, ShouldCloseWhileNoDataFrames) {
1117 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1118 static const InitFrame frames[] = {
1119 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED,
1120 CLOSE_DATA(SERVER_ERROR, "Internal Server Error")}};
1121 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1122 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1123 ERR_CONNECTION_CLOSED);
1124 set_stream(std::move(stream));
1125 Checkpoint checkpoint;
1126 {
1127 InSequence s;
1128 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1129 EXPECT_CALL(*event_interface_, HasPendingDataFrames())
1130 .WillOnce(Return(false))
1131 .WillOnce(Return(true))
1132 .WillOnce(Return(true));
1133 EXPECT_CALL(checkpoint, Call(1));
1134 #if DCHECK_IS_ON()
1135 EXPECT_CALL(*event_interface_, HasPendingDataFrames())
1136 .WillOnce(Return(false));
1137 #endif
1138 EXPECT_CALL(*event_interface_, OnClosingHandshake());
1139 EXPECT_CALL(*event_interface_,
1140 OnDropChannel(true, kWebSocketErrorInternalServerError,
1141 "Internal Server Error"));
1142 }
1143
1144 CreateChannelAndConnectSuccessfully();
1145 checkpoint.Call(1);
1146 ASSERT_EQ(CHANNEL_DELETED, channel_->ReadFrames());
1147 }
1148
1149 // A remote server could close the connection immediately after sending the
1150 // handshake response (most likely a bug in the server).
TEST_F(WebSocketChannelEventInterfaceTest,ConnectionCloseAfterHandshake)1151 TEST_F(WebSocketChannelEventInterfaceTest, ConnectionCloseAfterHandshake) {
1152 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1153 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1154 ERR_CONNECTION_CLOSED);
1155 set_stream(std::move(stream));
1156 {
1157 InSequence s;
1158 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1159 EXPECT_CALL(*event_interface_,
1160 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
1161 }
1162
1163 CreateChannelAndConnectSuccessfully();
1164 }
1165
TEST_F(WebSocketChannelEventInterfaceTest,NormalAsyncRead)1166 TEST_F(WebSocketChannelEventInterfaceTest, NormalAsyncRead) {
1167 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1168 static const InitFrame frames[] = {
1169 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1170 // We use this checkpoint object to verify that the callback isn't called
1171 // until we expect it to be.
1172 Checkpoint checkpoint;
1173 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
1174 set_stream(std::move(stream));
1175 {
1176 InSequence s;
1177 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1178 EXPECT_CALL(checkpoint, Call(1));
1179 EXPECT_CALL(*event_interface_,
1180 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
1181 AsVector("HELLO")));
1182 EXPECT_CALL(checkpoint, Call(2));
1183 }
1184
1185 CreateChannelAndConnectSuccessfully();
1186 checkpoint.Call(1);
1187 base::RunLoop().RunUntilIdle();
1188 checkpoint.Call(2);
1189 }
1190
1191 // Extra data can arrive while a read is being processed, resulting in the next
1192 // read completing synchronously.
TEST_F(WebSocketChannelEventInterfaceTest,AsyncThenSyncRead)1193 TEST_F(WebSocketChannelEventInterfaceTest, AsyncThenSyncRead) {
1194 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1195 static const InitFrame frames1[] = {
1196 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
1197 static const InitFrame frames2[] = {
1198 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "WORLD"}};
1199 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
1200 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames2);
1201 set_stream(std::move(stream));
1202 {
1203 InSequence s;
1204 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1205 EXPECT_CALL(*event_interface_,
1206 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
1207 AsVector("HELLO")));
1208 EXPECT_CALL(*event_interface_,
1209 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
1210 AsVector("WORLD")));
1211 }
1212
1213 CreateChannelAndConnectSuccessfully();
1214 base::RunLoop().RunUntilIdle();
1215 }
1216
1217 // Data frames are delivered the same regardless of how many reads they arrive
1218 // as.
TEST_F(WebSocketChannelEventInterfaceTest,FragmentedMessage)1219 TEST_F(WebSocketChannelEventInterfaceTest, FragmentedMessage) {
1220 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1221 // Here we have one message which arrived in five frames split across three
1222 // reads. It may have been reframed on arrival, but this class doesn't care
1223 // about that.
1224 static const InitFrame frames1[] = {
1225 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "THREE"},
1226 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1227 NOT_MASKED, " "}};
1228 static const InitFrame frames2[] = {
1229 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1230 NOT_MASKED, "SMALL"}};
1231 static const InitFrame frames3[] = {
1232 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1233 NOT_MASKED, " "},
1234 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1235 NOT_MASKED, "FRAMES"}};
1236 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
1237 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames2);
1238 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames3);
1239 set_stream(std::move(stream));
1240 {
1241 InSequence s;
1242 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1243 EXPECT_CALL(*event_interface_,
1244 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
1245 AsVector("THREE")));
1246 EXPECT_CALL(
1247 *event_interface_,
1248 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
1249 AsVector(" ")));
1250 EXPECT_CALL(
1251 *event_interface_,
1252 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
1253 AsVector("SMALL")));
1254 EXPECT_CALL(
1255 *event_interface_,
1256 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
1257 AsVector(" ")));
1258 EXPECT_CALL(
1259 *event_interface_,
1260 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
1261 AsVector("FRAMES")));
1262 }
1263
1264 CreateChannelAndConnectSuccessfully();
1265 base::RunLoop().RunUntilIdle();
1266 }
1267
1268 // A message can consist of one frame with null payload.
TEST_F(WebSocketChannelEventInterfaceTest,NullMessage)1269 TEST_F(WebSocketChannelEventInterfaceTest, NullMessage) {
1270 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1271 static const InitFrame frames[] = {
1272 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, nullptr}};
1273 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1274 set_stream(std::move(stream));
1275 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1276 EXPECT_CALL(
1277 *event_interface_,
1278 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText, AsVector("")));
1279 CreateChannelAndConnectSuccessfully();
1280 }
1281
1282 // Connection closed by the remote host without a closing handshake.
TEST_F(WebSocketChannelEventInterfaceTest,AsyncAbnormalClosure)1283 TEST_F(WebSocketChannelEventInterfaceTest, AsyncAbnormalClosure) {
1284 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1285 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
1286 ERR_CONNECTION_CLOSED);
1287 set_stream(std::move(stream));
1288 {
1289 InSequence s;
1290 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1291 EXPECT_CALL(*event_interface_,
1292 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
1293 }
1294
1295 CreateChannelAndConnectSuccessfully();
1296 base::RunLoop().RunUntilIdle();
1297 }
1298
1299 // A connection reset should produce the same event as an unexpected closure.
TEST_F(WebSocketChannelEventInterfaceTest,ConnectionReset)1300 TEST_F(WebSocketChannelEventInterfaceTest, ConnectionReset) {
1301 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1302 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
1303 ERR_CONNECTION_RESET);
1304 set_stream(std::move(stream));
1305 {
1306 InSequence s;
1307 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1308 EXPECT_CALL(*event_interface_,
1309 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
1310 }
1311
1312 CreateChannelAndConnectSuccessfully();
1313 base::RunLoop().RunUntilIdle();
1314 }
1315
1316 // RFC6455 5.1 "A client MUST close a connection if it detects a masked frame."
TEST_F(WebSocketChannelEventInterfaceTest,MaskedFramesAreRejected)1317 TEST_F(WebSocketChannelEventInterfaceTest, MaskedFramesAreRejected) {
1318 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1319 static const InitFrame frames[] = {
1320 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"}};
1321
1322 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
1323 set_stream(std::move(stream));
1324 {
1325 InSequence s;
1326 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1327 EXPECT_CALL(
1328 *event_interface_,
1329 OnFailChannel(
1330 "A server must not mask any frames that it sends to the client.", _,
1331 _));
1332 }
1333
1334 CreateChannelAndConnectSuccessfully();
1335 base::RunLoop().RunUntilIdle();
1336 }
1337
1338 // RFC6455 5.2 "If an unknown opcode is received, the receiving endpoint MUST
1339 // _Fail the WebSocket Connection_."
TEST_F(WebSocketChannelEventInterfaceTest,UnknownOpCodeIsRejected)1340 TEST_F(WebSocketChannelEventInterfaceTest, UnknownOpCodeIsRejected) {
1341 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1342 static const InitFrame frames[] = {{FINAL_FRAME, 4, NOT_MASKED, "HELLO"}};
1343
1344 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
1345 set_stream(std::move(stream));
1346 {
1347 InSequence s;
1348 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1349 EXPECT_CALL(*event_interface_,
1350 OnFailChannel("Unrecognized frame opcode: 4", _, _));
1351 }
1352
1353 CreateChannelAndConnectSuccessfully();
1354 base::RunLoop().RunUntilIdle();
1355 }
1356
1357 // RFC6455 5.4 "Control frames ... MAY be injected in the middle of a
1358 // fragmented message."
TEST_F(WebSocketChannelEventInterfaceTest,ControlFrameInDataMessage)1359 TEST_F(WebSocketChannelEventInterfaceTest, ControlFrameInDataMessage) {
1360 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1361 // We have one message of type Text split into two frames. In the middle is a
1362 // control message of type Pong.
1363 static const InitFrame frames1[] = {
1364 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
1365 NOT_MASKED, "SPLIT "}};
1366 static const InitFrame frames2[] = {
1367 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, ""}};
1368 static const InitFrame frames3[] = {
1369 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
1370 NOT_MASKED, "MESSAGE"}};
1371 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
1372 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames2);
1373 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames3);
1374 set_stream(std::move(stream));
1375 {
1376 InSequence s;
1377 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1378 EXPECT_CALL(*event_interface_,
1379 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
1380 AsVector("SPLIT ")));
1381 EXPECT_CALL(
1382 *event_interface_,
1383 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
1384 AsVector("MESSAGE")));
1385 }
1386
1387 CreateChannelAndConnectSuccessfully();
1388 base::RunLoop().RunUntilIdle();
1389 }
1390
1391 // It seems redundant to repeat the entirety of the above test, so just test a
1392 // Pong with null data.
TEST_F(WebSocketChannelEventInterfaceTest,PongWithNullData)1393 TEST_F(WebSocketChannelEventInterfaceTest, PongWithNullData) {
1394 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1395 static const InitFrame frames[] = {
1396 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, nullptr}};
1397 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
1398 set_stream(std::move(stream));
1399 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1400
1401 CreateChannelAndConnectSuccessfully();
1402 base::RunLoop().RunUntilIdle();
1403 }
1404
1405 // If a frame has an invalid header, then the connection is closed and
1406 // subsequent frames must not trigger events.
TEST_F(WebSocketChannelEventInterfaceTest,FrameAfterInvalidFrame)1407 TEST_F(WebSocketChannelEventInterfaceTest, FrameAfterInvalidFrame) {
1408 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1409 static const InitFrame frames[] = {
1410 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"},
1411 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, " WORLD"}};
1412
1413 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
1414 set_stream(std::move(stream));
1415 {
1416 InSequence s;
1417 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1418 EXPECT_CALL(
1419 *event_interface_,
1420 OnFailChannel(
1421 "A server must not mask any frames that it sends to the client.", _,
1422 _));
1423 }
1424
1425 CreateChannelAndConnectSuccessfully();
1426 base::RunLoop().RunUntilIdle();
1427 }
1428
1429 // If a write fails, the channel is dropped.
TEST_F(WebSocketChannelEventInterfaceTest,FailedWrite)1430 TEST_F(WebSocketChannelEventInterfaceTest, FailedWrite) {
1431 set_stream(std::make_unique<UnWriteableFakeWebSocketStream>());
1432 Checkpoint checkpoint;
1433 {
1434 InSequence s;
1435 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1436 EXPECT_CALL(checkpoint, Call(1));
1437 EXPECT_CALL(*event_interface_,
1438 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _));
1439 EXPECT_CALL(checkpoint, Call(2));
1440 }
1441
1442 CreateChannelAndConnectSuccessfully();
1443 checkpoint.Call(1);
1444
1445 EXPECT_EQ(channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
1446 AsIOBuffer("H"), 1U),
1447 WebSocketChannel::CHANNEL_DELETED);
1448 checkpoint.Call(2);
1449 }
1450
1451 // OnDropChannel() is called exactly once when StartClosingHandshake() is used.
TEST_F(WebSocketChannelEventInterfaceTest,SendCloseDropsChannel)1452 TEST_F(WebSocketChannelEventInterfaceTest, SendCloseDropsChannel) {
1453 set_stream(std::make_unique<EchoeyFakeWebSocketStream>());
1454 {
1455 InSequence s;
1456 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1457 EXPECT_CALL(*event_interface_, OnSendDataFrameDone());
1458 EXPECT_CALL(*event_interface_,
1459 OnDropChannel(true, kWebSocketNormalClosure, "Fred"));
1460 }
1461
1462 CreateChannelAndConnectSuccessfully();
1463
1464 ASSERT_EQ(CHANNEL_ALIVE,
1465 channel_->StartClosingHandshake(kWebSocketNormalClosure, "Fred"));
1466 base::RunLoop().RunUntilIdle();
1467 }
1468
1469 // StartClosingHandshake() also works before connection completes, and calls
1470 // OnDropChannel.
TEST_F(WebSocketChannelEventInterfaceTest,CloseDuringConnection)1471 TEST_F(WebSocketChannelEventInterfaceTest, CloseDuringConnection) {
1472 EXPECT_CALL(*event_interface_,
1473 OnDropChannel(false, kWebSocketErrorAbnormalClosure, ""));
1474
1475 CreateChannelAndConnect();
1476 ASSERT_EQ(CHANNEL_DELETED,
1477 channel_->StartClosingHandshake(kWebSocketNormalClosure, "Joe"));
1478 }
1479
1480 // OnDropChannel() is only called once when a write() on the socket triggers a
1481 // connection reset.
TEST_F(WebSocketChannelEventInterfaceTest,OnDropChannelCalledOnce)1482 TEST_F(WebSocketChannelEventInterfaceTest, OnDropChannelCalledOnce) {
1483 set_stream(std::make_unique<ResetOnWriteFakeWebSocketStream>());
1484 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1485
1486 EXPECT_CALL(*event_interface_,
1487 OnDropChannel(false, kWebSocketErrorAbnormalClosure, ""))
1488 .Times(1);
1489
1490 CreateChannelAndConnectSuccessfully();
1491
1492 EXPECT_EQ(channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
1493 AsIOBuffer("yt?"), 3U),
1494 WebSocketChannel::CHANNEL_ALIVE);
1495 base::RunLoop().RunUntilIdle();
1496 }
1497
1498 // When the remote server sends a Close frame with an empty payload,
1499 // WebSocketChannel should report code 1005, kWebSocketErrorNoStatusReceived.
TEST_F(WebSocketChannelEventInterfaceTest,CloseWithNoPayloadGivesStatus1005)1500 TEST_F(WebSocketChannelEventInterfaceTest, CloseWithNoPayloadGivesStatus1005) {
1501 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1502 static const InitFrame frames[] = {
1503 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, ""}};
1504 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1505 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1506 ERR_CONNECTION_CLOSED);
1507 set_stream(std::move(stream));
1508 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1509 EXPECT_CALL(*event_interface_, OnClosingHandshake());
1510 EXPECT_CALL(*event_interface_,
1511 OnDropChannel(true, kWebSocketErrorNoStatusReceived, _));
1512
1513 CreateChannelAndConnectSuccessfully();
1514 }
1515
1516 // A version of the above test with null payload.
TEST_F(WebSocketChannelEventInterfaceTest,CloseWithNullPayloadGivesStatus1005)1517 TEST_F(WebSocketChannelEventInterfaceTest,
1518 CloseWithNullPayloadGivesStatus1005) {
1519 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1520 static const InitFrame frames[] = {
1521 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, nullptr}};
1522 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1523 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1524 ERR_CONNECTION_CLOSED);
1525 set_stream(std::move(stream));
1526 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1527 EXPECT_CALL(*event_interface_, OnClosingHandshake());
1528 EXPECT_CALL(*event_interface_,
1529 OnDropChannel(true, kWebSocketErrorNoStatusReceived, _));
1530
1531 CreateChannelAndConnectSuccessfully();
1532 }
1533
1534 // If ReadFrames() returns ERR_WS_PROTOCOL_ERROR, then the connection must be
1535 // failed.
TEST_F(WebSocketChannelEventInterfaceTest,SyncProtocolErrorGivesStatus1002)1536 TEST_F(WebSocketChannelEventInterfaceTest, SyncProtocolErrorGivesStatus1002) {
1537 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1538 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1539 ERR_WS_PROTOCOL_ERROR);
1540 set_stream(std::move(stream));
1541 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1542
1543 EXPECT_CALL(*event_interface_, OnFailChannel("Invalid frame header", _, _));
1544
1545 CreateChannelAndConnectSuccessfully();
1546 }
1547
1548 // Async version of above test.
TEST_F(WebSocketChannelEventInterfaceTest,AsyncProtocolErrorGivesStatus1002)1549 TEST_F(WebSocketChannelEventInterfaceTest, AsyncProtocolErrorGivesStatus1002) {
1550 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1551 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
1552 ERR_WS_PROTOCOL_ERROR);
1553 set_stream(std::move(stream));
1554 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1555 EXPECT_CALL(*event_interface_, OnFailChannel("Invalid frame header", _, _));
1556
1557 CreateChannelAndConnectSuccessfully();
1558 base::RunLoop().RunUntilIdle();
1559 }
1560
TEST_F(WebSocketChannelEventInterfaceTest,StartHandshakeRequest)1561 TEST_F(WebSocketChannelEventInterfaceTest, StartHandshakeRequest) {
1562 {
1563 InSequence s;
1564 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1565 EXPECT_CALL(*event_interface_, OnStartOpeningHandshakeCalled());
1566 }
1567
1568 CreateChannelAndConnectSuccessfully();
1569
1570 auto request_info = std::make_unique<WebSocketHandshakeRequestInfo>(
1571 GURL("ws://www.example.com/"), base::Time());
1572 connect_data_.argument_saver.connect_delegate->OnStartOpeningHandshake(
1573 std::move(request_info));
1574
1575 base::RunLoop().RunUntilIdle();
1576 }
1577
TEST_F(WebSocketChannelEventInterfaceTest,FailJustAfterHandshake)1578 TEST_F(WebSocketChannelEventInterfaceTest, FailJustAfterHandshake) {
1579 {
1580 InSequence s;
1581 EXPECT_CALL(*event_interface_, OnStartOpeningHandshakeCalled());
1582 EXPECT_CALL(*event_interface_, OnFailChannel("bye", _, _));
1583 }
1584
1585 CreateChannelAndConnect();
1586
1587 WebSocketStream::ConnectDelegate* connect_delegate =
1588 connect_data_.argument_saver.connect_delegate.get();
1589 GURL url("ws://www.example.com/");
1590 auto request_info =
1591 std::make_unique<WebSocketHandshakeRequestInfo>(url, base::Time());
1592 auto response_headers =
1593 base::MakeRefCounted<HttpResponseHeaders>("HTTP/1.1 200 OK");
1594 auto response_info = std::make_unique<WebSocketHandshakeResponseInfo>(
1595 url, response_headers, IPEndPoint(), base::Time());
1596 connect_delegate->OnStartOpeningHandshake(std::move(request_info));
1597
1598 connect_delegate->OnFailure("bye", ERR_FAILED, absl::nullopt);
1599 base::RunLoop().RunUntilIdle();
1600 }
1601
1602 // Any frame after close is invalid. This test uses a Text frame. See also
1603 // test "PingAfterCloseIfRejected".
TEST_F(WebSocketChannelEventInterfaceTest,DataAfterCloseIsRejected)1604 TEST_F(WebSocketChannelEventInterfaceTest, DataAfterCloseIsRejected) {
1605 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1606 static const InitFrame frames[] = {
1607 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED,
1608 CLOSE_DATA(NORMAL_CLOSURE, "OK")},
1609 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "Payload"}};
1610 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1611 set_stream(std::move(stream));
1612 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1613
1614 {
1615 InSequence s;
1616 EXPECT_CALL(*event_interface_, OnClosingHandshake());
1617 EXPECT_CALL(*event_interface_,
1618 OnFailChannel("Data frame received after close", _, _));
1619 }
1620
1621 CreateChannelAndConnectSuccessfully();
1622 }
1623
1624 // A Close frame with a one-byte payload elicits a specific console error
1625 // message.
TEST_F(WebSocketChannelEventInterfaceTest,OneByteClosePayloadMessage)1626 TEST_F(WebSocketChannelEventInterfaceTest, OneByteClosePayloadMessage) {
1627 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1628 static const InitFrame frames[] = {
1629 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, "\x03"}};
1630 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1631 set_stream(std::move(stream));
1632 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1633 EXPECT_CALL(
1634 *event_interface_,
1635 OnFailChannel(
1636 "Received a broken close frame containing an invalid size body.", _,
1637 _));
1638
1639 CreateChannelAndConnectSuccessfully();
1640 }
1641
1642 // A Close frame with a reserved status code also elicits a specific console
1643 // error message.
TEST_F(WebSocketChannelEventInterfaceTest,ClosePayloadReservedStatusMessage)1644 TEST_F(WebSocketChannelEventInterfaceTest, ClosePayloadReservedStatusMessage) {
1645 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1646 static const InitFrame frames[] = {
1647 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1648 NOT_MASKED, CLOSE_DATA(ABNORMAL_CLOSURE, "Not valid on wire")}};
1649 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1650 set_stream(std::move(stream));
1651 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1652 EXPECT_CALL(
1653 *event_interface_,
1654 OnFailChannel(
1655 "Received a broken close frame containing a reserved status code.", _,
1656 _));
1657
1658 CreateChannelAndConnectSuccessfully();
1659 }
1660
1661 // A Close frame with invalid UTF-8 also elicits a specific console error
1662 // message.
TEST_F(WebSocketChannelEventInterfaceTest,ClosePayloadInvalidReason)1663 TEST_F(WebSocketChannelEventInterfaceTest, ClosePayloadInvalidReason) {
1664 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1665 static const InitFrame frames[] = {
1666 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1667 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "\xFF")}};
1668 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1669 set_stream(std::move(stream));
1670 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1671 EXPECT_CALL(
1672 *event_interface_,
1673 OnFailChannel("Received a broken close frame containing invalid UTF-8.",
1674 _, _));
1675
1676 CreateChannelAndConnectSuccessfully();
1677 }
1678
1679 // The reserved bits must all be clear on received frames. Extensions should
1680 // clear the bits when they are set correctly before passing on the frame.
TEST_F(WebSocketChannelEventInterfaceTest,ReservedBitsMustNotBeSet)1681 TEST_F(WebSocketChannelEventInterfaceTest, ReservedBitsMustNotBeSet) {
1682 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1683 static const InitFrame frames[] = {
1684 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
1685 NOT_MASKED, "sakana"}};
1686 // It is not worth adding support for reserved bits to InitFrame just for this
1687 // one test, so set the bit manually.
1688 std::vector<std::unique_ptr<WebSocketFrame>> raw_frames =
1689 CreateFrameVector(frames, &result_frame_data_);
1690 raw_frames[0]->header.reserved1 = true;
1691 stream->PrepareRawReadFrames(ReadableFakeWebSocketStream::SYNC, OK,
1692 std::move(raw_frames));
1693 set_stream(std::move(stream));
1694 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1695 EXPECT_CALL(*event_interface_,
1696 OnFailChannel("One or more reserved bits are on: reserved1 = 1, "
1697 "reserved2 = 0, reserved3 = 0",
1698 _, _));
1699
1700 CreateChannelAndConnectSuccessfully();
1701 }
1702
1703 // The closing handshake times out and sends an OnDropChannel event if no
1704 // response to the client Close message is received.
TEST_F(WebSocketChannelEventInterfaceTest,ClientInitiatedClosingHandshakeTimesOut)1705 TEST_F(WebSocketChannelEventInterfaceTest,
1706 ClientInitiatedClosingHandshakeTimesOut) {
1707 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1708 stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
1709 ERR_IO_PENDING);
1710 set_stream(std::move(stream));
1711 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1712 // This checkpoint object verifies that the OnDropChannel message comes after
1713 // the timeout.
1714 Checkpoint checkpoint;
1715 TestClosure completion;
1716 {
1717 InSequence s;
1718 EXPECT_CALL(checkpoint, Call(1));
1719 EXPECT_CALL(*event_interface_,
1720 OnDropChannel(false, kWebSocketErrorAbnormalClosure, _))
1721 .WillOnce(InvokeClosure(&completion));
1722 }
1723 CreateChannelAndConnectSuccessfully();
1724 // OneShotTimer is not very friendly to testing; there is no apparent way to
1725 // set an expectation on it. Instead the tests need to infer that the timeout
1726 // was fired by the behaviour of the WebSocketChannel object.
1727 channel_->SetClosingHandshakeTimeoutForTesting(
1728 base::Milliseconds(kVeryTinyTimeoutMillis));
1729 channel_->SetUnderlyingConnectionCloseTimeoutForTesting(
1730 base::Milliseconds(kVeryBigTimeoutMillis));
1731 ASSERT_EQ(CHANNEL_ALIVE,
1732 channel_->StartClosingHandshake(kWebSocketNormalClosure, ""));
1733 checkpoint.Call(1);
1734 completion.WaitForResult();
1735 }
1736
1737 // The closing handshake times out and sends an OnDropChannel event if a Close
1738 // message is received but the connection isn't closed by the remote host.
TEST_F(WebSocketChannelEventInterfaceTest,ServerInitiatedClosingHandshakeTimesOut)1739 TEST_F(WebSocketChannelEventInterfaceTest,
1740 ServerInitiatedClosingHandshakeTimesOut) {
1741 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1742 static const InitFrame frames[] = {
1743 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1744 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
1745 stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
1746 set_stream(std::move(stream));
1747 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1748 Checkpoint checkpoint;
1749 TestClosure completion;
1750 {
1751 InSequence s;
1752 EXPECT_CALL(checkpoint, Call(1));
1753 EXPECT_CALL(*event_interface_, OnClosingHandshake());
1754 EXPECT_CALL(*event_interface_,
1755 OnDropChannel(true, kWebSocketNormalClosure, _))
1756 .WillOnce(InvokeClosure(&completion));
1757 }
1758 CreateChannelAndConnectSuccessfully();
1759 channel_->SetClosingHandshakeTimeoutForTesting(
1760 base::Milliseconds(kVeryBigTimeoutMillis));
1761 channel_->SetUnderlyingConnectionCloseTimeoutForTesting(
1762 base::Milliseconds(kVeryTinyTimeoutMillis));
1763 checkpoint.Call(1);
1764 completion.WaitForResult();
1765 }
1766
1767 // We should stop calling ReadFrames() when data frames are pending.
TEST_F(WebSocketChannelStreamTest,PendingDataFrameStopsReadFrames)1768 TEST_F(WebSocketChannelStreamTest, PendingDataFrameStopsReadFrames) {
1769 static const InitFrame frames[] = {
1770 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
1771 Checkpoint checkpoint;
1772
1773 {
1774 InSequence s;
1775 EXPECT_CALL(*event_interface_, HasPendingDataFrames())
1776 .WillOnce(Return(false));
1777 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
1778 .WillOnce(ReturnFrames(&frames, &result_frame_data_));
1779 EXPECT_CALL(*event_interface_, HasPendingDataFrames())
1780 .WillOnce(Return(true));
1781 EXPECT_CALL(checkpoint, Call(1));
1782 EXPECT_CALL(*event_interface_, HasPendingDataFrames())
1783 .WillOnce(Return(true));
1784 EXPECT_CALL(checkpoint, Call(2));
1785 EXPECT_CALL(*event_interface_, HasPendingDataFrames())
1786 .WillOnce(Return(false));
1787 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
1788 .WillOnce(Return(ERR_IO_PENDING));
1789 }
1790
1791 CreateChannelAndConnectSuccessfully();
1792 checkpoint.Call(1);
1793 ASSERT_EQ(CHANNEL_ALIVE, channel_->ReadFrames());
1794 checkpoint.Call(2);
1795 ASSERT_EQ(CHANNEL_ALIVE, channel_->ReadFrames());
1796 }
1797
TEST_F(WebSocketChannelEventInterfaceTest,SingleFrameMessage)1798 TEST_F(WebSocketChannelEventInterfaceTest, SingleFrameMessage) {
1799 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1800 static const InitFrame frames[] = {
1801 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
1802 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1803 set_stream(std::move(stream));
1804 {
1805 InSequence s;
1806 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1807 EXPECT_CALL(*event_interface_,
1808 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
1809 AsVector("FOUR")));
1810 }
1811
1812 CreateChannelAndConnectSuccessfully();
1813 ASSERT_EQ(CHANNEL_ALIVE, channel_->ReadFrames());
1814 }
1815
TEST_F(WebSocketChannelEventInterfaceTest,EmptyMessage)1816 TEST_F(WebSocketChannelEventInterfaceTest, EmptyMessage) {
1817 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1818 static const InitFrame frames[] = {
1819 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED,
1820 "FIRST MESSAGE"},
1821 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, nullptr},
1822 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED,
1823 "THIRD MESSAGE"}};
1824 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1825 set_stream(std::move(stream));
1826 {
1827 InSequence s;
1828 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1829 EXPECT_CALL(*event_interface_,
1830 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
1831 AsVector("FIRST MESSAGE")));
1832 EXPECT_CALL(*event_interface_,
1833 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
1834 AsVector("")));
1835 EXPECT_CALL(*event_interface_,
1836 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
1837 AsVector("THIRD MESSAGE")));
1838 }
1839
1840 CreateChannelAndConnectSuccessfully();
1841 ASSERT_EQ(CHANNEL_ALIVE, channel_->ReadFrames());
1842 }
1843
1844 // A close frame should not overtake data frames.
TEST_F(WebSocketChannelEventInterfaceTest,CloseFrameShouldNotOvertakeDataFrames)1845 TEST_F(WebSocketChannelEventInterfaceTest,
1846 CloseFrameShouldNotOvertakeDataFrames) {
1847 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
1848 static const InitFrame frames[] = {
1849 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED,
1850 "FIRST "},
1851 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED,
1852 "MESSAGE"},
1853 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED,
1854 "SECOND "},
1855 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED,
1856 CLOSE_DATA(NORMAL_CLOSURE, "GOOD BYE")},
1857 };
1858 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
1859 set_stream(std::move(stream));
1860 Checkpoint checkpoint;
1861 InSequence s;
1862 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
1863 EXPECT_CALL(*event_interface_, HasPendingDataFrames()).WillOnce(Return(true));
1864 EXPECT_CALL(checkpoint, Call(1));
1865 EXPECT_CALL(*event_interface_, HasPendingDataFrames())
1866 .WillOnce(Return(false));
1867 EXPECT_CALL(*event_interface_,
1868 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
1869 AsVector("FIRST ")));
1870 EXPECT_CALL(*event_interface_,
1871 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
1872 AsVector("MESSAGE")));
1873 EXPECT_CALL(*event_interface_,
1874 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
1875 AsVector("SECOND ")));
1876 EXPECT_CALL(*event_interface_, OnClosingHandshake());
1877
1878 CreateChannelAndConnectSuccessfully();
1879 checkpoint.Call(1);
1880 ASSERT_EQ(CHANNEL_ALIVE, channel_->ReadFrames());
1881 }
1882
1883 // RFC6455 5.1 "a client MUST mask all frames that it sends to the server".
1884 // WebSocketChannel actually only sets the mask bit in the header, it doesn't
1885 // perform masking itself (not all transports actually use masking).
TEST_F(WebSocketChannelStreamTest,SentFramesAreMasked)1886 TEST_F(WebSocketChannelStreamTest, SentFramesAreMasked) {
1887 static const InitFrame expected[] = {
1888 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
1889 MASKED, "NEEDS MASKING"}};
1890 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
1891 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
1892 .WillOnce(Return(OK));
1893
1894 CreateChannelAndConnectSuccessfully();
1895 EXPECT_EQ(channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
1896 AsIOBuffer("NEEDS MASKING"), 13U),
1897 WebSocketChannel::CHANNEL_ALIVE);
1898 }
1899
1900 // RFC6455 5.5.1 "The application MUST NOT send any more data frames after
1901 // sending a Close frame."
TEST_F(WebSocketChannelStreamTest,NothingIsSentAfterClose)1902 TEST_F(WebSocketChannelStreamTest, NothingIsSentAfterClose) {
1903 static const InitFrame expected[] = {
1904 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1905 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Success")}};
1906 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
1907 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
1908 .WillOnce(Return(OK));
1909
1910 CreateChannelAndConnectSuccessfully();
1911 ASSERT_EQ(CHANNEL_ALIVE, channel_->StartClosingHandshake(1000, "Success"));
1912 EXPECT_EQ(channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
1913 AsIOBuffer("SHOULD BE IGNORED"), 18U),
1914 WebSocketChannel::CHANNEL_ALIVE);
1915 }
1916
1917 // RFC6455 5.5.1 "If an endpoint receives a Close frame and did not previously
1918 // send a Close frame, the endpoint MUST send a Close frame in response."
TEST_F(WebSocketChannelStreamTest,CloseIsEchoedBack)1919 TEST_F(WebSocketChannelStreamTest, CloseIsEchoedBack) {
1920 static const InitFrame frames[] = {
1921 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1922 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
1923 static const InitFrame expected[] = {
1924 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1925 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
1926 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
1927 .WillOnce(ReturnFrames(&frames, &result_frame_data_))
1928 .WillRepeatedly(Return(ERR_IO_PENDING));
1929 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
1930 .WillOnce(Return(OK));
1931
1932 CreateChannelAndConnectSuccessfully();
1933 }
1934
1935 // The converse of the above case; after sending a Close frame, we should not
1936 // send another one.
TEST_F(WebSocketChannelStreamTest,CloseOnlySentOnce)1937 TEST_F(WebSocketChannelStreamTest, CloseOnlySentOnce) {
1938 static const InitFrame expected[] = {
1939 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1940 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
1941 static const InitFrame frames_init[] = {
1942 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1943 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
1944
1945 // We store the parameters that were passed to ReadFrames() so that we can
1946 // call them explicitly later.
1947 CompletionOnceCallback read_callback;
1948 std::vector<std::unique_ptr<WebSocketFrame>>* frames = nullptr;
1949
1950 // Use a checkpoint to make the ordering of events clearer.
1951 Checkpoint checkpoint;
1952 {
1953 InSequence s;
1954 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce([&](auto f, auto cb) {
1955 frames = f;
1956 read_callback = std::move(cb);
1957 return ERR_IO_PENDING;
1958 });
1959 EXPECT_CALL(checkpoint, Call(1));
1960 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
1961 .WillOnce(Return(OK));
1962 EXPECT_CALL(checkpoint, Call(2));
1963 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
1964 .WillOnce(Return(ERR_IO_PENDING));
1965 EXPECT_CALL(checkpoint, Call(3));
1966 // WriteFrames() must not be called again. GoogleMock will ensure that the
1967 // test fails if it is.
1968 }
1969
1970 CreateChannelAndConnectSuccessfully();
1971 checkpoint.Call(1);
1972 ASSERT_EQ(CHANNEL_ALIVE,
1973 channel_->StartClosingHandshake(kWebSocketNormalClosure, "Close"));
1974 checkpoint.Call(2);
1975 ASSERT_TRUE(frames);
1976 *frames = CreateFrameVector(frames_init, &result_frame_data_);
1977 std::move(read_callback).Run(OK);
1978 checkpoint.Call(3);
1979 }
1980
1981 // Invalid close status codes should not be sent on the network.
TEST_F(WebSocketChannelStreamTest,InvalidCloseStatusCodeNotSent)1982 TEST_F(WebSocketChannelStreamTest, InvalidCloseStatusCodeNotSent) {
1983 static const InitFrame expected[] = {
1984 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
1985 MASKED, CLOSE_DATA(SERVER_ERROR, "")}};
1986
1987 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
1988
1989 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _));
1990
1991 CreateChannelAndConnectSuccessfully();
1992 ASSERT_EQ(CHANNEL_ALIVE, channel_->StartClosingHandshake(999, ""));
1993 }
1994
1995 // A Close frame with a reason longer than 123 bytes cannot be sent on the
1996 // network.
TEST_F(WebSocketChannelStreamTest,LongCloseReasonNotSent)1997 TEST_F(WebSocketChannelStreamTest, LongCloseReasonNotSent) {
1998 static const InitFrame expected[] = {
1999 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2000 MASKED, CLOSE_DATA(SERVER_ERROR, "")}};
2001
2002 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
2003
2004 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _));
2005
2006 CreateChannelAndConnectSuccessfully();
2007 ASSERT_EQ(CHANNEL_ALIVE,
2008 channel_->StartClosingHandshake(1000, std::string(124, 'A')));
2009 }
2010
2011 // We generate code 1005, kWebSocketErrorNoStatusReceived, when there is no
2012 // status in the Close message from the other side. Code 1005 is not allowed to
2013 // appear on the wire, so we should not echo it back. See test
2014 // CloseWithNoPayloadGivesStatus1005, above, for confirmation that code 1005 is
2015 // correctly generated internally.
TEST_F(WebSocketChannelStreamTest,Code1005IsNotEchoed)2016 TEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoed) {
2017 static const InitFrame frames[] = {
2018 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, ""}};
2019 static const InitFrame expected[] = {
2020 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, ""}};
2021 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2022 .WillOnce(ReturnFrames(&frames, &result_frame_data_))
2023 .WillRepeatedly(Return(ERR_IO_PENDING));
2024 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2025 .WillOnce(Return(OK));
2026
2027 CreateChannelAndConnectSuccessfully();
2028 }
2029
TEST_F(WebSocketChannelStreamTest,Code1005IsNotEchoedNull)2030 TEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoedNull) {
2031 static const InitFrame frames[] = {
2032 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, nullptr}};
2033 static const InitFrame expected[] = {
2034 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, ""}};
2035 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2036 .WillOnce(ReturnFrames(&frames, &result_frame_data_))
2037 .WillRepeatedly(Return(ERR_IO_PENDING));
2038 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2039 .WillOnce(Return(OK));
2040
2041 CreateChannelAndConnectSuccessfully();
2042 }
2043
2044 // Receiving an invalid UTF-8 payload in a Close frame causes us to fail the
2045 // connection.
TEST_F(WebSocketChannelStreamTest,CloseFrameInvalidUtf8)2046 TEST_F(WebSocketChannelStreamTest, CloseFrameInvalidUtf8) {
2047 static const InitFrame frames[] = {
2048 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2049 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "\xFF")}};
2050 static const InitFrame expected[] = {
2051 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2052 MASKED, CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in Close frame")}};
2053 NetLogWithSource net_log_with_source;
2054
2055 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2056 .WillOnce(ReturnFrames(&frames, &result_frame_data_))
2057 .WillRepeatedly(Return(ERR_IO_PENDING));
2058 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2059 .WillOnce(Return(OK));
2060 EXPECT_CALL(*mock_stream_, GetNetLogWithSource())
2061 .WillOnce(ReturnRef(net_log_with_source));
2062 EXPECT_CALL(*mock_stream_, Close());
2063
2064 CreateChannelAndConnectSuccessfully();
2065 }
2066
2067 // RFC6455 5.5.2 "Upon receipt of a Ping frame, an endpoint MUST send a Pong
2068 // frame in response"
2069 // 5.5.3 "A Pong frame sent in response to a Ping frame must have identical
2070 // "Application data" as found in the message body of the Ping frame being
2071 // replied to."
TEST_F(WebSocketChannelStreamTest,PingRepliedWithPong)2072 TEST_F(WebSocketChannelStreamTest, PingRepliedWithPong) {
2073 static const InitFrame frames[] = {
2074 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
2075 NOT_MASKED, "Application data"}};
2076 static const InitFrame expected[] = {
2077 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong,
2078 MASKED, "Application data"}};
2079 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2080 .WillOnce(ReturnFrames(&frames, &result_frame_data_))
2081 .WillRepeatedly(Return(ERR_IO_PENDING));
2082 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2083 .WillOnce(Return(OK));
2084
2085 CreateChannelAndConnectSuccessfully();
2086 }
2087
2088 // A ping with a null payload should be responded to with a Pong with a null
2089 // payload.
TEST_F(WebSocketChannelStreamTest,NullPingRepliedWithNullPong)2090 TEST_F(WebSocketChannelStreamTest, NullPingRepliedWithNullPong) {
2091 static const InitFrame frames[] = {
2092 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, nullptr}};
2093 static const InitFrame expected[] = {
2094 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, MASKED, nullptr}};
2095 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2096 .WillOnce(ReturnFrames(&frames, &result_frame_data_))
2097 .WillRepeatedly(Return(ERR_IO_PENDING));
2098 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2099 .WillOnce(Return(OK));
2100
2101 CreateChannelAndConnectSuccessfully();
2102 }
2103
TEST_F(WebSocketChannelStreamTest,PongInTheMiddleOfDataMessage)2104 TEST_F(WebSocketChannelStreamTest, PongInTheMiddleOfDataMessage) {
2105 static const InitFrame frames[] = {
2106 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
2107 NOT_MASKED, "Application data"}};
2108 static const InitFrame expected1[] = {
2109 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "Hello "}};
2110 static const InitFrame expected2[] = {
2111 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong,
2112 MASKED, "Application data"}};
2113 static const InitFrame expected3[] = {
2114 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2115 MASKED, "World"}};
2116 std::vector<std::unique_ptr<WebSocketFrame>>* read_frames;
2117 CompletionOnceCallback read_callback;
2118 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2119 .WillOnce([&](auto frames, auto cb) {
2120 read_frames = std::move(frames);
2121 read_callback = std::move(cb);
2122 return ERR_IO_PENDING;
2123 })
2124 .WillRepeatedly(Return(ERR_IO_PENDING));
2125 {
2126 InSequence s;
2127
2128 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
2129 .WillOnce(Return(OK));
2130 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
2131 .WillOnce(Return(OK));
2132 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected3), _))
2133 .WillOnce(Return(OK));
2134 }
2135
2136 CreateChannelAndConnectSuccessfully();
2137 EXPECT_EQ(channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
2138 AsIOBuffer("Hello "), 6U),
2139 WebSocketChannel::CHANNEL_ALIVE);
2140 *read_frames = CreateFrameVector(frames, &result_frame_data_);
2141 std::move(read_callback).Run(OK);
2142 EXPECT_EQ(channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
2143 AsIOBuffer("World"), 5U),
2144 WebSocketChannel::CHANNEL_ALIVE);
2145 }
2146
2147 // WriteFrames() may not be called until the previous write has completed.
2148 // WebSocketChannel must buffer writes that happen in the meantime.
TEST_F(WebSocketChannelStreamTest,WriteFramesOneAtATime)2149 TEST_F(WebSocketChannelStreamTest, WriteFramesOneAtATime) {
2150 static const InitFrame expected1[] = {
2151 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "Hello "}};
2152 static const InitFrame expected2[] = {
2153 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "World"}};
2154 CompletionOnceCallback write_callback;
2155 Checkpoint checkpoint;
2156
2157 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
2158 {
2159 InSequence s;
2160 EXPECT_CALL(checkpoint, Call(1));
2161 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
2162 .WillOnce([&](auto, auto cb) {
2163 write_callback = std::move(cb);
2164 return ERR_IO_PENDING;
2165 });
2166 EXPECT_CALL(checkpoint, Call(2));
2167 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
2168 .WillOnce(Return(ERR_IO_PENDING));
2169 EXPECT_CALL(checkpoint, Call(3));
2170 }
2171
2172 CreateChannelAndConnectSuccessfully();
2173 checkpoint.Call(1);
2174 EXPECT_EQ(channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
2175 AsIOBuffer("Hello "), 6U),
2176 WebSocketChannel::CHANNEL_ALIVE);
2177 EXPECT_EQ(channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
2178 AsIOBuffer("World"), 5U),
2179 WebSocketChannel::CHANNEL_ALIVE);
2180 checkpoint.Call(2);
2181 std::move(write_callback).Run(OK);
2182 checkpoint.Call(3);
2183 }
2184
2185 // WebSocketChannel must buffer frames while it is waiting for a write to
2186 // complete, and then send them in a single batch. The batching behaviour is
2187 // important to get good throughput in the "many small messages" case.
TEST_F(WebSocketChannelStreamTest,WaitingMessagesAreBatched)2188 TEST_F(WebSocketChannelStreamTest, WaitingMessagesAreBatched) {
2189 static const char input_letters[] = "Hello";
2190 static const InitFrame expected1[] = {
2191 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "H"}};
2192 static const InitFrame expected2[] = {
2193 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "e"},
2194 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "l"},
2195 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "l"},
2196 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "o"}};
2197 CompletionOnceCallback write_callback;
2198
2199 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
2200 {
2201 InSequence s;
2202 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
2203 .WillOnce([&](auto, auto cb) {
2204 write_callback = std::move(cb);
2205 return ERR_IO_PENDING;
2206 });
2207 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
2208 .WillOnce(Return(ERR_IO_PENDING));
2209 }
2210
2211 CreateChannelAndConnectSuccessfully();
2212 for (size_t i = 0; i < strlen(input_letters); ++i) {
2213 EXPECT_EQ(
2214 channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
2215 AsIOBuffer(std::string(1, input_letters[i])), 1U),
2216 WebSocketChannel::CHANNEL_ALIVE);
2217 }
2218 std::move(write_callback).Run(OK);
2219 }
2220
2221 // For convenience, most of these tests use Text frames. However, the WebSocket
2222 // protocol also has Binary frames and those need to be 8-bit clean. For the
2223 // sake of completeness, this test verifies that they are.
TEST_F(WebSocketChannelStreamTest,WrittenBinaryFramesAre8BitClean)2224 TEST_F(WebSocketChannelStreamTest, WrittenBinaryFramesAre8BitClean) {
2225 std::vector<std::unique_ptr<WebSocketFrame>>* frames = nullptr;
2226
2227 EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
2228 EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
2229 .WillOnce(DoAll(SaveArg<0>(&frames), Return(ERR_IO_PENDING)));
2230
2231 CreateChannelAndConnectSuccessfully();
2232 EXPECT_EQ(
2233 channel_->SendFrame(
2234 true, WebSocketFrameHeader::kOpCodeBinary,
2235 AsIOBuffer(std::string(kBinaryBlob, kBinaryBlob + kBinaryBlobSize)),
2236 kBinaryBlobSize),
2237 WebSocketChannel::CHANNEL_ALIVE);
2238 ASSERT_TRUE(frames != nullptr);
2239 ASSERT_EQ(1U, frames->size());
2240 const WebSocketFrame* out_frame = (*frames)[0].get();
2241 EXPECT_EQ(kBinaryBlobSize, out_frame->header.payload_length);
2242 ASSERT_TRUE(out_frame->payload);
2243 EXPECT_EQ(0, memcmp(kBinaryBlob, out_frame->payload, kBinaryBlobSize));
2244 }
2245
2246 // Test the read path for 8-bit cleanliness as well.
TEST_F(WebSocketChannelEventInterfaceTest,ReadBinaryFramesAre8BitClean)2247 TEST_F(WebSocketChannelEventInterfaceTest, ReadBinaryFramesAre8BitClean) {
2248 auto frame =
2249 std::make_unique<WebSocketFrame>(WebSocketFrameHeader::kOpCodeBinary);
2250 WebSocketFrameHeader& frame_header = frame->header;
2251 frame_header.final = true;
2252 frame_header.payload_length = kBinaryBlobSize;
2253 auto buffer = base::MakeRefCounted<IOBufferWithSize>(kBinaryBlobSize);
2254 memcpy(buffer->data(), kBinaryBlob, kBinaryBlobSize);
2255 frame->payload = buffer->data();
2256 std::vector<std::unique_ptr<WebSocketFrame>> frames;
2257 frames.push_back(std::move(frame));
2258 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
2259 stream->PrepareRawReadFrames(ReadableFakeWebSocketStream::SYNC, OK,
2260 std::move(frames));
2261 set_stream(std::move(stream));
2262 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
2263 EXPECT_CALL(
2264 *event_interface_,
2265 OnDataFrameVector(
2266 true, WebSocketFrameHeader::kOpCodeBinary,
2267 std::vector<char>(kBinaryBlob, kBinaryBlob + kBinaryBlobSize)));
2268
2269 CreateChannelAndConnectSuccessfully();
2270 }
2271
2272 // Invalid UTF-8 is not permitted in Text frames.
TEST_F(WebSocketChannelSendUtf8Test,InvalidUtf8Rejected)2273 TEST_F(WebSocketChannelSendUtf8Test, InvalidUtf8Rejected) {
2274 EXPECT_CALL(*event_interface_,
2275 OnFailChannel(
2276 "Browser sent a text frame containing invalid UTF-8", _, _));
2277
2278 CreateChannelAndConnectSuccessfully();
2279
2280 EXPECT_EQ(channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
2281 AsIOBuffer("\xff"), 1U),
2282 WebSocketChannel::CHANNEL_DELETED);
2283 }
2284
2285 // A Text message cannot end with a partial UTF-8 character.
TEST_F(WebSocketChannelSendUtf8Test,IncompleteCharacterInFinalFrame)2286 TEST_F(WebSocketChannelSendUtf8Test, IncompleteCharacterInFinalFrame) {
2287 EXPECT_CALL(*event_interface_,
2288 OnFailChannel(
2289 "Browser sent a text frame containing invalid UTF-8", _, _));
2290
2291 CreateChannelAndConnectSuccessfully();
2292
2293 EXPECT_EQ(channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
2294 AsIOBuffer("\xc2"), 1U),
2295 WebSocketChannel::CHANNEL_DELETED);
2296 }
2297
2298 // A non-final Text frame may end with a partial UTF-8 character (compare to
2299 // previous test).
TEST_F(WebSocketChannelSendUtf8Test,IncompleteCharacterInNonFinalFrame)2300 TEST_F(WebSocketChannelSendUtf8Test, IncompleteCharacterInNonFinalFrame) {
2301 CreateChannelAndConnectSuccessfully();
2302
2303 EXPECT_EQ(channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
2304 AsIOBuffer("\xc2"), 1U),
2305 WebSocketChannel::CHANNEL_ALIVE);
2306 }
2307
2308 // UTF-8 parsing context must be retained between frames.
TEST_F(WebSocketChannelSendUtf8Test,ValidCharacterSplitBetweenFrames)2309 TEST_F(WebSocketChannelSendUtf8Test, ValidCharacterSplitBetweenFrames) {
2310 CreateChannelAndConnectSuccessfully();
2311
2312 EXPECT_EQ(channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
2313 AsIOBuffer("\xf1"), 1U),
2314 WebSocketChannel::CHANNEL_ALIVE);
2315 EXPECT_EQ(channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
2316 AsIOBuffer("\x80\xa0\xbf"), 3U),
2317 WebSocketChannel::CHANNEL_ALIVE);
2318 }
2319
2320 // Similarly, an invalid character should be detected even if split.
TEST_F(WebSocketChannelSendUtf8Test,InvalidCharacterSplit)2321 TEST_F(WebSocketChannelSendUtf8Test, InvalidCharacterSplit) {
2322 EXPECT_CALL(*event_interface_,
2323 OnFailChannel(
2324 "Browser sent a text frame containing invalid UTF-8", _, _));
2325
2326 CreateChannelAndConnectSuccessfully();
2327
2328 EXPECT_EQ(channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
2329 AsIOBuffer("\xe1"), 1U),
2330 WebSocketChannel::CHANNEL_ALIVE);
2331 EXPECT_EQ(channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
2332 AsIOBuffer("\x80\xa0\xbf"), 3U),
2333 WebSocketChannel::CHANNEL_DELETED);
2334 }
2335
2336 // An invalid character must be detected in continuation frames.
TEST_F(WebSocketChannelSendUtf8Test,InvalidByteInContinuation)2337 TEST_F(WebSocketChannelSendUtf8Test, InvalidByteInContinuation) {
2338 EXPECT_CALL(*event_interface_,
2339 OnFailChannel(
2340 "Browser sent a text frame containing invalid UTF-8", _, _));
2341
2342 CreateChannelAndConnectSuccessfully();
2343
2344 EXPECT_EQ(channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
2345 AsIOBuffer("foo"), 3U),
2346 WebSocketChannel::CHANNEL_ALIVE);
2347 EXPECT_EQ(
2348 channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeContinuation,
2349 AsIOBuffer("bar"), 3U),
2350 WebSocketChannel::CHANNEL_ALIVE);
2351 EXPECT_EQ(channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
2352 AsIOBuffer("\xff"), 1U),
2353 WebSocketChannel::CHANNEL_DELETED);
2354 }
2355
2356 // However, continuation frames of a Binary frame will not be tested for UTF-8
2357 // validity.
TEST_F(WebSocketChannelSendUtf8Test,BinaryContinuationNotChecked)2358 TEST_F(WebSocketChannelSendUtf8Test, BinaryContinuationNotChecked) {
2359 CreateChannelAndConnectSuccessfully();
2360
2361 EXPECT_EQ(channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeBinary,
2362 AsIOBuffer("foo"), 3U),
2363 WebSocketChannel::CHANNEL_ALIVE);
2364 EXPECT_EQ(
2365 channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeContinuation,
2366 AsIOBuffer("bar"), 3U),
2367 WebSocketChannel::CHANNEL_ALIVE);
2368 EXPECT_EQ(channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
2369 AsIOBuffer("\xff"), 1U),
2370 WebSocketChannel::CHANNEL_ALIVE);
2371 }
2372
2373 // Multiple text messages can be validated without the validation state getting
2374 // confused.
TEST_F(WebSocketChannelSendUtf8Test,ValidateMultipleTextMessages)2375 TEST_F(WebSocketChannelSendUtf8Test, ValidateMultipleTextMessages) {
2376 CreateChannelAndConnectSuccessfully();
2377
2378 EXPECT_EQ(channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
2379 AsIOBuffer("foo"), 3U),
2380 WebSocketChannel::CHANNEL_ALIVE);
2381 EXPECT_EQ(channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
2382 AsIOBuffer("bar"), 3U),
2383 WebSocketChannel::CHANNEL_ALIVE);
2384 }
2385
2386 // UTF-8 validation is enforced on received Text frames.
TEST_F(WebSocketChannelEventInterfaceTest,ReceivedInvalidUtf8)2387 TEST_F(WebSocketChannelEventInterfaceTest, ReceivedInvalidUtf8) {
2388 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
2389 static const InitFrame frames[] = {
2390 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xff"}};
2391 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
2392 set_stream(std::move(stream));
2393
2394 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
2395 EXPECT_CALL(*event_interface_,
2396 OnFailChannel("Could not decode a text frame as UTF-8.", _, _));
2397
2398 CreateChannelAndConnectSuccessfully();
2399 base::RunLoop().RunUntilIdle();
2400 }
2401
2402 // Invalid UTF-8 is not sent over the network.
TEST_F(WebSocketChannelStreamTest,InvalidUtf8TextFrameNotSent)2403 TEST_F(WebSocketChannelStreamTest, InvalidUtf8TextFrameNotSent) {
2404 static const InitFrame expected[] = {{FINAL_FRAME,
2405 WebSocketFrameHeader::kOpCodeClose,
2406 MASKED, CLOSE_DATA(GOING_AWAY, "")}};
2407 NetLogWithSource net_log_with_source;
2408 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2409 .WillRepeatedly(Return(ERR_IO_PENDING));
2410 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2411 .WillOnce(Return(OK));
2412 EXPECT_CALL(*mock_stream_, GetNetLogWithSource())
2413 .WillOnce(ReturnRef(net_log_with_source));
2414 EXPECT_CALL(*mock_stream_, Close()).Times(1);
2415
2416 CreateChannelAndConnectSuccessfully();
2417
2418 EXPECT_EQ(channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
2419 AsIOBuffer("\xff"), 1U),
2420 WebSocketChannel::CHANNEL_DELETED);
2421 }
2422
2423 // The rest of the tests for receiving invalid UTF-8 test the communication with
2424 // the server. Since there is only one code path, it would be redundant to
2425 // perform the same tests on the EventInterface as well.
2426
2427 // If invalid UTF-8 is received in a Text frame, the connection is failed.
TEST_F(WebSocketChannelReceiveUtf8Test,InvalidTextFrameRejected)2428 TEST_F(WebSocketChannelReceiveUtf8Test, InvalidTextFrameRejected) {
2429 static const InitFrame frames[] = {
2430 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xff"}};
2431 static const InitFrame expected[] = {
2432 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
2433 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
2434 NetLogWithSource net_log_with_source;
2435 {
2436 InSequence s;
2437 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2438 .WillOnce(ReturnFrames(&frames, &result_frame_data_))
2439 .WillRepeatedly(Return(ERR_IO_PENDING));
2440 EXPECT_CALL(*mock_stream_, GetNetLogWithSource())
2441 .WillOnce(ReturnRef(net_log_with_source));
2442 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2443 .WillOnce(Return(OK));
2444 EXPECT_CALL(*mock_stream_, Close()).Times(1);
2445 }
2446
2447 CreateChannelAndConnectSuccessfully();
2448 }
2449
2450 // A received Text message is not permitted to end with a partial UTF-8
2451 // character.
TEST_F(WebSocketChannelReceiveUtf8Test,IncompleteCharacterReceived)2452 TEST_F(WebSocketChannelReceiveUtf8Test, IncompleteCharacterReceived) {
2453 static const InitFrame frames[] = {
2454 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xc2"}};
2455 static const InitFrame expected[] = {
2456 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
2457 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
2458 NetLogWithSource net_log_with_source;
2459 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2460 .WillOnce(ReturnFrames(&frames, &result_frame_data_))
2461 .WillRepeatedly(Return(ERR_IO_PENDING));
2462 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2463 .WillOnce(Return(OK));
2464 EXPECT_CALL(*mock_stream_, GetNetLogWithSource())
2465 .WillOnce(ReturnRef(net_log_with_source));
2466 EXPECT_CALL(*mock_stream_, Close()).Times(1);
2467
2468 CreateChannelAndConnectSuccessfully();
2469 }
2470
2471 // However, a non-final Text frame may end with a partial UTF-8 character.
TEST_F(WebSocketChannelReceiveUtf8Test,IncompleteCharacterIncompleteMessage)2472 TEST_F(WebSocketChannelReceiveUtf8Test, IncompleteCharacterIncompleteMessage) {
2473 static const InitFrame frames[] = {
2474 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xc2"}};
2475 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2476 .WillOnce(ReturnFrames(&frames, &result_frame_data_))
2477 .WillRepeatedly(Return(ERR_IO_PENDING));
2478
2479 CreateChannelAndConnectSuccessfully();
2480 }
2481
2482 // However, it will become an error if it is followed by an empty final frame.
TEST_F(WebSocketChannelReceiveUtf8Test,TricksyIncompleteCharacter)2483 TEST_F(WebSocketChannelReceiveUtf8Test, TricksyIncompleteCharacter) {
2484 static const InitFrame frames[] = {
2485 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xc2"},
2486 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, ""}};
2487 static const InitFrame expected[] = {
2488 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
2489 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
2490 NetLogWithSource net_log_with_source;
2491 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2492 .WillOnce(ReturnFrames(&frames, &result_frame_data_))
2493 .WillRepeatedly(Return(ERR_IO_PENDING));
2494 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2495 .WillOnce(Return(OK));
2496 EXPECT_CALL(*mock_stream_, GetNetLogWithSource())
2497 .WillOnce(ReturnRef(net_log_with_source));
2498 EXPECT_CALL(*mock_stream_, Close()).Times(1);
2499
2500 CreateChannelAndConnectSuccessfully();
2501 }
2502
2503 // UTF-8 parsing context must be retained between received frames of the same
2504 // message.
TEST_F(WebSocketChannelReceiveUtf8Test,ReceivedParsingContextRetained)2505 TEST_F(WebSocketChannelReceiveUtf8Test, ReceivedParsingContextRetained) {
2506 static const InitFrame frames[] = {
2507 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xf1"},
2508 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2509 NOT_MASKED, "\x80\xa0\xbf"}};
2510 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2511 .WillOnce(ReturnFrames(&frames, &result_frame_data_))
2512 .WillRepeatedly(Return(ERR_IO_PENDING));
2513
2514 CreateChannelAndConnectSuccessfully();
2515 }
2516
2517 // An invalid character must be detected even if split between frames.
TEST_F(WebSocketChannelReceiveUtf8Test,SplitInvalidCharacterReceived)2518 TEST_F(WebSocketChannelReceiveUtf8Test, SplitInvalidCharacterReceived) {
2519 static const InitFrame frames[] = {
2520 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xe1"},
2521 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2522 NOT_MASKED, "\x80\xa0\xbf"}};
2523 static const InitFrame expected[] = {
2524 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
2525 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
2526 NetLogWithSource net_log_with_source;
2527 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2528 .WillOnce(ReturnFrames(&frames, &result_frame_data_))
2529 .WillRepeatedly(Return(ERR_IO_PENDING));
2530 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2531 .WillOnce(Return(OK));
2532 EXPECT_CALL(*mock_stream_, GetNetLogWithSource())
2533 .WillOnce(ReturnRef(net_log_with_source));
2534 EXPECT_CALL(*mock_stream_, Close()).Times(1);
2535
2536 CreateChannelAndConnectSuccessfully();
2537 }
2538
2539 // An invalid character received in a continuation frame must be detected.
TEST_F(WebSocketChannelReceiveUtf8Test,InvalidReceivedIncontinuation)2540 TEST_F(WebSocketChannelReceiveUtf8Test, InvalidReceivedIncontinuation) {
2541 static const InitFrame frames[] = {
2542 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "foo"},
2543 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2544 NOT_MASKED, "bar"},
2545 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2546 NOT_MASKED, "\xff"}};
2547 static const InitFrame expected[] = {
2548 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
2549 CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
2550 NetLogWithSource net_log_with_source;
2551 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2552 .WillOnce(ReturnFrames(&frames, &result_frame_data_))
2553 .WillRepeatedly(Return(ERR_IO_PENDING));
2554 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2555 .WillOnce(Return(OK));
2556 EXPECT_CALL(*mock_stream_, GetNetLogWithSource())
2557 .WillOnce(ReturnRef(net_log_with_source));
2558 EXPECT_CALL(*mock_stream_, Close()).Times(1);
2559
2560 CreateChannelAndConnectSuccessfully();
2561 }
2562
2563 // Continuations of binary frames must not be tested for UTF-8 validity.
TEST_F(WebSocketChannelReceiveUtf8Test,ReceivedBinaryNotUtf8Tested)2564 TEST_F(WebSocketChannelReceiveUtf8Test, ReceivedBinaryNotUtf8Tested) {
2565 static const InitFrame frames[] = {
2566 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeBinary, NOT_MASKED, "foo"},
2567 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2568 NOT_MASKED, "bar"},
2569 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2570 NOT_MASKED, "\xff"}};
2571 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2572 .WillOnce(ReturnFrames(&frames, &result_frame_data_))
2573 .WillRepeatedly(Return(ERR_IO_PENDING));
2574
2575 CreateChannelAndConnectSuccessfully();
2576 }
2577
2578 // Multiple Text messages can be validated.
TEST_F(WebSocketChannelReceiveUtf8Test,ValidateMultipleReceived)2579 TEST_F(WebSocketChannelReceiveUtf8Test, ValidateMultipleReceived) {
2580 static const InitFrame frames[] = {
2581 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "foo"},
2582 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "bar"}};
2583 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2584 .WillOnce(ReturnFrames(&frames, &result_frame_data_))
2585 .WillRepeatedly(Return(ERR_IO_PENDING));
2586
2587 CreateChannelAndConnectSuccessfully();
2588 }
2589
2590 // A new data message cannot start in the middle of another data message.
TEST_F(WebSocketChannelEventInterfaceTest,BogusContinuation)2591 TEST_F(WebSocketChannelEventInterfaceTest, BogusContinuation) {
2592 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
2593 static const InitFrame frames[] = {
2594 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeBinary,
2595 NOT_MASKED, "frame1"},
2596 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
2597 NOT_MASKED, "frame2"}};
2598 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
2599 set_stream(std::move(stream));
2600
2601 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
2602 EXPECT_CALL(*event_interface_,
2603 OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeBinary,
2604 AsVector("frame1")));
2605 EXPECT_CALL(
2606 *event_interface_,
2607 OnFailChannel(
2608 "Received start of new message but previous message is unfinished.",
2609 _, _));
2610
2611 CreateChannelAndConnectSuccessfully();
2612 }
2613
2614 // A new message cannot start with a Continuation frame.
TEST_F(WebSocketChannelEventInterfaceTest,MessageStartingWithContinuation)2615 TEST_F(WebSocketChannelEventInterfaceTest, MessageStartingWithContinuation) {
2616 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
2617 static const InitFrame frames[] = {
2618 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2619 NOT_MASKED, "continuation"}};
2620 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
2621 set_stream(std::move(stream));
2622
2623 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
2624 EXPECT_CALL(*event_interface_,
2625 OnFailChannel("Received unexpected continuation frame.", _, _));
2626
2627 CreateChannelAndConnectSuccessfully();
2628 }
2629
2630 // A frame passed to the renderer must be either non-empty or have the final bit
2631 // set.
TEST_F(WebSocketChannelEventInterfaceTest,DataFramesNonEmptyOrFinal)2632 TEST_F(WebSocketChannelEventInterfaceTest, DataFramesNonEmptyOrFinal) {
2633 auto stream = std::make_unique<ReadableFakeWebSocketStream>();
2634 static const InitFrame frames[] = {
2635 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, ""},
2636 {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
2637 NOT_MASKED, ""},
2638 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, ""}};
2639 stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
2640 set_stream(std::move(stream));
2641
2642 EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _));
2643 EXPECT_CALL(
2644 *event_interface_,
2645 OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText, AsVector("")));
2646
2647 CreateChannelAndConnectSuccessfully();
2648 }
2649
2650 // Calls to OnSSLCertificateError() must be passed through to the event
2651 // interface with the correct URL attached.
TEST_F(WebSocketChannelEventInterfaceTest,OnSSLCertificateErrorCalled)2652 TEST_F(WebSocketChannelEventInterfaceTest, OnSSLCertificateErrorCalled) {
2653 const GURL wss_url("wss://example.com/sslerror");
2654 connect_data_.socket_url = wss_url;
2655 const SSLInfo ssl_info;
2656 const bool fatal = true;
2657 auto fake_callbacks = std::make_unique<FakeSSLErrorCallbacks>();
2658
2659 EXPECT_CALL(*event_interface_,
2660 OnSSLCertificateErrorCalled(NotNull(), wss_url, _, fatal));
2661
2662 CreateChannelAndConnect();
2663 connect_data_.argument_saver.connect_delegate->OnSSLCertificateError(
2664 std::move(fake_callbacks), net::ERR_CERT_DATE_INVALID, ssl_info, fatal);
2665 }
2666
2667 // Calls to OnAuthRequired() must be passed through to the event interface.
TEST_F(WebSocketChannelEventInterfaceTest,OnAuthRequiredCalled)2668 TEST_F(WebSocketChannelEventInterfaceTest, OnAuthRequiredCalled) {
2669 const GURL wss_url("wss://example.com/on_auth_required");
2670 connect_data_.socket_url = wss_url;
2671 AuthChallengeInfo auth_info;
2672 absl::optional<AuthCredentials> credentials;
2673 auto response_headers =
2674 base::MakeRefCounted<HttpResponseHeaders>("HTTP/1.1 200 OK");
2675 IPEndPoint remote_endpoint(net::IPAddress(127, 0, 0, 1), 80);
2676
2677 EXPECT_CALL(*event_interface_,
2678 OnAuthRequiredCalled(_, response_headers, _, &credentials))
2679 .WillOnce(Return(OK));
2680
2681 CreateChannelAndConnect();
2682 connect_data_.argument_saver.connect_delegate->OnAuthRequired(
2683 auth_info, response_headers, remote_endpoint, {}, &credentials);
2684 }
2685
2686 // If we receive another frame after Close, it is not valid. It is not
2687 // completely clear what behaviour is required from the standard in this case,
2688 // but the current implementation fails the connection. Since a Close has
2689 // already been sent, this just means closing the connection.
TEST_F(WebSocketChannelStreamTest,PingAfterCloseIsRejected)2690 TEST_F(WebSocketChannelStreamTest, PingAfterCloseIsRejected) {
2691 static const InitFrame frames[] = {
2692 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2693 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")},
2694 {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
2695 NOT_MASKED, "Ping body"}};
2696 static const InitFrame expected[] = {
2697 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2698 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
2699 NetLogWithSource net_log_with_source;
2700 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2701 .WillOnce(ReturnFrames(&frames, &result_frame_data_))
2702 .WillRepeatedly(Return(ERR_IO_PENDING));
2703 EXPECT_CALL(*mock_stream_, GetNetLogWithSource())
2704 .WillOnce(ReturnRef(net_log_with_source));
2705 {
2706 // We only need to verify the relative order of WriteFrames() and
2707 // Close(). The current implementation calls WriteFrames() for the Close
2708 // frame before calling ReadFrames() again, but that is an implementation
2709 // detail and better not to consider required behaviour.
2710 InSequence s;
2711 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2712 .WillOnce(Return(OK));
2713 EXPECT_CALL(*mock_stream_, Close()).Times(1);
2714 }
2715
2716 CreateChannelAndConnectSuccessfully();
2717 }
2718
2719 // A protocol error from the remote server should result in a close frame with
2720 // status 1002, followed by the connection closing.
TEST_F(WebSocketChannelStreamTest,ProtocolError)2721 TEST_F(WebSocketChannelStreamTest, ProtocolError) {
2722 static const InitFrame expected[] = {
2723 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2724 MASKED, CLOSE_DATA(PROTOCOL_ERROR, "WebSocket Protocol Error")}};
2725 NetLogWithSource net_log_with_source;
2726 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2727 .WillOnce(Return(ERR_WS_PROTOCOL_ERROR));
2728 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2729 .WillOnce(Return(OK));
2730 EXPECT_CALL(*mock_stream_, GetNetLogWithSource())
2731 .WillOnce(ReturnRef(net_log_with_source));
2732 EXPECT_CALL(*mock_stream_, Close());
2733
2734 CreateChannelAndConnectSuccessfully();
2735 }
2736
2737 // Set the closing handshake timeout to a very tiny value before connecting.
2738 class WebSocketChannelStreamTimeoutTest : public WebSocketChannelStreamTest {
2739 protected:
2740 WebSocketChannelStreamTimeoutTest() = default;
2741
CreateChannelAndConnectSuccessfully()2742 void CreateChannelAndConnectSuccessfully() override {
2743 set_stream(std::move(mock_stream_));
2744 CreateChannelAndConnect();
2745 channel_->SetClosingHandshakeTimeoutForTesting(
2746 base::Milliseconds(kVeryTinyTimeoutMillis));
2747 channel_->SetUnderlyingConnectionCloseTimeoutForTesting(
2748 base::Milliseconds(kVeryTinyTimeoutMillis));
2749 connect_data_.argument_saver.connect_delegate->OnSuccess(
2750 std::move(stream_), std::make_unique<WebSocketHandshakeResponseInfo>(
2751 GURL(), nullptr, IPEndPoint(), base::Time()));
2752 std::ignore = channel_->ReadFrames();
2753 }
2754 };
2755
2756 // In this case the server initiates the closing handshake with a Close
2757 // message. WebSocketChannel responds with a matching Close message, and waits
2758 // for the server to close the TCP/IP connection. The server never closes the
2759 // connection, so the closing handshake times out and WebSocketChannel closes
2760 // the connection itself.
TEST_F(WebSocketChannelStreamTimeoutTest,ServerInitiatedCloseTimesOut)2761 TEST_F(WebSocketChannelStreamTimeoutTest, ServerInitiatedCloseTimesOut) {
2762 static const InitFrame frames[] = {
2763 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2764 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
2765 static const InitFrame expected[] = {
2766 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2767 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
2768 NetLogWithSource net_log_with_source;
2769 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2770 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2771 EXPECT_CALL(*mock_stream_, GetNetLogWithSource())
2772 .WillOnce(ReturnRef(net_log_with_source));
2773 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2774 .WillOnce(ReturnFrames(&frames, &result_frame_data_))
2775 .WillRepeatedly(Return(ERR_IO_PENDING));
2776 Checkpoint checkpoint;
2777 TestClosure completion;
2778 {
2779 InSequence s;
2780 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2781 .WillOnce(Return(OK));
2782 EXPECT_CALL(checkpoint, Call(1));
2783 EXPECT_CALL(*mock_stream_, Close()).WillOnce(InvokeClosure(&completion));
2784 }
2785
2786 CreateChannelAndConnectSuccessfully();
2787 checkpoint.Call(1);
2788 completion.WaitForResult();
2789 }
2790
2791 // In this case the client initiates the closing handshake by sending a Close
2792 // message. WebSocketChannel waits for a Close message in response from the
2793 // server. The server never responds to the Close message, so the closing
2794 // handshake times out and WebSocketChannel closes the connection.
TEST_F(WebSocketChannelStreamTimeoutTest,ClientInitiatedCloseTimesOut)2795 TEST_F(WebSocketChannelStreamTimeoutTest, ClientInitiatedCloseTimesOut) {
2796 static const InitFrame expected[] = {
2797 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2798 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
2799 NetLogWithSource net_log_with_source;
2800 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2801 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2802 EXPECT_CALL(*mock_stream_, GetNetLogWithSource())
2803 .WillOnce(ReturnRef(net_log_with_source));
2804 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2805 .WillRepeatedly(Return(ERR_IO_PENDING));
2806 TestClosure completion;
2807 {
2808 InSequence s;
2809 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2810 .WillOnce(Return(OK));
2811 EXPECT_CALL(*mock_stream_, Close()).WillOnce(InvokeClosure(&completion));
2812 }
2813
2814 CreateChannelAndConnectSuccessfully();
2815 ASSERT_EQ(CHANNEL_ALIVE,
2816 channel_->StartClosingHandshake(kWebSocketNormalClosure, "OK"));
2817 completion.WaitForResult();
2818 }
2819
2820 // In this case the client initiates the closing handshake and the server
2821 // responds with a matching Close message. WebSocketChannel waits for the server
2822 // to close the TCP/IP connection, but it never does. The closing handshake
2823 // times out and WebSocketChannel closes the connection.
TEST_F(WebSocketChannelStreamTimeoutTest,ConnectionCloseTimesOut)2824 TEST_F(WebSocketChannelStreamTimeoutTest, ConnectionCloseTimesOut) {
2825 static const InitFrame expected[] = {
2826 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2827 MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
2828 static const InitFrame frames[] = {
2829 {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
2830 NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
2831 NetLogWithSource net_log_with_source;
2832 EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
2833 EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
2834 EXPECT_CALL(*mock_stream_, GetNetLogWithSource())
2835 .WillOnce(ReturnRef(net_log_with_source));
2836 TestClosure completion;
2837 std::vector<std::unique_ptr<WebSocketFrame>>* read_frames = nullptr;
2838 CompletionOnceCallback read_callback;
2839 {
2840 InSequence s;
2841 // Copy the arguments to ReadFrames so that the test can call the callback
2842 // after it has send the close message.
2843 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2844 .WillOnce([&](auto frames, auto cb) {
2845 read_frames = frames;
2846 read_callback = std::move(cb);
2847 return ERR_IO_PENDING;
2848 });
2849
2850 // The first real event that happens is the client sending the Close
2851 // message.
2852 EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
2853 .WillOnce(Return(OK));
2854 // The |read_frames| callback is called (from this test case) at this
2855 // point. ReadFrames is called again by WebSocketChannel, waiting for
2856 // ERR_CONNECTION_CLOSED.
2857 EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
2858 .WillOnce(Return(ERR_IO_PENDING));
2859 // The timeout happens and so WebSocketChannel closes the stream.
2860 EXPECT_CALL(*mock_stream_, Close()).WillOnce(InvokeClosure(&completion));
2861 }
2862
2863 CreateChannelAndConnectSuccessfully();
2864 ASSERT_EQ(CHANNEL_ALIVE,
2865 channel_->StartClosingHandshake(kWebSocketNormalClosure, "OK"));
2866 ASSERT_TRUE(read_frames);
2867 // Provide the "Close" message from the server.
2868 *read_frames = CreateFrameVector(frames, &result_frame_data_);
2869 std::move(read_callback).Run(OK);
2870 completion.WaitForResult();
2871 }
2872
2873 } // namespace
2874 } // namespace net
2875