Index: net/quic/chromium/quic_chromium_client_stream.cc |
diff --git a/net/quic/chromium/quic_chromium_client_stream.cc b/net/quic/chromium/quic_chromium_client_stream.cc |
index a084fe5c87241530bb9d7f47436b4f43381e64a9..0014b40ee101d7408e522d25357722a4b40f5214 100644 |
--- a/net/quic/chromium/quic_chromium_client_stream.cc |
+++ b/net/quic/chromium/quic_chromium_client_stream.cc |
@@ -54,10 +54,15 @@ void QuicChromiumClientStream::Handle::OnInitialHeadersAvailable() { |
ResetAndReturn(&read_headers_callback_).Run(rv); |
} |
-void QuicChromiumClientStream::Handle::OnTrailingHeadersAvailable( |
- const SpdyHeaderBlock& headers, |
- size_t frame_len) { |
- delegate_->OnTrailingHeadersAvailable(headers, frame_len); |
+void QuicChromiumClientStream::Handle::OnTrailingHeadersAvailable() { |
+ if (!read_headers_callback_) |
+ return; // Wait for ReadInitialHeaders to be called. |
+ |
+ int rv = ERR_QUIC_PROTOCOL_ERROR; |
+ if (!stream_->DeliverTrailingHeaders(read_headers_buffer_, &rv)) |
+ rv = ERR_QUIC_PROTOCOL_ERROR; |
+ |
+ ResetAndReturn(&read_headers_callback_).Run(rv); |
} |
void QuicChromiumClientStream::Handle::OnDataAvailable() { |
@@ -134,6 +139,21 @@ int QuicChromiumClientStream::Handle::ReadBody( |
return ERR_IO_PENDING; |
} |
+int QuicChromiumClientStream::Handle::ReadTrailingHeaders( |
+ SpdyHeaderBlock* header_block, |
+ const CompletionCallback& callback) { |
+ if (!stream_) |
+ return ERR_CONNECTION_CLOSED; |
+ |
+ int frame_len = 0; |
+ if (stream_->DeliverTrailingHeaders(header_block, &frame_len)) |
+ return frame_len; |
+ |
+ read_headers_buffer_ = header_block; |
+ read_headers_callback_ = callback; |
+ return ERR_IO_PENDING; |
+} |
+ |
size_t QuicChromiumClientStream::Handle::WriteHeaders( |
SpdyHeaderBlock header_block, |
bool fin, |
@@ -312,6 +332,7 @@ QuicChromiumClientStream::QuicChromiumClientStream( |
session_(session), |
can_migrate_(true), |
initial_headers_frame_len_(0), |
+ trailing_headers_frame_len_(0), |
weak_factory_(this) {} |
QuicChromiumClientStream::~QuicChromiumClientStream() { |
@@ -352,8 +373,11 @@ void QuicChromiumClientStream::OnTrailingHeadersComplete( |
size_t frame_len, |
const QuicHeaderList& header_list) { |
QuicSpdyStream::OnTrailingHeadersComplete(fin, frame_len, header_list); |
- NotifyHandleOfTrailingHeadersAvailableLater(received_trailers().Clone(), |
- frame_len); |
+ trailing_headers_frame_len_ = frame_len; |
+ if (handle_) { |
+ // The handle will be notified of the headers via a posted task. |
+ NotifyHandleOfTrailingHeadersAvailableLater(); |
+ } |
} |
void QuicChromiumClientStream::OnPromiseHeaderList( |
@@ -514,33 +538,23 @@ void QuicChromiumClientStream::NotifyHandleOfInitialHeadersAvailable() { |
handle_->OnInitialHeadersAvailable(); |
} |
-void QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailableLater( |
- SpdyHeaderBlock headers, |
- size_t frame_len) { |
+void QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailableLater() { |
DCHECK(handle_); |
base::ThreadTaskRunnerHandle::Get()->PostTask( |
FROM_HERE, |
base::Bind( |
&QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailable, |
- weak_factory_.GetWeakPtr(), base::Passed(std::move(headers)), |
- frame_len)); |
+ weak_factory_.GetWeakPtr())); |
} |
-void QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailable( |
- SpdyHeaderBlock headers, |
- size_t frame_len) { |
+void QuicChromiumClientStream::NotifyHandleOfTrailingHeadersAvailable() { |
if (!handle_) |
return; |
DCHECK(headers_delivered_); |
- // Only mark trailers consumed when we are about to notify delegate. |
- MarkTrailersConsumed(); |
// Post an async task to notify delegate of the FIN flag. |
NotifyHandleOfDataAvailableLater(); |
- net_log_.AddEvent( |
- NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_TRAILERS, |
- base::Bind(&SpdyHeaderBlockNetLogCallback, &headers)); |
- handle_->OnTrailingHeadersAvailable(headers, frame_len); |
+ handle_->OnTrailingHeadersAvailable(); |
} |
bool QuicChromiumClientStream::DeliverInitialHeaders(SpdyHeaderBlock* headers, |
@@ -558,6 +572,22 @@ bool QuicChromiumClientStream::DeliverInitialHeaders(SpdyHeaderBlock* headers, |
return true; |
} |
+bool QuicChromiumClientStream::DeliverTrailingHeaders(SpdyHeaderBlock* headers, |
+ int* frame_len) { |
+ if (received_trailers().empty()) |
+ return false; |
+ |
+ net_log_.AddEvent( |
+ NetLogEventType::QUIC_CHROMIUM_CLIENT_STREAM_READ_RESPONSE_TRAILERS, |
+ base::Bind(&SpdyHeaderBlockNetLogCallback, &received_trailers())); |
+ |
+ *headers = received_trailers().Clone(); |
+ *frame_len = trailing_headers_frame_len_; |
+ |
+ MarkTrailersConsumed(); |
+ return true; |
+} |
+ |
void QuicChromiumClientStream::NotifyHandleOfDataAvailableLater() { |
DCHECK(handle_); |
base::ThreadTaskRunnerHandle::Get()->PostTask( |