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