Commit 0da77e92 authored by darin's avatar darin Committed by Commit bot

Change WebSocketChannel to pass data via IOBuffer

This avoids having to copy the data between std::vector<char> and IOBuffer within the implementation of WebSocketChannel.

As a follow-up, I plan to see about eliminating a similar copy at the Mojo bindings layer in content/browser/websockets/.

Review-Url: https://codereview.chromium.org/2267233002
Cr-Commit-Position: refs/heads/master@{#422846}
parent 0704833d
......@@ -24,6 +24,7 @@
#include "content/browser/ssl/ssl_manager.h"
#include "content/public/browser/storage_partition.h"
#include "ipc/ipc_message.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
......@@ -93,7 +94,8 @@ class WebSocketImpl::WebSocketEventHandler final
const std::string& extensions) override;
ChannelState OnDataFrame(bool fin,
WebSocketMessageType type,
const std::vector<char>& data) override;
scoped_refptr<net::IOBuffer> buffer,
size_t buffer_size) override;
ChannelState OnClosingHandshake() override;
ChannelState OnFlowControl(int64_t quota) override;
ChannelState OnDropChannel(bool was_clean,
......@@ -167,15 +169,19 @@ ChannelState WebSocketImpl::WebSocketEventHandler::OnAddChannelResponse(
ChannelState WebSocketImpl::WebSocketEventHandler::OnDataFrame(
bool fin,
net::WebSocketFrameHeader::OpCode type,
const std::vector<char>& data) {
scoped_refptr<net::IOBuffer> buffer,
size_t buffer_size) {
DVLOG(3) << "WebSocketEventHandler::OnDataFrame @"
<< reinterpret_cast<void*>(this)
<< " fin=" << fin
<< " type=" << type << " data is " << data.size() << " bytes";
<< " type=" << type << " data is " << buffer_size << " bytes";
// TODO(darin): Avoid this copy.
std::vector<uint8_t> data_to_pass(data.size());
std::copy(data.begin(), data.end(), data_to_pass.begin());
std::vector<uint8_t> data_to_pass(buffer_size);
if (buffer_size > 0) {
std::copy(buffer->data(), buffer->data() + buffer_size,
data_to_pass.begin());
}
impl_->client_->OnDataFrame(fin, OpCodeToMessageType(type), data_to_pass);
......@@ -435,10 +441,11 @@ void WebSocketImpl::SendFrame(bool fin,
}
// TODO(darin): Avoid this copy.
std::vector<char> data_to_pass(data.size());
std::copy(data.begin(), data.end(), data_to_pass.begin());
scoped_refptr<net::IOBuffer> data_to_pass(new net::IOBuffer(data.size()));
std::copy(data.begin(), data.end(), data_to_pass->data());
channel_->SendFrame(fin, MessageTypeToOpCode(type), data_to_pass);
channel_->SendFrame(fin, MessageTypeToOpCode(type), std::move(data_to_pass),
data.size());
}
void WebSocketImpl::SendFlowControl(int64_t quota) {
......
......@@ -128,6 +128,16 @@ void GetFrameTypeForOpcode(WebSocketFrameHeader::OpCode opcode,
return;
}
class DependentIOBuffer : public WrappedIOBuffer {
public:
DependentIOBuffer(scoped_refptr<IOBuffer> buffer, size_t offset)
: WrappedIOBuffer(buffer->data() + offset), buffer_(std::move(buffer)) {}
private:
~DependentIOBuffer() override {}
scoped_refptr<net::IOBuffer> buffer_;
};
} // namespace
// A class to encapsulate a set of frames and information about the size of
......@@ -279,12 +289,12 @@ ChannelState WebSocketChannel::HandshakeNotificationSender::SendImmediately(
WebSocketChannel::PendingReceivedFrame::PendingReceivedFrame(
bool final,
WebSocketFrameHeader::OpCode opcode,
const scoped_refptr<IOBuffer>& data,
scoped_refptr<IOBuffer> data,
uint64_t offset,
uint64_t size)
: final_(final),
opcode_(opcode),
data_(data),
data_(std::move(data)),
offset_(offset),
size_(size) {}
......@@ -370,15 +380,16 @@ bool WebSocketChannel::InClosingState() const {
WebSocketChannel::ChannelState WebSocketChannel::SendFrame(
bool fin,
WebSocketFrameHeader::OpCode op_code,
const std::vector<char>& data) {
if (data.size() > INT_MAX) {
scoped_refptr<IOBuffer> buffer,
size_t buffer_size) {
if (buffer_size > INT_MAX) {
NOTREACHED() << "Frame size sanity check failed";
return CHANNEL_ALIVE;
}
if (stream_ == NULL) {
LOG(DFATAL) << "Got SendFrame without a connection established; "
<< "misbehaving renderer? fin=" << fin << " op_code=" << op_code
<< " data.size()=" << data.size();
<< " buffer_size=" << buffer_size;
return CHANNEL_ALIVE;
}
if (InClosingState()) {
......@@ -390,7 +401,7 @@ WebSocketChannel::ChannelState WebSocketChannel::SendFrame(
NOTREACHED() << "SendFrame() called in state " << state_;
return CHANNEL_ALIVE;
}
if (data.size() > base::checked_cast<size_t>(current_send_quota_)) {
if (buffer_size > base::checked_cast<size_t>(current_send_quota_)) {
// TODO(ricea): Kill renderer.
return FailChannel("Send quota exceeded", kWebSocketErrorGoingAway, "");
// |this| has been deleted.
......@@ -398,14 +409,14 @@ WebSocketChannel::ChannelState WebSocketChannel::SendFrame(
if (!WebSocketFrameHeader::IsKnownDataOpCode(op_code)) {
LOG(DFATAL) << "Got SendFrame with bogus op_code " << op_code
<< "; misbehaving renderer? fin=" << fin
<< " data.size()=" << data.size();
<< " buffer_size=" << buffer_size;
return CHANNEL_ALIVE;
}
if (op_code == WebSocketFrameHeader::kOpCodeText ||
(op_code == WebSocketFrameHeader::kOpCodeContinuation &&
sending_text_message_)) {
StreamingUtf8Validator::State state =
outgoing_utf8_validator_.AddBytes(data.data(), data.size());
outgoing_utf8_validator_.AddBytes(buffer->data(), buffer_size);
if (state == StreamingUtf8Validator::INVALID ||
(state == StreamingUtf8Validator::VALID_MIDPOINT && fin)) {
// TODO(ricea): Kill renderer.
......@@ -416,14 +427,12 @@ WebSocketChannel::ChannelState WebSocketChannel::SendFrame(
sending_text_message_ = !fin;
DCHECK(!fin || state == StreamingUtf8Validator::VALID_ENDPOINT);
}
current_send_quota_ -= data.size();
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.
scoped_refptr<IOBuffer> buffer(new IOBuffer(data.size()));
std::copy(data.begin(), data.end(), buffer->data());
return SendFrameFromIOBuffer(fin, op_code, buffer, data.size());
return SendFrameInternal(fin, op_code, std::move(buffer), buffer_size);
// |this| may have been deleted.
}
......@@ -443,15 +452,18 @@ ChannelState WebSocketChannel::SendFlowControl(int64_t quota) {
const uint64_t bytes_to_send =
std::min(base::checked_cast<uint64_t>(quota), data_size);
const bool final = front.final() && data_size == bytes_to_send;
const char* data =
front.data().get() ? front.data()->data() + front.offset() : NULL;
DCHECK(!bytes_to_send || data) << "Non empty data should not be null.";
const std::vector<char> data_vector(data, data + bytes_to_send);
scoped_refptr<IOBuffer> buffer_to_pass;
if (front.data()) {
buffer_to_pass = new DependentIOBuffer(front.data(), front.offset());
} else {
DCHECK(!bytes_to_send) << "Non empty data should not be null.";
}
DVLOG(3) << "Sending frame previously split due to quota to the "
<< "renderer: quota=" << quota << " data_size=" << data_size
<< " bytes_to_send=" << bytes_to_send;
if (event_interface_->OnDataFrame(final, front.opcode(), data_vector) ==
CHANNEL_DELETED)
if (event_interface_->OnDataFrame(final, front.opcode(),
std::move(buffer_to_pass),
bytes_to_send) == CHANNEL_DELETED)
return CHANNEL_DELETED;
if (bytes_to_send < data_size) {
front.DidConsume(bytes_to_send);
......@@ -832,14 +844,14 @@ ChannelState WebSocketChannel::HandleFrame(
}
// Respond to the frame appropriately to its type.
return HandleFrameByState(
opcode, frame->header.final, frame->data, frame->header.payload_length);
return HandleFrameByState(opcode, frame->header.final, std::move(frame->data),
frame->header.payload_length);
}
ChannelState WebSocketChannel::HandleFrameByState(
const WebSocketFrameHeader::OpCode opcode,
bool final,
const scoped_refptr<IOBuffer>& data_buffer,
scoped_refptr<IOBuffer> data_buffer,
uint64_t size) {
DCHECK_NE(RECV_CLOSED, state_)
<< "HandleFrame() does not support being called re-entrantly from within "
......@@ -857,13 +869,13 @@ ChannelState WebSocketChannel::HandleFrameByState(
case WebSocketFrameHeader::kOpCodeText: // fall-thru
case WebSocketFrameHeader::kOpCodeBinary:
case WebSocketFrameHeader::kOpCodeContinuation:
return HandleDataFrame(opcode, final, data_buffer, size);
return HandleDataFrame(opcode, final, std::move(data_buffer), size);
case WebSocketFrameHeader::kOpCodePing:
DVLOG(1) << "Got Ping of size " << size;
if (state_ == CONNECTED)
return SendFrameFromIOBuffer(
true, WebSocketFrameHeader::kOpCodePong, data_buffer, size);
return SendFrameInternal(true, WebSocketFrameHeader::kOpCodePong,
std::move(data_buffer), size);
DVLOG(3) << "Ignored ping in state " << state_;
return CHANNEL_ALIVE;
......@@ -876,7 +888,7 @@ ChannelState WebSocketChannel::HandleFrameByState(
uint16_t code = kWebSocketNormalClosure;
std::string reason;
std::string message;
if (!ParseClose(data_buffer, size, &code, &reason, &message)) {
if (!ParseClose(std::move(data_buffer), size, &code, &reason, &message)) {
return FailChannel(message, code, reason);
}
// TODO(ricea): Find a way to safely log the message from the close
......@@ -896,7 +908,7 @@ ChannelState WebSocketChannel::HandleFrameByState(
ChannelState WebSocketChannel::HandleDataFrame(
WebSocketFrameHeader::OpCode opcode,
bool final,
const scoped_refptr<IOBuffer>& data_buffer,
scoped_refptr<IOBuffer> data_buffer,
uint64_t size) {
if (state_ != CONNECTED) {
DVLOG(3) << "Ignored data packet received in state " << state_;
......@@ -963,14 +975,11 @@ ChannelState WebSocketChannel::HandleDataFrame(
final = false;
}
// TODO(ricea): Can this copy be eliminated?
const char* const data_begin = size ? data_buffer->data() : NULL;
const char* const data_end = data_begin + size;
const std::vector<char> data(data_begin, data_end);
current_receive_quota_ -= size;
// Sends the received frame to the renderer process.
return event_interface_->OnDataFrame(final, opcode_to_send, data);
return event_interface_->OnDataFrame(final, opcode_to_send,
std::move(data_buffer), size);
}
ChannelState WebSocketChannel::HandleCloseFrame(uint16_t code,
......@@ -1033,10 +1042,10 @@ ChannelState WebSocketChannel::RespondToClosingHandshake() {
return event_interface_->OnClosingHandshake();
}
ChannelState WebSocketChannel::SendFrameFromIOBuffer(
ChannelState WebSocketChannel::SendFrameInternal(
bool fin,
WebSocketFrameHeader::OpCode op_code,
const scoped_refptr<IOBuffer>& buffer,
scoped_refptr<IOBuffer> buffer,
uint64_t size) {
DCHECK(state_ == CONNECTED || state_ == RECV_CLOSED);
DCHECK(stream_);
......@@ -1046,7 +1055,7 @@ ChannelState WebSocketChannel::SendFrameFromIOBuffer(
header.final = fin;
header.masked = true;
header.payload_length = size;
frame->data = buffer;
frame->data = std::move(buffer);
if (data_being_sent_) {
// Either the link to the WebSocket server is saturated, or several messages
......@@ -1108,14 +1117,13 @@ ChannelState WebSocketChannel::SendClose(uint16_t code,
std::copy(
reason.begin(), reason.end(), body->data() + kWebSocketCloseCodeLength);
}
if (SendFrameFromIOBuffer(
true, WebSocketFrameHeader::kOpCodeClose, body, size) ==
CHANNEL_DELETED)
if (SendFrameInternal(true, WebSocketFrameHeader::kOpCodeClose,
std::move(body), size) == CHANNEL_DELETED)
return CHANNEL_DELETED;
return CHANNEL_ALIVE;
}
bool WebSocketChannel::ParseClose(const scoped_refptr<IOBuffer>& buffer,
bool WebSocketChannel::ParseClose(scoped_refptr<IOBuffer> buffer,
uint64_t size,
uint16_t* code,
std::string* reason,
......
......@@ -82,16 +82,17 @@ class NET_EXPORT WebSocketChannel {
// caller to ensure that they have sufficient send quota to send this data,
// otherwise the connection will be closed without sending. |fin| indicates
// the last frame in a message, equivalent to "FIN" as specified in section
// 5.2 of RFC6455. |data| is the "Payload Data". If |op_code| is kOpCodeText,
// or it is kOpCodeContinuation and the type the message is Text, then |data|
// must be a chunk of a valid UTF-8 message, however there is no requirement
// for |data| to be split on character boundaries. Calling SendFrame may
// result in synchronous calls to |event_interface_| which may result in this
// object being deleted. In that case, the return value will be
// CHANNEL_DELETED.
// 5.2 of RFC6455. |buffer->data()| is the "Payload Data". If |op_code| is
// kOpCodeText, or it is kOpCodeContinuation and the type the message is
// Text, then |buffer->data()| must be a chunk of a valid UTF-8 message,
// however there is no requirement for |buffer->data()| to be split on
// character boundaries. Calling SendFrame may result in synchronous calls to
// |event_interface_| which may result in this object being deleted. In that
// case, the return value will be CHANNEL_DELETED.
ChannelState SendFrame(bool fin,
WebSocketFrameHeader::OpCode op_code,
const std::vector<char>& data);
scoped_refptr<IOBuffer> buffer,
size_t buffer_size);
// Sends |quota| units of flow control to the remote side. If the underlying
// transport has a concept of |quota|, then it permits the remote server to
......@@ -159,7 +160,7 @@ class NET_EXPORT WebSocketChannel {
public:
PendingReceivedFrame(bool final,
WebSocketFrameHeader::OpCode opcode,
const scoped_refptr<IOBuffer>& data,
scoped_refptr<IOBuffer> data,
uint64_t offset,
uint64_t size);
PendingReceivedFrame(const PendingReceivedFrame& other);
......@@ -286,7 +287,7 @@ class NET_EXPORT WebSocketChannel {
// HandleFrame() method.
ChannelState HandleFrameByState(const WebSocketFrameHeader::OpCode opcode,
bool final,
const scoped_refptr<IOBuffer>& data_buffer,
scoped_refptr<IOBuffer> data_buffer,
uint64_t size) WARN_UNUSED_RESULT;
// Forwards a received data frame to the renderer, if connected. If
......@@ -294,7 +295,7 @@ class NET_EXPORT WebSocketChannel {
// will fail the channel. Also checks the UTF-8 validity of text frames.
ChannelState HandleDataFrame(WebSocketFrameHeader::OpCode opcode,
bool final,
const scoped_refptr<IOBuffer>& data_buffer,
scoped_refptr<IOBuffer> data_buffer,
uint64_t size) WARN_UNUSED_RESULT;
// Handles an incoming close frame with |code| and |reason|.
......@@ -309,10 +310,10 @@ class NET_EXPORT WebSocketChannel {
// when the current write finishes. |fin| and |op_code| are defined as for
// SendFrame() above, except that |op_code| may also be a control frame
// opcode.
ChannelState SendFrameFromIOBuffer(bool fin,
WebSocketFrameHeader::OpCode op_code,
const scoped_refptr<IOBuffer>& buffer,
uint64_t size) WARN_UNUSED_RESULT;
ChannelState SendFrameInternal(bool fin,
WebSocketFrameHeader::OpCode op_code,
scoped_refptr<IOBuffer> buffer,
uint64_t buffer_size) WARN_UNUSED_RESULT;
// Performs the "Fail the WebSocket Connection" operation as defined in
// RFC6455. A NotifyFailure message is sent to the renderer with |message|.
......@@ -340,7 +341,7 @@ class NET_EXPORT WebSocketChannel {
// is 1, or the supplied code is not permitted to be sent over the network,
// then false is returned and |message| is set to an appropriate console
// message.
bool ParseClose(const scoped_refptr<IOBuffer>& buffer,
bool ParseClose(scoped_refptr<IOBuffer> buffer,
uint64_t size,
uint16_t* code,
std::string* reason,
......
......@@ -158,13 +158,22 @@ class MockWebSocketEventInterface : public WebSocketEventInterface {
public:
MockWebSocketEventInterface() {}
ChannelState OnDataFrame(bool fin,
WebSocketMessageType type,
scoped_refptr<IOBuffer> buffer,
size_t buffer_size) override {
const char* data = buffer ? buffer->data() : nullptr;
return OnDataFrameVector(fin, type,
std::vector<char>(data, data + buffer_size));
}
MOCK_METHOD2(OnAddChannelResponse,
ChannelState(const std::string&,
const std::string&)); // NOLINT
MOCK_METHOD3(OnDataFrame,
MOCK_METHOD3(OnDataFrameVector,
ChannelState(bool,
WebSocketMessageType,
const std::vector<char>&)); // NOLINT
const std::vector<char>&)); // NOLINT
MOCK_METHOD1(OnFlowControl, ChannelState(int64_t)); // NOLINT
MOCK_METHOD0(OnClosingHandshake, ChannelState(void)); // NOLINT
MOCK_METHOD1(OnFailChannel, ChannelState(const std::string&)); // NOLINT
......@@ -208,7 +217,8 @@ class FakeWebSocketEventInterface : public WebSocketEventInterface {
}
ChannelState OnDataFrame(bool fin,
WebSocketMessageType type,
const std::vector<char>& data) override {
scoped_refptr<IOBuffer> data,
size_t data_size) override {
return CHANNEL_ALIVE;
}
ChannelState OnFlowControl(int64_t quota) override { return CHANNEL_ALIVE; }
......@@ -733,13 +743,19 @@ struct WebSocketStreamCreationCallbackArgumentSaver {
std::unique_ptr<WebSocketStream::ConnectDelegate> connect_delegate;
};
// Converts a std::string to a std::vector<char>. For test purposes, it is
// convenient to be able to specify data as a string, but the
// WebSocketEventInterface requires the vector<char> type.
std::vector<char> AsVector(const std::string& s) {
std::vector<char> AsVector(const base::StringPiece& s) {
return std::vector<char>(s.begin(), s.end());
}
// Converts a base::StringPiece to a IOBuffer. For test purposes, it is
// convenient to be able to specify data as a string, but the
// WebSocketEventInterface requires the IOBuffer type.
scoped_refptr<IOBuffer> AsIOBuffer(const base::StringPiece& s) {
scoped_refptr<IOBuffer> buffer(new IOBuffer(s.size()));
std::copy(s.begin(), s.end(), buffer->data());
return buffer;
}
class FakeSSLErrorCallbacks
: public WebSocketEventInterface::SSLErrorCallbacks {
public:
......@@ -882,7 +898,8 @@ class ChannelDeletingFakeWebSocketEventInterface
ChannelState OnDataFrame(bool fin,
WebSocketMessageType type,
const std::vector<char>& data) override {
scoped_refptr<IOBuffer> data,
size_t data_size) override {
return fixture_->DeleteIfDeleting(EVENT_ON_DATA_FRAME);
}
......@@ -1107,9 +1124,9 @@ TEST_F(WebSocketChannelDeletingTest, OnFlowControlAfterSend) {
CreateChannelAndConnectSuccessfully();
ASSERT_TRUE(channel_);
deleting_ = EVENT_ON_FLOW_CONTROL;
channel_->SendFrame(true,
WebSocketFrameHeader::kOpCodeText,
std::vector<char>(kDefaultInitialQuota, 'B'));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer(std::string(kDefaultInitialQuota, 'B')),
kDefaultInitialQuota);
EXPECT_EQ(nullptr, channel_.get());
}
......@@ -1146,8 +1163,8 @@ TEST_F(WebSocketChannelDeletingTest, OnDropChannelWriteError) {
deleting_ = EVENT_ON_DROP_CHANNEL;
CreateChannelAndConnectSuccessfully();
ASSERT_TRUE(channel_);
channel_->SendFrame(
true, WebSocketFrameHeader::kOpCodeText, AsVector("this will fail"));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer("this will fail"), 14U);
EXPECT_EQ(nullptr, channel_.get());
}
......@@ -1209,9 +1226,9 @@ TEST_F(WebSocketChannelDeletingTest, FailChannelInSendFrame) {
deleting_ = EVENT_ON_FAIL_CHANNEL;
CreateChannelAndConnectSuccessfully();
ASSERT_TRUE(channel_);
channel_->SendFrame(true,
WebSocketFrameHeader::kOpCodeText,
std::vector<char>(kDefaultInitialQuota * 2, 'T'));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer(std::string(kDefaultInitialQuota * 2, 'T')),
kDefaultInitialQuota * 2);
EXPECT_EQ(nullptr, channel_.get());
}
......@@ -1396,10 +1413,9 @@ TEST_F(WebSocketChannelEventInterfaceTest, DataLeftFromHandshake) {
InSequence s;
EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
EXPECT_CALL(*event_interface_, OnFlowControl(_));
EXPECT_CALL(
*event_interface_,
OnDataFrame(
true, WebSocketFrameHeader::kOpCodeText, AsVector("HELLO")));
EXPECT_CALL(*event_interface_,
OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
AsVector("HELLO")));
}
CreateChannelAndConnectSuccessfully();
......@@ -1465,10 +1481,9 @@ TEST_F(WebSocketChannelEventInterfaceTest, NormalAsyncRead) {
EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
EXPECT_CALL(*event_interface_, OnFlowControl(_));
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(
*event_interface_,
OnDataFrame(
true, WebSocketFrameHeader::kOpCodeText, AsVector("HELLO")));
EXPECT_CALL(*event_interface_,
OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
AsVector("HELLO")));
EXPECT_CALL(checkpoint, Call(2));
}
......@@ -1494,14 +1509,12 @@ TEST_F(WebSocketChannelEventInterfaceTest, AsyncThenSyncRead) {
InSequence s;
EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
EXPECT_CALL(*event_interface_, OnFlowControl(_));
EXPECT_CALL(
*event_interface_,
OnDataFrame(
true, WebSocketFrameHeader::kOpCodeText, AsVector("HELLO")));
EXPECT_CALL(
*event_interface_,
OnDataFrame(
true, WebSocketFrameHeader::kOpCodeText, AsVector("WORLD")));
EXPECT_CALL(*event_interface_,
OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
AsVector("HELLO")));
EXPECT_CALL(*event_interface_,
OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
AsVector("WORLD")));
}
CreateChannelAndConnectSuccessfully();
......@@ -1536,26 +1549,25 @@ TEST_F(WebSocketChannelEventInterfaceTest, FragmentedMessage) {
InSequence s;
EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
EXPECT_CALL(*event_interface_, OnFlowControl(_));
EXPECT_CALL(*event_interface_,
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
AsVector("THREE")));
EXPECT_CALL(
*event_interface_,
OnDataFrame(
false, WebSocketFrameHeader::kOpCodeText, AsVector("THREE")));
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
AsVector(" ")));
EXPECT_CALL(
*event_interface_,
OnDataFrame(
false, WebSocketFrameHeader::kOpCodeContinuation, AsVector(" ")));
EXPECT_CALL(*event_interface_,
OnDataFrame(false,
WebSocketFrameHeader::kOpCodeContinuation,
AsVector("SMALL")));
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("SMALL")));
EXPECT_CALL(
*event_interface_,
OnDataFrame(
false, WebSocketFrameHeader::kOpCodeContinuation, AsVector(" ")));
EXPECT_CALL(*event_interface_,
OnDataFrame(true,
WebSocketFrameHeader::kOpCodeContinuation,
AsVector("FRAMES")));
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
AsVector(" ")));
EXPECT_CALL(
*event_interface_,
OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("FRAMES")));
}
CreateChannelAndConnectSuccessfully();
......@@ -1574,7 +1586,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, NullMessage) {
EXPECT_CALL(*event_interface_, OnFlowControl(_));
EXPECT_CALL(
*event_interface_,
OnDataFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("")));
OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText, AsVector("")));
CreateChannelAndConnectSuccessfully();
}
......@@ -1683,14 +1695,13 @@ TEST_F(WebSocketChannelEventInterfaceTest, ControlFrameInDataMessage) {
InSequence s;
EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
EXPECT_CALL(*event_interface_, OnFlowControl(_));
EXPECT_CALL(*event_interface_,
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
AsVector("SPLIT ")));
EXPECT_CALL(
*event_interface_,
OnDataFrame(
false, WebSocketFrameHeader::kOpCodeText, AsVector("SPLIT ")));
EXPECT_CALL(*event_interface_,
OnDataFrame(true,
WebSocketFrameHeader::kOpCodeContinuation,
AsVector("MESSAGE")));
OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("MESSAGE")));
}
CreateChannelAndConnectSuccessfully();
......@@ -1749,7 +1760,8 @@ TEST_F(WebSocketChannelEventInterfaceTest, SmallWriteDoesntUpdateQuota) {
}
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("B"));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsIOBuffer("B"),
1U);
}
// If we send enough to go below |send_quota_low_water_mark_| we should get our
......@@ -1770,9 +1782,9 @@ TEST_F(WebSocketChannelEventInterfaceTest, LargeWriteUpdatesQuota) {
CreateChannelAndConnectSuccessfully();
checkpoint.Call(1);
channel_->SendFrame(true,
WebSocketFrameHeader::kOpCodeText,
std::vector<char>(kDefaultInitialQuota, 'B'));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer(std::string(kDefaultInitialQuota, 'B')),
kDefaultInitialQuota);
checkpoint.Call(2);
}
......@@ -1795,14 +1807,14 @@ TEST_F(WebSocketChannelEventInterfaceTest, QuotaReallyIsRefreshed) {
CreateChannelAndConnectSuccessfully();
checkpoint.Call(1);
channel_->SendFrame(true,
WebSocketFrameHeader::kOpCodeText,
std::vector<char>(kDefaultQuotaRefreshTrigger, 'D'));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer(std::string(kDefaultQuotaRefreshTrigger, 'D')),
kDefaultQuotaRefreshTrigger);
checkpoint.Call(2);
// We should have received more quota at this point.
channel_->SendFrame(true,
WebSocketFrameHeader::kOpCodeText,
std::vector<char>(kDefaultQuotaRefreshTrigger, 'E'));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer(std::string(kDefaultQuotaRefreshTrigger, 'E')),
kDefaultQuotaRefreshTrigger);
checkpoint.Call(3);
}
......@@ -1818,9 +1830,9 @@ TEST_F(WebSocketChannelEventInterfaceTest, WriteOverQuotaIsRejected) {
}
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(true,
WebSocketFrameHeader::kOpCodeText,
std::vector<char>(kDefaultInitialQuota + 1, 'C'));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer(std::string(kDefaultInitialQuota + 1, 'C')),
kDefaultInitialQuota + 1);
}
// If a write fails, the channel is dropped.
......@@ -1840,7 +1852,8 @@ TEST_F(WebSocketChannelEventInterfaceTest, FailedWrite) {
CreateChannelAndConnectSuccessfully();
checkpoint.Call(1);
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("H"));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsIOBuffer("H"),
1U);
checkpoint.Call(2);
}
......@@ -1886,7 +1899,8 @@ TEST_F(WebSocketChannelEventInterfaceTest, OnDropChannelCalledOnce) {
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("yt?"));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer("yt?"), 3U);
base::RunLoop().RunUntilIdle();
}
......@@ -2335,17 +2349,17 @@ TEST_F(WebSocketChannelFlowControlTest, SingleFrameMessageSplitSync) {
InSequence s;
EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
EXPECT_CALL(*event_interface_, OnFlowControl(_));
EXPECT_CALL(*event_interface_,
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
AsVector("FO")));
EXPECT_CALL(
*event_interface_,
OnDataFrame(false, WebSocketFrameHeader::kOpCodeText, AsVector("FO")));
EXPECT_CALL(
*event_interface_,
OnDataFrame(
false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("U")));
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("U")));
EXPECT_CALL(
*event_interface_,
OnDataFrame(
true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("R")));
OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("R")));
}
CreateChannelAndConnectWithQuota(2);
......@@ -2368,19 +2382,19 @@ TEST_F(WebSocketChannelFlowControlTest, SingleFrameMessageSplitAsync) {
EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
EXPECT_CALL(*event_interface_, OnFlowControl(_));
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(
*event_interface_,
OnDataFrame(false, WebSocketFrameHeader::kOpCodeText, AsVector("FO")));
EXPECT_CALL(*event_interface_,
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
AsVector("FO")));
EXPECT_CALL(checkpoint, Call(2));
EXPECT_CALL(
*event_interface_,
OnDataFrame(
false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("U")));
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("U")));
EXPECT_CALL(checkpoint, Call(3));
EXPECT_CALL(
*event_interface_,
OnDataFrame(
true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("R")));
OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("R")));
}
CreateChannelAndConnectWithQuota(2);
......@@ -2414,25 +2428,24 @@ TEST_F(WebSocketChannelFlowControlTest, MultipleFrameSplit) {
EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
EXPECT_CALL(*event_interface_, OnFlowControl(_));
EXPECT_CALL(*event_interface_,
OnDataFrame(false,
WebSocketFrameHeader::kOpCodeText,
AsVector("FIRST FRAME IS")));
EXPECT_CALL(*event_interface_,
OnDataFrame(false,
WebSocketFrameHeader::kOpCodeContinuation,
AsVector(" 25 BYTES. ")));
EXPECT_CALL(*event_interface_,
OnDataFrame(false,
WebSocketFrameHeader::kOpCodeContinuation,
AsVector("SECOND FRAME IS 26 BYTES. ")));
EXPECT_CALL(*event_interface_,
OnDataFrame(false,
WebSocketFrameHeader::kOpCodeContinuation,
AsVector("FINAL ")));
EXPECT_CALL(*event_interface_,
OnDataFrame(true,
WebSocketFrameHeader::kOpCodeContinuation,
AsVector("FRAME IS 24 BYTES.")));
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
AsVector("FIRST FRAME IS")));
EXPECT_CALL(
*event_interface_,
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
AsVector(" 25 BYTES. ")));
EXPECT_CALL(
*event_interface_,
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("SECOND FRAME IS 26 BYTES. ")));
EXPECT_CALL(
*event_interface_,
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("FINAL ")));
EXPECT_CALL(
*event_interface_,
OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("FRAME IS 24 BYTES.")));
}
CreateChannelAndConnectWithQuota(14);
ASSERT_EQ(CHANNEL_ALIVE, channel_->SendFlowControl(43));
......@@ -2457,21 +2470,18 @@ TEST_F(WebSocketChannelFlowControlTest, EmptyMessageNoQuota) {
EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
EXPECT_CALL(*event_interface_, OnFlowControl(_));
EXPECT_CALL(*event_interface_,
OnDataFrame(false,
WebSocketFrameHeader::kOpCodeText,
AsVector("FIRST ")));
EXPECT_CALL(*event_interface_,
OnDataFrame(true,
WebSocketFrameHeader::kOpCodeContinuation,
AsVector("MESSAGE")));
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
AsVector("FIRST ")));
EXPECT_CALL(
*event_interface_,
OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("MESSAGE")));
EXPECT_CALL(*event_interface_,
OnDataFrame(true,
WebSocketFrameHeader::kOpCodeText,
AsVector("")));
OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
AsVector("")));
EXPECT_CALL(*event_interface_,
OnDataFrame(true,
WebSocketFrameHeader::kOpCodeText,
AsVector("THIRD MESSAGE")));
OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText,
AsVector("THIRD MESSAGE")));
}
CreateChannelAndConnectWithQuota(6);
......@@ -2499,23 +2509,25 @@ TEST_F(WebSocketChannelFlowControlTest, CloseFrameShouldNotOvertakeDataFrames) {
EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
EXPECT_CALL(*event_interface_, OnFlowControl(_));
EXPECT_CALL(*event_interface_,
OnDataFrame(false, WebSocketFrameHeader::kOpCodeText,
AsVector("FIRST ")));
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
AsVector("FIRST ")));
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(*event_interface_,
OnDataFrame(false, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("MESSAG")));
EXPECT_CALL(
*event_interface_,
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("MESSAG")));
EXPECT_CALL(checkpoint, Call(2));
EXPECT_CALL(*event_interface_,
OnDataFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("E")));
OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("E")));
EXPECT_CALL(*event_interface_,
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeText,
AsVector("SECON")));
EXPECT_CALL(checkpoint, Call(3));
EXPECT_CALL(
*event_interface_,
OnDataFrame(false, WebSocketFrameHeader::kOpCodeText, AsVector("SECON")));
EXPECT_CALL(checkpoint, Call(3));
EXPECT_CALL(*event_interface_,
OnDataFrame(false, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("D ")));
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeContinuation,
AsVector("D ")));
EXPECT_CALL(*event_interface_, OnClosingHandshake());
EXPECT_CALL(checkpoint, Call(4));
......@@ -2543,8 +2555,8 @@ TEST_F(WebSocketChannelStreamTest, SentFramesAreMasked) {
.WillOnce(Return(OK));
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(
true, WebSocketFrameHeader::kOpCodeText, AsVector("NEEDS MASKING"));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer("NEEDS MASKING"), 13U);
}
// RFC6455 5.5.1 "The application MUST NOT send any more data frames after
......@@ -2561,8 +2573,8 @@ TEST_F(WebSocketChannelStreamTest, NothingIsSentAfterClose) {
CreateChannelAndConnectSuccessfully();
ASSERT_EQ(CHANNEL_ALIVE, channel_->StartClosingHandshake(1000, "Success"));
channel_->SendFrame(
true, WebSocketFrameHeader::kOpCodeText, AsVector("SHOULD BE IGNORED"));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer("SHOULD BE IGNORED"), 18U);
}
// RFC6455 5.5.1 "If an endpoint receives a Close frame and did not previously
......@@ -2803,12 +2815,12 @@ TEST_F(WebSocketChannelStreamTest, PongInTheMiddleOfDataMessage) {
}
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(
false, WebSocketFrameHeader::kOpCodeText, AsVector("Hello "));
channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer("Hello "), 6U);
*read_frames = CreateFrameVector(frames);
read_callback.Run(OK);
channel_->SendFrame(
true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("World"));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
AsIOBuffer("World"), 5U);
}
// WriteFrames() may not be called until the previous write has completed.
......@@ -2837,10 +2849,10 @@ TEST_F(WebSocketChannelStreamTest, WriteFramesOneAtATime) {
CreateChannelAndConnectSuccessfully();
checkpoint.Call(1);
channel_->SendFrame(
false, WebSocketFrameHeader::kOpCodeText, AsVector("Hello "));
channel_->SendFrame(
true, WebSocketFrameHeader::kOpCodeText, AsVector("World"));
channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer("Hello "), 6U);
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer("World"), 5U);
checkpoint.Call(2);
write_callback.Run(OK);
checkpoint.Call(3);
......@@ -2873,9 +2885,8 @@ TEST_F(WebSocketChannelStreamTest, WaitingMessagesAreBatched) {
CreateChannelAndConnectSuccessfully();
for (size_t i = 0; i < strlen(input_letters); ++i) {
channel_->SendFrame(true,
WebSocketFrameHeader::kOpCodeText,
std::vector<char>(1, input_letters[i]));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer(std::string(1, input_letters[i])), 1U);
}
write_callback.Run(OK);
}
......@@ -2894,9 +2905,9 @@ TEST_F(WebSocketChannelStreamTest, SendGoingAwayOnRendererQuotaExceeded) {
EXPECT_CALL(*mock_stream_, Close());
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(true,
WebSocketFrameHeader::kOpCodeText,
std::vector<char>(kDefaultInitialQuota + 1, 'C'));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer(std::string(kDefaultInitialQuota + 1, 'C')),
kDefaultInitialQuota + 1);
}
// For convenience, most of these tests use Text frames. However, the WebSocket
......@@ -2913,9 +2924,9 @@ TEST_F(WebSocketChannelStreamTest, WrittenBinaryFramesAre8BitClean) {
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(
true,
WebSocketFrameHeader::kOpCodeBinary,
std::vector<char>(kBinaryBlob, kBinaryBlob + kBinaryBlobSize));
true, WebSocketFrameHeader::kOpCodeBinary,
AsIOBuffer(std::string(kBinaryBlob, kBinaryBlob + kBinaryBlobSize)),
kBinaryBlobSize);
ASSERT_TRUE(frames != nullptr);
ASSERT_EQ(1U, frames->size());
const WebSocketFrame* out_frame = (*frames)[0].get();
......@@ -2942,11 +2953,11 @@ TEST_F(WebSocketChannelEventInterfaceTest, ReadBinaryFramesAre8BitClean) {
set_stream(std::move(stream));
EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
EXPECT_CALL(*event_interface_, OnFlowControl(_));
EXPECT_CALL(*event_interface_,
OnDataFrame(true,
WebSocketFrameHeader::kOpCodeBinary,
std::vector<char>(kBinaryBlob,
kBinaryBlob + kBinaryBlobSize)));
EXPECT_CALL(
*event_interface_,
OnDataFrameVector(
true, WebSocketFrameHeader::kOpCodeBinary,
std::vector<char>(kBinaryBlob, kBinaryBlob + kBinaryBlobSize)));
CreateChannelAndConnectSuccessfully();
}
......@@ -2959,8 +2970,8 @@ TEST_F(WebSocketChannelSendUtf8Test, InvalidUtf8Rejected) {
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(
true, WebSocketFrameHeader::kOpCodeText, AsVector("\xff"));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer("\xff"), 1U);
}
// A Text message cannot end with a partial UTF-8 character.
......@@ -2971,8 +2982,8 @@ TEST_F(WebSocketChannelSendUtf8Test, IncompleteCharacterInFinalFrame) {
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(
true, WebSocketFrameHeader::kOpCodeText, AsVector("\xc2"));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer("\xc2"), 1U);
}
// A non-final Text frame may end with a partial UTF-8 character (compare to
......@@ -2980,19 +2991,18 @@ TEST_F(WebSocketChannelSendUtf8Test, IncompleteCharacterInFinalFrame) {
TEST_F(WebSocketChannelSendUtf8Test, IncompleteCharacterInNonFinalFrame) {
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(
false, WebSocketFrameHeader::kOpCodeText, AsVector("\xc2"));
channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer("\xc2"), 1U);
}
// UTF-8 parsing context must be retained between frames.
TEST_F(WebSocketChannelSendUtf8Test, ValidCharacterSplitBetweenFrames) {
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(
false, WebSocketFrameHeader::kOpCodeText, AsVector("\xf1"));
channel_->SendFrame(true,
WebSocketFrameHeader::kOpCodeContinuation,
AsVector("\x80\xa0\xbf"));
channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer("\xf1"), 1U);
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
AsIOBuffer("\x80\xa0\xbf"), 3U);
}
// Similarly, an invalid character should be detected even if split.
......@@ -3003,11 +3013,10 @@ TEST_F(WebSocketChannelSendUtf8Test, InvalidCharacterSplit) {
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(
false, WebSocketFrameHeader::kOpCodeText, AsVector("\xe1"));
channel_->SendFrame(true,
WebSocketFrameHeader::kOpCodeContinuation,
AsVector("\x80\xa0\xbf"));
channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer("\xe1"), 1U);
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
AsIOBuffer("\x80\xa0\xbf"), 3U);
}
// An invalid character must be detected in continuation frames.
......@@ -3018,12 +3027,12 @@ TEST_F(WebSocketChannelSendUtf8Test, InvalidByteInContinuation) {
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(
false, WebSocketFrameHeader::kOpCodeText, AsVector("foo"));
channel_->SendFrame(
false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("bar"));
channel_->SendFrame(
true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("\xff"));
channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer("foo"), 3U);
channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeContinuation,
AsIOBuffer("bar"), 3U);
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
AsIOBuffer("\xff"), 1U);
}
// However, continuation frames of a Binary frame will not be tested for UTF-8
......@@ -3031,12 +3040,12 @@ TEST_F(WebSocketChannelSendUtf8Test, InvalidByteInContinuation) {
TEST_F(WebSocketChannelSendUtf8Test, BinaryContinuationNotChecked) {
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(
false, WebSocketFrameHeader::kOpCodeBinary, AsVector("foo"));
channel_->SendFrame(
false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("bar"));
channel_->SendFrame(
true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("\xff"));
channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeBinary,
AsIOBuffer("foo"), 3U);
channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeContinuation,
AsIOBuffer("bar"), 3U);
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
AsIOBuffer("\xff"), 1U);
}
// Multiple text messages can be validated without the validation state getting
......@@ -3044,8 +3053,10 @@ TEST_F(WebSocketChannelSendUtf8Test, BinaryContinuationNotChecked) {
TEST_F(WebSocketChannelSendUtf8Test, ValidateMultipleTextMessages) {
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("foo"));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("bar"));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer("foo"), 3U);
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer("bar"), 3U);
}
// UTF-8 validation is enforced on received Text frames.
......@@ -3081,8 +3092,8 @@ TEST_F(WebSocketChannelStreamTest, InvalidUtf8TextFrameNotSent) {
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(
true, WebSocketFrameHeader::kOpCodeText, AsVector("\xff"));
channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
AsIOBuffer("\xff"), 1U);
}
// The rest of the tests for receiving invalid UTF-8 test the communication with
......@@ -3251,10 +3262,9 @@ TEST_F(WebSocketChannelEventInterfaceTest, BogusContinuation) {
EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _));
EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota));
EXPECT_CALL(
*event_interface_,
OnDataFrame(
false, WebSocketFrameHeader::kOpCodeBinary, AsVector("frame1")));
EXPECT_CALL(*event_interface_,
OnDataFrameVector(false, WebSocketFrameHeader::kOpCodeBinary,
AsVector("frame1")));
EXPECT_CALL(
*event_interface_,
OnFailChannel(
......@@ -3298,7 +3308,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, DataFramesNonEmptyOrFinal) {
EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota));
EXPECT_CALL(
*event_interface_,
OnDataFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("")));
OnDataFrameVector(true, WebSocketFrameHeader::kOpCodeText, AsVector("")));
CreateChannelAndConnectSuccessfully();
}
......@@ -3514,7 +3524,8 @@ TEST_F(WebSocketChannelTest, CurrentSendQuotaUpdated) {
channel_->SendFrame(
true, WebSocketFrameHeader::kOpCodeText,
std::vector<char>(static_cast<size_t>(kMessageSize), 'a'));
AsIOBuffer(std::string(static_cast<size_t>(kMessageSize), 'a')),
static_cast<size_t>(kMessageSize));
int new_send_quota = channel_->current_send_quota();
EXPECT_EQ(kMessageSize, initial_send_quota - new_send_quota);
}
......
......@@ -71,7 +71,8 @@ class ConnectTestingEventInterface : public WebSocketEventInterface {
ChannelState OnDataFrame(bool fin,
WebSocketMessageType type,
const std::vector<char>& data) override;
scoped_refptr<IOBuffer> data,
size_t data_size) override;
ChannelState OnFlowControl(int64_t quota) override;
......@@ -142,7 +143,8 @@ ChannelState ConnectTestingEventInterface::OnAddChannelResponse(
ChannelState ConnectTestingEventInterface::OnDataFrame(
bool fin,
WebSocketMessageType type,
const std::vector<char>& data) {
scoped_refptr<IOBuffer> data,
size_t data_size) {
return CHANNEL_ALIVE;
}
......
......@@ -13,12 +13,14 @@
#include "base/compiler_specific.h" // for WARN_UNUSED_RESULT
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "net/base/net_export.h"
class GURL;
namespace net {
class IOBuffer;
class SSLInfo;
struct WebSocketHandshakeRequestInfo;
struct WebSocketHandshakeResponseInfo;
......@@ -47,10 +49,10 @@ class NET_EXPORT WebSocketEventInterface {
// Called when a data frame has been received from the remote host and needs
// to be forwarded to the renderer process.
virtual ChannelState OnDataFrame(
bool fin,
WebSocketMessageType type,
const std::vector<char>& data) WARN_UNUSED_RESULT = 0;
virtual ChannelState OnDataFrame(bool fin,
WebSocketMessageType type,
scoped_refptr<IOBuffer> buffer,
size_t buffer_size) WARN_UNUSED_RESULT = 0;
// Called to provide more send quota for this channel to the renderer
// process. Currently the quota units are always bytes of message body
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment