summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-12 01:00:40 +0000
committerrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-12 01:00:40 +0000
commite37ce37a62b59a55d2c7f90cae0dc7c7dec6a038 (patch)
treef58e9e44aa649a129478c4ff12eaa0ee7afe9e4d /net
parent91066fd43e011a34aea9140739c39c653425a823 (diff)
downloadchromium_src-e37ce37a62b59a55d2c7f90cae0dc7c7dec6a038.zip
chromium_src-e37ce37a62b59a55d2c7f90cae0dc7c7dec6a038.tar.gz
chromium_src-e37ce37a62b59a55d2c7f90cae0dc7c7dec6a038.tar.bz2
SPDY - chunked upload - cleanup of spdy_http_stream to read the data
in SendBody instead of SendBodyComplete. SpdyHttpStream inherits from ChunkCallback (SpdyStream doesn't inherit from ChunkCallback). OnChunkAvailable is handled by SpdyHttpStream. In unit tests, added new tests (similar to http_stream_parser_unittest for chunked uploads), to delay sending of chunked data. Also added sending of window_update during chunk uploads. Verified that these tests fail with the old code and run ok with the new changes. This change also fixed chunked uploads hanging (or stalling) for speech recgonition. Many many thanks to sleevi for suggesting the way to clean up the SpdyHttpStream's SendBody and SendBodyComplete code. R=rch@chromium.org, rsleevi@chromium.org TEST=network unit tests BUG=113107, 136044 Review URL: https://chromiumcodereview.appspot.com/10689034 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@146255 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/base/upload_data_stream.cc6
-rw-r--r--net/base/upload_data_stream.h10
-rw-r--r--net/spdy/spdy_http_stream.cc87
-rw-r--r--net/spdy/spdy_http_stream.h15
-rw-r--r--net/spdy/spdy_http_stream_spdy2_unittest.cc160
-rw-r--r--net/spdy/spdy_http_stream_spdy3_unittest.cc285
-rw-r--r--net/spdy/spdy_network_transaction_spdy2_unittest.cc9
-rw-r--r--net/spdy/spdy_network_transaction_spdy3_unittest.cc58
-rw-r--r--net/spdy/spdy_proxy_client_socket.cc3
-rw-r--r--net/spdy/spdy_proxy_client_socket.h1
-rw-r--r--net/spdy/spdy_session_spdy2_unittest.cc2
-rw-r--r--net/spdy/spdy_session_spdy3_unittest.cc2
-rw-r--r--net/spdy/spdy_stream.cc31
-rw-r--r--net/spdy/spdy_stream.h10
-rw-r--r--net/spdy/spdy_stream_spdy2_unittest.cc2
-rw-r--r--net/spdy/spdy_stream_spdy3_unittest.cc2
-rw-r--r--net/spdy/spdy_websocket_stream.cc4
-rw-r--r--net/spdy/spdy_websocket_stream.h1
18 files changed, 556 insertions, 132 deletions
diff --git a/net/base/upload_data_stream.cc b/net/base/upload_data_stream.cc
index e86c1b3..9791a91 100644
--- a/net/base/upload_data_stream.cc
+++ b/net/base/upload_data_stream.cc
@@ -15,6 +15,12 @@ namespace net {
bool UploadDataStream::merge_chunks_ = true;
+// static
+void UploadDataStream::ResetMergeChunks() {
+ // WARNING: merge_chunks_ must match the above initializer.
+ merge_chunks_ = true;
+}
+
UploadDataStream::UploadDataStream(UploadData* upload_data)
: upload_data_(upload_data),
element_index_(0),
diff --git a/net/base/upload_data_stream.h b/net/base/upload_data_stream.h
index 82885dc..3d060f9 100644
--- a/net/base/upload_data_stream.h
+++ b/net/base/upload_data_stream.h
@@ -64,10 +64,16 @@ class NET_EXPORT UploadDataStream {
// Returns true if the upload data in the stream is entirely in memory.
bool IsInMemory() const;
- // This method is provided only to be used by unit tests.
+ private:
+ friend class SpdyHttpStreamSpdy2Test;
+ friend class SpdyHttpStreamSpdy3Test;
+ friend class SpdyNetworkTransactionSpdy2Test;
+ friend class SpdyNetworkTransactionSpdy3Test;
+
+ // These methods are provided only to be used by unit tests.
+ static void ResetMergeChunks();
static void set_merge_chunks(bool merge) { merge_chunks_ = merge; }
- private:
scoped_refptr<UploadData> upload_data_;
// Index of the current upload element (i.e. the element currently being
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc
index 170e3e1..dce5f13 100644
--- a/net/spdy/spdy_http_stream.cc
+++ b/net/spdy/spdy_http_stream.cc
@@ -36,7 +36,8 @@ SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session,
user_buffer_len_(0),
buffered_read_callback_pending_(false),
more_read_data_pending_(false),
- direct_(direct) { }
+ direct_(direct),
+ waiting_for_chunk_(false) { }
void SpdyHttpStream::InitializeWithExistingStream(SpdyStream* spdy_stream) {
stream_ = spdy_stream;
@@ -45,6 +46,8 @@ void SpdyHttpStream::InitializeWithExistingStream(SpdyStream* spdy_stream) {
}
SpdyHttpStream::~SpdyHttpStream() {
+ if (request_body_stream_ != NULL)
+ request_body_stream_->set_chunk_callback(NULL);
if (stream_)
stream_->DetachDelegate();
}
@@ -182,11 +185,6 @@ bool SpdyHttpStream::IsConnectionReusable() const {
return false;
}
-void SpdyHttpStream::set_chunk_callback(ChunkCallback* callback) {
- if (request_body_stream_ != NULL)
- request_body_stream_->set_chunk_callback(callback);
-}
-
int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers,
scoped_ptr<UploadDataStream> request_body,
HttpResponseInfo* response,
@@ -213,6 +211,7 @@ int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers,
if (request_body != NULL) {
if (request_body->size() || request_body->is_chunked()) {
request_body_stream_.reset(request_body.release());
+ request_body_stream_->set_chunk_callback(this);
// Use kMaxSpdyFrameChunkSize as the buffer size, since the request
// body data is written with this size at a time.
raw_request_body_buf_ = new IOBufferWithSize(kMaxSpdyFrameChunkSize);
@@ -241,9 +240,9 @@ int SpdyHttpStream::SendRequest(const HttpRequestHeaders& request_headers,
if (push_response_info_.get()) {
*response = *(push_response_info_.get());
push_response_info_.reset();
- }
- else
+ } else {
DCHECK_EQ(static_cast<HttpResponseInfo*>(NULL), response_info_);
+ }
response_info_ = response;
@@ -271,6 +270,35 @@ void SpdyHttpStream::Cancel() {
stream_->Cancel();
}
+int SpdyHttpStream::SendData() {
+ CHECK(request_body_stream_.get());
+ CHECK_EQ(0, request_body_buf_->BytesRemaining());
+
+ // Read the data from the request body stream.
+ const int bytes_read = request_body_stream_->Read(
+ raw_request_body_buf_, raw_request_body_buf_->size());
+ DCHECK(!waiting_for_chunk_ || bytes_read != ERR_IO_PENDING);
+
+ if (request_body_stream_->is_chunked() && bytes_read == ERR_IO_PENDING) {
+ waiting_for_chunk_ = true;
+ return ERR_IO_PENDING;
+ }
+
+ waiting_for_chunk_ = false;
+
+ // ERR_IO_PENDING with chunked encoding is the only possible error.
+ DCHECK_GE(bytes_read, 0);
+
+ request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_,
+ bytes_read);
+
+ const bool eof = request_body_stream_->IsEOF();
+ return stream_->WriteStreamData(
+ request_body_buf_,
+ request_body_buf_->BytesRemaining(),
+ eof ? DATA_FLAG_FIN : DATA_FLAG_NONE);
+}
+
bool SpdyHttpStream::OnSendHeadersComplete(int status) {
if (!callback_.is_null())
DoCallback(status);
@@ -279,20 +307,19 @@ bool SpdyHttpStream::OnSendHeadersComplete(int status) {
int SpdyHttpStream::OnSendBody() {
CHECK(request_body_stream_.get());
+ const bool eof = request_body_stream_->IsEOF();
+ if (request_body_buf_->BytesRemaining() > 0) {
+ return stream_->WriteStreamData(
+ request_body_buf_,
+ request_body_buf_->BytesRemaining(),
+ eof ? DATA_FLAG_FIN : DATA_FLAG_NONE);
+ }
- // TODO(satorux): Clean up the logic here. This behavior is weird. Reading
- // of upload data should happen in OnSendBody(). crbug.com/113107.
- //
- // Nothing to send. This happens when OnSendBody() is first called.
- // A read of the upload data stream is initiated in OnSendBodyComplete().
- if (request_body_buf_->BytesRemaining() == 0)
+ // The entire body data has been sent.
+ if (eof)
return OK;
- const bool eof = request_body_stream_->IsEOF();
- return stream_->WriteStreamData(
- request_body_buf_,
- request_body_buf_->BytesRemaining(),
- eof ? DATA_FLAG_FIN : DATA_FLAG_NONE);
+ return SendData();
}
int SpdyHttpStream::OnSendBodyComplete(int status, bool* eof) {
@@ -311,19 +338,6 @@ int SpdyHttpStream::OnSendBodyComplete(int status, bool* eof) {
// Check if the entire body data has been sent.
*eof = (request_body_stream_->IsEOF() &&
!request_body_buf_->BytesRemaining());
- if (*eof)
- return OK;
-
- // Read the data from the request body stream.
- const int bytes_read = request_body_stream_->Read(
- raw_request_body_buf_, raw_request_body_buf_->size());
- if (request_body_stream_->is_chunked() && bytes_read == ERR_IO_PENDING)
- return ERR_IO_PENDING;
- // ERR_IO_PENDING with chunked encoding is the only possible error.
- DCHECK_GE(bytes_read, 0);
-
- request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_,
- bytes_read);
return OK;
}
@@ -406,6 +420,8 @@ void SpdyHttpStream::OnDataSent(int length) {
void SpdyHttpStream::OnClose(int status) {
bool invoked_callback = false;
+ if (request_body_stream_ != NULL)
+ request_body_stream_->set_chunk_callback(NULL);
if (status == net::OK) {
// We need to complete any pending buffered read now.
invoked_callback = DoBufferedReadCallback();
@@ -414,6 +430,13 @@ void SpdyHttpStream::OnClose(int status) {
DoCallback(status);
}
+void SpdyHttpStream::OnChunkAvailable() {
+ if (!waiting_for_chunk_)
+ return;
+ DCHECK(request_body_stream_->is_chunked());
+ SendData();
+}
+
void SpdyHttpStream::ScheduleBufferedReadCallback() {
// If there is already a scheduled DoBufferedReadCallback, don't issue
// another one. Mark that we have received more data and return.
diff --git a/net/spdy/spdy_http_stream.h b/net/spdy/spdy_http_stream.h
index 990e14a..97cd173 100644
--- a/net/spdy/spdy_http_stream.h
+++ b/net/spdy/spdy_http_stream.h
@@ -13,6 +13,7 @@
#include "base/memory/weak_ptr.h"
#include "net/base/completion_callback.h"
#include "net/base/net_log.h"
+#include "net/base/upload_data.h"
#include "net/http/http_request_info.h"
#include "net/http/http_stream.h"
#include "net/spdy/spdy_protocol.h"
@@ -30,7 +31,8 @@ class UploadDataStream;
// The SpdyHttpStream is a HTTP-specific type of stream known to a SpdySession.
class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate,
- public HttpStream {
+ public HttpStream,
+ public ChunkCallback {
public:
SpdyHttpStream(SpdySession* spdy_session, bool direct);
virtual ~SpdyHttpStream();
@@ -82,7 +84,9 @@ class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate,
virtual void OnDataReceived(const char* buffer, int bytes) OVERRIDE;
virtual void OnDataSent(int length) OVERRIDE;
virtual void OnClose(int status) OVERRIDE;
- virtual void set_chunk_callback(ChunkCallback* callback) OVERRIDE;
+
+ // ChunkCallback implementation.
+ virtual void OnChunkAvailable() OVERRIDE;
private:
FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionSpdy2Test,
@@ -94,6 +98,10 @@ class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate,
FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionSpdy3Test,
FlowControlNegativeSendWindowSize);
+ // Reads the data (whether chunked or not) from the request body stream and
+ // sends the data by calling WriteStreamData on the underlying SpdyStream.
+ int SendData();
+
// Call the user callback.
void DoCallback(int rv);
@@ -146,6 +154,9 @@ class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate,
// Is this spdy stream direct to the origin server (or to a proxy).
bool direct_;
+ // Is the connection stalled waiting for an upload data chunk.
+ bool waiting_for_chunk_;
+
bool send_last_chunk_;
DISALLOW_COPY_AND_ASSIGN(SpdyHttpStream);
diff --git a/net/spdy/spdy_http_stream_spdy2_unittest.cc b/net/spdy/spdy_http_stream_spdy2_unittest.cc
index c3c37a6..397fe1d 100644
--- a/net/spdy/spdy_http_stream_spdy2_unittest.cc
+++ b/net/spdy/spdy_http_stream_spdy2_unittest.cc
@@ -31,9 +31,14 @@ class SpdyHttpStreamSpdy2Test : public testing::Test {
virtual void TearDown() {
crypto::ECSignatureCreator::SetFactoryForTesting(NULL);
+ UploadDataStream::ResetMergeChunks();
MessageLoop::current()->RunAllPending();
}
+ void set_merge_chunks(bool merge) {
+ UploadDataStream::set_merge_chunks(merge);
+ }
+
int InitSession(MockRead* reads, size_t reads_count,
MockWrite* writes, size_t writes_count,
HostPortPair& host_port_pair) {
@@ -118,20 +123,20 @@ TEST_F(SpdyHttpStreamSpdy2Test, SendRequest) {
}
TEST_F(SpdyHttpStreamSpdy2Test, SendChunkedPost) {
- UploadDataStream::set_merge_chunks(false);
+ set_merge_chunks(false);
scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false));
scoped_ptr<SpdyFrame> chunk2(ConstructSpdyBodyFrame(1, true));
MockWrite writes[] = {
- CreateMockWrite(*req.get(), 1),
- CreateMockWrite(*chunk1, 2), // POST upload frames
- CreateMockWrite(*chunk2, 3),
+ CreateMockWrite(*req.get(), 0),
+ CreateMockWrite(*chunk1, 1), // POST upload frames
+ CreateMockWrite(*chunk2, 2),
};
scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
MockRead reads[] = {
- CreateMockRead(*resp, 4),
- CreateMockRead(*chunk1, 5),
+ CreateMockRead(*resp, 3),
+ CreateMockRead(*chunk1, 4),
CreateMockRead(*chunk2, 5),
MockRead(SYNCHRONOUS, 0, 6) // EOF
};
@@ -178,6 +183,149 @@ TEST_F(SpdyHttpStreamSpdy2Test, SendChunkedPost) {
EXPECT_TRUE(data()->at_write_eof());
}
+// Test to ensure the SpdyStream state machine does not get confused when a
+// chunk becomes available while a write is pending.
+TEST_F(SpdyHttpStreamSpdy2Test, DelayedSendChunkedPost) {
+ set_merge_chunks(false);
+
+ const char kUploadData1[] = "12345678";
+ const int kUploadData1Size = arraysize(kUploadData1)-1;
+ scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
+ scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false));
+ scoped_ptr<SpdyFrame> chunk2(
+ ConstructSpdyBodyFrame(1, kUploadData1, kUploadData1Size, false));
+ scoped_ptr<SpdyFrame> chunk3(ConstructSpdyBodyFrame(1, true));
+ MockWrite writes[] = {
+ CreateMockWrite(*req.get(), 0),
+ CreateMockWrite(*chunk1, 1), // POST upload frames
+ CreateMockWrite(*chunk2, 2),
+ CreateMockWrite(*chunk3, 3),
+ };
+ scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
+ MockRead reads[] = {
+ CreateMockRead(*resp, 4),
+ CreateMockRead(*chunk1, 5),
+ CreateMockRead(*chunk2, 6),
+ CreateMockRead(*chunk3, 7),
+ MockRead(ASYNC, 0, 8) // EOF
+ };
+
+ HostPortPair host_port_pair("www.google.com", 80);
+ HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
+
+ scoped_ptr<DeterministicSocketData> data(
+ new DeterministicSocketData(reads, arraysize(reads),
+ writes, arraysize(writes)));
+
+ DeterministicMockClientSocketFactory* socket_factory =
+ session_deps_.deterministic_socket_factory.get();
+ socket_factory->AddSocketDataProvider(data.get());
+
+ http_session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
+ &session_deps_);
+ session_ = http_session_->spdy_session_pool()->Get(pair, BoundNetLog());
+ transport_params_ = new TransportSocketParams(host_port_pair,
+ MEDIUM, false, false,
+ OnHostResolutionCallback());
+
+ TestCompletionCallback callback;
+ scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
+
+ EXPECT_EQ(ERR_IO_PENDING,
+ connection->Init(host_port_pair.ToString(),
+ transport_params_,
+ MEDIUM,
+ callback.callback(),
+ http_session_->GetTransportSocketPool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL),
+ BoundNetLog()));
+
+ callback.WaitForResult();
+ EXPECT_EQ(OK,
+ session_->InitializeWithSocket(connection.release(), false, OK));
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.google.com/");
+ request.upload_data = new UploadData();
+ request.upload_data->set_is_chunked(true);
+
+ BoundNetLog net_log;
+ scoped_ptr<SpdyHttpStream> http_stream(
+ new SpdyHttpStream(session_.get(), true));
+ ASSERT_EQ(OK,
+ http_stream->InitializeStream(&request,
+ net_log,
+ CompletionCallback()));
+
+ scoped_ptr<UploadDataStream> upload_stream(
+ new UploadDataStream(request.upload_data));
+ ASSERT_EQ(OK, upload_stream->Init());
+
+ request.upload_data->AppendChunk(kUploadData, kUploadDataSize, false);
+
+ HttpRequestHeaders headers;
+ HttpResponseInfo response;
+ // This will attempt to Write() the initial request and headers, which will
+ // complete asynchronously.
+ EXPECT_EQ(ERR_IO_PENDING,
+ http_stream->SendRequest(headers,
+ upload_stream.Pass(),
+ &response,
+ callback.callback()));
+ EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair));
+
+ // Complete the initial request write and the first chunk.
+ data->RunFor(2);
+ ASSERT_TRUE(callback.have_result());
+ EXPECT_GT(callback.WaitForResult(), 0);
+
+ // Now append the final two chunks which will enqueue two more writes.
+ request.upload_data->AppendChunk(kUploadData1, kUploadData1Size, false);
+ request.upload_data->AppendChunk(kUploadData, kUploadDataSize, true);
+
+ // Finish writing all the chunks.
+ data->RunFor(2);
+
+ // Read response headers.
+ data->RunFor(1);
+ ASSERT_EQ(OK, http_stream->ReadResponseHeaders(callback.callback()));
+
+ // Read and check |chunk1| response.
+ data->RunFor(1);
+ scoped_refptr<IOBuffer> buf1(new IOBuffer(kUploadDataSize));
+ ASSERT_EQ(kUploadDataSize,
+ http_stream->ReadResponseBody(buf1,
+ kUploadDataSize,
+ callback.callback()));
+ EXPECT_EQ(kUploadData, std::string(buf1->data(), kUploadDataSize));
+
+ // Read and check |chunk2| response.
+ data->RunFor(1);
+ scoped_refptr<IOBuffer> buf2(new IOBuffer(kUploadData1Size));
+ ASSERT_EQ(kUploadData1Size,
+ http_stream->ReadResponseBody(buf2,
+ kUploadData1Size,
+ callback.callback()));
+ EXPECT_EQ(kUploadData1, std::string(buf2->data(), kUploadData1Size));
+
+ // Read and check |chunk3| response.
+ data->RunFor(1);
+ scoped_refptr<IOBuffer> buf3(new IOBuffer(kUploadDataSize));
+ ASSERT_EQ(kUploadDataSize,
+ http_stream->ReadResponseBody(buf3,
+ kUploadDataSize,
+ callback.callback()));
+ EXPECT_EQ(kUploadData, std::string(buf3->data(), kUploadDataSize));
+
+ // Finish reading the |EOF|.
+ data->RunFor(1);
+ ASSERT_TRUE(response.headers.get());
+ ASSERT_EQ(200, response.headers->response_code());
+ EXPECT_TRUE(data->at_read_eof());
+ EXPECT_TRUE(data->at_write_eof());
+}
+
// Test case for bug: http://code.google.com/p/chromium/issues/detail?id=50058
TEST_F(SpdyHttpStreamSpdy2Test, SpdyURLTest) {
const char * const full_url = "http://www.google.com/foo?query=what#anchor";
diff --git a/net/spdy/spdy_http_stream_spdy3_unittest.cc b/net/spdy/spdy_http_stream_spdy3_unittest.cc
index 53b4940..21a2f62 100644
--- a/net/spdy/spdy_http_stream_spdy3_unittest.cc
+++ b/net/spdy/spdy_http_stream_spdy3_unittest.cc
@@ -34,9 +34,14 @@ class SpdyHttpStreamSpdy3Test : public testing::Test {
virtual void TearDown() {
crypto::ECSignatureCreator::SetFactoryForTesting(NULL);
+ UploadDataStream::ResetMergeChunks();
MessageLoop::current()->RunAllPending();
}
+ void set_merge_chunks(bool merge) {
+ UploadDataStream::set_merge_chunks(merge);
+ }
+
int InitSession(MockRead* reads, size_t reads_count,
MockWrite* writes, size_t writes_count,
HostPortPair& host_port_pair) {
@@ -126,20 +131,20 @@ TEST_F(SpdyHttpStreamSpdy3Test, SendRequest) {
}
TEST_F(SpdyHttpStreamSpdy3Test, SendChunkedPost) {
- UploadDataStream::set_merge_chunks(false);
+ set_merge_chunks(false);
scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false));
scoped_ptr<SpdyFrame> chunk2(ConstructSpdyBodyFrame(1, true));
MockWrite writes[] = {
- CreateMockWrite(*req.get(), 1),
- CreateMockWrite(*chunk1, 2), // POST upload frames
- CreateMockWrite(*chunk2, 3),
+ CreateMockWrite(*req.get(), 0),
+ CreateMockWrite(*chunk1, 1), // POST upload frames
+ CreateMockWrite(*chunk2, 2),
};
scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
MockRead reads[] = {
- CreateMockRead(*resp, 4),
- CreateMockRead(*chunk1, 5),
+ CreateMockRead(*resp, 3),
+ CreateMockRead(*chunk1, 4),
CreateMockRead(*chunk2, 5),
MockRead(SYNCHRONOUS, 0, 6) // EOF
};
@@ -186,6 +191,274 @@ TEST_F(SpdyHttpStreamSpdy3Test, SendChunkedPost) {
EXPECT_TRUE(data()->at_write_eof());
}
+// Test to ensure the SpdyStream state machine does not get confused when a
+// chunk becomes available while a write is pending.
+TEST_F(SpdyHttpStreamSpdy3Test, DelayedSendChunkedPost) {
+ set_merge_chunks(false);
+
+ const char kUploadData1[] = "12345678";
+ const int kUploadData1Size = arraysize(kUploadData1)-1;
+ scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
+ scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false));
+ scoped_ptr<SpdyFrame> chunk2(
+ ConstructSpdyBodyFrame(1, kUploadData1, kUploadData1Size, false));
+ scoped_ptr<SpdyFrame> chunk3(ConstructSpdyBodyFrame(1, true));
+ MockWrite writes[] = {
+ CreateMockWrite(*req.get(), 0),
+ CreateMockWrite(*chunk1, 1), // POST upload frames
+ CreateMockWrite(*chunk2, 2),
+ CreateMockWrite(*chunk3, 3),
+ };
+ scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
+ MockRead reads[] = {
+ CreateMockRead(*resp, 4),
+ CreateMockRead(*chunk1, 5),
+ CreateMockRead(*chunk2, 6),
+ CreateMockRead(*chunk3, 7),
+ MockRead(ASYNC, 0, 8) // EOF
+ };
+
+ HostPortPair host_port_pair("www.google.com", 80);
+ HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
+
+ scoped_ptr<DeterministicSocketData> data(
+ new DeterministicSocketData(reads, arraysize(reads),
+ writes, arraysize(writes)));
+
+ DeterministicMockClientSocketFactory* socket_factory =
+ session_deps_.deterministic_socket_factory.get();
+ socket_factory->AddSocketDataProvider(data.get());
+
+ http_session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
+ &session_deps_);
+ session_ = http_session_->spdy_session_pool()->Get(pair, BoundNetLog());
+ transport_params_ = new TransportSocketParams(host_port_pair,
+ MEDIUM, false, false,
+ OnHostResolutionCallback());
+
+ TestCompletionCallback callback;
+ scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
+
+ EXPECT_EQ(ERR_IO_PENDING,
+ connection->Init(host_port_pair.ToString(),
+ transport_params_,
+ MEDIUM,
+ callback.callback(),
+ http_session_->GetTransportSocketPool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL),
+ BoundNetLog()));
+
+ callback.WaitForResult();
+ EXPECT_EQ(OK,
+ session_->InitializeWithSocket(connection.release(), false, OK));
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.google.com/");
+ request.upload_data = new UploadData();
+ request.upload_data->set_is_chunked(true);
+
+ BoundNetLog net_log;
+ scoped_ptr<SpdyHttpStream> http_stream(
+ new SpdyHttpStream(session_.get(), true));
+ ASSERT_EQ(OK,
+ http_stream->InitializeStream(&request,
+ net_log,
+ CompletionCallback()));
+
+ scoped_ptr<UploadDataStream> upload_stream(
+ new UploadDataStream(request.upload_data));
+ ASSERT_EQ(OK, upload_stream->Init());
+
+ request.upload_data->AppendChunk(kUploadData, kUploadDataSize, false);
+
+ HttpRequestHeaders headers;
+ HttpResponseInfo response;
+ // This will attempt to Write() the initial request and headers, which will
+ // complete asynchronously.
+ EXPECT_EQ(ERR_IO_PENDING,
+ http_stream->SendRequest(headers,
+ upload_stream.Pass(),
+ &response,
+ callback.callback()));
+ EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair));
+
+ // Complete the initial request write and the first chunk.
+ data->RunFor(2);
+ ASSERT_TRUE(callback.have_result());
+ EXPECT_GT(callback.WaitForResult(), 0);
+
+ // Now append the final two chunks which will enqueue two more writes.
+ request.upload_data->AppendChunk(kUploadData1, kUploadData1Size, false);
+ request.upload_data->AppendChunk(kUploadData, kUploadDataSize, true);
+
+ // Finish writing all the chunks.
+ data->RunFor(2);
+
+ // Read response headers.
+ data->RunFor(1);
+ ASSERT_EQ(OK, http_stream->ReadResponseHeaders(callback.callback()));
+
+ // Read and check |chunk1| response.
+ data->RunFor(1);
+ scoped_refptr<IOBuffer> buf1(new IOBuffer(kUploadDataSize));
+ ASSERT_EQ(kUploadDataSize,
+ http_stream->ReadResponseBody(buf1,
+ kUploadDataSize,
+ callback.callback()));
+ EXPECT_EQ(kUploadData, std::string(buf1->data(), kUploadDataSize));
+
+ // Read and check |chunk2| response.
+ data->RunFor(1);
+ scoped_refptr<IOBuffer> buf2(new IOBuffer(kUploadData1Size));
+ ASSERT_EQ(kUploadData1Size,
+ http_stream->ReadResponseBody(buf2,
+ kUploadData1Size,
+ callback.callback()));
+ EXPECT_EQ(kUploadData1, std::string(buf2->data(), kUploadData1Size));
+
+ // Read and check |chunk3| response.
+ data->RunFor(1);
+ scoped_refptr<IOBuffer> buf3(new IOBuffer(kUploadDataSize));
+ ASSERT_EQ(kUploadDataSize,
+ http_stream->ReadResponseBody(buf3,
+ kUploadDataSize,
+ callback.callback()));
+ EXPECT_EQ(kUploadData, std::string(buf3->data(), kUploadDataSize));
+
+ // Finish reading the |EOF|.
+ data->RunFor(1);
+ ASSERT_TRUE(response.headers.get());
+ ASSERT_EQ(200, response.headers->response_code());
+ EXPECT_TRUE(data->at_read_eof());
+ EXPECT_TRUE(data->at_write_eof());
+}
+
+// Test the receipt of a WINDOW_UPDATE frame while waiting for a chunk to be
+// made available is handled correctly.
+TEST_F(SpdyHttpStreamSpdy3Test, DelayedSendChunkedPostWithWindowUpdate) {
+ set_merge_chunks(false);
+
+ scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
+ scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, true));
+ MockWrite writes[] = {
+ CreateMockWrite(*req.get(), 0),
+ CreateMockWrite(*chunk1, 1),
+ };
+ scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
+ scoped_ptr<SpdyFrame> window_update(
+ ConstructSpdyWindowUpdate(1, kUploadDataSize));
+ MockRead reads[] = {
+ CreateMockRead(*window_update, 2),
+ CreateMockRead(*resp, 3),
+ CreateMockRead(*chunk1, 4),
+ MockRead(ASYNC, 0, 5) // EOF
+ };
+
+ HostPortPair host_port_pair("www.google.com", 80);
+ HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
+
+ scoped_ptr<DeterministicSocketData> data(
+ new DeterministicSocketData(reads, arraysize(reads),
+ writes, arraysize(writes)));
+
+ DeterministicMockClientSocketFactory* socket_factory =
+ session_deps_.deterministic_socket_factory.get();
+ socket_factory->AddSocketDataProvider(data.get());
+
+ http_session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
+ &session_deps_);
+ session_ = http_session_->spdy_session_pool()->Get(pair, BoundNetLog());
+ transport_params_ = new TransportSocketParams(host_port_pair,
+ MEDIUM, false, false,
+ OnHostResolutionCallback());
+
+ TestCompletionCallback callback;
+ scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
+
+ EXPECT_EQ(ERR_IO_PENDING,
+ connection->Init(host_port_pair.ToString(),
+ transport_params_,
+ MEDIUM,
+ callback.callback(),
+ http_session_->GetTransportSocketPool(
+ HttpNetworkSession::NORMAL_SOCKET_POOL),
+ BoundNetLog()));
+
+ callback.WaitForResult();
+ EXPECT_EQ(OK,
+ session_->InitializeWithSocket(connection.release(), false, OK));
+
+ HttpRequestInfo request;
+ request.method = "POST";
+ request.url = GURL("http://www.google.com/");
+ request.upload_data = new UploadData();
+ request.upload_data->set_is_chunked(true);
+
+ BoundNetLog net_log;
+ scoped_ptr<SpdyHttpStream> http_stream(
+ new SpdyHttpStream(session_.get(), true));
+ ASSERT_EQ(OK,
+ http_stream->InitializeStream(&request,
+ net_log,
+ CompletionCallback()));
+
+ scoped_ptr<UploadDataStream> upload_stream(
+ new UploadDataStream(request.upload_data));
+ ASSERT_EQ(OK, upload_stream->Init());
+
+ request.upload_data->AppendChunk(kUploadData, kUploadDataSize, true);
+
+ HttpRequestHeaders headers;
+ HttpResponseInfo response;
+ // This will attempt to Write() the initial request and headers, which will
+ // complete asynchronously.
+ EXPECT_EQ(ERR_IO_PENDING,
+ http_stream->SendRequest(headers,
+ upload_stream.Pass(),
+ &response,
+ callback.callback()));
+ EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair));
+
+ // Complete the initial request write and first chunk.
+ data->RunFor(2);
+ ASSERT_TRUE(callback.have_result());
+ EXPECT_GT(callback.WaitForResult(), 0);
+
+ // Verify that the window size has decreased.
+ ASSERT_TRUE(http_stream->stream() != NULL);
+ EXPECT_NE(static_cast<int>(kSpdyStreamInitialWindowSize),
+ http_stream->stream()->send_window_size());
+
+ // Read window update.
+ data->RunFor(1);
+
+ // Verify the window update.
+ ASSERT_TRUE(http_stream->stream() != NULL);
+ EXPECT_EQ(static_cast<int>(kSpdyStreamInitialWindowSize),
+ http_stream->stream()->send_window_size());
+
+ // Read response headers.
+ data->RunFor(1);
+ ASSERT_EQ(OK, http_stream->ReadResponseHeaders(callback.callback()));
+
+ // Read and check |chunk1| response.
+ data->RunFor(1);
+ scoped_refptr<IOBuffer> buf1(new IOBuffer(kUploadDataSize));
+ ASSERT_EQ(kUploadDataSize,
+ http_stream->ReadResponseBody(buf1,
+ kUploadDataSize,
+ callback.callback()));
+ EXPECT_EQ(kUploadData, std::string(buf1->data(), kUploadDataSize));
+
+ // Finish reading the |EOF|.
+ data->RunFor(1);
+ ASSERT_TRUE(response.headers.get());
+ ASSERT_EQ(200, response.headers->response_code());
+ EXPECT_TRUE(data->at_read_eof());
+ EXPECT_TRUE(data->at_write_eof());
+}
+
// Test case for bug: http://code.google.com/p/chromium/issues/detail?id=50058
TEST_F(SpdyHttpStreamSpdy3Test, SpdyURLTest) {
const char * const full_url = "http://www.google.com/foo?query=what#anchor";
diff --git a/net/spdy/spdy_network_transaction_spdy2_unittest.cc b/net/spdy/spdy_network_transaction_spdy2_unittest.cc
index 81e9e66..53fe545 100644
--- a/net/spdy/spdy_network_transaction_spdy2_unittest.cc
+++ b/net/spdy/spdy_network_transaction_spdy2_unittest.cc
@@ -35,6 +35,7 @@ enum SpdyNetworkTransactionSpdy2TestTypes {
SPDYNOSSL,
SPDYSSL,
};
+
class SpdyNetworkTransactionSpdy2Test
: public ::testing::TestWithParam<SpdyNetworkTransactionSpdy2TestTypes> {
protected:
@@ -47,10 +48,15 @@ class SpdyNetworkTransactionSpdy2Test
}
virtual void TearDown() {
+ UploadDataStream::ResetMergeChunks();
// Empty the current queue.
MessageLoop::current()->RunAllPending();
}
+ void set_merge_chunks(bool merge) {
+ UploadDataStream::set_merge_chunks(merge);
+ }
+
struct TransactionHelperResult {
int rv;
std::string status_line;
@@ -1587,7 +1593,8 @@ TEST_P(SpdyNetworkTransactionSpdy2Test, Post) {
// Test that a chunked POST works.
TEST_P(SpdyNetworkTransactionSpdy2Test, ChunkedPost) {
- UploadDataStream::set_merge_chunks(false);
+ set_merge_chunks(false);
+
scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false));
scoped_ptr<SpdyFrame> chunk2(ConstructSpdyBodyFrame(1, true));
diff --git a/net/spdy/spdy_network_transaction_spdy3_unittest.cc b/net/spdy/spdy_network_transaction_spdy3_unittest.cc
index 975285e..e66bad9 100644
--- a/net/spdy/spdy_network_transaction_spdy3_unittest.cc
+++ b/net/spdy/spdy_network_transaction_spdy3_unittest.cc
@@ -47,10 +47,15 @@ class SpdyNetworkTransactionSpdy3Test
}
virtual void TearDown() {
+ UploadDataStream::ResetMergeChunks();
// Empty the current queue.
MessageLoop::current()->RunAllPending();
}
+ void set_merge_chunks(bool merge) {
+ UploadDataStream::set_merge_chunks(merge);
+ }
+
struct TransactionHelperResult {
int rv;
std::string status_line;
@@ -85,8 +90,7 @@ class SpdyNetworkTransactionSpdy3Test
default:
NOTREACHED();
}
- }
-
+ }
~NormalSpdyTransactionHelper() {
// Any test which doesn't close the socket by sending it an EOF will
@@ -1595,7 +1599,8 @@ TEST_P(SpdyNetworkTransactionSpdy3Test, Post) {
// Test that a chunked POST works.
TEST_P(SpdyNetworkTransactionSpdy3Test, ChunkedPost) {
- UploadDataStream::set_merge_chunks(false);
+ set_merge_chunks(false);
+
scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false));
scoped_ptr<SpdyFrame> chunk2(ConstructSpdyBodyFrame(1, true));
@@ -2030,10 +2035,9 @@ TEST_P(SpdyNetworkTransactionSpdy3Test, WindowUpdateSent) {
helper.VerifyDataConsumed();
}
-// Test that WINDOW_UPDATE frame causing overflow is handled correctly. We
-// use the same trick as in the above test to enforce our scenario.
+// Test that WINDOW_UPDATE frame causing overflow is handled correctly.
TEST_P(SpdyNetworkTransactionSpdy3Test, WindowUpdateOverflow) {
- // number of full frames we hope to write (but will not, used to
+ // Number of full frames we hope to write (but will not, used to
// set content-length header correctly)
static int kFrameCount = 3;
@@ -2049,31 +2053,22 @@ TEST_P(SpdyNetworkTransactionSpdy3Test, WindowUpdateOverflow) {
// We're not going to write a data frame with FIN, we'll receive a bad
// WINDOW_UPDATE while sending a request and will send a RST_STREAM frame.
MockWrite writes[] = {
- CreateMockWrite(*req),
- CreateMockWrite(*body),
- CreateMockWrite(*rst),
+ CreateMockWrite(*req, 0),
+ CreateMockWrite(*body, 2),
+ CreateMockWrite(*rst, 3),
};
static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow
scoped_ptr<SpdyFrame> window_update(
ConstructSpdyWindowUpdate(1, kDeltaWindowSize));
- scoped_ptr<SpdyFrame> window_update2(
- ConstructSpdyWindowUpdate(2, kDeltaWindowSize));
- scoped_ptr<SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0));
-
MockRead reads[] = {
- CreateMockRead(*window_update2),
- CreateMockRead(*window_update2),
- CreateMockRead(*window_update),
- CreateMockRead(*window_update),
- CreateMockRead(*window_update),
- MockRead(ASYNC, ERR_IO_PENDING, 0), // Wait for the RST to be written.
- MockRead(ASYNC, 0, 0) // EOF
+ CreateMockRead(*window_update, 1),
+ MockRead(ASYNC, 0, 4) // EOF
};
- scoped_ptr<DelayedSocketData> data(
- new DelayedSocketData(0, reads, arraysize(reads),
- writes, arraysize(writes)));
+ scoped_ptr<DeterministicSocketData> data(
+ new DeterministicSocketData(reads, arraysize(reads),
+ writes, arraysize(writes)));
// Setup the request
HttpRequestInfo request;
@@ -2085,23 +2080,18 @@ TEST_P(SpdyNetworkTransactionSpdy3Test, WindowUpdateOverflow) {
NormalSpdyTransactionHelper helper(request,
BoundNetLog(), GetParam(), NULL);
- helper.AddData(data.get());
+ helper.SetDeterministic();
helper.RunPreTestSetup();
-
+ helper.AddDeterministicData(data.get());
HttpNetworkTransaction* trans = helper.trans();
TestCompletionCallback callback;
int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog());
+ ASSERT_EQ(ERR_IO_PENDING, rv);
- EXPECT_EQ(ERR_IO_PENDING, rv);
- rv = callback.WaitForResult();
- EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv);
-
- data->CompleteRead();
-
- ASSERT_TRUE(helper.session() != NULL);
- ASSERT_TRUE(helper.session()->spdy_session_pool() != NULL);
- helper.session()->spdy_session_pool()->CloseAllSessions();
+ data->RunFor(5);
+ ASSERT_TRUE(callback.have_result());
+ EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult());
helper.VerifyDataConsumed();
}
diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc
index bc8f792..b3ab28f 100644
--- a/net/spdy/spdy_proxy_client_socket.cc
+++ b/net/spdy/spdy_proxy_client_socket.cc
@@ -547,7 +547,4 @@ void SpdyProxyClientSocket::OnClose(int status) {
write_callback.Run(ERR_CONNECTION_CLOSED);
}
-void SpdyProxyClientSocket::set_chunk_callback(ChunkCallback* /*callback*/) {
-}
-
} // namespace net
diff --git a/net/spdy/spdy_proxy_client_socket.h b/net/spdy/spdy_proxy_client_socket.h
index a9fd53c..70f6ae6 100644
--- a/net/spdy/spdy_proxy_client_socket.h
+++ b/net/spdy/spdy_proxy_client_socket.h
@@ -98,7 +98,6 @@ class NET_EXPORT_PRIVATE SpdyProxyClientSocket : public ProxyClientSocket,
virtual void OnDataReceived(const char* data, int length) OVERRIDE;
virtual void OnDataSent(int length) OVERRIDE;
virtual void OnClose(int status) OVERRIDE;
- virtual void set_chunk_callback(ChunkCallback* /*callback*/) OVERRIDE;
private:
enum State {
diff --git a/net/spdy/spdy_session_spdy2_unittest.cc b/net/spdy/spdy_session_spdy2_unittest.cc
index 6ee4257..1f44220 100644
--- a/net/spdy/spdy_session_spdy2_unittest.cc
+++ b/net/spdy/spdy_session_spdy2_unittest.cc
@@ -63,8 +63,6 @@ class TestSpdyStreamDelegate : public net::SpdyStream::Delegate {
callback.Run(OK);
}
- virtual void set_chunk_callback(net::ChunkCallback *) {}
-
private:
CompletionCallback callback_;
};
diff --git a/net/spdy/spdy_session_spdy3_unittest.cc b/net/spdy/spdy_session_spdy3_unittest.cc
index 299186e..68a5de5 100644
--- a/net/spdy/spdy_session_spdy3_unittest.cc
+++ b/net/spdy/spdy_session_spdy3_unittest.cc
@@ -63,8 +63,6 @@ class TestSpdyStreamDelegate : public net::SpdyStream::Delegate {
callback.Run(OK);
}
- virtual void set_chunk_callback(net::ChunkCallback *) {}
-
private:
CompletionCallback callback_;
};
diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc
index ed403bb..2b85a27 100644
--- a/net/spdy/spdy_stream.cc
+++ b/net/spdy/spdy_stream.cc
@@ -128,8 +128,6 @@ void SpdyStream::PushedStreamReplayData() {
}
void SpdyStream::DetachDelegate() {
- if (delegate_)
- delegate_->set_chunk_callback(NULL);
delegate_ = NULL;
if (!closed())
Cancel();
@@ -165,15 +163,13 @@ void SpdyStream::IncreaseSendWindowSize(int32 delta_window_size) {
DCHECK(session_->is_flow_control_enabled());
DCHECK_GE(delta_window_size, 1);
- int32 new_window_size = send_window_size_ + delta_window_size;
-
- // We should ignore WINDOW_UPDATEs received before or after this state,
- // since before means we've not written SYN_STREAM yet (i.e. it's too
- // early) and after means we've written a DATA frame with FIN bit.
- if (io_state_ != STATE_SEND_BODY_COMPLETE)
+ // Ignore late WINDOW_UPDATEs.
+ if (closed())
return;
- // it's valid for send_window_size_ to become negative (via an incoming
+ int32 new_window_size = send_window_size_ + delta_window_size;
+
+ // It's valid for send_window_size_ to become negative (via an incoming
// SETTINGS), in which case incoming WINDOW_UPDATEs will eventually make
// it positive; however, if send_window_size_ is positive and incoming
// WINDOW_UPDATE makes it negative, we have an overflow.
@@ -192,6 +188,7 @@ void SpdyStream::IncreaseSendWindowSize(int32 delta_window_size) {
NetLog::TYPE_SPDY_STREAM_UPDATE_SEND_WINDOW,
base::Bind(&NetLogSpdyStreamWindowUpdateCallback,
stream_id_, delta_window_size, send_window_size_));
+
PossiblyResumeIfStalled();
}
@@ -434,13 +431,6 @@ void SpdyStream::OnWriteComplete(int bytes) {
DoLoop(bytes);
}
-void SpdyStream::OnChunkAvailable() {
- DCHECK(io_state_ == STATE_SEND_HEADERS || io_state_ == STATE_SEND_BODY ||
- io_state_ == STATE_SEND_BODY_COMPLETE);
- if (io_state_ == STATE_SEND_BODY)
- OnWriteComplete(0);
-}
-
int SpdyStream::GetProtocolVersion() const {
return session_->GetProtocolVersion();
}
@@ -456,10 +446,8 @@ void SpdyStream::OnClose(int status) {
response_status_ = status;
Delegate* delegate = delegate_;
delegate_ = NULL;
- if (delegate) {
- delegate->set_chunk_callback(NULL);
+ if (delegate)
delegate->OnClose(status);
- }
}
void SpdyStream::Cancel() {
@@ -476,9 +464,6 @@ void SpdyStream::Close() {
}
int SpdyStream::SendRequest(bool has_upload_data) {
- if (delegate_)
- delegate_->set_chunk_callback(this);
-
// Pushed streams do not send any data, and should always be in STATE_OPEN or
// STATE_DONE. However, we still want to return IO_PENDING to mimic non-push
// behavior.
@@ -702,7 +687,7 @@ int SpdyStream::DoSendHeadersComplete(int result) {
// DoSendBody is called to send the optional body for the request. This call
// will also be called as each write of a chunk of the body completes.
int SpdyStream::DoSendBody() {
- // If we're already in the STATE_SENDING_BODY state, then we've already
+ // If we're already in the STATE_SEND_BODY state, then we've already
// sent a portion of the body. In that case, we need to first consume
// the bytes written in the body stream. Note that the bytes written is
// the number of bytes in the frame that were written, only consume the
diff --git a/net/spdy/spdy_stream.h b/net/spdy/spdy_stream.h
index e3baa4b..80d9e50 100644
--- a/net/spdy/spdy_stream.h
+++ b/net/spdy/spdy_stream.h
@@ -19,7 +19,6 @@
#include "net/base/request_priority.h"
#include "net/base/server_bound_cert_service.h"
#include "net/base/ssl_client_cert_type.h"
-#include "net/base/upload_data.h"
#include "net/socket/ssl_client_socket.h"
#include "net/spdy/spdy_framer.h"
#include "net/spdy/spdy_protocol.h"
@@ -40,8 +39,7 @@ class SSLInfo;
// initiated by the server, only the SpdySession will maintain any reference,
// until such a time as a client object requests a stream for the path.
class NET_EXPORT_PRIVATE SpdyStream
- : public base::RefCounted<SpdyStream>,
- public ChunkCallback {
+ : public base::RefCounted<SpdyStream> {
public:
// Delegate handles protocol specific behavior of spdy stream.
class NET_EXPORT_PRIVATE Delegate {
@@ -81,9 +79,6 @@ class NET_EXPORT_PRIVATE SpdyStream
// Called when SpdyStream is closed.
virtual void OnClose(int status) = 0;
- // Sets the callback to be invoked when a new chunk is available to upload.
- virtual void set_chunk_callback(ChunkCallback* callback) = 0;
-
protected:
friend class base::RefCounted<Delegate>;
virtual ~Delegate() {}
@@ -253,9 +248,6 @@ class NET_EXPORT_PRIVATE SpdyStream
// true.
GURL GetUrl() const;
- // ChunkCallback methods.
- virtual void OnChunkAvailable() OVERRIDE;
-
int GetProtocolVersion() const;
private:
diff --git a/net/spdy/spdy_stream_spdy2_unittest.cc b/net/spdy/spdy_stream_spdy2_unittest.cc
index 4d7fd48..c9b09e6 100644
--- a/net/spdy/spdy_stream_spdy2_unittest.cc
+++ b/net/spdy/spdy_stream_spdy2_unittest.cc
@@ -71,8 +71,6 @@ class TestSpdyStreamDelegate : public SpdyStream::Delegate {
callback_.Reset();
callback.Run(OK);
}
- virtual void set_chunk_callback(net::ChunkCallback *) {}
-
bool send_headers_completed() const { return send_headers_completed_; }
const linked_ptr<SpdyHeaderBlock>& response() const {
return response_;
diff --git a/net/spdy/spdy_stream_spdy3_unittest.cc b/net/spdy/spdy_stream_spdy3_unittest.cc
index b7db4e2..f941651 100644
--- a/net/spdy/spdy_stream_spdy3_unittest.cc
+++ b/net/spdy/spdy_stream_spdy3_unittest.cc
@@ -71,8 +71,6 @@ class TestSpdyStreamDelegate : public SpdyStream::Delegate {
callback_.Reset();
callback.Run(OK);
}
- virtual void set_chunk_callback(net::ChunkCallback *) {}
-
bool send_headers_completed() const { return send_headers_completed_; }
const linked_ptr<SpdyHeaderBlock>& response() const {
return response_;
diff --git a/net/spdy/spdy_websocket_stream.cc b/net/spdy/spdy_websocket_stream.cc
index 56fbe7a..5a9a541 100644
--- a/net/spdy/spdy_websocket_stream.cc
+++ b/net/spdy/spdy_websocket_stream.cc
@@ -129,10 +129,6 @@ void SpdyWebSocketStream::OnClose(int status) {
delegate->OnCloseSpdyStream();
}
-void SpdyWebSocketStream::set_chunk_callback(ChunkCallback* callback) {
- // Do nothing. SpdyWebSocketStream doesn't send any chunked data.
-}
-
void SpdyWebSocketStream::OnSpdyStreamCreated(int result) {
DCHECK_NE(ERR_IO_PENDING, result);
if (result == OK) {
diff --git a/net/spdy/spdy_websocket_stream.h b/net/spdy/spdy_websocket_stream.h
index fd243aa..2ac0e5c 100644
--- a/net/spdy/spdy_websocket_stream.h
+++ b/net/spdy/spdy_websocket_stream.h
@@ -80,7 +80,6 @@ class NET_EXPORT_PRIVATE SpdyWebSocketStream
virtual void OnDataReceived(const char* data, int length) OVERRIDE;
virtual void OnDataSent(int length) OVERRIDE;
virtual void OnClose(int status) OVERRIDE;
- virtual void set_chunk_callback(ChunkCallback* callback) OVERRIDE;
private:
FRIEND_TEST_ALL_PREFIXES(SpdyWebSocketStreamSpdy2Test, Basic);