diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/net/websockets | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-c30a6232df03e1efbd9f3b226777b07e087a1122.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/net/websockets')
-rw-r--r-- | chromium/net/websockets/websocket_channel.cc | 42 | ||||
-rw-r--r-- | chromium/net/websockets/websocket_channel.h | 17 | ||||
-rw-r--r-- | chromium/net/websockets/websocket_channel_test.cc | 251 | ||||
-rw-r--r-- | chromium/net/websockets/websocket_deflate_parameters.h | 2 | ||||
-rw-r--r-- | chromium/net/websockets/websocket_end_to_end_test.cc | 10 | ||||
-rw-r--r-- | chromium/net/websockets/websocket_event_interface.h | 9 | ||||
-rw-r--r-- | chromium/net/websockets/websocket_stream_cookie_test.cc | 16 | ||||
-rw-r--r-- | chromium/net/websockets/websocket_stream_test.cc | 40 |
8 files changed, 112 insertions, 275 deletions
diff --git a/chromium/net/websockets/websocket_channel.cc b/chromium/net/websockets/websocket_channel.cc index dea22fcf40c..67365d39c64 100644 --- a/chromium/net/websockets/websocket_channel.cc +++ b/chromium/net/websockets/websocket_channel.cc @@ -44,8 +44,6 @@ namespace { using base::StreamingUtf8Validator; -const int kDefaultSendQuotaLowWaterMark = 1 << 16; -const int kDefaultSendQuotaHighWaterMark = 1 << 17; const size_t kWebSocketCloseCodeLength = 2; // Timeout for waiting for the server to acknowledge a closing handshake. const int kClosingHandshakeTimeoutSeconds = 60; @@ -286,9 +284,6 @@ WebSocketChannel::WebSocketChannel( URLRequestContext* url_request_context) : event_interface_(std::move(event_interface)), url_request_context_(url_request_context), - send_quota_low_water_mark_(kDefaultSendQuotaLowWaterMark), - send_quota_high_water_mark_(kDefaultSendQuotaHighWaterMark), - current_send_quota_(0), closing_handshake_timeout_( base::TimeDelta::FromSeconds(kClosingHandshakeTimeoutSeconds)), underlying_connection_close_timeout_(base::TimeDelta::FromSeconds( @@ -354,12 +349,6 @@ WebSocketChannel::ChannelState WebSocketChannel::SendFrame( } DCHECK_EQ(state_, CONNECTED); - if (buffer_size > base::checked_cast<size_t>(current_send_quota_)) { - // TODO(ricea): Kill renderer. - FailChannel("Send quota exceeded", kWebSocketErrorGoingAway, ""); - return CHANNEL_DELETED; - // |this| has been deleted. - } DCHECK(WebSocketFrameHeader::IsKnownDataOpCode(op_code)) << "Got SendFrame with bogus op_code " << op_code << " fin=" << fin @@ -381,11 +370,7 @@ WebSocketChannel::ChannelState WebSocketChannel::SendFrame( sending_text_message_ = !fin; DCHECK(!fin || state == StreamingUtf8Validator::VALID_ENDPOINT); } - current_send_quota_ -= buffer_size; - // TODO(ricea): If current_send_quota_ has dropped below - // send_quota_low_water_mark_, it might be good to increase the "low - // water mark" and "high water mark", but only if the link to the WebSocket - // server is not saturated. + return SendFrameInternal(fin, op_code, std::move(buffer), buffer_size); // |this| may have been deleted. } @@ -519,12 +504,8 @@ void WebSocketChannel::OnConnectSuccess( // |stream_request_| is not used once the connection has succeeded. stream_request_.reset(); - // TODO(ricea): Get flow control information from the WebSocketStream once we - // have a multiplexing WebSocketStream. - current_send_quota_ = send_quota_high_water_mark_; event_interface_->OnAddChannelResponse( - std::move(response), stream_->GetSubProtocol(), stream_->GetExtensions(), - send_quota_high_water_mark_); + std::move(response), stream_->GetSubProtocol(), stream_->GetExtensions()); // |this| may have been deleted after OnAddChannelResponse. } @@ -599,21 +580,7 @@ ChannelState WebSocketChannel::OnWriteDone(bool synchronous, int result) { return WriteFrames(); } else { data_being_sent_.reset(); - if (current_send_quota_ < send_quota_low_water_mark_) { - // TODO(ricea): Increase low_water_mark and high_water_mark if - // throughput is high, reduce them if throughput is low. Low water - // mark needs to be >= the bandwidth delay product *of the IPC - // channel*. Because factors like context-switch time, thread wake-up - // time, and bus speed come into play it is complex and probably needs - // to be determined empirically. - DCHECK_LE(send_quota_low_water_mark_, send_quota_high_water_mark_); - // TODO(ricea): Truncate quota by the quota specified by the remote - // server, if the protocol in use supports quota. - int fresh_quota = send_quota_high_water_mark_ - current_send_quota_; - current_send_quota_ += fresh_quota; - event_interface_->OnSendFlowControlQuotaAdded(fresh_quota); - return CHANNEL_ALIVE; - } + event_interface_->OnSendDataFrameDone(); } return CHANNEL_ALIVE; @@ -961,8 +928,6 @@ ChannelState WebSocketChannel::SendFrameInternal( if (data_being_sent_) { // Either the link to the WebSocket server is saturated, or several messages // are being sent in a batch. - // TODO(ricea): Keep some statistics to work out the situation and adjust - // quota appropriately. if (!data_to_send_next_) data_to_send_next_ = std::make_unique<SendBuffer>(); data_to_send_next_->AddFrame(std::move(frame), std::move(buffer)); @@ -1016,6 +981,7 @@ ChannelState WebSocketChannel::SendClose(uint16_t code, std::copy( reason.begin(), reason.end(), body->data() + kWebSocketCloseCodeLength); } + return SendFrameInternal(true, WebSocketFrameHeader::kOpCodeClose, std::move(body), size); } diff --git a/chromium/net/websockets/websocket_channel.h b/chromium/net/websockets/websocket_channel.h index d05207e8bc3..d5e78537456 100644 --- a/chromium/net/websockets/websocket_channel.h +++ b/chromium/net/websockets/websocket_channel.h @@ -118,12 +118,6 @@ class NET_EXPORT WebSocketChannel { ChannelState StartClosingHandshake(uint16_t code, const std::string& reason) WARN_UNUSED_RESULT; - // Returns the current send quota. This value is unsafe to use outside of the - // browser IO thread because it changes asynchronously. The value is only - // valid for the execution of the current Task or until SendFrame() is called, - // whichever happens sooner. - int current_send_quota() const { return current_send_quota_; } - // Starts the connection process, using a specified creator callback rather // than the default. This is exposed for testing. void SendAddChannelRequestForTesting( @@ -359,17 +353,6 @@ class NET_EXPORT WebSocketChannel { // during the connection process. std::unique_ptr<WebSocketStreamRequest> stream_request_; - // If the renderer's send quota reaches this level, it is sent a quota - // refresh. "quota units" are currently bytes. TODO(ricea): Update the - // definition of quota units when necessary. - int send_quota_low_water_mark_; - // The level the quota is refreshed to when it reaches the low_water_mark - // (quota units). - int send_quota_high_water_mark_; - // The current amount of quota that the renderer has available for sending - // on this logical channel (quota units). - int current_send_quota_; - // Timer for the closing handshake. base::OneShotTimer close_timer_; diff --git a/chromium/net/websockets/websocket_channel_test.cc b/chromium/net/websockets/websocket_channel_test.cc index 07f90d5b23b..b0c3478692a 100644 --- a/chromium/net/websockets/websocket_channel_test.cc +++ b/chromium/net/websockets/websocket_channel_test.cc @@ -131,15 +131,6 @@ const char kBinaryBlob[] = {'\n', '\r', // BACKWARDS CRNL }; const size_t kBinaryBlobSize = base::size(kBinaryBlob); -// The amount of quota a new connection gets by default. -// TODO(ricea): If kDefaultSendQuotaHighWaterMark changes, then this value will -// need to be updated. -const size_t kDefaultInitialQuota = 1 << 17; -// The amount of bytes we need to send after the initial connection to trigger a -// quota refresh. TODO(ricea): Change this if kDefaultSendQuotaHighWaterMark or -// kDefaultSendQuotaLowWaterMark change. -const size_t kDefaultQuotaRefreshTrigger = (1 << 16) + 1; - const int kVeryBigTimeoutMillis = 60 * 60 * 24 * 1000; // TestTimeouts::tiny_timeout() is 100ms! I could run halfway around the world @@ -167,17 +158,16 @@ class MockWebSocketEventInterface : public WebSocketEventInterface { } MOCK_METHOD1(OnCreateURLRequest, void(URLRequest*)); - MOCK_METHOD4(OnAddChannelResponse, + MOCK_METHOD3(OnAddChannelResponse, void(std::unique_ptr<WebSocketHandshakeResponseInfo> response, const std::string&, - const std::string&, - int64_t)); // NOLINT + const std::string&)); // NOLINT MOCK_METHOD3(OnDataFrameVector, void(bool, WebSocketMessageType, const std::vector<char>&)); // NOLINT MOCK_METHOD0(HasPendingDataFrames, bool(void)); // NOLINT - MOCK_METHOD1(OnSendFlowControlQuotaAdded, void(int64_t)); // NOLINT + MOCK_METHOD0(OnSendDataFrameDone, void(void)); // NOLINT MOCK_METHOD0(OnClosingHandshake, void(void)); // NOLINT MOCK_METHOD1(OnFailChannel, void(const std::string&)); // NOLINT MOCK_METHOD3(OnDropChannel, @@ -225,13 +215,12 @@ class FakeWebSocketEventInterface : public WebSocketEventInterface { void OnAddChannelResponse( std::unique_ptr<WebSocketHandshakeResponseInfo> response, const std::string& selected_protocol, - const std::string& extensions, - int64_t send_flow_control_quota) override {} + const std::string& extensions) override {} void OnDataFrame(bool fin, WebSocketMessageType type, base::span<const char> data_span) override {} + void OnSendDataFrameDone() override {} bool HasPendingDataFrames() override { return false; } - void OnSendFlowControlQuotaAdded(int64_t quota) override {} void OnClosingHandshake() override {} void OnFailChannel(const std::string& message) override {} void OnDropChannel(bool was_clean, @@ -930,11 +919,12 @@ class WebSocketChannelStreamTest : public WebSocketChannelEventInterfaceTest { // whether these methods are called or not. EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)) + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)) .Times(AnyNumber()); EXPECT_CALL(*event_interface_, OnDataFrameVector(_, _, _)) .Times(AnyNumber()); EXPECT_CALL(*event_interface_, OnClosingHandshake()).Times(AnyNumber()); + EXPECT_CALL(*event_interface_, OnSendDataFrameDone()).Times(AnyNumber()); EXPECT_CALL(*event_interface_, OnFailChannel(_)).Times(AnyNumber()); EXPECT_CALL(*event_interface_, OnDropChannel(_, _, _)).Times(AnyNumber()); } @@ -961,8 +951,9 @@ class WebSocketChannelSendUtf8Test set_stream(std::make_unique<WriteableFakeWebSocketStream>()); // For the purpose of the tests using this fixture, it doesn't matter // whether these methods are called or not. - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)) + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)) .Times(AnyNumber()); + EXPECT_CALL(*event_interface_, OnSendDataFrameDone()).Times(AnyNumber()); } }; @@ -1006,7 +997,7 @@ TEST_F(WebSocketChannelTest, EverythingIsPassedToTheCreatorFunction) { TEST_F(WebSocketChannelEventInterfaceTest, ConnectSuccessReported) { // false means success. - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, "", "", _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, "", "")); CreateChannelAndConnect(); @@ -1031,7 +1022,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, NonWebSocketSchemeRejected) { } TEST_F(WebSocketChannelEventInterfaceTest, ProtocolPassed) { - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, "Bob", "", _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, "Bob", "")); CreateChannelAndConnect(); @@ -1044,7 +1035,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, ProtocolPassed) { TEST_F(WebSocketChannelEventInterfaceTest, ExtensionsPassed) { EXPECT_CALL(*event_interface_, - OnAddChannelResponse(_, "", "extension1, extension2", _)); + OnAddChannelResponse(_, "", "extension1, extension2")); CreateChannelAndConnect(); @@ -1066,7 +1057,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, DataLeftFromHandshake) { set_stream(std::move(stream)); { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText, AsVector("HELLO"))); @@ -1088,7 +1079,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, CloseAfterHandshake) { set_stream(std::move(stream)); { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnClosingHandshake()); EXPECT_CALL( *event_interface_, @@ -1112,7 +1103,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, ShouldCloseWhileNoDataFrames) { Checkpoint checkpoint; { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, HasPendingDataFrames()) .WillOnce(Return(false)) .WillOnce(Return(true)) @@ -1142,7 +1133,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, ConnectionCloseAfterHandshake) { set_stream(std::move(stream)); { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnDropChannel(false, kWebSocketErrorAbnormalClosure, _)); } @@ -1161,7 +1152,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, NormalAsyncRead) { set_stream(std::move(stream)); { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(checkpoint, Call(1)); EXPECT_CALL(*event_interface_, OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText, @@ -1188,7 +1179,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, AsyncThenSyncRead) { set_stream(std::move(stream)); { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText, AsVector("HELLO"))); @@ -1226,7 +1217,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, FragmentedMessage) { set_stream(std::move(stream)); { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText, AsVector("THREE"))); @@ -1259,7 +1250,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, NullMessage) { {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, nullptr}}; stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL( *event_interface_, OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText, AsVector(""))); @@ -1274,7 +1265,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, AsyncAbnormalClosure) { set_stream(std::move(stream)); { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnDropChannel(false, kWebSocketErrorAbnormalClosure, _)); } @@ -1291,7 +1282,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, ConnectionReset) { set_stream(std::move(stream)); { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnDropChannel(false, kWebSocketErrorAbnormalClosure, _)); } @@ -1310,7 +1301,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, MaskedFramesAreRejected) { set_stream(std::move(stream)); { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL( *event_interface_, OnFailChannel( @@ -1331,7 +1322,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, UnknownOpCodeIsRejected) { set_stream(std::move(stream)); { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnFailChannel("Unrecognized frame opcode: 4")); } @@ -1360,7 +1351,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, ControlFrameInDataMessage) { set_stream(std::move(stream)); { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText, AsVector("SPLIT "))); @@ -1382,7 +1373,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, PongWithNullData) { {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, nullptr}}; stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); CreateChannelAndConnectSuccessfully(); base::RunLoop().RunUntilIdle(); @@ -1400,7 +1391,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, FrameAfterInvalidFrame) { set_stream(std::move(stream)); { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL( *event_interface_, OnFailChannel( @@ -1411,105 +1402,13 @@ TEST_F(WebSocketChannelEventInterfaceTest, FrameAfterInvalidFrame) { base::RunLoop().RunUntilIdle(); } -// If the renderer sends lots of small writes, we don't want to update the quota -// for each one. -TEST_F(WebSocketChannelEventInterfaceTest, SmallWriteDoesntUpdateQuota) { - set_stream(std::make_unique<WriteableFakeWebSocketStream>()); - { - InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); - } - - CreateChannelAndConnectSuccessfully(); - EXPECT_EQ(channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, - AsIOBuffer("B"), 1U), - WebSocketChannel::CHANNEL_ALIVE); -} - -// If we send enough to go below |send_quota_low_water_mark_| we should get our -// quota refreshed. -TEST_F(WebSocketChannelEventInterfaceTest, LargeWriteUpdatesQuota) { - set_stream(std::make_unique<WriteableFakeWebSocketStream>()); - // We use this checkpoint object to verify that the quota update comes after - // the write. - Checkpoint checkpoint; - { - InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); - EXPECT_CALL(checkpoint, Call(1)); - EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_)); - EXPECT_CALL(checkpoint, Call(2)); - } - - CreateChannelAndConnectSuccessfully(); - checkpoint.Call(1); - EXPECT_EQ( - channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, - AsIOBuffer(std::string(kDefaultInitialQuota, 'B')), - kDefaultInitialQuota), - WebSocketChannel::CHANNEL_ALIVE); - checkpoint.Call(2); -} - -// Verify that our quota actually is refreshed when we are told it is. -TEST_F(WebSocketChannelEventInterfaceTest, QuotaReallyIsRefreshed) { - set_stream(std::make_unique<WriteableFakeWebSocketStream>()); - Checkpoint checkpoint; - { - InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); - EXPECT_CALL(checkpoint, Call(1)); - EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_)); - EXPECT_CALL(checkpoint, Call(2)); - // If quota was not really refreshed, we would get an OnDropChannel() - // message. - EXPECT_CALL(*event_interface_, OnSendFlowControlQuotaAdded(_)); - EXPECT_CALL(checkpoint, Call(3)); - } - - CreateChannelAndConnectSuccessfully(); - checkpoint.Call(1); - EXPECT_EQ(channel_->SendFrame( - true, WebSocketFrameHeader::kOpCodeText, - AsIOBuffer(std::string(kDefaultQuotaRefreshTrigger, 'D')), - kDefaultQuotaRefreshTrigger), - WebSocketChannel::CHANNEL_ALIVE); - checkpoint.Call(2); - // We should have received more quota at this point. - EXPECT_EQ(channel_->SendFrame( - true, WebSocketFrameHeader::kOpCodeText, - AsIOBuffer(std::string(kDefaultQuotaRefreshTrigger, 'E')), - kDefaultQuotaRefreshTrigger), - WebSocketChannel::CHANNEL_ALIVE); - checkpoint.Call(3); -} - -// If we send more than the available quota then the connection will be closed -// with an error. -TEST_F(WebSocketChannelEventInterfaceTest, WriteOverQuotaIsRejected) { - set_stream(std::make_unique<WriteableFakeWebSocketStream>()); - { - InSequence s; - EXPECT_CALL(*event_interface_, - OnAddChannelResponse(_, _, _, kDefaultInitialQuota)); - EXPECT_CALL(*event_interface_, OnFailChannel("Send quota exceeded")); - } - - CreateChannelAndConnectSuccessfully(); - EXPECT_EQ(channel_->SendFrame( - true, WebSocketFrameHeader::kOpCodeText, - AsIOBuffer(std::string(kDefaultInitialQuota + 1, 'C')), - kDefaultInitialQuota + 1), - WebSocketChannel::CHANNEL_DELETED); -} - // If a write fails, the channel is dropped. TEST_F(WebSocketChannelEventInterfaceTest, FailedWrite) { set_stream(std::make_unique<UnWriteableFakeWebSocketStream>()); Checkpoint checkpoint; { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(checkpoint, Call(1)); EXPECT_CALL(*event_interface_, OnDropChannel(false, kWebSocketErrorAbnormalClosure, _)); @@ -1530,7 +1429,8 @@ TEST_F(WebSocketChannelEventInterfaceTest, SendCloseDropsChannel) { set_stream(std::make_unique<EchoeyFakeWebSocketStream>()); { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); + EXPECT_CALL(*event_interface_, OnSendDataFrameDone()); EXPECT_CALL(*event_interface_, OnDropChannel(true, kWebSocketNormalClosure, "Fred")); } @@ -1557,7 +1457,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, CloseDuringConnection) { // connection reset. TEST_F(WebSocketChannelEventInterfaceTest, OnDropChannelCalledOnce) { set_stream(std::make_unique<ResetOnWriteFakeWebSocketStream>()); - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnDropChannel(false, kWebSocketErrorAbnormalClosure, "")) @@ -1581,7 +1481,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, CloseWithNoPayloadGivesStatus1005) { stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC, ERR_CONNECTION_CLOSED); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnClosingHandshake()); EXPECT_CALL(*event_interface_, OnDropChannel(true, kWebSocketErrorNoStatusReceived, _)); @@ -1599,7 +1499,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC, ERR_CONNECTION_CLOSED); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnClosingHandshake()); EXPECT_CALL(*event_interface_, OnDropChannel(true, kWebSocketErrorNoStatusReceived, _)); @@ -1614,7 +1514,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, SyncProtocolErrorGivesStatus1002) { stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC, ERR_WS_PROTOCOL_ERROR); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnFailChannel("Invalid frame header")); @@ -1627,7 +1527,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, AsyncProtocolErrorGivesStatus1002) { stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC, ERR_WS_PROTOCOL_ERROR); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnFailChannel("Invalid frame header")); CreateChannelAndConnectSuccessfully(); @@ -1637,7 +1537,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, AsyncProtocolErrorGivesStatus1002) { TEST_F(WebSocketChannelEventInterfaceTest, StartHandshakeRequest) { { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnStartOpeningHandshakeCalled()); } @@ -1685,7 +1585,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, DataAfterCloseIsRejected) { {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "Payload"}}; stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); { InSequence s; @@ -1705,7 +1605,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, OneByteClosePayloadMessage) { {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, "\x03"}}; stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL( *event_interface_, OnFailChannel( @@ -1723,7 +1623,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, ClosePayloadReservedStatusMessage) { NOT_MASKED, CLOSE_DATA(ABNORMAL_CLOSURE, "Not valid on wire")}}; stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL( *event_interface_, OnFailChannel( @@ -1741,7 +1641,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, ClosePayloadInvalidReason) { NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "\xFF")}}; stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL( *event_interface_, OnFailChannel( @@ -1765,7 +1665,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, ReservedBitsMustNotBeSet) { stream->PrepareRawReadFrames(ReadableFakeWebSocketStream::SYNC, OK, std::move(raw_frames)); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnFailChannel( "One or more reserved bits are on: reserved1 = 1, " @@ -1782,7 +1682,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC, ERR_IO_PENDING); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); // This checkpoint object verifies that the OnDropChannel message comes after // the timeout. Checkpoint checkpoint; @@ -1818,7 +1718,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}}; stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); Checkpoint checkpoint; TestClosure completion; { @@ -1877,7 +1777,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, SingleFrameMessage) { set_stream(std::move(stream)); { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText, AsVector("FOUR"))); @@ -1899,7 +1799,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, EmptyMessage) { set_stream(std::move(stream)); { InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText, AsVector("FIRST MESSAGE"))); @@ -1933,7 +1833,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, set_stream(std::move(stream)); Checkpoint checkpoint; InSequence s; - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, HasPendingDataFrames()).WillOnce(Return(true)); EXPECT_CALL(checkpoint, Call(1)); EXPECT_CALL(*event_interface_, HasPendingDataFrames()) @@ -2283,26 +2183,6 @@ TEST_F(WebSocketChannelStreamTest, WaitingMessagesAreBatched) { std::move(write_callback).Run(OK); } -// When the renderer sends more on a channel than it has quota for, we send the -// remote server a kWebSocketErrorGoingAway error code. -TEST_F(WebSocketChannelStreamTest, SendGoingAwayOnRendererQuotaExceeded) { - static const InitFrame expected[] = { - {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, - MASKED, CLOSE_DATA(GOING_AWAY, "")}}; - EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _)) - .WillOnce(Return(ERR_IO_PENDING)); - EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _)) - .WillOnce(Return(OK)); - EXPECT_CALL(*mock_stream_, Close()); - - CreateChannelAndConnectSuccessfully(); - EXPECT_EQ(channel_->SendFrame( - true, WebSocketFrameHeader::kOpCodeText, - AsIOBuffer(std::string(kDefaultInitialQuota + 1, 'C')), - kDefaultInitialQuota + 1), - WebSocketChannel::CHANNEL_DELETED); -} - // For convenience, most of these tests use Text frames. However, the WebSocket // protocol also has Binary frames and those need to be 8-bit clean. For the // sake of completeness, this test verifies that they are. @@ -2345,7 +2225,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, ReadBinaryFramesAre8BitClean) { stream->PrepareRawReadFrames(ReadableFakeWebSocketStream::SYNC, OK, std::move(frames)); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _, _)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL( *event_interface_, OnDataFrameVector( @@ -2477,8 +2357,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, ReceivedInvalidUtf8) { stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, - OnAddChannelResponse(_, _, _, kDefaultInitialQuota)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnFailChannel("Could not decode a text frame as UTF-8.")); @@ -2667,8 +2546,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, BogusContinuation) { stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, - OnAddChannelResponse(_, _, _, kDefaultInitialQuota)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeBinary, AsVector("frame1"))); @@ -2689,8 +2567,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, MessageStartingWithContinuation) { stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, - OnAddChannelResponse(_, _, _, kDefaultInitialQuota)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL(*event_interface_, OnFailChannel("Received unexpected continuation frame.")); @@ -2709,8 +2586,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, DataFramesNonEmptyOrFinal) { stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); set_stream(std::move(stream)); - EXPECT_CALL(*event_interface_, - OnAddChannelResponse(_, _, _, kDefaultInitialQuota)); + EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)); EXPECT_CALL( *event_interface_, OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText, AsVector(""))); @@ -2925,30 +2801,5 @@ TEST_F(WebSocketChannelStreamTimeoutTest, ConnectionCloseTimesOut) { completion.WaitForResult(); } -// Verify that current_send_quota() returns a non-zero value for a newly -// connected channel. -TEST_F(WebSocketChannelTest, CurrentSendQuotaNonZero) { - CreateChannelAndConnectSuccessfully(); - EXPECT_GT(channel_->current_send_quota(), 0); -} - -// Verify that current_send_quota() is updated when SendFrame() is called. -TEST_F(WebSocketChannelTest, CurrentSendQuotaUpdated) { - const int kMessageSize = 5; - set_stream(std::make_unique<WriteableFakeWebSocketStream>()); - CreateChannelAndConnectSuccessfully(); - - int initial_send_quota = channel_->current_send_quota(); - EXPECT_GE(initial_send_quota, kMessageSize); - - EXPECT_EQ(channel_->SendFrame( - true, WebSocketFrameHeader::kOpCodeText, - AsIOBuffer(std::string(static_cast<size_t>(kMessageSize), 'a')), - static_cast<size_t>(kMessageSize)), - WebSocketChannel::CHANNEL_ALIVE); - int new_send_quota = channel_->current_send_quota(); - EXPECT_EQ(kMessageSize, initial_send_quota - new_send_quota); -} - } // namespace } // namespace net diff --git a/chromium/net/websockets/websocket_deflate_parameters.h b/chromium/net/websockets/websocket_deflate_parameters.h index 1898e1d7a12..f5653e28006 100644 --- a/chromium/net/websockets/websocket_deflate_parameters.h +++ b/chromium/net/websockets/websocket_deflate_parameters.h @@ -9,7 +9,7 @@ #include <string> -#include "base/logging.h" +#include "base/check.h" #include "net/base/net_export.h" #include "net/websockets/websocket_deflater.h" #include "net/websockets/websocket_extension.h" diff --git a/chromium/net/websockets/websocket_end_to_end_test.cc b/chromium/net/websockets/websocket_end_to_end_test.cc index caf50d9e26d..27e9cc34aa0 100644 --- a/chromium/net/websockets/websocket_end_to_end_test.cc +++ b/chromium/net/websockets/websocket_end_to_end_test.cc @@ -100,8 +100,7 @@ class ConnectTestingEventInterface : public WebSocketEventInterface { void OnAddChannelResponse( std::unique_ptr<WebSocketHandshakeResponseInfo> response, const std::string& selected_subprotocol, - const std::string& extensions, - int64_t send_flow_control_quota) override; + const std::string& extensions) override; void OnDataFrame(bool fin, WebSocketMessageType type, @@ -109,7 +108,7 @@ class ConnectTestingEventInterface : public WebSocketEventInterface { bool HasPendingDataFrames() override { return false; } - void OnSendFlowControlQuotaAdded(int64_t quota) override; + void OnSendDataFrameDone() override; void OnClosingHandshake() override; @@ -170,8 +169,7 @@ std::string ConnectTestingEventInterface::extensions() const { void ConnectTestingEventInterface::OnAddChannelResponse( std::unique_ptr<WebSocketHandshakeResponseInfo> response, const std::string& selected_subprotocol, - const std::string& extensions, - int64_t send_flow_control_quota) { + const std::string& extensions) { selected_subprotocol_ = selected_subprotocol; extensions_ = extensions; QuitNestedEventLoop(); @@ -182,7 +180,7 @@ void ConnectTestingEventInterface::OnDataFrame(bool fin, base::span<const char> payload) { } -void ConnectTestingEventInterface::OnSendFlowControlQuotaAdded(int64_t quota) {} +void ConnectTestingEventInterface::OnSendDataFrameDone() {} void ConnectTestingEventInterface::OnClosingHandshake() {} diff --git a/chromium/net/websockets/websocket_event_interface.h b/chromium/net/websockets/websocket_event_interface.h index 63eb1b4fa4b..df55472067e 100644 --- a/chromium/net/websockets/websocket_event_interface.h +++ b/chromium/net/websockets/websocket_event_interface.h @@ -48,8 +48,7 @@ class NET_EXPORT WebSocketEventInterface { virtual void OnAddChannelResponse( std::unique_ptr<WebSocketHandshakeResponseInfo> response, const std::string& selected_subprotocol, - const std::string& extensions, - int64_t send_flow_control_quota) = 0; + const std::string& extensions) = 0; // Called when a data frame has been received from the remote host and needs // to be forwarded to the renderer process. @@ -64,9 +63,9 @@ class NET_EXPORT WebSocketEventInterface { // out. The network service should not read more from network until that. virtual bool HasPendingDataFrames() = 0; - // Called to provide more send quota for this channel to the renderer - // process. - virtual void OnSendFlowControlQuotaAdded(int64_t quota) = 0; + // Called once for each call to SendFrame() once the frame has been passed to + // the OS. + virtual void OnSendDataFrameDone() = 0; // Called when the remote server has Started the WebSocket Closing // Handshake. The client should not attempt to send any more messages after diff --git a/chromium/net/websockets/websocket_stream_cookie_test.cc b/chromium/net/websockets/websocket_stream_cookie_test.cc index d1e9aca194d..f2e105f23d2 100644 --- a/chromium/net/websockets/websocket_stream_cookie_test.cc +++ b/chromium/net/websockets/websocket_stream_cookie_test.cc @@ -15,6 +15,7 @@ #include "net/base/isolation_info.h" #include "net/cookies/canonical_cookie.h" #include "net/cookies/canonical_cookie_test_helpers.h" +#include "net/cookies/cookie_inclusion_status.h" #include "net/cookies/cookie_store.h" #include "net/cookies/cookie_util.h" #include "net/http/http_request_headers.h" @@ -85,11 +86,10 @@ class WebSocketStreamClientUseCookieTest base::RunLoop().RunUntilIdle(); } - static void SetCookieHelperFunction( - const base::RepeatingClosure& task, - base::WeakPtr<bool> weak_is_called, - base::WeakPtr<bool> weak_result, - CanonicalCookie::CookieInclusionStatus status) { + static void SetCookieHelperFunction(const base::RepeatingClosure& task, + base::WeakPtr<bool> weak_is_called, + base::WeakPtr<bool> weak_result, + CookieInclusionStatus status) { *weak_is_called = true; *weak_result = status.IsInclude(); base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, task); @@ -122,10 +122,10 @@ class WebSocketStreamServerSetCookieTest base::OnceClosure task, base::WeakPtr<bool> weak_is_called, base::WeakPtr<CookieList> weak_result, - const CookieStatusList& cookie_list, - const CookieStatusList& excluded_cookies) { + const CookieAccessResultList& cookie_list, + const CookieAccessResultList& excluded_cookies) { *weak_is_called = true; - *weak_result = cookie_util::StripStatuses(cookie_list); + *weak_result = cookie_util::StripAccessResults(cookie_list); base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(task)); } }; diff --git a/chromium/net/websockets/websocket_stream_test.cc b/chromium/net/websockets/websocket_stream_test.cc index d4dfb6f582b..7784392afa2 100644 --- a/chromium/net/websockets/websocket_stream_test.cc +++ b/chromium/net/websockets/websocket_stream_test.cc @@ -1749,5 +1749,45 @@ TEST_P(WebSocketStreamCreateTest, ContinueSSLRequestAfterDelete) { ssl_error_callbacks_->ContinueSSLRequest(); } +TEST_P(WebSocketStreamCreateTest, HandleConnectionCloseInFirstSegment) { + std::string request = + WebSocketStandardRequest("/", "www.example.org", Origin(), "", ""); + + // The response headers are immediately followed by a close frame, length 11, + // code 1013, reason "Try Again". + std::string close_body = "\x03\xf5Try Again"; + std::string response = WebSocketStandardResponse(std::string()) + "\x88" + + static_cast<char>(close_body.size()) + close_body; + MockRead reads[] = { + MockRead(SYNCHRONOUS, response.data(), response.size(), 1), + MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 2), + }; + MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, request.c_str())}; + std::unique_ptr<SequencedSocketData> socket_data( + BuildSocketData(reads, writes)); + socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); + CreateAndConnectRawExpectations("ws://www.example.org/", NoSubProtocols(), + HttpRequestHeaders(), std::move(socket_data)); + WaitUntilConnectDone(); + ASSERT_TRUE(stream_); + + std::vector<std::unique_ptr<WebSocketFrame>> frames; + TestCompletionCallback callback1; + int rv1 = stream_->ReadFrames(&frames, callback1.callback()); + rv1 = callback1.GetResult(rv1); + ASSERT_THAT(rv1, IsOk()); + ASSERT_EQ(1U, frames.size()); + EXPECT_EQ(frames[0]->header.opcode, WebSocketFrameHeader::kOpCodeClose); + EXPECT_TRUE(frames[0]->header.final); + EXPECT_EQ(close_body, + std::string(frames[0]->payload, frames[0]->header.payload_length)); + + std::vector<std::unique_ptr<WebSocketFrame>> empty_frames; + TestCompletionCallback callback2; + int rv2 = stream_->ReadFrames(&empty_frames, callback2.callback()); + rv2 = callback2.GetResult(rv2); + ASSERT_THAT(rv2, IsError(ERR_CONNECTION_CLOSED)); +} + } // namespace } // namespace net |