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