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_stream.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <algorithm>
8*6777b538SAndroid Build Coastguard Worker #include <iterator>
9*6777b538SAndroid Build Coastguard Worker #include <string>
10*6777b538SAndroid Build Coastguard Worker #include <string_view>
11*6777b538SAndroid Build Coastguard Worker #include <tuple>
12*6777b538SAndroid Build Coastguard Worker #include <utility>
13*6777b538SAndroid Build Coastguard Worker #include <vector>
14*6777b538SAndroid Build Coastguard Worker
15*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/memory/weak_ptr.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_samples.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/run_loop.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/test/metrics/histogram_tester.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/test/scoped_feature_list.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/timer/mock_timer.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/timer/timer.h"
26*6777b538SAndroid Build Coastguard Worker #include "net/base/auth.h"
27*6777b538SAndroid Build Coastguard Worker #include "net/base/features.h"
28*6777b538SAndroid Build Coastguard Worker #include "net/base/isolation_info.h"
29*6777b538SAndroid Build Coastguard Worker #include "net/base/net_errors.h"
30*6777b538SAndroid Build Coastguard Worker #include "net/base/request_priority.h"
31*6777b538SAndroid Build Coastguard Worker #include "net/base/test_completion_callback.h"
32*6777b538SAndroid Build Coastguard Worker #include "net/base/url_util.h"
33*6777b538SAndroid Build Coastguard Worker #include "net/cookies/cookie_setting_override.h"
34*6777b538SAndroid Build Coastguard Worker #include "net/cookies/site_for_cookies.h"
35*6777b538SAndroid Build Coastguard Worker #include "net/http/http_network_session.h"
36*6777b538SAndroid Build Coastguard Worker #include "net/http/http_request_headers.h"
37*6777b538SAndroid Build Coastguard Worker #include "net/http/http_response_headers.h"
38*6777b538SAndroid Build Coastguard Worker #include "net/log/net_log_with_source.h"
39*6777b538SAndroid Build Coastguard Worker #include "net/socket/next_proto.h"
40*6777b538SAndroid Build Coastguard Worker #include "net/socket/socket_test_util.h"
41*6777b538SAndroid Build Coastguard Worker #include "net/spdy/spdy_test_util_common.h"
42*6777b538SAndroid Build Coastguard Worker #include "net/ssl/ssl_info.h"
43*6777b538SAndroid Build Coastguard Worker #include "net/test/cert_test_util.h"
44*6777b538SAndroid Build Coastguard Worker #include "net/test/gtest_util.h"
45*6777b538SAndroid Build Coastguard Worker #include "net/test/test_data_directory.h"
46*6777b538SAndroid Build Coastguard Worker #include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h"
47*6777b538SAndroid Build Coastguard Worker #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h"
48*6777b538SAndroid Build Coastguard Worker #include "net/third_party/quiche/src/quiche/spdy/test_tools/spdy_test_utils.h"
49*6777b538SAndroid Build Coastguard Worker #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
50*6777b538SAndroid Build Coastguard Worker #include "net/url_request/url_request.h"
51*6777b538SAndroid Build Coastguard Worker #include "net/url_request/url_request_context.h"
52*6777b538SAndroid Build Coastguard Worker #include "net/url_request/url_request_test_util.h"
53*6777b538SAndroid Build Coastguard Worker #include "net/websockets/websocket_frame.h"
54*6777b538SAndroid Build Coastguard Worker #include "net/websockets/websocket_handshake_request_info.h"
55*6777b538SAndroid Build Coastguard Worker #include "net/websockets/websocket_handshake_response_info.h"
56*6777b538SAndroid Build Coastguard Worker #include "net/websockets/websocket_handshake_stream_base.h"
57*6777b538SAndroid Build Coastguard Worker #include "net/websockets/websocket_stream_create_test_base.h"
58*6777b538SAndroid Build Coastguard Worker #include "net/websockets/websocket_test_util.h"
59*6777b538SAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock.h"
60*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
61*6777b538SAndroid Build Coastguard Worker #include "url/gurl.h"
62*6777b538SAndroid Build Coastguard Worker #include "url/origin.h"
63*6777b538SAndroid Build Coastguard Worker
64*6777b538SAndroid Build Coastguard Worker using ::net::test::IsError;
65*6777b538SAndroid Build Coastguard Worker using ::net::test::IsOk;
66*6777b538SAndroid Build Coastguard Worker using ::testing::TestWithParam;
67*6777b538SAndroid Build Coastguard Worker using ::testing::Values;
68*6777b538SAndroid Build Coastguard Worker
69*6777b538SAndroid Build Coastguard Worker namespace net {
70*6777b538SAndroid Build Coastguard Worker namespace {
71*6777b538SAndroid Build Coastguard Worker
72*6777b538SAndroid Build Coastguard Worker enum HandshakeStreamType { BASIC_HANDSHAKE_STREAM, HTTP2_HANDSHAKE_STREAM };
73*6777b538SAndroid Build Coastguard Worker
74*6777b538SAndroid Build Coastguard Worker // Simple builder for a SequencedSocketData object to save repetitive code.
75*6777b538SAndroid Build Coastguard Worker // It always sets the connect data to MockConnect(SYNCHRONOUS, OK), so it cannot
76*6777b538SAndroid Build Coastguard Worker // be used in tests where the connect fails. In practice, those tests never have
77*6777b538SAndroid Build Coastguard Worker // any read/write data and so can't benefit from it anyway. The arrays are not
78*6777b538SAndroid Build Coastguard Worker // copied. It is up to the caller to ensure they stay in scope until the test
79*6777b538SAndroid Build Coastguard Worker // ends.
BuildSocketData(base::span<MockRead> reads,base::span<MockWrite> writes)80*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SequencedSocketData> BuildSocketData(
81*6777b538SAndroid Build Coastguard Worker base::span<MockRead> reads,
82*6777b538SAndroid Build Coastguard Worker base::span<MockWrite> writes) {
83*6777b538SAndroid Build Coastguard Worker auto socket_data = std::make_unique<SequencedSocketData>(reads, writes);
84*6777b538SAndroid Build Coastguard Worker socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
85*6777b538SAndroid Build Coastguard Worker return socket_data;
86*6777b538SAndroid Build Coastguard Worker }
87*6777b538SAndroid Build Coastguard Worker
88*6777b538SAndroid Build Coastguard Worker // Builder for a SequencedSocketData that expects nothing. This does not
89*6777b538SAndroid Build Coastguard Worker // set the connect data, so the calling code must do that explicitly.
BuildNullSocketData()90*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SequencedSocketData> BuildNullSocketData() {
91*6777b538SAndroid Build Coastguard Worker return std::make_unique<SequencedSocketData>();
92*6777b538SAndroid Build Coastguard Worker }
93*6777b538SAndroid Build Coastguard Worker
94*6777b538SAndroid Build Coastguard Worker class MockWeakTimer : public base::MockOneShotTimer {
95*6777b538SAndroid Build Coastguard Worker public:
96*6777b538SAndroid Build Coastguard Worker MockWeakTimer() = default;
97*6777b538SAndroid Build Coastguard Worker
AsWeakPtr()98*6777b538SAndroid Build Coastguard Worker base::WeakPtr<MockWeakTimer> AsWeakPtr() {
99*6777b538SAndroid Build Coastguard Worker return weak_ptr_factory_.GetWeakPtr();
100*6777b538SAndroid Build Coastguard Worker }
101*6777b538SAndroid Build Coastguard Worker
102*6777b538SAndroid Build Coastguard Worker private:
103*6777b538SAndroid Build Coastguard Worker base::WeakPtrFactory<MockWeakTimer> weak_ptr_factory_{this};
104*6777b538SAndroid Build Coastguard Worker };
105*6777b538SAndroid Build Coastguard Worker
106*6777b538SAndroid Build Coastguard Worker constexpr char kOrigin[] = "http://www.example.org";
107*6777b538SAndroid Build Coastguard Worker
Origin()108*6777b538SAndroid Build Coastguard Worker static url::Origin Origin() {
109*6777b538SAndroid Build Coastguard Worker return url::Origin::Create(GURL(kOrigin));
110*6777b538SAndroid Build Coastguard Worker }
111*6777b538SAndroid Build Coastguard Worker
SiteForCookies()112*6777b538SAndroid Build Coastguard Worker static net::SiteForCookies SiteForCookies() {
113*6777b538SAndroid Build Coastguard Worker return net::SiteForCookies::FromOrigin(Origin());
114*6777b538SAndroid Build Coastguard Worker }
115*6777b538SAndroid Build Coastguard Worker
CreateIsolationInfo()116*6777b538SAndroid Build Coastguard Worker static IsolationInfo CreateIsolationInfo() {
117*6777b538SAndroid Build Coastguard Worker url::Origin origin = Origin();
118*6777b538SAndroid Build Coastguard Worker return IsolationInfo::Create(IsolationInfo::RequestType::kOther, origin,
119*6777b538SAndroid Build Coastguard Worker origin, SiteForCookies::FromOrigin(origin));
120*6777b538SAndroid Build Coastguard Worker }
121*6777b538SAndroid Build Coastguard Worker
122*6777b538SAndroid Build Coastguard Worker class WebSocketStreamCreateTest
123*6777b538SAndroid Build Coastguard Worker : public TestWithParam<std::tuple<HandshakeStreamType, bool>>,
124*6777b538SAndroid Build Coastguard Worker public WebSocketStreamCreateTestBase {
125*6777b538SAndroid Build Coastguard Worker protected:
WebSocketStreamCreateTest()126*6777b538SAndroid Build Coastguard Worker WebSocketStreamCreateTest()
127*6777b538SAndroid Build Coastguard Worker : stream_type_(std::get<HandshakeStreamType>(GetParam())),
128*6777b538SAndroid Build Coastguard Worker spdy_util_(/*use_priority_header=*/true) {
129*6777b538SAndroid Build Coastguard Worker // Make sure these tests all pass with connection partitioning enabled. The
130*6777b538SAndroid Build Coastguard Worker // disabled case is less interesting, and is tested more directly at lower
131*6777b538SAndroid Build Coastguard Worker // layers.
132*6777b538SAndroid Build Coastguard Worker if (PriorityHeaderEnabled()) {
133*6777b538SAndroid Build Coastguard Worker feature_list_.InitWithFeatures(
134*6777b538SAndroid Build Coastguard Worker {features::kPartitionConnectionsByNetworkIsolationKey,
135*6777b538SAndroid Build Coastguard Worker net::features::kPriorityHeader},
136*6777b538SAndroid Build Coastguard Worker {});
137*6777b538SAndroid Build Coastguard Worker } else {
138*6777b538SAndroid Build Coastguard Worker feature_list_.InitWithFeatures(
139*6777b538SAndroid Build Coastguard Worker {features::kPartitionConnectionsByNetworkIsolationKey},
140*6777b538SAndroid Build Coastguard Worker {net::features::kPriorityHeader});
141*6777b538SAndroid Build Coastguard Worker }
142*6777b538SAndroid Build Coastguard Worker }
143*6777b538SAndroid Build Coastguard Worker
~WebSocketStreamCreateTest()144*6777b538SAndroid Build Coastguard Worker ~WebSocketStreamCreateTest() override {
145*6777b538SAndroid Build Coastguard Worker // Permit any endpoint locks to be released.
146*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
147*6777b538SAndroid Build Coastguard Worker stream_.reset();
148*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
149*6777b538SAndroid Build Coastguard Worker }
150*6777b538SAndroid Build Coastguard Worker
151*6777b538SAndroid Build Coastguard Worker // Normally it's easier to use CreateAndConnectRawExpectations() instead. This
152*6777b538SAndroid Build Coastguard Worker // method is only needed when multiple sockets are involved.
AddRawExpectations(std::unique_ptr<SequencedSocketData> socket_data)153*6777b538SAndroid Build Coastguard Worker void AddRawExpectations(std::unique_ptr<SequencedSocketData> socket_data) {
154*6777b538SAndroid Build Coastguard Worker url_request_context_host_.AddRawExpectations(std::move(socket_data));
155*6777b538SAndroid Build Coastguard Worker }
156*6777b538SAndroid Build Coastguard Worker
AddSSLData()157*6777b538SAndroid Build Coastguard Worker void AddSSLData() {
158*6777b538SAndroid Build Coastguard Worker auto ssl_data = std::make_unique<SSLSocketDataProvider>(ASYNC, OK);
159*6777b538SAndroid Build Coastguard Worker ssl_data->ssl_info.cert =
160*6777b538SAndroid Build Coastguard Worker ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem");
161*6777b538SAndroid Build Coastguard Worker if (stream_type_ == HTTP2_HANDSHAKE_STREAM)
162*6777b538SAndroid Build Coastguard Worker ssl_data->next_proto = kProtoHTTP2;
163*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(ssl_data->ssl_info.cert.get());
164*6777b538SAndroid Build Coastguard Worker url_request_context_host_.AddSSLSocketDataProvider(std::move(ssl_data));
165*6777b538SAndroid Build Coastguard Worker }
166*6777b538SAndroid Build Coastguard Worker
SetTimer(std::unique_ptr<base::OneShotTimer> timer)167*6777b538SAndroid Build Coastguard Worker void SetTimer(std::unique_ptr<base::OneShotTimer> timer) {
168*6777b538SAndroid Build Coastguard Worker timer_ = std::move(timer);
169*6777b538SAndroid Build Coastguard Worker }
170*6777b538SAndroid Build Coastguard Worker
SetAdditionalResponseData(std::string additional_data)171*6777b538SAndroid Build Coastguard Worker void SetAdditionalResponseData(std::string additional_data) {
172*6777b538SAndroid Build Coastguard Worker additional_data_ = std::move(additional_data);
173*6777b538SAndroid Build Coastguard Worker }
174*6777b538SAndroid Build Coastguard Worker
SetHttp2ResponseStatus(const char * const http2_response_status)175*6777b538SAndroid Build Coastguard Worker void SetHttp2ResponseStatus(const char* const http2_response_status) {
176*6777b538SAndroid Build Coastguard Worker http2_response_status_ = http2_response_status;
177*6777b538SAndroid Build Coastguard Worker }
178*6777b538SAndroid Build Coastguard Worker
SetResetWebSocketHttp2Stream(bool reset_websocket_http2_stream)179*6777b538SAndroid Build Coastguard Worker void SetResetWebSocketHttp2Stream(bool reset_websocket_http2_stream) {
180*6777b538SAndroid Build Coastguard Worker reset_websocket_http2_stream_ = reset_websocket_http2_stream;
181*6777b538SAndroid Build Coastguard Worker }
182*6777b538SAndroid Build Coastguard Worker
183*6777b538SAndroid Build Coastguard Worker // Set up mock data and start websockets request, either for WebSocket
184*6777b538SAndroid Build Coastguard Worker // upgraded from an HTTP/1 connection, or for a WebSocket request over HTTP/2.
CreateAndConnectStandard(std::string_view url,const std::vector<std::string> & sub_protocols,const WebSocketExtraHeaders & send_additional_request_headers,const WebSocketExtraHeaders & extra_request_headers,const WebSocketExtraHeaders & extra_response_headers,bool has_storage_access=false)185*6777b538SAndroid Build Coastguard Worker void CreateAndConnectStandard(
186*6777b538SAndroid Build Coastguard Worker std::string_view url,
187*6777b538SAndroid Build Coastguard Worker const std::vector<std::string>& sub_protocols,
188*6777b538SAndroid Build Coastguard Worker const WebSocketExtraHeaders& send_additional_request_headers,
189*6777b538SAndroid Build Coastguard Worker const WebSocketExtraHeaders& extra_request_headers,
190*6777b538SAndroid Build Coastguard Worker const WebSocketExtraHeaders& extra_response_headers,
191*6777b538SAndroid Build Coastguard Worker bool has_storage_access = false) {
192*6777b538SAndroid Build Coastguard Worker const GURL socket_url(url);
193*6777b538SAndroid Build Coastguard Worker const std::string socket_host = GetHostAndOptionalPort(socket_url);
194*6777b538SAndroid Build Coastguard Worker const std::string socket_path = socket_url.path();
195*6777b538SAndroid Build Coastguard Worker
196*6777b538SAndroid Build Coastguard Worker if (stream_type_ == BASIC_HANDSHAKE_STREAM) {
197*6777b538SAndroid Build Coastguard Worker url_request_context_host_.SetExpectations(
198*6777b538SAndroid Build Coastguard Worker WebSocketStandardRequest(socket_path, socket_host, Origin(),
199*6777b538SAndroid Build Coastguard Worker send_additional_request_headers,
200*6777b538SAndroid Build Coastguard Worker extra_request_headers),
201*6777b538SAndroid Build Coastguard Worker WebSocketStandardResponse(
202*6777b538SAndroid Build Coastguard Worker WebSocketExtraHeadersToString(extra_response_headers)) +
203*6777b538SAndroid Build Coastguard Worker additional_data_);
204*6777b538SAndroid Build Coastguard Worker CreateAndConnectStream(socket_url, sub_protocols, Origin(),
205*6777b538SAndroid Build Coastguard Worker SiteForCookies(), has_storage_access,
206*6777b538SAndroid Build Coastguard Worker CreateIsolationInfo(),
207*6777b538SAndroid Build Coastguard Worker WebSocketExtraHeadersToHttpRequestHeaders(
208*6777b538SAndroid Build Coastguard Worker send_additional_request_headers),
209*6777b538SAndroid Build Coastguard Worker std::move(timer_));
210*6777b538SAndroid Build Coastguard Worker return;
211*6777b538SAndroid Build Coastguard Worker }
212*6777b538SAndroid Build Coastguard Worker
213*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(stream_type_, HTTP2_HANDSHAKE_STREAM);
214*6777b538SAndroid Build Coastguard Worker
215*6777b538SAndroid Build Coastguard Worker // TODO(bnc): Find a way to clear
216*6777b538SAndroid Build Coastguard Worker // spdy_session_pool.enable_sending_initial_data_ to avoid sending
217*6777b538SAndroid Build Coastguard Worker // connection preface, initial settings, and window update.
218*6777b538SAndroid Build Coastguard Worker
219*6777b538SAndroid Build Coastguard Worker // HTTP/2 connection preface.
220*6777b538SAndroid Build Coastguard Worker frames_.emplace_back(spdy::test::MakeSerializedFrame(
221*6777b538SAndroid Build Coastguard Worker const_cast<char*>(spdy::kHttp2ConnectionHeaderPrefix),
222*6777b538SAndroid Build Coastguard Worker spdy::kHttp2ConnectionHeaderPrefixSize));
223*6777b538SAndroid Build Coastguard Worker AddWrite(&frames_.back());
224*6777b538SAndroid Build Coastguard Worker
225*6777b538SAndroid Build Coastguard Worker // Server advertises WebSockets over HTTP/2 support.
226*6777b538SAndroid Build Coastguard Worker spdy::SettingsMap read_settings;
227*6777b538SAndroid Build Coastguard Worker read_settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1;
228*6777b538SAndroid Build Coastguard Worker frames_.push_back(spdy_util_.ConstructSpdySettings(read_settings));
229*6777b538SAndroid Build Coastguard Worker AddRead(&frames_.back());
230*6777b538SAndroid Build Coastguard Worker
231*6777b538SAndroid Build Coastguard Worker // Initial SETTINGS frame.
232*6777b538SAndroid Build Coastguard Worker spdy::SettingsMap write_settings;
233*6777b538SAndroid Build Coastguard Worker write_settings[spdy::SETTINGS_HEADER_TABLE_SIZE] = kSpdyMaxHeaderTableSize;
234*6777b538SAndroid Build Coastguard Worker write_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] = 6 * 1024 * 1024;
235*6777b538SAndroid Build Coastguard Worker write_settings[spdy::SETTINGS_MAX_HEADER_LIST_SIZE] =
236*6777b538SAndroid Build Coastguard Worker kSpdyMaxHeaderListSize;
237*6777b538SAndroid Build Coastguard Worker write_settings[spdy::SETTINGS_ENABLE_PUSH] = 0;
238*6777b538SAndroid Build Coastguard Worker frames_.push_back(spdy_util_.ConstructSpdySettings(write_settings));
239*6777b538SAndroid Build Coastguard Worker AddWrite(&frames_.back());
240*6777b538SAndroid Build Coastguard Worker
241*6777b538SAndroid Build Coastguard Worker // Initial window update frame.
242*6777b538SAndroid Build Coastguard Worker frames_.push_back(spdy_util_.ConstructSpdyWindowUpdate(0, 0x00ef0001));
243*6777b538SAndroid Build Coastguard Worker AddWrite(&frames_.back());
244*6777b538SAndroid Build Coastguard Worker
245*6777b538SAndroid Build Coastguard Worker // SETTINGS ACK sent as a response to server's SETTINGS frame.
246*6777b538SAndroid Build Coastguard Worker frames_.push_back(spdy_util_.ConstructSpdySettingsAck());
247*6777b538SAndroid Build Coastguard Worker AddWrite(&frames_.back());
248*6777b538SAndroid Build Coastguard Worker
249*6777b538SAndroid Build Coastguard Worker // First request. This is necessary, because a WebSockets request currently
250*6777b538SAndroid Build Coastguard Worker // does not open a new HTTP/2 connection, it only uses an existing one.
251*6777b538SAndroid Build Coastguard Worker const char* const kExtraRequestHeaders[] = {
252*6777b538SAndroid Build Coastguard Worker "user-agent", "", "accept-encoding", "gzip, deflate",
253*6777b538SAndroid Build Coastguard Worker "accept-language", "en-us,fr"};
254*6777b538SAndroid Build Coastguard Worker frames_.push_back(spdy_util_.ConstructSpdyGet(
255*6777b538SAndroid Build Coastguard Worker kExtraRequestHeaders, std::size(kExtraRequestHeaders) / 2, 1,
256*6777b538SAndroid Build Coastguard Worker DEFAULT_PRIORITY));
257*6777b538SAndroid Build Coastguard Worker AddWrite(&frames_.back());
258*6777b538SAndroid Build Coastguard Worker
259*6777b538SAndroid Build Coastguard Worker // SETTINGS ACK frame sent by the server in response to the client's
260*6777b538SAndroid Build Coastguard Worker // initial SETTINGS frame.
261*6777b538SAndroid Build Coastguard Worker frames_.push_back(spdy_util_.ConstructSpdySettingsAck());
262*6777b538SAndroid Build Coastguard Worker AddRead(&frames_.back());
263*6777b538SAndroid Build Coastguard Worker
264*6777b538SAndroid Build Coastguard Worker // Response headers to first request.
265*6777b538SAndroid Build Coastguard Worker frames_.push_back(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1));
266*6777b538SAndroid Build Coastguard Worker AddRead(&frames_.back());
267*6777b538SAndroid Build Coastguard Worker
268*6777b538SAndroid Build Coastguard Worker // Response body to first request.
269*6777b538SAndroid Build Coastguard Worker frames_.push_back(spdy_util_.ConstructSpdyDataFrame(1, true));
270*6777b538SAndroid Build Coastguard Worker AddRead(&frames_.back());
271*6777b538SAndroid Build Coastguard Worker
272*6777b538SAndroid Build Coastguard Worker // First request is closed.
273*6777b538SAndroid Build Coastguard Worker spdy_util_.UpdateWithStreamDestruction(1);
274*6777b538SAndroid Build Coastguard Worker
275*6777b538SAndroid Build Coastguard Worker // WebSocket request.
276*6777b538SAndroid Build Coastguard Worker spdy::Http2HeaderBlock request_headers = WebSocketHttp2Request(
277*6777b538SAndroid Build Coastguard Worker socket_path, socket_host, kOrigin, extra_request_headers);
278*6777b538SAndroid Build Coastguard Worker frames_.push_back(spdy_util_.ConstructSpdyHeaders(
279*6777b538SAndroid Build Coastguard Worker 3, std::move(request_headers), DEFAULT_PRIORITY, false));
280*6777b538SAndroid Build Coastguard Worker AddWrite(&frames_.back());
281*6777b538SAndroid Build Coastguard Worker
282*6777b538SAndroid Build Coastguard Worker if (reset_websocket_http2_stream_) {
283*6777b538SAndroid Build Coastguard Worker frames_.push_back(
284*6777b538SAndroid Build Coastguard Worker spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
285*6777b538SAndroid Build Coastguard Worker AddRead(&frames_.back());
286*6777b538SAndroid Build Coastguard Worker } else {
287*6777b538SAndroid Build Coastguard Worker // Response to WebSocket request.
288*6777b538SAndroid Build Coastguard Worker std::vector<std::string> extra_response_header_keys;
289*6777b538SAndroid Build Coastguard Worker std::vector<const char*> extra_response_headers_vector;
290*6777b538SAndroid Build Coastguard Worker for (const auto& extra_header : extra_response_headers) {
291*6777b538SAndroid Build Coastguard Worker // Save a lowercase copy of the header key.
292*6777b538SAndroid Build Coastguard Worker extra_response_header_keys.push_back(
293*6777b538SAndroid Build Coastguard Worker base::ToLowerASCII(extra_header.first));
294*6777b538SAndroid Build Coastguard Worker // Save a pointer to this lowercase copy.
295*6777b538SAndroid Build Coastguard Worker extra_response_headers_vector.push_back(
296*6777b538SAndroid Build Coastguard Worker extra_response_header_keys.back().c_str());
297*6777b538SAndroid Build Coastguard Worker // Save a pointer to the original header value provided by the caller.
298*6777b538SAndroid Build Coastguard Worker extra_response_headers_vector.push_back(extra_header.second.c_str());
299*6777b538SAndroid Build Coastguard Worker }
300*6777b538SAndroid Build Coastguard Worker frames_.push_back(spdy_util_.ConstructSpdyReplyError(
301*6777b538SAndroid Build Coastguard Worker http2_response_status_, extra_response_headers_vector.data(),
302*6777b538SAndroid Build Coastguard Worker extra_response_headers_vector.size() / 2, 3));
303*6777b538SAndroid Build Coastguard Worker AddRead(&frames_.back());
304*6777b538SAndroid Build Coastguard Worker
305*6777b538SAndroid Build Coastguard Worker // WebSocket data received.
306*6777b538SAndroid Build Coastguard Worker if (!additional_data_.empty()) {
307*6777b538SAndroid Build Coastguard Worker frames_.push_back(
308*6777b538SAndroid Build Coastguard Worker spdy_util_.ConstructSpdyDataFrame(3, additional_data_, true));
309*6777b538SAndroid Build Coastguard Worker AddRead(&frames_.back());
310*6777b538SAndroid Build Coastguard Worker }
311*6777b538SAndroid Build Coastguard Worker
312*6777b538SAndroid Build Coastguard Worker // Client cancels HTTP/2 stream when request is destroyed.
313*6777b538SAndroid Build Coastguard Worker frames_.push_back(
314*6777b538SAndroid Build Coastguard Worker spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL));
315*6777b538SAndroid Build Coastguard Worker AddWrite(&frames_.back());
316*6777b538SAndroid Build Coastguard Worker }
317*6777b538SAndroid Build Coastguard Worker
318*6777b538SAndroid Build Coastguard Worker // EOF.
319*6777b538SAndroid Build Coastguard Worker reads_.emplace_back(ASYNC, 0, sequence_number_++);
320*6777b538SAndroid Build Coastguard Worker
321*6777b538SAndroid Build Coastguard Worker auto socket_data = std::make_unique<SequencedSocketData>(reads_, writes_);
322*6777b538SAndroid Build Coastguard Worker socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
323*6777b538SAndroid Build Coastguard Worker AddRawExpectations(std::move(socket_data));
324*6777b538SAndroid Build Coastguard Worker
325*6777b538SAndroid Build Coastguard Worker // Send first request. This makes sure server's
326*6777b538SAndroid Build Coastguard Worker // spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL advertisement is read.
327*6777b538SAndroid Build Coastguard Worker URLRequestContext* context =
328*6777b538SAndroid Build Coastguard Worker url_request_context_host_.GetURLRequestContext();
329*6777b538SAndroid Build Coastguard Worker TestDelegate delegate;
330*6777b538SAndroid Build Coastguard Worker std::unique_ptr<URLRequest> request = context->CreateRequest(
331*6777b538SAndroid Build Coastguard Worker GURL("https://www.example.org/"), DEFAULT_PRIORITY, &delegate,
332*6777b538SAndroid Build Coastguard Worker TRAFFIC_ANNOTATION_FOR_TESTS, /*is_for_websockets=*/false);
333*6777b538SAndroid Build Coastguard Worker // The IsolationInfo has to match for a socket to be reused.
334*6777b538SAndroid Build Coastguard Worker request->set_isolation_info(CreateIsolationInfo());
335*6777b538SAndroid Build Coastguard Worker request->Start();
336*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(request->is_pending());
337*6777b538SAndroid Build Coastguard Worker delegate.RunUntilComplete();
338*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(request->is_pending());
339*6777b538SAndroid Build Coastguard Worker
340*6777b538SAndroid Build Coastguard Worker CreateAndConnectStream(socket_url, sub_protocols, Origin(),
341*6777b538SAndroid Build Coastguard Worker SiteForCookies(), has_storage_access,
342*6777b538SAndroid Build Coastguard Worker CreateIsolationInfo(),
343*6777b538SAndroid Build Coastguard Worker WebSocketExtraHeadersToHttpRequestHeaders(
344*6777b538SAndroid Build Coastguard Worker send_additional_request_headers),
345*6777b538SAndroid Build Coastguard Worker std::move(timer_));
346*6777b538SAndroid Build Coastguard Worker }
347*6777b538SAndroid Build Coastguard Worker
348*6777b538SAndroid Build Coastguard Worker // Like CreateAndConnectStandard(), but allow for arbitrary response body.
349*6777b538SAndroid Build Coastguard Worker // Only for HTTP/1-based WebSockets.
CreateAndConnectCustomResponse(std::string_view url,const std::vector<std::string> & sub_protocols,const WebSocketExtraHeaders & send_additional_request_headers,const WebSocketExtraHeaders & extra_request_headers,const std::string & response_body,bool has_storage_access=false)350*6777b538SAndroid Build Coastguard Worker void CreateAndConnectCustomResponse(
351*6777b538SAndroid Build Coastguard Worker std::string_view url,
352*6777b538SAndroid Build Coastguard Worker const std::vector<std::string>& sub_protocols,
353*6777b538SAndroid Build Coastguard Worker const WebSocketExtraHeaders& send_additional_request_headers,
354*6777b538SAndroid Build Coastguard Worker const WebSocketExtraHeaders& extra_request_headers,
355*6777b538SAndroid Build Coastguard Worker const std::string& response_body,
356*6777b538SAndroid Build Coastguard Worker bool has_storage_access = false) {
357*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(BASIC_HANDSHAKE_STREAM, stream_type_);
358*6777b538SAndroid Build Coastguard Worker
359*6777b538SAndroid Build Coastguard Worker const GURL socket_url(url);
360*6777b538SAndroid Build Coastguard Worker const std::string socket_host = GetHostAndOptionalPort(socket_url);
361*6777b538SAndroid Build Coastguard Worker const std::string socket_path = socket_url.path();
362*6777b538SAndroid Build Coastguard Worker
363*6777b538SAndroid Build Coastguard Worker url_request_context_host_.SetExpectations(
364*6777b538SAndroid Build Coastguard Worker WebSocketStandardRequest(socket_path, socket_host, Origin(),
365*6777b538SAndroid Build Coastguard Worker send_additional_request_headers,
366*6777b538SAndroid Build Coastguard Worker extra_request_headers),
367*6777b538SAndroid Build Coastguard Worker response_body);
368*6777b538SAndroid Build Coastguard Worker CreateAndConnectStream(socket_url, sub_protocols, Origin(),
369*6777b538SAndroid Build Coastguard Worker SiteForCookies(), has_storage_access,
370*6777b538SAndroid Build Coastguard Worker CreateIsolationInfo(),
371*6777b538SAndroid Build Coastguard Worker WebSocketExtraHeadersToHttpRequestHeaders(
372*6777b538SAndroid Build Coastguard Worker send_additional_request_headers),
373*6777b538SAndroid Build Coastguard Worker nullptr);
374*6777b538SAndroid Build Coastguard Worker }
375*6777b538SAndroid Build Coastguard Worker
376*6777b538SAndroid Build Coastguard Worker // Like CreateAndConnectStandard(), but take extra response headers as a
377*6777b538SAndroid Build Coastguard Worker // string. This can save space in case of a very large response.
378*6777b538SAndroid Build Coastguard Worker // Only for HTTP/1-based WebSockets.
CreateAndConnectStringResponse(std::string_view url,const std::vector<std::string> & sub_protocols,const std::string & extra_response_headers,bool has_storage_access=false)379*6777b538SAndroid Build Coastguard Worker void CreateAndConnectStringResponse(
380*6777b538SAndroid Build Coastguard Worker std::string_view url,
381*6777b538SAndroid Build Coastguard Worker const std::vector<std::string>& sub_protocols,
382*6777b538SAndroid Build Coastguard Worker const std::string& extra_response_headers,
383*6777b538SAndroid Build Coastguard Worker bool has_storage_access = false) {
384*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(BASIC_HANDSHAKE_STREAM, stream_type_);
385*6777b538SAndroid Build Coastguard Worker
386*6777b538SAndroid Build Coastguard Worker const GURL socket_url(url);
387*6777b538SAndroid Build Coastguard Worker const std::string socket_host = GetHostAndOptionalPort(socket_url);
388*6777b538SAndroid Build Coastguard Worker const std::string socket_path = socket_url.path();
389*6777b538SAndroid Build Coastguard Worker
390*6777b538SAndroid Build Coastguard Worker url_request_context_host_.SetExpectations(
391*6777b538SAndroid Build Coastguard Worker WebSocketStandardRequest(socket_path, socket_host, Origin(),
392*6777b538SAndroid Build Coastguard Worker /*send_additional_request_headers=*/{},
393*6777b538SAndroid Build Coastguard Worker /*extra_headers=*/{}),
394*6777b538SAndroid Build Coastguard Worker WebSocketStandardResponse(extra_response_headers));
395*6777b538SAndroid Build Coastguard Worker CreateAndConnectStream(socket_url, sub_protocols, Origin(),
396*6777b538SAndroid Build Coastguard Worker SiteForCookies(), has_storage_access,
397*6777b538SAndroid Build Coastguard Worker CreateIsolationInfo(), HttpRequestHeaders(),
398*6777b538SAndroid Build Coastguard Worker nullptr);
399*6777b538SAndroid Build Coastguard Worker }
400*6777b538SAndroid Build Coastguard Worker
401*6777b538SAndroid Build Coastguard Worker // Like CreateAndConnectStandard(), but take raw mock data.
CreateAndConnectRawExpectations(std::string_view url,const std::vector<std::string> & sub_protocols,const HttpRequestHeaders & additional_headers,std::unique_ptr<SequencedSocketData> socket_data,bool has_storage_access=false)402*6777b538SAndroid Build Coastguard Worker void CreateAndConnectRawExpectations(
403*6777b538SAndroid Build Coastguard Worker std::string_view url,
404*6777b538SAndroid Build Coastguard Worker const std::vector<std::string>& sub_protocols,
405*6777b538SAndroid Build Coastguard Worker const HttpRequestHeaders& additional_headers,
406*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SequencedSocketData> socket_data,
407*6777b538SAndroid Build Coastguard Worker bool has_storage_access = false) {
408*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(BASIC_HANDSHAKE_STREAM, stream_type_);
409*6777b538SAndroid Build Coastguard Worker
410*6777b538SAndroid Build Coastguard Worker AddRawExpectations(std::move(socket_data));
411*6777b538SAndroid Build Coastguard Worker CreateAndConnectStream(GURL(url), sub_protocols, Origin(), SiteForCookies(),
412*6777b538SAndroid Build Coastguard Worker has_storage_access, CreateIsolationInfo(),
413*6777b538SAndroid Build Coastguard Worker additional_headers, std::move(timer_));
414*6777b538SAndroid Build Coastguard Worker }
415*6777b538SAndroid Build Coastguard Worker
PriorityHeaderEnabled() const416*6777b538SAndroid Build Coastguard Worker bool PriorityHeaderEnabled() const { return std::get<bool>(GetParam()); }
417*6777b538SAndroid Build Coastguard Worker
418*6777b538SAndroid Build Coastguard Worker private:
AddWrite(const spdy::SpdySerializedFrame * frame)419*6777b538SAndroid Build Coastguard Worker void AddWrite(const spdy::SpdySerializedFrame* frame) {
420*6777b538SAndroid Build Coastguard Worker writes_.emplace_back(ASYNC, frame->data(), frame->size(),
421*6777b538SAndroid Build Coastguard Worker sequence_number_++);
422*6777b538SAndroid Build Coastguard Worker }
423*6777b538SAndroid Build Coastguard Worker
AddRead(const spdy::SpdySerializedFrame * frame)424*6777b538SAndroid Build Coastguard Worker void AddRead(const spdy::SpdySerializedFrame* frame) {
425*6777b538SAndroid Build Coastguard Worker reads_.emplace_back(ASYNC, frame->data(), frame->size(),
426*6777b538SAndroid Build Coastguard Worker sequence_number_++);
427*6777b538SAndroid Build Coastguard Worker }
428*6777b538SAndroid Build Coastguard Worker
429*6777b538SAndroid Build Coastguard Worker protected:
430*6777b538SAndroid Build Coastguard Worker const HandshakeStreamType stream_type_;
431*6777b538SAndroid Build Coastguard Worker
432*6777b538SAndroid Build Coastguard Worker private:
433*6777b538SAndroid Build Coastguard Worker base::test::ScopedFeatureList feature_list_;
434*6777b538SAndroid Build Coastguard Worker
435*6777b538SAndroid Build Coastguard Worker std::unique_ptr<base::OneShotTimer> timer_;
436*6777b538SAndroid Build Coastguard Worker std::string additional_data_;
437*6777b538SAndroid Build Coastguard Worker const char* http2_response_status_ = "200";
438*6777b538SAndroid Build Coastguard Worker bool reset_websocket_http2_stream_ = false;
439*6777b538SAndroid Build Coastguard Worker SpdyTestUtil spdy_util_;
440*6777b538SAndroid Build Coastguard Worker NetLogWithSource log_;
441*6777b538SAndroid Build Coastguard Worker
442*6777b538SAndroid Build Coastguard Worker int sequence_number_ = 0;
443*6777b538SAndroid Build Coastguard Worker
444*6777b538SAndroid Build Coastguard Worker // Store mock HTTP/2 data.
445*6777b538SAndroid Build Coastguard Worker std::vector<spdy::SpdySerializedFrame> frames_;
446*6777b538SAndroid Build Coastguard Worker
447*6777b538SAndroid Build Coastguard Worker // Store MockRead and MockWrite objects that have pointers to above data.
448*6777b538SAndroid Build Coastguard Worker std::vector<MockRead> reads_;
449*6777b538SAndroid Build Coastguard Worker std::vector<MockWrite> writes_;
450*6777b538SAndroid Build Coastguard Worker };
451*6777b538SAndroid Build Coastguard Worker
452*6777b538SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(All,
453*6777b538SAndroid Build Coastguard Worker WebSocketStreamCreateTest,
454*6777b538SAndroid Build Coastguard Worker testing::Combine(Values(BASIC_HANDSHAKE_STREAM),
455*6777b538SAndroid Build Coastguard Worker testing::Bool()));
456*6777b538SAndroid Build Coastguard Worker
457*6777b538SAndroid Build Coastguard Worker using WebSocketMultiProtocolStreamCreateTest = WebSocketStreamCreateTest;
458*6777b538SAndroid Build Coastguard Worker
459*6777b538SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(All,
460*6777b538SAndroid Build Coastguard Worker WebSocketMultiProtocolStreamCreateTest,
461*6777b538SAndroid Build Coastguard Worker testing::Combine(Values(BASIC_HANDSHAKE_STREAM,
462*6777b538SAndroid Build Coastguard Worker HTTP2_HANDSHAKE_STREAM),
463*6777b538SAndroid Build Coastguard Worker testing::Bool()));
464*6777b538SAndroid Build Coastguard Worker
465*6777b538SAndroid Build Coastguard Worker // There are enough tests of the Sec-WebSocket-Extensions header that they
466*6777b538SAndroid Build Coastguard Worker // deserve their own test fixture.
467*6777b538SAndroid Build Coastguard Worker class WebSocketStreamCreateExtensionTest
468*6777b538SAndroid Build Coastguard Worker : public WebSocketMultiProtocolStreamCreateTest {
469*6777b538SAndroid Build Coastguard Worker protected:
470*6777b538SAndroid Build Coastguard Worker // Performs a standard connect, with the value of the Sec-WebSocket-Extensions
471*6777b538SAndroid Build Coastguard Worker // header in the response set to |extensions_header_value|. Runs the event
472*6777b538SAndroid Build Coastguard Worker // loop to allow the connect to complete.
CreateAndConnectWithExtensions(const std::string & extensions_header_value)473*6777b538SAndroid Build Coastguard Worker void CreateAndConnectWithExtensions(
474*6777b538SAndroid Build Coastguard Worker const std::string& extensions_header_value) {
475*6777b538SAndroid Build Coastguard Worker AddSSLData();
476*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard(
477*6777b538SAndroid Build Coastguard Worker "wss://www.example.org/testing_path", NoSubProtocols(), {}, {},
478*6777b538SAndroid Build Coastguard Worker {{"Sec-WebSocket-Extensions", extensions_header_value}});
479*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
480*6777b538SAndroid Build Coastguard Worker }
481*6777b538SAndroid Build Coastguard Worker };
482*6777b538SAndroid Build Coastguard Worker
483*6777b538SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(All,
484*6777b538SAndroid Build Coastguard Worker WebSocketStreamCreateExtensionTest,
485*6777b538SAndroid Build Coastguard Worker testing::Combine(Values(BASIC_HANDSHAKE_STREAM,
486*6777b538SAndroid Build Coastguard Worker HTTP2_HANDSHAKE_STREAM),
487*6777b538SAndroid Build Coastguard Worker testing::Bool()));
488*6777b538SAndroid Build Coastguard Worker
489*6777b538SAndroid Build Coastguard Worker // Common code to construct expectations for authentication tests that receive
490*6777b538SAndroid Build Coastguard Worker // the auth challenge on one connection and then create a second connection to
491*6777b538SAndroid Build Coastguard Worker // send the authenticated request on.
492*6777b538SAndroid Build Coastguard Worker class CommonAuthTestHelper {
493*6777b538SAndroid Build Coastguard Worker public:
CommonAuthTestHelper()494*6777b538SAndroid Build Coastguard Worker CommonAuthTestHelper() : reads_(), writes_() {}
495*6777b538SAndroid Build Coastguard Worker
496*6777b538SAndroid Build Coastguard Worker CommonAuthTestHelper(const CommonAuthTestHelper&) = delete;
497*6777b538SAndroid Build Coastguard Worker CommonAuthTestHelper& operator=(const CommonAuthTestHelper&) = delete;
498*6777b538SAndroid Build Coastguard Worker
BuildAuthSocketData(std::string response1,std::string request2,std::string response2)499*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SequencedSocketData> BuildAuthSocketData(
500*6777b538SAndroid Build Coastguard Worker std::string response1,
501*6777b538SAndroid Build Coastguard Worker std::string request2,
502*6777b538SAndroid Build Coastguard Worker std::string response2) {
503*6777b538SAndroid Build Coastguard Worker request1_ = WebSocketStandardRequest("/", "www.example.org", Origin(),
504*6777b538SAndroid Build Coastguard Worker /*send_additional_request_headers=*/{},
505*6777b538SAndroid Build Coastguard Worker /*extra_headers=*/{});
506*6777b538SAndroid Build Coastguard Worker response1_ = std::move(response1);
507*6777b538SAndroid Build Coastguard Worker request2_ = std::move(request2);
508*6777b538SAndroid Build Coastguard Worker response2_ = std::move(response2);
509*6777b538SAndroid Build Coastguard Worker writes_[0] = MockWrite(SYNCHRONOUS, 0, request1_.c_str());
510*6777b538SAndroid Build Coastguard Worker reads_[0] = MockRead(SYNCHRONOUS, 1, response1_.c_str());
511*6777b538SAndroid Build Coastguard Worker writes_[1] = MockWrite(SYNCHRONOUS, 2, request2_.c_str());
512*6777b538SAndroid Build Coastguard Worker reads_[1] = MockRead(SYNCHRONOUS, 3, response2_.c_str());
513*6777b538SAndroid Build Coastguard Worker reads_[2] = MockRead(SYNCHRONOUS, OK, 4); // Close connection
514*6777b538SAndroid Build Coastguard Worker
515*6777b538SAndroid Build Coastguard Worker return BuildSocketData(reads_, writes_);
516*6777b538SAndroid Build Coastguard Worker }
517*6777b538SAndroid Build Coastguard Worker
518*6777b538SAndroid Build Coastguard Worker private:
519*6777b538SAndroid Build Coastguard Worker // These need to be object-scoped since they have to remain valid until all
520*6777b538SAndroid Build Coastguard Worker // socket operations in the test are complete.
521*6777b538SAndroid Build Coastguard Worker std::string request1_;
522*6777b538SAndroid Build Coastguard Worker std::string request2_;
523*6777b538SAndroid Build Coastguard Worker std::string response1_;
524*6777b538SAndroid Build Coastguard Worker std::string response2_;
525*6777b538SAndroid Build Coastguard Worker MockRead reads_[3];
526*6777b538SAndroid Build Coastguard Worker MockWrite writes_[2];
527*6777b538SAndroid Build Coastguard Worker };
528*6777b538SAndroid Build Coastguard Worker
529*6777b538SAndroid Build Coastguard Worker // Data and methods for BasicAuth tests.
530*6777b538SAndroid Build Coastguard Worker class WebSocketStreamCreateBasicAuthTest : public WebSocketStreamCreateTest {
531*6777b538SAndroid Build Coastguard Worker protected:
CreateAndConnectAuthHandshake(std::string_view url,std::string_view base64_user_pass,std::string_view response2)532*6777b538SAndroid Build Coastguard Worker void CreateAndConnectAuthHandshake(std::string_view url,
533*6777b538SAndroid Build Coastguard Worker std::string_view base64_user_pass,
534*6777b538SAndroid Build Coastguard Worker std::string_view response2) {
535*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations(
536*6777b538SAndroid Build Coastguard Worker url, NoSubProtocols(), HttpRequestHeaders(),
537*6777b538SAndroid Build Coastguard Worker helper_.BuildAuthSocketData(kUnauthorizedResponse,
538*6777b538SAndroid Build Coastguard Worker RequestExpectation(base64_user_pass),
539*6777b538SAndroid Build Coastguard Worker std::string(response2)));
540*6777b538SAndroid Build Coastguard Worker }
541*6777b538SAndroid Build Coastguard Worker
RequestExpectation(std::string_view base64_user_pass)542*6777b538SAndroid Build Coastguard Worker static std::string RequestExpectation(std::string_view base64_user_pass) {
543*6777b538SAndroid Build Coastguard Worker // Copy base64_user_pass to a std::string in case it is not nul-terminated.
544*6777b538SAndroid Build Coastguard Worker std::string base64_user_pass_string(base64_user_pass);
545*6777b538SAndroid Build Coastguard Worker return base::StringPrintf(
546*6777b538SAndroid Build Coastguard Worker "GET / HTTP/1.1\r\n"
547*6777b538SAndroid Build Coastguard Worker "Host: www.example.org\r\n"
548*6777b538SAndroid Build Coastguard Worker "Connection: Upgrade\r\n"
549*6777b538SAndroid Build Coastguard Worker "Pragma: no-cache\r\n"
550*6777b538SAndroid Build Coastguard Worker "Cache-Control: no-cache\r\n"
551*6777b538SAndroid Build Coastguard Worker "Authorization: Basic %s\r\n"
552*6777b538SAndroid Build Coastguard Worker "Upgrade: websocket\r\n"
553*6777b538SAndroid Build Coastguard Worker "Origin: http://www.example.org\r\n"
554*6777b538SAndroid Build Coastguard Worker "Sec-WebSocket-Version: 13\r\n"
555*6777b538SAndroid Build Coastguard Worker "User-Agent: \r\n"
556*6777b538SAndroid Build Coastguard Worker "Accept-Encoding: gzip, deflate\r\n"
557*6777b538SAndroid Build Coastguard Worker "Accept-Language: en-us,fr\r\n"
558*6777b538SAndroid Build Coastguard Worker "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
559*6777b538SAndroid Build Coastguard Worker "Sec-WebSocket-Extensions: permessage-deflate; "
560*6777b538SAndroid Build Coastguard Worker "client_max_window_bits\r\n"
561*6777b538SAndroid Build Coastguard Worker "\r\n",
562*6777b538SAndroid Build Coastguard Worker base64_user_pass_string.c_str());
563*6777b538SAndroid Build Coastguard Worker }
564*6777b538SAndroid Build Coastguard Worker
565*6777b538SAndroid Build Coastguard Worker static const char kUnauthorizedResponse[];
566*6777b538SAndroid Build Coastguard Worker
567*6777b538SAndroid Build Coastguard Worker CommonAuthTestHelper helper_;
568*6777b538SAndroid Build Coastguard Worker };
569*6777b538SAndroid Build Coastguard Worker
570*6777b538SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(All,
571*6777b538SAndroid Build Coastguard Worker WebSocketStreamCreateBasicAuthTest,
572*6777b538SAndroid Build Coastguard Worker testing::Combine(Values(BASIC_HANDSHAKE_STREAM),
573*6777b538SAndroid Build Coastguard Worker testing::Bool()));
574*6777b538SAndroid Build Coastguard Worker
575*6777b538SAndroid Build Coastguard Worker class WebSocketStreamCreateDigestAuthTest : public WebSocketStreamCreateTest {
576*6777b538SAndroid Build Coastguard Worker protected:
577*6777b538SAndroid Build Coastguard Worker static const char kUnauthorizedResponse[];
578*6777b538SAndroid Build Coastguard Worker static const char kAuthorizedRequest[];
579*6777b538SAndroid Build Coastguard Worker
580*6777b538SAndroid Build Coastguard Worker CommonAuthTestHelper helper_;
581*6777b538SAndroid Build Coastguard Worker };
582*6777b538SAndroid Build Coastguard Worker
583*6777b538SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(All,
584*6777b538SAndroid Build Coastguard Worker WebSocketStreamCreateDigestAuthTest,
585*6777b538SAndroid Build Coastguard Worker testing::Combine(Values(BASIC_HANDSHAKE_STREAM),
586*6777b538SAndroid Build Coastguard Worker testing::Bool()));
587*6777b538SAndroid Build Coastguard Worker
588*6777b538SAndroid Build Coastguard Worker const char WebSocketStreamCreateBasicAuthTest::kUnauthorizedResponse[] =
589*6777b538SAndroid Build Coastguard Worker "HTTP/1.1 401 Unauthorized\r\n"
590*6777b538SAndroid Build Coastguard Worker "Content-Length: 0\r\n"
591*6777b538SAndroid Build Coastguard Worker "WWW-Authenticate: Basic realm=\"camelot\"\r\n"
592*6777b538SAndroid Build Coastguard Worker "\r\n";
593*6777b538SAndroid Build Coastguard Worker
594*6777b538SAndroid Build Coastguard Worker // These negotiation values are borrowed from
595*6777b538SAndroid Build Coastguard Worker // http_auth_handler_digest_unittest.cc. Feel free to come up with new ones if
596*6777b538SAndroid Build Coastguard Worker // you are bored. Only the weakest (no qop) variants of Digest authentication
597*6777b538SAndroid Build Coastguard Worker // can be tested by this method, because the others involve random input.
598*6777b538SAndroid Build Coastguard Worker const char WebSocketStreamCreateDigestAuthTest::kUnauthorizedResponse[] =
599*6777b538SAndroid Build Coastguard Worker "HTTP/1.1 401 Unauthorized\r\n"
600*6777b538SAndroid Build Coastguard Worker "Content-Length: 0\r\n"
601*6777b538SAndroid Build Coastguard Worker "WWW-Authenticate: Digest realm=\"Oblivion\", nonce=\"nonce-value\"\r\n"
602*6777b538SAndroid Build Coastguard Worker "\r\n";
603*6777b538SAndroid Build Coastguard Worker
604*6777b538SAndroid Build Coastguard Worker const char WebSocketStreamCreateDigestAuthTest::kAuthorizedRequest[] =
605*6777b538SAndroid Build Coastguard Worker "GET / HTTP/1.1\r\n"
606*6777b538SAndroid Build Coastguard Worker "Host: www.example.org\r\n"
607*6777b538SAndroid Build Coastguard Worker "Connection: Upgrade\r\n"
608*6777b538SAndroid Build Coastguard Worker "Pragma: no-cache\r\n"
609*6777b538SAndroid Build Coastguard Worker "Cache-Control: no-cache\r\n"
610*6777b538SAndroid Build Coastguard Worker "Authorization: Digest username=\"FooBar\", realm=\"Oblivion\", "
611*6777b538SAndroid Build Coastguard Worker "nonce=\"nonce-value\", uri=\"/\", "
612*6777b538SAndroid Build Coastguard Worker "response=\"f72ff54ebde2f928860f806ec04acd1b\"\r\n"
613*6777b538SAndroid Build Coastguard Worker "Upgrade: websocket\r\n"
614*6777b538SAndroid Build Coastguard Worker "Origin: http://www.example.org\r\n"
615*6777b538SAndroid Build Coastguard Worker "Sec-WebSocket-Version: 13\r\n"
616*6777b538SAndroid Build Coastguard Worker "User-Agent: \r\n"
617*6777b538SAndroid Build Coastguard Worker "Accept-Encoding: gzip, deflate\r\n"
618*6777b538SAndroid Build Coastguard Worker "Accept-Language: en-us,fr\r\n"
619*6777b538SAndroid Build Coastguard Worker "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
620*6777b538SAndroid Build Coastguard Worker "Sec-WebSocket-Extensions: permessage-deflate; "
621*6777b538SAndroid Build Coastguard Worker "client_max_window_bits\r\n"
622*6777b538SAndroid Build Coastguard Worker "\r\n";
623*6777b538SAndroid Build Coastguard Worker
624*6777b538SAndroid Build Coastguard Worker // Confirm that the basic case works as expected.
TEST_P(WebSocketMultiProtocolStreamCreateTest,SimpleSuccess)625*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketMultiProtocolStreamCreateTest, SimpleSuccess) {
626*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
627*6777b538SAndroid Build Coastguard Worker
628*6777b538SAndroid Build Coastguard Worker AddSSLData();
629*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(url_request_);
630*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard("wss://www.example.org/", NoSubProtocols(), {}, {},
631*6777b538SAndroid Build Coastguard Worker {});
632*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(request_info_);
633*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(response_info_);
634*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(url_request_);
635*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
636*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
637*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(stream_);
638*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(request_info_);
639*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(response_info_);
640*6777b538SAndroid Build Coastguard Worker
641*6777b538SAndroid Build Coastguard Worker // Histograms are only updated on stream request destruction.
642*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
643*6777b538SAndroid Build Coastguard Worker stream_.reset();
644*6777b538SAndroid Build Coastguard Worker
645*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(ERR_WS_UPGRADE,
646*6777b538SAndroid Build Coastguard Worker url_request_context_host_.network_delegate().last_error());
647*6777b538SAndroid Build Coastguard Worker
648*6777b538SAndroid Build Coastguard Worker auto samples = histogram_tester.GetHistogramSamplesSinceCreation(
649*6777b538SAndroid Build Coastguard Worker "Net.WebSocket.HandshakeResult2");
650*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->TotalCount());
651*6777b538SAndroid Build Coastguard Worker if (stream_type_ == BASIC_HANDSHAKE_STREAM) {
652*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1,
653*6777b538SAndroid Build Coastguard Worker samples->GetCount(static_cast<int>(
654*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::HandshakeResult::CONNECTED)));
655*6777b538SAndroid Build Coastguard Worker } else {
656*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(stream_type_, HTTP2_HANDSHAKE_STREAM);
657*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
658*6777b538SAndroid Build Coastguard Worker 1,
659*6777b538SAndroid Build Coastguard Worker samples->GetCount(static_cast<int>(
660*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::HandshakeResult::HTTP2_CONNECTED)));
661*6777b538SAndroid Build Coastguard Worker }
662*6777b538SAndroid Build Coastguard Worker }
663*6777b538SAndroid Build Coastguard Worker
TEST_P(WebSocketStreamCreateTest,HandshakeInfo)664*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, HandshakeInfo) {
665*6777b538SAndroid Build Coastguard Worker static constexpr char kResponse[] =
666*6777b538SAndroid Build Coastguard Worker "HTTP/1.1 101 Switching Protocols\r\n"
667*6777b538SAndroid Build Coastguard Worker "Upgrade: websocket\r\n"
668*6777b538SAndroid Build Coastguard Worker "Connection: Upgrade\r\n"
669*6777b538SAndroid Build Coastguard Worker "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
670*6777b538SAndroid Build Coastguard Worker "foo: bar, baz\r\n"
671*6777b538SAndroid Build Coastguard Worker "hoge: fuga\r\n"
672*6777b538SAndroid Build Coastguard Worker "hoge: piyo\r\n"
673*6777b538SAndroid Build Coastguard Worker "\r\n";
674*6777b538SAndroid Build Coastguard Worker
675*6777b538SAndroid Build Coastguard Worker CreateAndConnectCustomResponse("ws://www.example.org/", NoSubProtocols(), {},
676*6777b538SAndroid Build Coastguard Worker {}, kResponse);
677*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(request_info_);
678*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(response_info_);
679*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
680*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(stream_);
681*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(request_info_);
682*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(response_info_);
683*6777b538SAndroid Build Coastguard Worker std::vector<HeaderKeyValuePair> request_headers =
684*6777b538SAndroid Build Coastguard Worker RequestHeadersToVector(request_info_->headers);
685*6777b538SAndroid Build Coastguard Worker // We examine the contents of request_info_ and response_info_
686*6777b538SAndroid Build Coastguard Worker // mainly only in this test case.
687*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(GURL("ws://www.example.org/"), request_info_->url);
688*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(GURL("ws://www.example.org/"), response_info_->url);
689*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(101, response_info_->headers->response_code());
690*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Switching Protocols", response_info_->headers->GetStatusText());
691*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(12u, request_headers.size());
692*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("Host", "www.example.org"), request_headers[0]);
693*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("Connection", "Upgrade"), request_headers[1]);
694*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("Pragma", "no-cache"), request_headers[2]);
695*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("Cache-Control", "no-cache"),
696*6777b538SAndroid Build Coastguard Worker request_headers[3]);
697*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), request_headers[4]);
698*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("Origin", "http://www.example.org"),
699*6777b538SAndroid Build Coastguard Worker request_headers[5]);
700*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("Sec-WebSocket-Version", "13"),
701*6777b538SAndroid Build Coastguard Worker request_headers[6]);
702*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("User-Agent", ""), request_headers[7]);
703*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("Accept-Encoding", "gzip, deflate"),
704*6777b538SAndroid Build Coastguard Worker request_headers[8]);
705*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("Accept-Language", "en-us,fr"),
706*6777b538SAndroid Build Coastguard Worker request_headers[9]);
707*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Sec-WebSocket-Key", request_headers[10].first);
708*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("Sec-WebSocket-Extensions",
709*6777b538SAndroid Build Coastguard Worker "permessage-deflate; client_max_window_bits"),
710*6777b538SAndroid Build Coastguard Worker request_headers[11]);
711*6777b538SAndroid Build Coastguard Worker
712*6777b538SAndroid Build Coastguard Worker std::vector<HeaderKeyValuePair> response_headers =
713*6777b538SAndroid Build Coastguard Worker ResponseHeadersToVector(*response_info_->headers.get());
714*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(6u, response_headers.size());
715*6777b538SAndroid Build Coastguard Worker // Sort the headers for ease of verification.
716*6777b538SAndroid Build Coastguard Worker std::sort(response_headers.begin(), response_headers.end());
717*6777b538SAndroid Build Coastguard Worker
718*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("Connection", "Upgrade"), response_headers[0]);
719*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Sec-WebSocket-Accept", response_headers[1].first);
720*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("Upgrade", "websocket"), response_headers[2]);
721*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("foo", "bar, baz"), response_headers[3]);
722*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("hoge", "fuga"), response_headers[4]);
723*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("hoge", "piyo"), response_headers[5]);
724*6777b538SAndroid Build Coastguard Worker }
725*6777b538SAndroid Build Coastguard Worker
726*6777b538SAndroid Build Coastguard Worker // Confirms that request headers are overriden/added after handshake
TEST_P(WebSocketStreamCreateTest,HandshakeOverrideHeaders)727*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, HandshakeOverrideHeaders) {
728*6777b538SAndroid Build Coastguard Worker WebSocketExtraHeaders additional_headers(
729*6777b538SAndroid Build Coastguard Worker {{"User-Agent", "OveRrIde"}, {"rAnDomHeader", "foobar"}});
730*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard("ws://www.example.org/", NoSubProtocols(),
731*6777b538SAndroid Build Coastguard Worker additional_headers, additional_headers, {});
732*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(request_info_);
733*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(response_info_);
734*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
735*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
736*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(stream_);
737*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(request_info_);
738*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(response_info_);
739*6777b538SAndroid Build Coastguard Worker
740*6777b538SAndroid Build Coastguard Worker std::vector<HeaderKeyValuePair> request_headers =
741*6777b538SAndroid Build Coastguard Worker RequestHeadersToVector(request_info_->headers);
742*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("User-Agent", "OveRrIde"), request_headers[4]);
743*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HeaderKeyValuePair("rAnDomHeader", "foobar"), request_headers[5]);
744*6777b538SAndroid Build Coastguard Worker }
745*6777b538SAndroid Build Coastguard Worker
TEST_P(WebSocketStreamCreateTest,OmitsHasStorageAccess)746*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, OmitsHasStorageAccess) {
747*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard("ws://www.example.org/", NoSubProtocols(), {}, {},
748*6777b538SAndroid Build Coastguard Worker {}, /*has_storage_access=*/false);
749*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
750*6777b538SAndroid Build Coastguard Worker
751*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(
752*6777b538SAndroid Build Coastguard Worker url_request_context_host_.network_delegate()
753*6777b538SAndroid Build Coastguard Worker .cookie_setting_overrides_records(),
754*6777b538SAndroid Build Coastguard Worker testing::ElementsAre(CookieSettingOverrides(), CookieSettingOverrides()));
755*6777b538SAndroid Build Coastguard Worker }
756*6777b538SAndroid Build Coastguard Worker
TEST_P(WebSocketStreamCreateTest,PlumbsHasStorageAccess)757*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, PlumbsHasStorageAccess) {
758*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard("ws://www.example.org/", NoSubProtocols(), {}, {},
759*6777b538SAndroid Build Coastguard Worker {}, /*has_storage_access=*/true);
760*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
761*6777b538SAndroid Build Coastguard Worker
762*6777b538SAndroid Build Coastguard Worker CookieSettingOverrides expected_overrides;
763*6777b538SAndroid Build Coastguard Worker expected_overrides.Put(CookieSettingOverride::kStorageAccessGrantEligible);
764*6777b538SAndroid Build Coastguard Worker
765*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(url_request_context_host_.network_delegate()
766*6777b538SAndroid Build Coastguard Worker .cookie_setting_overrides_records(),
767*6777b538SAndroid Build Coastguard Worker testing::ElementsAre(expected_overrides, expected_overrides));
768*6777b538SAndroid Build Coastguard Worker }
769*6777b538SAndroid Build Coastguard Worker
770*6777b538SAndroid Build Coastguard Worker // Confirm that the stream isn't established until the message loop runs.
TEST_P(WebSocketStreamCreateTest,NeedsToRunLoop)771*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, NeedsToRunLoop) {
772*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard("ws://www.example.org/", NoSubProtocols(), {}, {},
773*6777b538SAndroid Build Coastguard Worker {});
774*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
775*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
776*6777b538SAndroid Build Coastguard Worker }
777*6777b538SAndroid Build Coastguard Worker
778*6777b538SAndroid Build Coastguard Worker // Check the path is used.
TEST_P(WebSocketMultiProtocolStreamCreateTest,PathIsUsed)779*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketMultiProtocolStreamCreateTest, PathIsUsed) {
780*6777b538SAndroid Build Coastguard Worker AddSSLData();
781*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard("wss://www.example.org/testing_path",
782*6777b538SAndroid Build Coastguard Worker NoSubProtocols(), {}, {}, {});
783*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
784*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
785*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(stream_);
786*6777b538SAndroid Build Coastguard Worker }
787*6777b538SAndroid Build Coastguard Worker
788*6777b538SAndroid Build Coastguard Worker // Check that sub-protocols are sent and parsed.
TEST_P(WebSocketMultiProtocolStreamCreateTest,SubProtocolIsUsed)789*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketMultiProtocolStreamCreateTest, SubProtocolIsUsed) {
790*6777b538SAndroid Build Coastguard Worker AddSSLData();
791*6777b538SAndroid Build Coastguard Worker std::vector<std::string> sub_protocols;
792*6777b538SAndroid Build Coastguard Worker sub_protocols.push_back("chatv11.chromium.org");
793*6777b538SAndroid Build Coastguard Worker sub_protocols.push_back("chatv20.chromium.org");
794*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard(
795*6777b538SAndroid Build Coastguard Worker "wss://www.example.org/testing_path", sub_protocols, {},
796*6777b538SAndroid Build Coastguard Worker {{"Sec-WebSocket-Protocol",
797*6777b538SAndroid Build Coastguard Worker "chatv11.chromium.org, chatv20.chromium.org"}},
798*6777b538SAndroid Build Coastguard Worker {{"Sec-WebSocket-Protocol", "chatv20.chromium.org"}});
799*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
800*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(stream_);
801*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
802*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("chatv20.chromium.org", stream_->GetSubProtocol());
803*6777b538SAndroid Build Coastguard Worker }
804*6777b538SAndroid Build Coastguard Worker
805*6777b538SAndroid Build Coastguard Worker // Unsolicited sub-protocols are rejected.
TEST_P(WebSocketMultiProtocolStreamCreateTest,UnsolicitedSubProtocol)806*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketMultiProtocolStreamCreateTest, UnsolicitedSubProtocol) {
807*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
808*6777b538SAndroid Build Coastguard Worker
809*6777b538SAndroid Build Coastguard Worker AddSSLData();
810*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard(
811*6777b538SAndroid Build Coastguard Worker "wss://www.example.org/testing_path", NoSubProtocols(), {}, {},
812*6777b538SAndroid Build Coastguard Worker {{"Sec-WebSocket-Protocol", "chatv20.chromium.org"}});
813*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
814*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
815*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
816*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error during WebSocket handshake: "
817*6777b538SAndroid Build Coastguard Worker "Response must not include 'Sec-WebSocket-Protocol' header "
818*6777b538SAndroid Build Coastguard Worker "if not present in request: chatv20.chromium.org",
819*6777b538SAndroid Build Coastguard Worker failure_message());
820*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(ERR_INVALID_RESPONSE,
821*6777b538SAndroid Build Coastguard Worker url_request_context_host_.network_delegate().last_error());
822*6777b538SAndroid Build Coastguard Worker
823*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
824*6777b538SAndroid Build Coastguard Worker
825*6777b538SAndroid Build Coastguard Worker auto samples = histogram_tester.GetHistogramSamplesSinceCreation(
826*6777b538SAndroid Build Coastguard Worker "Net.WebSocket.HandshakeResult2");
827*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->TotalCount());
828*6777b538SAndroid Build Coastguard Worker if (stream_type_ == BASIC_HANDSHAKE_STREAM) {
829*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
830*6777b538SAndroid Build Coastguard Worker 1,
831*6777b538SAndroid Build Coastguard Worker samples->GetCount(static_cast<int>(
832*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::HandshakeResult::FAILED_SUBPROTO)));
833*6777b538SAndroid Build Coastguard Worker } else {
834*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(stream_type_, HTTP2_HANDSHAKE_STREAM);
835*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->GetCount(static_cast<int>(
836*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::HandshakeResult::
837*6777b538SAndroid Build Coastguard Worker HTTP2_FAILED_SUBPROTO)));
838*6777b538SAndroid Build Coastguard Worker }
839*6777b538SAndroid Build Coastguard Worker }
840*6777b538SAndroid Build Coastguard Worker
841*6777b538SAndroid Build Coastguard Worker // Missing sub-protocol response is rejected.
TEST_P(WebSocketMultiProtocolStreamCreateTest,UnacceptedSubProtocol)842*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketMultiProtocolStreamCreateTest, UnacceptedSubProtocol) {
843*6777b538SAndroid Build Coastguard Worker AddSSLData();
844*6777b538SAndroid Build Coastguard Worker std::vector<std::string> sub_protocols;
845*6777b538SAndroid Build Coastguard Worker sub_protocols.push_back("chat.example.com");
846*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard("wss://www.example.org/testing_path", sub_protocols,
847*6777b538SAndroid Build Coastguard Worker {}, {{"Sec-WebSocket-Protocol", "chat.example.com"}},
848*6777b538SAndroid Build Coastguard Worker {});
849*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
850*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
851*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
852*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error during WebSocket handshake: "
853*6777b538SAndroid Build Coastguard Worker "Sent non-empty 'Sec-WebSocket-Protocol' header "
854*6777b538SAndroid Build Coastguard Worker "but no response was received",
855*6777b538SAndroid Build Coastguard Worker failure_message());
856*6777b538SAndroid Build Coastguard Worker }
857*6777b538SAndroid Build Coastguard Worker
858*6777b538SAndroid Build Coastguard Worker // Only one sub-protocol can be accepted.
TEST_P(WebSocketMultiProtocolStreamCreateTest,MultipleSubProtocolsInResponse)859*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketMultiProtocolStreamCreateTest, MultipleSubProtocolsInResponse) {
860*6777b538SAndroid Build Coastguard Worker AddSSLData();
861*6777b538SAndroid Build Coastguard Worker std::vector<std::string> sub_protocols;
862*6777b538SAndroid Build Coastguard Worker sub_protocols.push_back("chatv11.chromium.org");
863*6777b538SAndroid Build Coastguard Worker sub_protocols.push_back("chatv20.chromium.org");
864*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard("wss://www.example.org/testing_path", sub_protocols,
865*6777b538SAndroid Build Coastguard Worker {},
866*6777b538SAndroid Build Coastguard Worker {{"Sec-WebSocket-Protocol",
867*6777b538SAndroid Build Coastguard Worker "chatv11.chromium.org, chatv20.chromium.org"}},
868*6777b538SAndroid Build Coastguard Worker {{"Sec-WebSocket-Protocol",
869*6777b538SAndroid Build Coastguard Worker "chatv11.chromium.org, chatv20.chromium.org"}});
870*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
871*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
872*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
873*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
874*6777b538SAndroid Build Coastguard Worker "Error during WebSocket handshake: "
875*6777b538SAndroid Build Coastguard Worker "'Sec-WebSocket-Protocol' header must not appear "
876*6777b538SAndroid Build Coastguard Worker "more than once in a response",
877*6777b538SAndroid Build Coastguard Worker failure_message());
878*6777b538SAndroid Build Coastguard Worker }
879*6777b538SAndroid Build Coastguard Worker
880*6777b538SAndroid Build Coastguard Worker // Unmatched sub-protocol should be rejected.
TEST_P(WebSocketMultiProtocolStreamCreateTest,UnmatchedSubProtocolInResponse)881*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketMultiProtocolStreamCreateTest, UnmatchedSubProtocolInResponse) {
882*6777b538SAndroid Build Coastguard Worker AddSSLData();
883*6777b538SAndroid Build Coastguard Worker std::vector<std::string> sub_protocols;
884*6777b538SAndroid Build Coastguard Worker sub_protocols.push_back("chatv11.chromium.org");
885*6777b538SAndroid Build Coastguard Worker sub_protocols.push_back("chatv20.chromium.org");
886*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard(
887*6777b538SAndroid Build Coastguard Worker "wss://www.example.org/testing_path", sub_protocols, {},
888*6777b538SAndroid Build Coastguard Worker {{"Sec-WebSocket-Protocol",
889*6777b538SAndroid Build Coastguard Worker "chatv11.chromium.org, chatv20.chromium.org"}},
890*6777b538SAndroid Build Coastguard Worker {{"Sec-WebSocket-Protocol", "chatv21.chromium.org"}});
891*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
892*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
893*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
894*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error during WebSocket handshake: "
895*6777b538SAndroid Build Coastguard Worker "'Sec-WebSocket-Protocol' header value 'chatv21.chromium.org' "
896*6777b538SAndroid Build Coastguard Worker "in response does not match any of sent values",
897*6777b538SAndroid Build Coastguard Worker failure_message());
898*6777b538SAndroid Build Coastguard Worker }
899*6777b538SAndroid Build Coastguard Worker
900*6777b538SAndroid Build Coastguard Worker // permessage-deflate extension basic success case.
TEST_P(WebSocketStreamCreateExtensionTest,PerMessageDeflateSuccess)901*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateExtensionTest, PerMessageDeflateSuccess) {
902*6777b538SAndroid Build Coastguard Worker CreateAndConnectWithExtensions("permessage-deflate");
903*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(stream_);
904*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
905*6777b538SAndroid Build Coastguard Worker }
906*6777b538SAndroid Build Coastguard Worker
907*6777b538SAndroid Build Coastguard Worker // permessage-deflate extensions success with all parameters.
TEST_P(WebSocketStreamCreateExtensionTest,PerMessageDeflateParamsSuccess)908*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateExtensionTest, PerMessageDeflateParamsSuccess) {
909*6777b538SAndroid Build Coastguard Worker CreateAndConnectWithExtensions(
910*6777b538SAndroid Build Coastguard Worker "permessage-deflate; client_no_context_takeover; "
911*6777b538SAndroid Build Coastguard Worker "server_max_window_bits=11; client_max_window_bits=13; "
912*6777b538SAndroid Build Coastguard Worker "server_no_context_takeover");
913*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(stream_);
914*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
915*6777b538SAndroid Build Coastguard Worker }
916*6777b538SAndroid Build Coastguard Worker
917*6777b538SAndroid Build Coastguard Worker // Verify that incoming messages are actually decompressed with
918*6777b538SAndroid Build Coastguard Worker // permessage-deflate enabled.
TEST_P(WebSocketStreamCreateExtensionTest,PerMessageDeflateInflates)919*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateExtensionTest, PerMessageDeflateInflates) {
920*6777b538SAndroid Build Coastguard Worker AddSSLData();
921*6777b538SAndroid Build Coastguard Worker SetAdditionalResponseData(std::string(
922*6777b538SAndroid Build Coastguard Worker "\xc1\x07" // WebSocket header (FIN + RSV1, Text payload 7 bytes)
923*6777b538SAndroid Build Coastguard Worker "\xf2\x48\xcd\xc9\xc9\x07\x00", // "Hello" DEFLATE compressed
924*6777b538SAndroid Build Coastguard Worker 9));
925*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard(
926*6777b538SAndroid Build Coastguard Worker "wss://www.example.org/testing_path", NoSubProtocols(), {}, {},
927*6777b538SAndroid Build Coastguard Worker {{"Sec-WebSocket-Extensions", "permessage-deflate"}});
928*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
929*6777b538SAndroid Build Coastguard Worker
930*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(stream_);
931*6777b538SAndroid Build Coastguard Worker std::vector<std::unique_ptr<WebSocketFrame>> frames;
932*6777b538SAndroid Build Coastguard Worker TestCompletionCallback callback;
933*6777b538SAndroid Build Coastguard Worker int rv = stream_->ReadFrames(&frames, callback.callback());
934*6777b538SAndroid Build Coastguard Worker rv = callback.GetResult(rv);
935*6777b538SAndroid Build Coastguard Worker ASSERT_THAT(rv, IsOk());
936*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(1U, frames.size());
937*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(5U, frames[0]->header.payload_length);
938*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(std::string("Hello"),
939*6777b538SAndroid Build Coastguard Worker std::string(frames[0]->payload, frames[0]->header.payload_length));
940*6777b538SAndroid Build Coastguard Worker }
941*6777b538SAndroid Build Coastguard Worker
942*6777b538SAndroid Build Coastguard Worker // Unknown extension in the response is rejected
TEST_P(WebSocketStreamCreateExtensionTest,UnknownExtension)943*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateExtensionTest, UnknownExtension) {
944*6777b538SAndroid Build Coastguard Worker CreateAndConnectWithExtensions("x-unknown-extension");
945*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
946*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
947*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error during WebSocket handshake: "
948*6777b538SAndroid Build Coastguard Worker "Found an unsupported extension 'x-unknown-extension' "
949*6777b538SAndroid Build Coastguard Worker "in 'Sec-WebSocket-Extensions' header",
950*6777b538SAndroid Build Coastguard Worker failure_message());
951*6777b538SAndroid Build Coastguard Worker }
952*6777b538SAndroid Build Coastguard Worker
953*6777b538SAndroid Build Coastguard Worker // Malformed extensions are rejected (this file does not cover all possible
954*6777b538SAndroid Build Coastguard Worker // parse failures, as the parser is covered thoroughly by its own unit tests).
TEST_P(WebSocketStreamCreateExtensionTest,MalformedExtension)955*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateExtensionTest, MalformedExtension) {
956*6777b538SAndroid Build Coastguard Worker CreateAndConnectWithExtensions(";");
957*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
958*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
959*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
960*6777b538SAndroid Build Coastguard Worker "Error during WebSocket handshake: 'Sec-WebSocket-Extensions' header "
961*6777b538SAndroid Build Coastguard Worker "value is rejected by the parser: ;",
962*6777b538SAndroid Build Coastguard Worker failure_message());
963*6777b538SAndroid Build Coastguard Worker }
964*6777b538SAndroid Build Coastguard Worker
965*6777b538SAndroid Build Coastguard Worker // The permessage-deflate extension may only be specified once.
TEST_P(WebSocketStreamCreateExtensionTest,OnlyOnePerMessageDeflateAllowed)966*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateExtensionTest, OnlyOnePerMessageDeflateAllowed) {
967*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
968*6777b538SAndroid Build Coastguard Worker
969*6777b538SAndroid Build Coastguard Worker CreateAndConnectWithExtensions(
970*6777b538SAndroid Build Coastguard Worker "permessage-deflate, permessage-deflate; client_max_window_bits=10");
971*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
972*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
973*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
974*6777b538SAndroid Build Coastguard Worker "Error during WebSocket handshake: "
975*6777b538SAndroid Build Coastguard Worker "Received duplicate permessage-deflate response",
976*6777b538SAndroid Build Coastguard Worker failure_message());
977*6777b538SAndroid Build Coastguard Worker
978*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
979*6777b538SAndroid Build Coastguard Worker
980*6777b538SAndroid Build Coastguard Worker auto samples = histogram_tester.GetHistogramSamplesSinceCreation(
981*6777b538SAndroid Build Coastguard Worker "Net.WebSocket.HandshakeResult2");
982*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->TotalCount());
983*6777b538SAndroid Build Coastguard Worker if (stream_type_ == BASIC_HANDSHAKE_STREAM) {
984*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
985*6777b538SAndroid Build Coastguard Worker 1,
986*6777b538SAndroid Build Coastguard Worker samples->GetCount(static_cast<int>(
987*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::HandshakeResult::FAILED_EXTENSIONS)));
988*6777b538SAndroid Build Coastguard Worker } else {
989*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(stream_type_, HTTP2_HANDSHAKE_STREAM);
990*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->GetCount(static_cast<int>(
991*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::HandshakeResult::
992*6777b538SAndroid Build Coastguard Worker HTTP2_FAILED_EXTENSIONS)));
993*6777b538SAndroid Build Coastguard Worker }
994*6777b538SAndroid Build Coastguard Worker }
995*6777b538SAndroid Build Coastguard Worker
996*6777b538SAndroid Build Coastguard Worker // client_max_window_bits must have an argument
TEST_P(WebSocketStreamCreateExtensionTest,NoMaxWindowBitsArgument)997*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateExtensionTest, NoMaxWindowBitsArgument) {
998*6777b538SAndroid Build Coastguard Worker CreateAndConnectWithExtensions("permessage-deflate; client_max_window_bits");
999*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
1000*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1001*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
1002*6777b538SAndroid Build Coastguard Worker "Error during WebSocket handshake: Error in permessage-deflate: "
1003*6777b538SAndroid Build Coastguard Worker "client_max_window_bits must have value",
1004*6777b538SAndroid Build Coastguard Worker failure_message());
1005*6777b538SAndroid Build Coastguard Worker }
1006*6777b538SAndroid Build Coastguard Worker
1007*6777b538SAndroid Build Coastguard Worker // Other cases for permessage-deflate parameters are tested in
1008*6777b538SAndroid Build Coastguard Worker // websocket_deflate_parameters_test.cc.
1009*6777b538SAndroid Build Coastguard Worker
1010*6777b538SAndroid Build Coastguard Worker // TODO(ricea): Check that WebSocketDeflateStream is initialised with the
1011*6777b538SAndroid Build Coastguard Worker // arguments from the server. This is difficult because the data written to the
1012*6777b538SAndroid Build Coastguard Worker // socket is randomly masked.
1013*6777b538SAndroid Build Coastguard Worker
1014*6777b538SAndroid Build Coastguard Worker // Additional Sec-WebSocket-Accept headers should be rejected.
TEST_P(WebSocketStreamCreateTest,DoubleAccept)1015*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, DoubleAccept) {
1016*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard(
1017*6777b538SAndroid Build Coastguard Worker "ws://www.example.org/", NoSubProtocols(), {}, {},
1018*6777b538SAndroid Build Coastguard Worker {{"Sec-WebSocket-Accept", "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="}});
1019*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1020*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
1021*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1022*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error during WebSocket handshake: "
1023*6777b538SAndroid Build Coastguard Worker "'Sec-WebSocket-Accept' header must not appear "
1024*6777b538SAndroid Build Coastguard Worker "more than once in a response",
1025*6777b538SAndroid Build Coastguard Worker failure_message());
1026*6777b538SAndroid Build Coastguard Worker }
1027*6777b538SAndroid Build Coastguard Worker
1028*6777b538SAndroid Build Coastguard Worker // When upgrading an HTTP/1 connection, response code 200 is invalid and must be
1029*6777b538SAndroid Build Coastguard Worker // rejected. Response code 101 means success. On the other hand, when
1030*6777b538SAndroid Build Coastguard Worker // requesting a WebSocket stream over HTTP/2, response code 101 is invalid and
1031*6777b538SAndroid Build Coastguard Worker // must be rejected. Response code 200 means success.
TEST_P(WebSocketMultiProtocolStreamCreateTest,InvalidStatusCode)1032*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketMultiProtocolStreamCreateTest, InvalidStatusCode) {
1033*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
1034*6777b538SAndroid Build Coastguard Worker
1035*6777b538SAndroid Build Coastguard Worker AddSSLData();
1036*6777b538SAndroid Build Coastguard Worker if (stream_type_ == BASIC_HANDSHAKE_STREAM) {
1037*6777b538SAndroid Build Coastguard Worker static constexpr char kInvalidStatusCodeResponse[] =
1038*6777b538SAndroid Build Coastguard Worker "HTTP/1.1 200 OK\r\n"
1039*6777b538SAndroid Build Coastguard Worker "Upgrade: websocket\r\n"
1040*6777b538SAndroid Build Coastguard Worker "Connection: Upgrade\r\n"
1041*6777b538SAndroid Build Coastguard Worker "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
1042*6777b538SAndroid Build Coastguard Worker "\r\n";
1043*6777b538SAndroid Build Coastguard Worker CreateAndConnectCustomResponse("wss://www.example.org/", NoSubProtocols(),
1044*6777b538SAndroid Build Coastguard Worker {}, {}, kInvalidStatusCodeResponse);
1045*6777b538SAndroid Build Coastguard Worker } else {
1046*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(stream_type_, HTTP2_HANDSHAKE_STREAM);
1047*6777b538SAndroid Build Coastguard Worker SetHttp2ResponseStatus("101");
1048*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard("wss://www.example.org/", NoSubProtocols(), {}, {},
1049*6777b538SAndroid Build Coastguard Worker {});
1050*6777b538SAndroid Build Coastguard Worker }
1051*6777b538SAndroid Build Coastguard Worker
1052*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1053*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
1054*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1055*6777b538SAndroid Build Coastguard Worker auto samples = histogram_tester.GetHistogramSamplesSinceCreation(
1056*6777b538SAndroid Build Coastguard Worker "Net.WebSocket.HandshakeResult2");
1057*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->TotalCount());
1058*6777b538SAndroid Build Coastguard Worker
1059*6777b538SAndroid Build Coastguard Worker if (stream_type_ == BASIC_HANDSHAKE_STREAM) {
1060*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 200",
1061*6777b538SAndroid Build Coastguard Worker failure_message());
1062*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(failure_response_code(), 200);
1063*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
1064*6777b538SAndroid Build Coastguard Worker 1, samples->GetCount(static_cast<int>(
1065*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::HandshakeResult::INVALID_STATUS)));
1066*6777b538SAndroid Build Coastguard Worker } else {
1067*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(stream_type_, HTTP2_HANDSHAKE_STREAM);
1068*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 101",
1069*6777b538SAndroid Build Coastguard Worker failure_message());
1070*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(failure_response_code(), 101);
1071*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->GetCount(static_cast<int>(
1072*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::HandshakeResult::
1073*6777b538SAndroid Build Coastguard Worker HTTP2_INVALID_STATUS)));
1074*6777b538SAndroid Build Coastguard Worker }
1075*6777b538SAndroid Build Coastguard Worker }
1076*6777b538SAndroid Build Coastguard Worker
1077*6777b538SAndroid Build Coastguard Worker // Redirects are not followed (according to the WHATWG WebSocket API, which
1078*6777b538SAndroid Build Coastguard Worker // overrides RFC6455 for browser applications).
TEST_P(WebSocketMultiProtocolStreamCreateTest,RedirectsRejected)1079*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketMultiProtocolStreamCreateTest, RedirectsRejected) {
1080*6777b538SAndroid Build Coastguard Worker AddSSLData();
1081*6777b538SAndroid Build Coastguard Worker if (stream_type_ == BASIC_HANDSHAKE_STREAM) {
1082*6777b538SAndroid Build Coastguard Worker static constexpr char kRedirectResponse[] =
1083*6777b538SAndroid Build Coastguard Worker "HTTP/1.1 302 Moved Temporarily\r\n"
1084*6777b538SAndroid Build Coastguard Worker "Content-Type: text/html\r\n"
1085*6777b538SAndroid Build Coastguard Worker "Content-Length: 34\r\n"
1086*6777b538SAndroid Build Coastguard Worker "Connection: keep-alive\r\n"
1087*6777b538SAndroid Build Coastguard Worker "Location: wss://www.example.org/other\r\n"
1088*6777b538SAndroid Build Coastguard Worker "\r\n"
1089*6777b538SAndroid Build Coastguard Worker "<title>Moved</title><h1>Moved</h1>";
1090*6777b538SAndroid Build Coastguard Worker CreateAndConnectCustomResponse("wss://www.example.org/", NoSubProtocols(),
1091*6777b538SAndroid Build Coastguard Worker {}, {}, kRedirectResponse);
1092*6777b538SAndroid Build Coastguard Worker } else {
1093*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(stream_type_, HTTP2_HANDSHAKE_STREAM);
1094*6777b538SAndroid Build Coastguard Worker SetHttp2ResponseStatus("302");
1095*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard("wss://www.example.org/", NoSubProtocols(), {}, {},
1096*6777b538SAndroid Build Coastguard Worker {});
1097*6777b538SAndroid Build Coastguard Worker }
1098*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1099*6777b538SAndroid Build Coastguard Worker
1100*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1101*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 302",
1102*6777b538SAndroid Build Coastguard Worker failure_message());
1103*6777b538SAndroid Build Coastguard Worker }
1104*6777b538SAndroid Build Coastguard Worker
1105*6777b538SAndroid Build Coastguard Worker // Malformed responses should be rejected. HttpStreamParser will accept just
1106*6777b538SAndroid Build Coastguard Worker // about any garbage in the middle of the headers. To make it give up, the junk
1107*6777b538SAndroid Build Coastguard Worker // has to be at the start of the response. Even then, it just gets treated as an
1108*6777b538SAndroid Build Coastguard Worker // HTTP/0.9 response.
TEST_P(WebSocketStreamCreateTest,MalformedResponse)1109*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, MalformedResponse) {
1110*6777b538SAndroid Build Coastguard Worker static constexpr char kMalformedResponse[] =
1111*6777b538SAndroid Build Coastguard Worker "220 mx.google.com ESMTP\r\n"
1112*6777b538SAndroid Build Coastguard Worker "HTTP/1.1 101 OK\r\n"
1113*6777b538SAndroid Build Coastguard Worker "Upgrade: websocket\r\n"
1114*6777b538SAndroid Build Coastguard Worker "Connection: Upgrade\r\n"
1115*6777b538SAndroid Build Coastguard Worker "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
1116*6777b538SAndroid Build Coastguard Worker "\r\n";
1117*6777b538SAndroid Build Coastguard Worker CreateAndConnectCustomResponse("ws://www.example.org/", NoSubProtocols(), {},
1118*6777b538SAndroid Build Coastguard Worker {}, kMalformedResponse);
1119*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1120*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1121*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error during WebSocket handshake: Invalid status line",
1122*6777b538SAndroid Build Coastguard Worker failure_message());
1123*6777b538SAndroid Build Coastguard Worker }
1124*6777b538SAndroid Build Coastguard Worker
1125*6777b538SAndroid Build Coastguard Worker // Upgrade header must be present.
TEST_P(WebSocketStreamCreateTest,MissingUpgradeHeader)1126*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, MissingUpgradeHeader) {
1127*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
1128*6777b538SAndroid Build Coastguard Worker
1129*6777b538SAndroid Build Coastguard Worker static constexpr char kMissingUpgradeResponse[] =
1130*6777b538SAndroid Build Coastguard Worker "HTTP/1.1 101 Switching Protocols\r\n"
1131*6777b538SAndroid Build Coastguard Worker "Connection: Upgrade\r\n"
1132*6777b538SAndroid Build Coastguard Worker "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
1133*6777b538SAndroid Build Coastguard Worker "\r\n";
1134*6777b538SAndroid Build Coastguard Worker CreateAndConnectCustomResponse("ws://www.example.org/", NoSubProtocols(), {},
1135*6777b538SAndroid Build Coastguard Worker {}, kMissingUpgradeResponse);
1136*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1137*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1138*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error during WebSocket handshake: 'Upgrade' header is missing",
1139*6777b538SAndroid Build Coastguard Worker failure_message());
1140*6777b538SAndroid Build Coastguard Worker
1141*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
1142*6777b538SAndroid Build Coastguard Worker
1143*6777b538SAndroid Build Coastguard Worker auto samples = histogram_tester.GetHistogramSamplesSinceCreation(
1144*6777b538SAndroid Build Coastguard Worker "Net.WebSocket.HandshakeResult2");
1145*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->TotalCount());
1146*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
1147*6777b538SAndroid Build Coastguard Worker 1, samples->GetCount(static_cast<int>(
1148*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::HandshakeResult::FAILED_UPGRADE)));
1149*6777b538SAndroid Build Coastguard Worker }
1150*6777b538SAndroid Build Coastguard Worker
1151*6777b538SAndroid Build Coastguard Worker // There must only be one upgrade header.
TEST_P(WebSocketStreamCreateTest,DoubleUpgradeHeader)1152*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, DoubleUpgradeHeader) {
1153*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard("ws://www.example.org/", NoSubProtocols(), {}, {},
1154*6777b538SAndroid Build Coastguard Worker {{"Upgrade", "HTTP/2.0"}});
1155*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1156*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1157*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error during WebSocket handshake: "
1158*6777b538SAndroid Build Coastguard Worker "'Upgrade' header must not appear more than once in a response",
1159*6777b538SAndroid Build Coastguard Worker failure_message());
1160*6777b538SAndroid Build Coastguard Worker }
1161*6777b538SAndroid Build Coastguard Worker
1162*6777b538SAndroid Build Coastguard Worker // There must only be one correct upgrade header.
TEST_P(WebSocketStreamCreateTest,IncorrectUpgradeHeader)1163*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, IncorrectUpgradeHeader) {
1164*6777b538SAndroid Build Coastguard Worker static constexpr char kMissingUpgradeResponse[] =
1165*6777b538SAndroid Build Coastguard Worker "HTTP/1.1 101 Switching Protocols\r\n"
1166*6777b538SAndroid Build Coastguard Worker "Connection: Upgrade\r\n"
1167*6777b538SAndroid Build Coastguard Worker "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
1168*6777b538SAndroid Build Coastguard Worker "Upgrade: hogefuga\r\n"
1169*6777b538SAndroid Build Coastguard Worker "\r\n";
1170*6777b538SAndroid Build Coastguard Worker CreateAndConnectCustomResponse("ws://www.example.org/", NoSubProtocols(), {},
1171*6777b538SAndroid Build Coastguard Worker {}, kMissingUpgradeResponse);
1172*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1173*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1174*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error during WebSocket handshake: "
1175*6777b538SAndroid Build Coastguard Worker "'Upgrade' header value is not 'WebSocket': hogefuga",
1176*6777b538SAndroid Build Coastguard Worker failure_message());
1177*6777b538SAndroid Build Coastguard Worker }
1178*6777b538SAndroid Build Coastguard Worker
1179*6777b538SAndroid Build Coastguard Worker // Connection header must be present.
TEST_P(WebSocketStreamCreateTest,MissingConnectionHeader)1180*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, MissingConnectionHeader) {
1181*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
1182*6777b538SAndroid Build Coastguard Worker
1183*6777b538SAndroid Build Coastguard Worker static constexpr char kMissingConnectionResponse[] =
1184*6777b538SAndroid Build Coastguard Worker "HTTP/1.1 101 Switching Protocols\r\n"
1185*6777b538SAndroid Build Coastguard Worker "Upgrade: websocket\r\n"
1186*6777b538SAndroid Build Coastguard Worker "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
1187*6777b538SAndroid Build Coastguard Worker "\r\n";
1188*6777b538SAndroid Build Coastguard Worker CreateAndConnectCustomResponse("ws://www.example.org/", NoSubProtocols(), {},
1189*6777b538SAndroid Build Coastguard Worker {}, kMissingConnectionResponse);
1190*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1191*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1192*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error during WebSocket handshake: "
1193*6777b538SAndroid Build Coastguard Worker "'Connection' header is missing",
1194*6777b538SAndroid Build Coastguard Worker failure_message());
1195*6777b538SAndroid Build Coastguard Worker
1196*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
1197*6777b538SAndroid Build Coastguard Worker
1198*6777b538SAndroid Build Coastguard Worker auto samples = histogram_tester.GetHistogramSamplesSinceCreation(
1199*6777b538SAndroid Build Coastguard Worker "Net.WebSocket.HandshakeResult2");
1200*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->TotalCount());
1201*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
1202*6777b538SAndroid Build Coastguard Worker 1,
1203*6777b538SAndroid Build Coastguard Worker samples->GetCount(static_cast<int>(
1204*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::HandshakeResult::FAILED_CONNECTION)));
1205*6777b538SAndroid Build Coastguard Worker }
1206*6777b538SAndroid Build Coastguard Worker
1207*6777b538SAndroid Build Coastguard Worker // Connection header must contain "Upgrade".
TEST_P(WebSocketStreamCreateTest,IncorrectConnectionHeader)1208*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, IncorrectConnectionHeader) {
1209*6777b538SAndroid Build Coastguard Worker static constexpr char kMissingConnectionResponse[] =
1210*6777b538SAndroid Build Coastguard Worker "HTTP/1.1 101 Switching Protocols\r\n"
1211*6777b538SAndroid Build Coastguard Worker "Upgrade: websocket\r\n"
1212*6777b538SAndroid Build Coastguard Worker "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
1213*6777b538SAndroid Build Coastguard Worker "Connection: hogefuga\r\n"
1214*6777b538SAndroid Build Coastguard Worker "\r\n";
1215*6777b538SAndroid Build Coastguard Worker CreateAndConnectCustomResponse("ws://www.example.org/", NoSubProtocols(), {},
1216*6777b538SAndroid Build Coastguard Worker {}, kMissingConnectionResponse);
1217*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1218*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1219*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error during WebSocket handshake: "
1220*6777b538SAndroid Build Coastguard Worker "'Connection' header value must contain 'Upgrade'",
1221*6777b538SAndroid Build Coastguard Worker failure_message());
1222*6777b538SAndroid Build Coastguard Worker }
1223*6777b538SAndroid Build Coastguard Worker
1224*6777b538SAndroid Build Coastguard Worker // Connection header is permitted to contain other tokens.
TEST_P(WebSocketStreamCreateTest,AdditionalTokenInConnectionHeader)1225*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, AdditionalTokenInConnectionHeader) {
1226*6777b538SAndroid Build Coastguard Worker static constexpr char kAdditionalConnectionTokenResponse[] =
1227*6777b538SAndroid Build Coastguard Worker "HTTP/1.1 101 Switching Protocols\r\n"
1228*6777b538SAndroid Build Coastguard Worker "Upgrade: websocket\r\n"
1229*6777b538SAndroid Build Coastguard Worker "Connection: Upgrade, Keep-Alive\r\n"
1230*6777b538SAndroid Build Coastguard Worker "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
1231*6777b538SAndroid Build Coastguard Worker "\r\n";
1232*6777b538SAndroid Build Coastguard Worker CreateAndConnectCustomResponse("ws://www.example.org/", NoSubProtocols(), {},
1233*6777b538SAndroid Build Coastguard Worker {}, kAdditionalConnectionTokenResponse);
1234*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1235*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
1236*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(stream_);
1237*6777b538SAndroid Build Coastguard Worker }
1238*6777b538SAndroid Build Coastguard Worker
1239*6777b538SAndroid Build Coastguard Worker // Sec-WebSocket-Accept header must be present.
TEST_P(WebSocketStreamCreateTest,MissingSecWebSocketAccept)1240*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, MissingSecWebSocketAccept) {
1241*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
1242*6777b538SAndroid Build Coastguard Worker
1243*6777b538SAndroid Build Coastguard Worker static constexpr char kMissingAcceptResponse[] =
1244*6777b538SAndroid Build Coastguard Worker "HTTP/1.1 101 Switching Protocols\r\n"
1245*6777b538SAndroid Build Coastguard Worker "Upgrade: websocket\r\n"
1246*6777b538SAndroid Build Coastguard Worker "Connection: Upgrade\r\n"
1247*6777b538SAndroid Build Coastguard Worker "\r\n";
1248*6777b538SAndroid Build Coastguard Worker CreateAndConnectCustomResponse("ws://www.example.org/", NoSubProtocols(), {},
1249*6777b538SAndroid Build Coastguard Worker {}, kMissingAcceptResponse);
1250*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1251*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1252*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error during WebSocket handshake: "
1253*6777b538SAndroid Build Coastguard Worker "'Sec-WebSocket-Accept' header is missing",
1254*6777b538SAndroid Build Coastguard Worker failure_message());
1255*6777b538SAndroid Build Coastguard Worker
1256*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
1257*6777b538SAndroid Build Coastguard Worker
1258*6777b538SAndroid Build Coastguard Worker auto samples = histogram_tester.GetHistogramSamplesSinceCreation(
1259*6777b538SAndroid Build Coastguard Worker "Net.WebSocket.HandshakeResult2");
1260*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->TotalCount());
1261*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1,
1262*6777b538SAndroid Build Coastguard Worker samples->GetCount(static_cast<int>(
1263*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::HandshakeResult::FAILED_ACCEPT)));
1264*6777b538SAndroid Build Coastguard Worker }
1265*6777b538SAndroid Build Coastguard Worker
1266*6777b538SAndroid Build Coastguard Worker // Sec-WebSocket-Accept header must match the key that was sent.
TEST_P(WebSocketStreamCreateTest,WrongSecWebSocketAccept)1267*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, WrongSecWebSocketAccept) {
1268*6777b538SAndroid Build Coastguard Worker static constexpr char kIncorrectAcceptResponse[] =
1269*6777b538SAndroid Build Coastguard Worker "HTTP/1.1 101 Switching Protocols\r\n"
1270*6777b538SAndroid Build Coastguard Worker "Upgrade: websocket\r\n"
1271*6777b538SAndroid Build Coastguard Worker "Connection: Upgrade\r\n"
1272*6777b538SAndroid Build Coastguard Worker "Sec-WebSocket-Accept: x/byyPZ2tOFvJCGkkugcKvqhhPk=\r\n"
1273*6777b538SAndroid Build Coastguard Worker "\r\n";
1274*6777b538SAndroid Build Coastguard Worker CreateAndConnectCustomResponse("ws://www.example.org/", NoSubProtocols(), {},
1275*6777b538SAndroid Build Coastguard Worker {}, kIncorrectAcceptResponse);
1276*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1277*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1278*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error during WebSocket handshake: "
1279*6777b538SAndroid Build Coastguard Worker "Incorrect 'Sec-WebSocket-Accept' header value",
1280*6777b538SAndroid Build Coastguard Worker failure_message());
1281*6777b538SAndroid Build Coastguard Worker }
1282*6777b538SAndroid Build Coastguard Worker
1283*6777b538SAndroid Build Coastguard Worker // Cancellation works.
TEST_P(WebSocketStreamCreateTest,Cancellation)1284*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, Cancellation) {
1285*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard("ws://www.example.org/", NoSubProtocols(), {}, {},
1286*6777b538SAndroid Build Coastguard Worker {});
1287*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
1288*6777b538SAndroid Build Coastguard Worker // WaitUntilConnectDone doesn't work in this case.
1289*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
1290*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
1291*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
1292*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(request_info_);
1293*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(response_info_);
1294*6777b538SAndroid Build Coastguard Worker }
1295*6777b538SAndroid Build Coastguard Worker
1296*6777b538SAndroid Build Coastguard Worker // Connect failure must look just like negotiation failure.
TEST_P(WebSocketStreamCreateTest,ConnectionFailure)1297*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, ConnectionFailure) {
1298*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SequencedSocketData> socket_data(BuildNullSocketData());
1299*6777b538SAndroid Build Coastguard Worker socket_data->set_connect_data(
1300*6777b538SAndroid Build Coastguard Worker MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
1301*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations("ws://www.example.org/", NoSubProtocols(),
1302*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders(), std::move(socket_data));
1303*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1304*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1305*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_REFUSED",
1306*6777b538SAndroid Build Coastguard Worker failure_message());
1307*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(request_info_);
1308*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(response_info_);
1309*6777b538SAndroid Build Coastguard Worker }
1310*6777b538SAndroid Build Coastguard Worker
1311*6777b538SAndroid Build Coastguard Worker // Connect timeout must look just like any other failure.
TEST_P(WebSocketStreamCreateTest,ConnectionTimeout)1312*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, ConnectionTimeout) {
1313*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SequencedSocketData> socket_data(BuildNullSocketData());
1314*6777b538SAndroid Build Coastguard Worker socket_data->set_connect_data(
1315*6777b538SAndroid Build Coastguard Worker MockConnect(ASYNC, ERR_CONNECTION_TIMED_OUT));
1316*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations("ws://www.example.org/", NoSubProtocols(),
1317*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders(), std::move(socket_data));
1318*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1319*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1320*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT",
1321*6777b538SAndroid Build Coastguard Worker failure_message());
1322*6777b538SAndroid Build Coastguard Worker }
1323*6777b538SAndroid Build Coastguard Worker
1324*6777b538SAndroid Build Coastguard Worker // The server doesn't respond to the opening handshake.
TEST_P(WebSocketStreamCreateTest,HandshakeTimeout)1325*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, HandshakeTimeout) {
1326*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SequencedSocketData> socket_data(BuildNullSocketData());
1327*6777b538SAndroid Build Coastguard Worker socket_data->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
1328*6777b538SAndroid Build Coastguard Worker auto timer = std::make_unique<MockWeakTimer>();
1329*6777b538SAndroid Build Coastguard Worker base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr();
1330*6777b538SAndroid Build Coastguard Worker SetTimer(std::move(timer));
1331*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations("ws://www.example.org/", NoSubProtocols(),
1332*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders(), std::move(socket_data));
1333*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
1334*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(weak_timer.get());
1335*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(weak_timer->IsRunning());
1336*6777b538SAndroid Build Coastguard Worker
1337*6777b538SAndroid Build Coastguard Worker weak_timer->Fire();
1338*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1339*6777b538SAndroid Build Coastguard Worker
1340*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1341*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("WebSocket opening handshake timed out", failure_message());
1342*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(weak_timer.get());
1343*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(weak_timer->IsRunning());
1344*6777b538SAndroid Build Coastguard Worker }
1345*6777b538SAndroid Build Coastguard Worker
1346*6777b538SAndroid Build Coastguard Worker // When the connection establishes the timer should be stopped.
TEST_P(WebSocketStreamCreateTest,HandshakeTimerOnSuccess)1347*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, HandshakeTimerOnSuccess) {
1348*6777b538SAndroid Build Coastguard Worker auto timer = std::make_unique<MockWeakTimer>();
1349*6777b538SAndroid Build Coastguard Worker base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr();
1350*6777b538SAndroid Build Coastguard Worker
1351*6777b538SAndroid Build Coastguard Worker SetTimer(std::move(timer));
1352*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard("ws://www.example.org/", NoSubProtocols(), {}, {},
1353*6777b538SAndroid Build Coastguard Worker {});
1354*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(weak_timer);
1355*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(weak_timer->IsRunning());
1356*6777b538SAndroid Build Coastguard Worker
1357*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1358*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
1359*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(stream_);
1360*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(weak_timer);
1361*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(weak_timer->IsRunning());
1362*6777b538SAndroid Build Coastguard Worker }
1363*6777b538SAndroid Build Coastguard Worker
1364*6777b538SAndroid Build Coastguard Worker // When the connection fails the timer should be stopped.
TEST_P(WebSocketStreamCreateTest,HandshakeTimerOnFailure)1365*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, HandshakeTimerOnFailure) {
1366*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SequencedSocketData> socket_data(BuildNullSocketData());
1367*6777b538SAndroid Build Coastguard Worker socket_data->set_connect_data(
1368*6777b538SAndroid Build Coastguard Worker MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
1369*6777b538SAndroid Build Coastguard Worker auto timer = std::make_unique<MockWeakTimer>();
1370*6777b538SAndroid Build Coastguard Worker base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr();
1371*6777b538SAndroid Build Coastguard Worker SetTimer(std::move(timer));
1372*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations("ws://www.example.org/", NoSubProtocols(),
1373*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders(), std::move(socket_data));
1374*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(weak_timer.get());
1375*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(weak_timer->IsRunning());
1376*6777b538SAndroid Build Coastguard Worker
1377*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1378*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1379*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Error in connection establishment: net::ERR_CONNECTION_REFUSED",
1380*6777b538SAndroid Build Coastguard Worker failure_message());
1381*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(weak_timer.get());
1382*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(weak_timer->IsRunning());
1383*6777b538SAndroid Build Coastguard Worker }
1384*6777b538SAndroid Build Coastguard Worker
1385*6777b538SAndroid Build Coastguard Worker // Cancellation during connect works.
TEST_P(WebSocketStreamCreateTest,CancellationDuringConnect)1386*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, CancellationDuringConnect) {
1387*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SequencedSocketData> socket_data(BuildNullSocketData());
1388*6777b538SAndroid Build Coastguard Worker socket_data->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
1389*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations("ws://www.example.org/", NoSubProtocols(),
1390*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders(), std::move(socket_data));
1391*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
1392*6777b538SAndroid Build Coastguard Worker // WaitUntilConnectDone doesn't work in this case.
1393*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
1394*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
1395*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
1396*6777b538SAndroid Build Coastguard Worker }
1397*6777b538SAndroid Build Coastguard Worker
1398*6777b538SAndroid Build Coastguard Worker // Cancellation during write of the request headers works.
TEST_P(WebSocketStreamCreateTest,CancellationDuringWrite)1399*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, CancellationDuringWrite) {
1400*6777b538SAndroid Build Coastguard Worker // First write never completes.
1401*6777b538SAndroid Build Coastguard Worker MockWrite writes[] = {MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 0)};
1402*6777b538SAndroid Build Coastguard Worker auto socket_data =
1403*6777b538SAndroid Build Coastguard Worker std::make_unique<SequencedSocketData>(base::span<MockRead>(), writes);
1404*6777b538SAndroid Build Coastguard Worker auto* socket_data_ptr = socket_data.get();
1405*6777b538SAndroid Build Coastguard Worker socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
1406*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations("ws://www.example.org/", NoSubProtocols(),
1407*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders(), std::move(socket_data));
1408*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
1409*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(socket_data_ptr->AllWriteDataConsumed());
1410*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
1411*6777b538SAndroid Build Coastguard Worker // WaitUntilConnectDone doesn't work in this case.
1412*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
1413*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
1414*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
1415*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(request_info_);
1416*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(response_info_);
1417*6777b538SAndroid Build Coastguard Worker }
1418*6777b538SAndroid Build Coastguard Worker
1419*6777b538SAndroid Build Coastguard Worker // Cancellation during read of the response headers works.
TEST_P(WebSocketStreamCreateTest,CancellationDuringRead)1420*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, CancellationDuringRead) {
1421*6777b538SAndroid Build Coastguard Worker std::string request = WebSocketStandardRequest(
1422*6777b538SAndroid Build Coastguard Worker "/", "www.example.org", Origin(), /*send_additional_request_headers=*/{},
1423*6777b538SAndroid Build Coastguard Worker /*extra_headers=*/{});
1424*6777b538SAndroid Build Coastguard Worker MockWrite writes[] = {MockWrite(ASYNC, 0, request.c_str())};
1425*6777b538SAndroid Build Coastguard Worker MockRead reads[] = {
1426*6777b538SAndroid Build Coastguard Worker MockRead(SYNCHRONOUS, ERR_IO_PENDING, 1),
1427*6777b538SAndroid Build Coastguard Worker };
1428*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SequencedSocketData> socket_data(
1429*6777b538SAndroid Build Coastguard Worker BuildSocketData(reads, writes));
1430*6777b538SAndroid Build Coastguard Worker SequencedSocketData* socket_data_raw_ptr = socket_data.get();
1431*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations("ws://www.example.org/", NoSubProtocols(),
1432*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders(), std::move(socket_data));
1433*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
1434*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(socket_data_raw_ptr->AllReadDataConsumed());
1435*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
1436*6777b538SAndroid Build Coastguard Worker // WaitUntilConnectDone doesn't work in this case.
1437*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
1438*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
1439*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
1440*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(request_info_);
1441*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(response_info_);
1442*6777b538SAndroid Build Coastguard Worker }
1443*6777b538SAndroid Build Coastguard Worker
1444*6777b538SAndroid Build Coastguard Worker // Over-size response headers (> 256KB) should not cause a crash. This is a
1445*6777b538SAndroid Build Coastguard Worker // regression test for crbug.com/339456. It is based on the layout test
1446*6777b538SAndroid Build Coastguard Worker // "cookie-flood.html".
TEST_P(WebSocketStreamCreateTest,VeryLargeResponseHeaders)1447*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, VeryLargeResponseHeaders) {
1448*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
1449*6777b538SAndroid Build Coastguard Worker
1450*6777b538SAndroid Build Coastguard Worker std::string set_cookie_headers;
1451*6777b538SAndroid Build Coastguard Worker set_cookie_headers.reserve(24 * 20000);
1452*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < 20000; ++i) {
1453*6777b538SAndroid Build Coastguard Worker set_cookie_headers += base::StringPrintf("Set-Cookie: ws-%d=1\r\n", i);
1454*6777b538SAndroid Build Coastguard Worker }
1455*6777b538SAndroid Build Coastguard Worker ASSERT_GT(set_cookie_headers.size(), 256U * 1024U);
1456*6777b538SAndroid Build Coastguard Worker CreateAndConnectStringResponse("ws://www.example.org/", NoSubProtocols(),
1457*6777b538SAndroid Build Coastguard Worker set_cookie_headers);
1458*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1459*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1460*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(response_info_);
1461*6777b538SAndroid Build Coastguard Worker
1462*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
1463*6777b538SAndroid Build Coastguard Worker
1464*6777b538SAndroid Build Coastguard Worker auto samples = histogram_tester.GetHistogramSamplesSinceCreation(
1465*6777b538SAndroid Build Coastguard Worker "Net.WebSocket.HandshakeResult2");
1466*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->TotalCount());
1467*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->GetCount(static_cast<int>(
1468*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::HandshakeResult::FAILED)));
1469*6777b538SAndroid Build Coastguard Worker }
1470*6777b538SAndroid Build Coastguard Worker
1471*6777b538SAndroid Build Coastguard Worker // If the remote host closes the connection without sending headers, we should
1472*6777b538SAndroid Build Coastguard Worker // log the console message "Connection closed before receiving a handshake
1473*6777b538SAndroid Build Coastguard Worker // response".
TEST_P(WebSocketStreamCreateTest,NoResponse)1474*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, NoResponse) {
1475*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
1476*6777b538SAndroid Build Coastguard Worker
1477*6777b538SAndroid Build Coastguard Worker std::string request = WebSocketStandardRequest(
1478*6777b538SAndroid Build Coastguard Worker "/", "www.example.org", Origin(), /*send_additional_request_headers=*/{},
1479*6777b538SAndroid Build Coastguard Worker /*extra_headers=*/{});
1480*6777b538SAndroid Build Coastguard Worker MockWrite writes[] = {MockWrite(ASYNC, request.data(), request.size(), 0)};
1481*6777b538SAndroid Build Coastguard Worker MockRead reads[] = {MockRead(ASYNC, 0, 1)};
1482*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SequencedSocketData> socket_data(
1483*6777b538SAndroid Build Coastguard Worker BuildSocketData(reads, writes));
1484*6777b538SAndroid Build Coastguard Worker SequencedSocketData* socket_data_raw_ptr = socket_data.get();
1485*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations("ws://www.example.org/", NoSubProtocols(),
1486*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders(), std::move(socket_data));
1487*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
1488*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(socket_data_raw_ptr->AllReadDataConsumed());
1489*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1490*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
1491*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(response_info_);
1492*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Connection closed before receiving a handshake response",
1493*6777b538SAndroid Build Coastguard Worker failure_message());
1494*6777b538SAndroid Build Coastguard Worker
1495*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
1496*6777b538SAndroid Build Coastguard Worker
1497*6777b538SAndroid Build Coastguard Worker auto samples = histogram_tester.GetHistogramSamplesSinceCreation(
1498*6777b538SAndroid Build Coastguard Worker "Net.WebSocket.HandshakeResult2");
1499*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->TotalCount());
1500*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
1501*6777b538SAndroid Build Coastguard Worker 1, samples->GetCount(static_cast<int>(
1502*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::HandshakeResult::EMPTY_RESPONSE)));
1503*6777b538SAndroid Build Coastguard Worker }
1504*6777b538SAndroid Build Coastguard Worker
TEST_P(WebSocketStreamCreateTest,SelfSignedCertificateFailure)1505*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, SelfSignedCertificateFailure) {
1506*6777b538SAndroid Build Coastguard Worker auto ssl_socket_data = std::make_unique<SSLSocketDataProvider>(
1507*6777b538SAndroid Build Coastguard Worker ASYNC, ERR_CERT_AUTHORITY_INVALID);
1508*6777b538SAndroid Build Coastguard Worker ssl_socket_data->ssl_info.cert =
1509*6777b538SAndroid Build Coastguard Worker ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der");
1510*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(ssl_socket_data->ssl_info.cert.get());
1511*6777b538SAndroid Build Coastguard Worker url_request_context_host_.AddSSLSocketDataProvider(
1512*6777b538SAndroid Build Coastguard Worker std::move(ssl_socket_data));
1513*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SequencedSocketData> raw_socket_data(BuildNullSocketData());
1514*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations("wss://www.example.org/", NoSubProtocols(),
1515*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders(),
1516*6777b538SAndroid Build Coastguard Worker std::move(raw_socket_data));
1517*6777b538SAndroid Build Coastguard Worker // WaitUntilConnectDone doesn't work in this case.
1518*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
1519*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
1520*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(ssl_error_callbacks_);
1521*6777b538SAndroid Build Coastguard Worker ssl_error_callbacks_->CancelSSLRequest(ERR_CERT_AUTHORITY_INVALID,
1522*6777b538SAndroid Build Coastguard Worker &ssl_info_);
1523*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1524*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1525*6777b538SAndroid Build Coastguard Worker }
1526*6777b538SAndroid Build Coastguard Worker
TEST_P(WebSocketStreamCreateTest,SelfSignedCertificateSuccess)1527*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, SelfSignedCertificateSuccess) {
1528*6777b538SAndroid Build Coastguard Worker auto ssl_socket_data = std::make_unique<SSLSocketDataProvider>(
1529*6777b538SAndroid Build Coastguard Worker ASYNC, ERR_CERT_AUTHORITY_INVALID);
1530*6777b538SAndroid Build Coastguard Worker ssl_socket_data->ssl_info.cert =
1531*6777b538SAndroid Build Coastguard Worker ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der");
1532*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(ssl_socket_data->ssl_info.cert.get());
1533*6777b538SAndroid Build Coastguard Worker url_request_context_host_.AddSSLSocketDataProvider(
1534*6777b538SAndroid Build Coastguard Worker std::move(ssl_socket_data));
1535*6777b538SAndroid Build Coastguard Worker url_request_context_host_.AddSSLSocketDataProvider(
1536*6777b538SAndroid Build Coastguard Worker std::make_unique<SSLSocketDataProvider>(ASYNC, OK));
1537*6777b538SAndroid Build Coastguard Worker AddRawExpectations(BuildNullSocketData());
1538*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard("wss://www.example.org/", NoSubProtocols(), {}, {},
1539*6777b538SAndroid Build Coastguard Worker {});
1540*6777b538SAndroid Build Coastguard Worker // WaitUntilConnectDone doesn't work in this case.
1541*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
1542*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(ssl_error_callbacks_);
1543*6777b538SAndroid Build Coastguard Worker ssl_error_callbacks_->ContinueSSLRequest();
1544*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1545*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
1546*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(stream_);
1547*6777b538SAndroid Build Coastguard Worker }
1548*6777b538SAndroid Build Coastguard Worker
1549*6777b538SAndroid Build Coastguard Worker // If the server requests authorisation, but we have no credentials, the
1550*6777b538SAndroid Build Coastguard Worker // connection should fail cleanly.
TEST_P(WebSocketStreamCreateBasicAuthTest,FailureNoCredentials)1551*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateBasicAuthTest, FailureNoCredentials) {
1552*6777b538SAndroid Build Coastguard Worker CreateAndConnectCustomResponse("ws://www.example.org/", NoSubProtocols(), {},
1553*6777b538SAndroid Build Coastguard Worker {}, kUnauthorizedResponse);
1554*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1555*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1556*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("HTTP Authentication failed; no valid credentials available",
1557*6777b538SAndroid Build Coastguard Worker failure_message());
1558*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(response_info_);
1559*6777b538SAndroid Build Coastguard Worker }
1560*6777b538SAndroid Build Coastguard Worker
TEST_P(WebSocketStreamCreateBasicAuthTest,SuccessPasswordInUrl)1561*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateBasicAuthTest, SuccessPasswordInUrl) {
1562*6777b538SAndroid Build Coastguard Worker CreateAndConnectAuthHandshake("ws://foo:[email protected]/", "Zm9vOmJhcg==",
1563*6777b538SAndroid Build Coastguard Worker WebSocketStandardResponse(std::string()));
1564*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1565*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
1566*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(stream_);
1567*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(response_info_);
1568*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(101, response_info_->headers->response_code());
1569*6777b538SAndroid Build Coastguard Worker }
1570*6777b538SAndroid Build Coastguard Worker
TEST_P(WebSocketStreamCreateBasicAuthTest,FailureIncorrectPasswordInUrl)1571*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateBasicAuthTest, FailureIncorrectPasswordInUrl) {
1572*6777b538SAndroid Build Coastguard Worker CreateAndConnectAuthHandshake("ws://foo:[email protected]/",
1573*6777b538SAndroid Build Coastguard Worker "Zm9vOmJheg==", kUnauthorizedResponse);
1574*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1575*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1576*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(response_info_);
1577*6777b538SAndroid Build Coastguard Worker }
1578*6777b538SAndroid Build Coastguard Worker
TEST_P(WebSocketStreamCreateBasicAuthTest,SuccessfulConnectionReuse)1579*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateBasicAuthTest, SuccessfulConnectionReuse) {
1580*6777b538SAndroid Build Coastguard Worker std::string request1 = WebSocketStandardRequest(
1581*6777b538SAndroid Build Coastguard Worker "/", "www.example.org", Origin(), /*send_additional_request_headers=*/{},
1582*6777b538SAndroid Build Coastguard Worker /*extra_headers=*/{});
1583*6777b538SAndroid Build Coastguard Worker std::string response1 = kUnauthorizedResponse;
1584*6777b538SAndroid Build Coastguard Worker std::string request2 = WebSocketStandardRequest(
1585*6777b538SAndroid Build Coastguard Worker "/", "www.example.org", Origin(),
1586*6777b538SAndroid Build Coastguard Worker {{"Authorization", "Basic Zm9vOmJhcg=="}}, /*extra_headers=*/{});
1587*6777b538SAndroid Build Coastguard Worker std::string response2 = WebSocketStandardResponse(std::string());
1588*6777b538SAndroid Build Coastguard Worker MockWrite writes[] = {
1589*6777b538SAndroid Build Coastguard Worker MockWrite(SYNCHRONOUS, 0, request1.c_str()),
1590*6777b538SAndroid Build Coastguard Worker MockWrite(SYNCHRONOUS, 2, request2.c_str()),
1591*6777b538SAndroid Build Coastguard Worker };
1592*6777b538SAndroid Build Coastguard Worker MockRead reads[3] = {
1593*6777b538SAndroid Build Coastguard Worker MockRead(SYNCHRONOUS, 1, response1.c_str()),
1594*6777b538SAndroid Build Coastguard Worker MockRead(SYNCHRONOUS, 3, response2.c_str()),
1595*6777b538SAndroid Build Coastguard Worker MockRead(SYNCHRONOUS, ERR_IO_PENDING, 4),
1596*6777b538SAndroid Build Coastguard Worker };
1597*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations("ws://foo:[email protected]/",
1598*6777b538SAndroid Build Coastguard Worker NoSubProtocols(), HttpRequestHeaders(),
1599*6777b538SAndroid Build Coastguard Worker BuildSocketData(reads, writes));
1600*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1601*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
1602*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(stream_);
1603*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(response_info_);
1604*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(101, response_info_->headers->response_code());
1605*6777b538SAndroid Build Coastguard Worker }
1606*6777b538SAndroid Build Coastguard Worker
TEST_P(WebSocketStreamCreateBasicAuthTest,OnAuthRequiredCancelAuth)1607*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateBasicAuthTest, OnAuthRequiredCancelAuth) {
1608*6777b538SAndroid Build Coastguard Worker CreateAndConnectCustomResponse("ws://www.example.org/", NoSubProtocols(), {},
1609*6777b538SAndroid Build Coastguard Worker {}, kUnauthorizedResponse);
1610*6777b538SAndroid Build Coastguard Worker
1611*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(request_info_);
1612*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(response_info_);
1613*6777b538SAndroid Build Coastguard Worker on_auth_required_rv_ = ERR_IO_PENDING;
1614*6777b538SAndroid Build Coastguard Worker WaitUntilOnAuthRequired();
1615*6777b538SAndroid Build Coastguard Worker
1616*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
1617*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
1618*6777b538SAndroid Build Coastguard Worker
1619*6777b538SAndroid Build Coastguard Worker std::move(on_auth_required_callback_).Run(nullptr);
1620*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1621*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
1622*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1623*6777b538SAndroid Build Coastguard Worker }
1624*6777b538SAndroid Build Coastguard Worker
TEST_P(WebSocketStreamCreateBasicAuthTest,OnAuthRequiredSetAuth)1625*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateBasicAuthTest, OnAuthRequiredSetAuth) {
1626*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations(
1627*6777b538SAndroid Build Coastguard Worker "ws://www.example.org/", NoSubProtocols(), HttpRequestHeaders(),
1628*6777b538SAndroid Build Coastguard Worker helper_.BuildAuthSocketData(kUnauthorizedResponse,
1629*6777b538SAndroid Build Coastguard Worker RequestExpectation("Zm9vOmJheg=="),
1630*6777b538SAndroid Build Coastguard Worker WebSocketStandardResponse(std::string())));
1631*6777b538SAndroid Build Coastguard Worker
1632*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(request_info_);
1633*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(response_info_);
1634*6777b538SAndroid Build Coastguard Worker on_auth_required_rv_ = ERR_IO_PENDING;
1635*6777b538SAndroid Build Coastguard Worker WaitUntilOnAuthRequired();
1636*6777b538SAndroid Build Coastguard Worker
1637*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(stream_);
1638*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
1639*6777b538SAndroid Build Coastguard Worker
1640*6777b538SAndroid Build Coastguard Worker AuthCredentials credentials(u"foo", u"baz");
1641*6777b538SAndroid Build Coastguard Worker std::move(on_auth_required_callback_).Run(&credentials);
1642*6777b538SAndroid Build Coastguard Worker
1643*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1644*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(stream_);
1645*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
1646*6777b538SAndroid Build Coastguard Worker }
1647*6777b538SAndroid Build Coastguard Worker
1648*6777b538SAndroid Build Coastguard Worker // Digest auth has the same connection semantics as Basic auth, so we can
1649*6777b538SAndroid Build Coastguard Worker // generally assume that whatever works for Basic auth will also work for
1650*6777b538SAndroid Build Coastguard Worker // Digest. There's just one test here, to confirm that it works at all.
TEST_P(WebSocketStreamCreateDigestAuthTest,DigestPasswordInUrl)1651*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateDigestAuthTest, DigestPasswordInUrl) {
1652*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations(
1653*6777b538SAndroid Build Coastguard Worker "ws://FooBar:[email protected]/", NoSubProtocols(),
1654*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders(),
1655*6777b538SAndroid Build Coastguard Worker helper_.BuildAuthSocketData(kUnauthorizedResponse, kAuthorizedRequest,
1656*6777b538SAndroid Build Coastguard Worker WebSocketStandardResponse(std::string())));
1657*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1658*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
1659*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(stream_);
1660*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(response_info_);
1661*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(101, response_info_->headers->response_code());
1662*6777b538SAndroid Build Coastguard Worker }
1663*6777b538SAndroid Build Coastguard Worker
TEST_P(WebSocketMultiProtocolStreamCreateTest,Incomplete)1664*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketMultiProtocolStreamCreateTest, Incomplete) {
1665*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
1666*6777b538SAndroid Build Coastguard Worker
1667*6777b538SAndroid Build Coastguard Worker AddSSLData();
1668*6777b538SAndroid Build Coastguard Worker if (stream_type_ == BASIC_HANDSHAKE_STREAM) {
1669*6777b538SAndroid Build Coastguard Worker std::string request = WebSocketStandardRequest(
1670*6777b538SAndroid Build Coastguard Worker "/", "www.example.org", Origin(),
1671*6777b538SAndroid Build Coastguard Worker /*send_additional_request_headers=*/{}, /*extra_headers=*/{});
1672*6777b538SAndroid Build Coastguard Worker MockRead reads[] = {MockRead(ASYNC, ERR_IO_PENDING, 0)};
1673*6777b538SAndroid Build Coastguard Worker MockWrite writes[] = {MockWrite(ASYNC, 1, request.c_str())};
1674*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations("wss://www.example.org/", NoSubProtocols(),
1675*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders(),
1676*6777b538SAndroid Build Coastguard Worker BuildSocketData(reads, writes));
1677*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
1678*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
1679*6777b538SAndroid Build Coastguard Worker
1680*6777b538SAndroid Build Coastguard Worker auto samples = histogram_tester.GetHistogramSamplesSinceCreation(
1681*6777b538SAndroid Build Coastguard Worker "Net.WebSocket.HandshakeResult2");
1682*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->TotalCount());
1683*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1,
1684*6777b538SAndroid Build Coastguard Worker samples->GetCount(static_cast<int>(
1685*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::HandshakeResult::INCOMPLETE)));
1686*6777b538SAndroid Build Coastguard Worker } else {
1687*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(stream_type_, HTTP2_HANDSHAKE_STREAM);
1688*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard("wss://www.example.org/", NoSubProtocols(), {}, {},
1689*6777b538SAndroid Build Coastguard Worker {});
1690*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
1691*6777b538SAndroid Build Coastguard Worker
1692*6777b538SAndroid Build Coastguard Worker auto samples = histogram_tester.GetHistogramSamplesSinceCreation(
1693*6777b538SAndroid Build Coastguard Worker "Net.WebSocket.HandshakeResult2");
1694*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->TotalCount());
1695*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
1696*6777b538SAndroid Build Coastguard Worker 1,
1697*6777b538SAndroid Build Coastguard Worker samples->GetCount(static_cast<int>(
1698*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::HandshakeResult::HTTP2_INCOMPLETE)));
1699*6777b538SAndroid Build Coastguard Worker }
1700*6777b538SAndroid Build Coastguard Worker }
1701*6777b538SAndroid Build Coastguard Worker
TEST_P(WebSocketMultiProtocolStreamCreateTest,Http2StreamReset)1702*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketMultiProtocolStreamCreateTest, Http2StreamReset) {
1703*6777b538SAndroid Build Coastguard Worker AddSSLData();
1704*6777b538SAndroid Build Coastguard Worker
1705*6777b538SAndroid Build Coastguard Worker if (stream_type_ == BASIC_HANDSHAKE_STREAM) {
1706*6777b538SAndroid Build Coastguard Worker // This is a dummy transaction to avoid crash in ~URLRequestContext().
1707*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard("wss://www.example.org/", NoSubProtocols(), {}, {},
1708*6777b538SAndroid Build Coastguard Worker {});
1709*6777b538SAndroid Build Coastguard Worker } else {
1710*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(stream_type_, HTTP2_HANDSHAKE_STREAM);
1711*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
1712*6777b538SAndroid Build Coastguard Worker
1713*6777b538SAndroid Build Coastguard Worker SetResetWebSocketHttp2Stream(true);
1714*6777b538SAndroid Build Coastguard Worker CreateAndConnectStandard("wss://www.example.org/", NoSubProtocols(), {}, {},
1715*6777b538SAndroid Build Coastguard Worker {});
1716*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
1717*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
1718*6777b538SAndroid Build Coastguard Worker
1719*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1720*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Stream closed with error: net::ERR_HTTP2_PROTOCOL_ERROR",
1721*6777b538SAndroid Build Coastguard Worker failure_message());
1722*6777b538SAndroid Build Coastguard Worker
1723*6777b538SAndroid Build Coastguard Worker auto samples = histogram_tester.GetHistogramSamplesSinceCreation(
1724*6777b538SAndroid Build Coastguard Worker "Net.WebSocket.HandshakeResult2");
1725*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->TotalCount());
1726*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(
1727*6777b538SAndroid Build Coastguard Worker 1, samples->GetCount(static_cast<int>(
1728*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::HandshakeResult::HTTP2_FAILED)));
1729*6777b538SAndroid Build Coastguard Worker }
1730*6777b538SAndroid Build Coastguard Worker }
1731*6777b538SAndroid Build Coastguard Worker
TEST_P(WebSocketStreamCreateTest,HandleErrConnectionClosed)1732*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, HandleErrConnectionClosed) {
1733*6777b538SAndroid Build Coastguard Worker base::HistogramTester histogram_tester;
1734*6777b538SAndroid Build Coastguard Worker
1735*6777b538SAndroid Build Coastguard Worker static constexpr char kTruncatedResponse[] =
1736*6777b538SAndroid Build Coastguard Worker "HTTP/1.1 101 Switching Protocols\r\n"
1737*6777b538SAndroid Build Coastguard Worker "Upgrade: websocket\r\n"
1738*6777b538SAndroid Build Coastguard Worker "Connection: Upgrade\r\n"
1739*6777b538SAndroid Build Coastguard Worker "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
1740*6777b538SAndroid Build Coastguard Worker "Cache-Control: no-sto";
1741*6777b538SAndroid Build Coastguard Worker
1742*6777b538SAndroid Build Coastguard Worker std::string request = WebSocketStandardRequest(
1743*6777b538SAndroid Build Coastguard Worker "/", "www.example.org", Origin(), /*send_additional_request_headers=*/{},
1744*6777b538SAndroid Build Coastguard Worker /*extra_headers=*/{});
1745*6777b538SAndroid Build Coastguard Worker MockRead reads[] = {
1746*6777b538SAndroid Build Coastguard Worker MockRead(SYNCHRONOUS, 1, kTruncatedResponse),
1747*6777b538SAndroid Build Coastguard Worker MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 2),
1748*6777b538SAndroid Build Coastguard Worker };
1749*6777b538SAndroid Build Coastguard Worker MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, request.c_str())};
1750*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SequencedSocketData> socket_data(
1751*6777b538SAndroid Build Coastguard Worker BuildSocketData(reads, writes));
1752*6777b538SAndroid Build Coastguard Worker socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
1753*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations("ws://www.example.org/", NoSubProtocols(),
1754*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders(), std::move(socket_data));
1755*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1756*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1757*6777b538SAndroid Build Coastguard Worker
1758*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
1759*6777b538SAndroid Build Coastguard Worker
1760*6777b538SAndroid Build Coastguard Worker auto samples = histogram_tester.GetHistogramSamplesSinceCreation(
1761*6777b538SAndroid Build Coastguard Worker "Net.WebSocket.HandshakeResult2");
1762*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->TotalCount());
1763*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(1, samples->GetCount(static_cast<int>(
1764*6777b538SAndroid Build Coastguard Worker WebSocketHandshakeStreamBase::HandshakeResult::
1765*6777b538SAndroid Build Coastguard Worker FAILED_SWITCHING_PROTOCOLS)));
1766*6777b538SAndroid Build Coastguard Worker }
1767*6777b538SAndroid Build Coastguard Worker
TEST_P(WebSocketStreamCreateTest,HandleErrTunnelConnectionFailed)1768*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, HandleErrTunnelConnectionFailed) {
1769*6777b538SAndroid Build Coastguard Worker static constexpr char kConnectRequest[] =
1770*6777b538SAndroid Build Coastguard Worker "CONNECT www.example.org:80 HTTP/1.1\r\n"
1771*6777b538SAndroid Build Coastguard Worker "Host: www.example.org:80\r\n"
1772*6777b538SAndroid Build Coastguard Worker "Proxy-Connection: keep-alive\r\n"
1773*6777b538SAndroid Build Coastguard Worker "\r\n";
1774*6777b538SAndroid Build Coastguard Worker
1775*6777b538SAndroid Build Coastguard Worker static constexpr char kProxyResponse[] =
1776*6777b538SAndroid Build Coastguard Worker "HTTP/1.1 403 Forbidden\r\n"
1777*6777b538SAndroid Build Coastguard Worker "Content-Type: text/html\r\n"
1778*6777b538SAndroid Build Coastguard Worker "Content-Length: 9\r\n"
1779*6777b538SAndroid Build Coastguard Worker "Connection: keep-alive\r\n"
1780*6777b538SAndroid Build Coastguard Worker "\r\n"
1781*6777b538SAndroid Build Coastguard Worker "Forbidden";
1782*6777b538SAndroid Build Coastguard Worker
1783*6777b538SAndroid Build Coastguard Worker MockRead reads[] = {MockRead(SYNCHRONOUS, 1, kProxyResponse)};
1784*6777b538SAndroid Build Coastguard Worker MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, kConnectRequest)};
1785*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SequencedSocketData> socket_data(
1786*6777b538SAndroid Build Coastguard Worker BuildSocketData(reads, writes));
1787*6777b538SAndroid Build Coastguard Worker url_request_context_host_.SetProxyConfig("https=proxy:8000");
1788*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations("ws://www.example.org/", NoSubProtocols(),
1789*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders(), std::move(socket_data));
1790*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1791*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(has_failed());
1792*6777b538SAndroid Build Coastguard Worker EXPECT_EQ("Establishing a tunnel via proxy server failed.",
1793*6777b538SAndroid Build Coastguard Worker failure_message());
1794*6777b538SAndroid Build Coastguard Worker }
1795*6777b538SAndroid Build Coastguard Worker
TEST_P(WebSocketStreamCreateTest,CancelSSLRequestAfterDelete)1796*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, CancelSSLRequestAfterDelete) {
1797*6777b538SAndroid Build Coastguard Worker auto ssl_socket_data = std::make_unique<SSLSocketDataProvider>(
1798*6777b538SAndroid Build Coastguard Worker ASYNC, ERR_CERT_AUTHORITY_INVALID);
1799*6777b538SAndroid Build Coastguard Worker ssl_socket_data->ssl_info.cert =
1800*6777b538SAndroid Build Coastguard Worker ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der");
1801*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(ssl_socket_data->ssl_info.cert.get());
1802*6777b538SAndroid Build Coastguard Worker url_request_context_host_.AddSSLSocketDataProvider(
1803*6777b538SAndroid Build Coastguard Worker std::move(ssl_socket_data));
1804*6777b538SAndroid Build Coastguard Worker
1805*6777b538SAndroid Build Coastguard Worker MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET, 0)};
1806*6777b538SAndroid Build Coastguard Worker MockWrite writes[] = {MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET, 1)};
1807*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SequencedSocketData> raw_socket_data(
1808*6777b538SAndroid Build Coastguard Worker BuildSocketData(reads, writes));
1809*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations("wss://www.example.org/", NoSubProtocols(),
1810*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders(),
1811*6777b538SAndroid Build Coastguard Worker std::move(raw_socket_data));
1812*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
1813*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
1814*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(ssl_error_callbacks_);
1815*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
1816*6777b538SAndroid Build Coastguard Worker ssl_error_callbacks_->CancelSSLRequest(ERR_CERT_AUTHORITY_INVALID,
1817*6777b538SAndroid Build Coastguard Worker &ssl_info_);
1818*6777b538SAndroid Build Coastguard Worker }
1819*6777b538SAndroid Build Coastguard Worker
TEST_P(WebSocketStreamCreateTest,ContinueSSLRequestAfterDelete)1820*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, ContinueSSLRequestAfterDelete) {
1821*6777b538SAndroid Build Coastguard Worker auto ssl_socket_data = std::make_unique<SSLSocketDataProvider>(
1822*6777b538SAndroid Build Coastguard Worker ASYNC, ERR_CERT_AUTHORITY_INVALID);
1823*6777b538SAndroid Build Coastguard Worker ssl_socket_data->ssl_info.cert =
1824*6777b538SAndroid Build Coastguard Worker ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der");
1825*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(ssl_socket_data->ssl_info.cert.get());
1826*6777b538SAndroid Build Coastguard Worker url_request_context_host_.AddSSLSocketDataProvider(
1827*6777b538SAndroid Build Coastguard Worker std::move(ssl_socket_data));
1828*6777b538SAndroid Build Coastguard Worker
1829*6777b538SAndroid Build Coastguard Worker MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_CONNECTION_RESET, 0)};
1830*6777b538SAndroid Build Coastguard Worker MockWrite writes[] = {MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET, 1)};
1831*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SequencedSocketData> raw_socket_data(
1832*6777b538SAndroid Build Coastguard Worker BuildSocketData(reads, writes));
1833*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations("wss://www.example.org/", NoSubProtocols(),
1834*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders(),
1835*6777b538SAndroid Build Coastguard Worker std::move(raw_socket_data));
1836*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
1837*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(has_failed());
1838*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(ssl_error_callbacks_);
1839*6777b538SAndroid Build Coastguard Worker stream_request_.reset();
1840*6777b538SAndroid Build Coastguard Worker ssl_error_callbacks_->ContinueSSLRequest();
1841*6777b538SAndroid Build Coastguard Worker }
1842*6777b538SAndroid Build Coastguard Worker
TEST_P(WebSocketStreamCreateTest,HandleConnectionCloseInFirstSegment)1843*6777b538SAndroid Build Coastguard Worker TEST_P(WebSocketStreamCreateTest, HandleConnectionCloseInFirstSegment) {
1844*6777b538SAndroid Build Coastguard Worker std::string request = WebSocketStandardRequest(
1845*6777b538SAndroid Build Coastguard Worker "/", "www.example.org", Origin(), /*send_additional_request_headers=*/{},
1846*6777b538SAndroid Build Coastguard Worker /*extra_headers=*/{});
1847*6777b538SAndroid Build Coastguard Worker
1848*6777b538SAndroid Build Coastguard Worker // The response headers are immediately followed by a close frame, length 11,
1849*6777b538SAndroid Build Coastguard Worker // code 1013, reason "Try Again".
1850*6777b538SAndroid Build Coastguard Worker std::string close_body = "\x03\xf5Try Again";
1851*6777b538SAndroid Build Coastguard Worker std::string response = WebSocketStandardResponse(std::string()) + "\x88" +
1852*6777b538SAndroid Build Coastguard Worker static_cast<char>(close_body.size()) + close_body;
1853*6777b538SAndroid Build Coastguard Worker MockRead reads[] = {
1854*6777b538SAndroid Build Coastguard Worker MockRead(SYNCHRONOUS, response.data(), response.size(), 1),
1855*6777b538SAndroid Build Coastguard Worker MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 2),
1856*6777b538SAndroid Build Coastguard Worker };
1857*6777b538SAndroid Build Coastguard Worker MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, request.c_str())};
1858*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SequencedSocketData> socket_data(
1859*6777b538SAndroid Build Coastguard Worker BuildSocketData(reads, writes));
1860*6777b538SAndroid Build Coastguard Worker socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
1861*6777b538SAndroid Build Coastguard Worker CreateAndConnectRawExpectations("ws://www.example.org/", NoSubProtocols(),
1862*6777b538SAndroid Build Coastguard Worker HttpRequestHeaders(), std::move(socket_data));
1863*6777b538SAndroid Build Coastguard Worker WaitUntilConnectDone();
1864*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(stream_);
1865*6777b538SAndroid Build Coastguard Worker
1866*6777b538SAndroid Build Coastguard Worker std::vector<std::unique_ptr<WebSocketFrame>> frames;
1867*6777b538SAndroid Build Coastguard Worker TestCompletionCallback callback1;
1868*6777b538SAndroid Build Coastguard Worker int rv1 = stream_->ReadFrames(&frames, callback1.callback());
1869*6777b538SAndroid Build Coastguard Worker rv1 = callback1.GetResult(rv1);
1870*6777b538SAndroid Build Coastguard Worker ASSERT_THAT(rv1, IsOk());
1871*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(1U, frames.size());
1872*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(frames[0]->header.opcode, WebSocketFrameHeader::kOpCodeClose);
1873*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(frames[0]->header.final);
1874*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(close_body,
1875*6777b538SAndroid Build Coastguard Worker std::string(frames[0]->payload, frames[0]->header.payload_length));
1876*6777b538SAndroid Build Coastguard Worker
1877*6777b538SAndroid Build Coastguard Worker std::vector<std::unique_ptr<WebSocketFrame>> empty_frames;
1878*6777b538SAndroid Build Coastguard Worker TestCompletionCallback callback2;
1879*6777b538SAndroid Build Coastguard Worker int rv2 = stream_->ReadFrames(&empty_frames, callback2.callback());
1880*6777b538SAndroid Build Coastguard Worker rv2 = callback2.GetResult(rv2);
1881*6777b538SAndroid Build Coastguard Worker ASSERT_THAT(rv2, IsError(ERR_CONNECTION_CLOSED));
1882*6777b538SAndroid Build Coastguard Worker }
1883*6777b538SAndroid Build Coastguard Worker
1884*6777b538SAndroid Build Coastguard Worker } // namespace
1885*6777b538SAndroid Build Coastguard Worker } // namespace net
1886