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