summaryrefslogtreecommitdiff
path: root/chromium/net/websockets
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/net/websockets
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-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.cc42
-rw-r--r--chromium/net/websockets/websocket_channel.h17
-rw-r--r--chromium/net/websockets/websocket_channel_test.cc251
-rw-r--r--chromium/net/websockets/websocket_deflate_parameters.h2
-rw-r--r--chromium/net/websockets/websocket_end_to_end_test.cc10
-rw-r--r--chromium/net/websockets/websocket_event_interface.h9
-rw-r--r--chromium/net/websockets/websocket_stream_cookie_test.cc16
-rw-r--r--chromium/net/websockets/websocket_stream_test.cc40
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