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