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