Chromium Code Reviews| Index: net/spdy/spdy_session.cc |
| diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc |
| index fc549d5af311a4adc4bdfbc04152b4c81558a782..01cb874ac22d502258aa5886c3709c83690dd5c0 100644 |
| --- a/net/spdy/spdy_session.cc |
| +++ b/net/spdy/spdy_session.cc |
| @@ -13,6 +13,7 @@ |
| #include "base/compiler_specific.h" |
| #include "base/location.h" |
| #include "base/logging.h" |
| +#include "base/memory/ptr_util.h" |
| #include "base/metrics/histogram_macros.h" |
| #include "base/metrics/sparse_histogram.h" |
| #include "base/profiler/scoped_tracker.h" |
| @@ -265,6 +266,20 @@ std::unique_ptr<base::Value> NetLogSpdyAdoptedPushStreamCallback( |
| return std::move(dict); |
| } |
| +std::unique_ptr<base::Value> NetLogSpdyPriorityCallback( |
| + SpdyStreamId stream_id, |
| + SpdyStreamId parent_stream_id, |
| + int weight, |
| + bool exclusive, |
| + NetLogCaptureMode capture_mode) { |
| + std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
|
Bence
2017/01/05 17:14:46
Please use MakeUnique in new code, see https://cs.
Tom Bergan
2017/01/06 00:08:41
Done. Also did a search/replace on the other NetLo
|
| + dict->SetInteger("stream_id", stream_id); |
| + dict->SetInteger("parent_stream_id", parent_stream_id); |
| + dict->SetInteger("weight", weight); |
| + dict->SetBoolean("exclusive", exclusive); |
| + return std::move(dict); |
| +} |
| + |
| // Helper function to return the total size of an array of objects |
| // with .size() member functions. |
| template <typename T, size_t N> size_t GetTotalSize(const T (&arr)[N]) { |
| @@ -772,6 +787,7 @@ bool SpdySession::VerifyDomainAuthentication(const std::string& domain) { |
| } |
| int SpdySession::GetPushStream(const GURL& url, |
| + RequestPriority priority, |
| base::WeakPtr<SpdyStream>* stream, |
| const NetLogWithSource& stream_net_log) { |
| CHECK(!in_io_loop_); |
| @@ -785,7 +801,26 @@ int SpdySession::GetPushStream(const GURL& url, |
| if (*stream) { |
| DCHECK_LT(streams_pushed_and_claimed_count_, streams_pushed_count_); |
| streams_pushed_and_claimed_count_++; |
| + |
| + // If the stream is still open, update its priority to match |
| + // the priority of the matching request. |
| + if (!(*stream)->IsClosed() && (*stream)->priority() != priority) { |
| + (*stream)->set_priority(priority); |
| + |
| + // Send PRIORITY updates. |
| + auto updates = priority_dependency_state_.OnStreamUpdate( |
| + (*stream)->stream_id(), |
| + ConvertRequestPriorityToSpdyPriority(priority)); |
| + for (auto u : updates) { |
| + ActiveStreamMap::iterator it = active_streams_.find(u.id); |
| + DCHECK(it != active_streams_.end()); |
| + int weight = Spdy3PriorityToHttp2Weight( |
| + ConvertRequestPriorityToSpdyPriority(it->second->priority())); |
| + EnqueuePriorityFrame(u.id, u.dependent_stream_id, weight, u.exclusive); |
| + } |
| + } |
| } |
| + |
| return OK; |
| } |
| @@ -1011,8 +1046,8 @@ std::unique_ptr<SpdySerializedFrame> SpdySession::CreateHeaders( |
| SpdyStreamId dependent_stream_id = 0; |
| bool exclusive = false; |
| - priority_dependency_state_.OnStreamSynSent(stream_id, spdy_priority, |
| - &dependent_stream_id, &exclusive); |
| + priority_dependency_state_.OnStreamCreation(stream_id, spdy_priority, |
| + &dependent_stream_id, &exclusive); |
| if (net_log().IsCapturing()) { |
| net_log().AddEvent( |
| @@ -1270,6 +1305,28 @@ void SpdySession::EnqueueResetStreamFrame(SpdyStreamId stream_id, |
| RecordProtocolErrorHistogram(MapRstStreamStatusToProtocolError(status)); |
| } |
| +void SpdySession::EnqueuePriorityFrame(SpdyStreamId stream_id, |
| + SpdyStreamId dependency_id, |
| + int weight, |
| + bool exclusive) { |
| + net_log().AddEvent(NetLogEventType::HTTP2_STREAM_UPDATE_PRIORITY, |
| + base::Bind(&NetLogSpdyPriorityCallback, stream_id, |
| + dependency_id, weight, exclusive)); |
| + |
| + DCHECK(buffered_spdy_framer_.get()); |
| + std::unique_ptr<SpdySerializedFrame> frame( |
| + buffered_spdy_framer_->CreatePriority(stream_id, dependency_id, weight, |
| + exclusive)); |
| + |
| + // PRIORITY frames describe sequenced updates to the tree, so they must |
| + // be serialized. We do this by queueing all PRIORITY frames at HIGHEST |
| + // priority. |
| + EnqueueWrite(HIGHEST, PRIORITY, |
| + base::MakeUnique<SimpleBufferProducer>( |
| + base::MakeUnique<SpdyBuffer>(std::move(frame))), |
| + base::WeakPtr<SpdyStream>()); |
| +} |
| + |
| void SpdySession::PumpReadLoop(ReadState expected_read_state, int result) { |
| CHECK(!in_io_loop_); |
| if (availability_state_ == STATE_DRAINING) { |
| @@ -2408,7 +2465,6 @@ void SpdySession::OnWindowUpdate(SpdyStreamId stream_id, |
| void SpdySession::TryCreatePushStream(SpdyStreamId stream_id, |
| SpdyStreamId associated_stream_id, |
| - SpdyPriority priority, |
| SpdyHeaderBlock headers) { |
| // Server-initiated streams should have even sequence numbers. |
| if ((stream_id & 0x1) != 0) { |
| @@ -2443,8 +2499,8 @@ void SpdySession::TryCreatePushStream(SpdyStreamId stream_id, |
| last_accepted_push_stream_id_ = stream_id; |
| - RequestPriority request_priority = |
| - ConvertSpdyPriorityToRequestPriority(priority); |
| + // Pushed streams are speculative, so they start at an IDLE priority. |
| + const RequestPriority request_priority = IDLE; |
| if (availability_state_ == STATE_GOING_AWAY) { |
| // TODO(akalin): This behavior isn't in the SPDY spec, although it |
| @@ -2561,6 +2617,16 @@ void SpdySession::TryCreatePushStream(SpdyStreamId stream_id, |
| stream_max_recv_window_size_, net_log_)); |
| stream->set_stream_id(stream_id); |
| + // Convert RequestPriority to a SpdyPriority to send in a PRIORITY frame. |
| + SpdyPriority spdy_priority = |
| + ConvertRequestPriorityToSpdyPriority(request_priority); |
| + SpdyStreamId dependency_id = 0; |
| + bool exclusive = false; |
| + priority_dependency_state_.OnStreamCreation(stream_id, spdy_priority, |
| + &dependency_id, &exclusive); |
| + EnqueuePriorityFrame(stream_id, dependency_id, |
| + Spdy3PriorityToHttp2Weight(spdy_priority), exclusive); |
| + |
| // PUSH_PROMISE arrives on associated stream. |
| associated_it->second->AddRawReceivedBytes(last_compressed_frame_len_); |
| last_compressed_frame_len_ = 0; |
| @@ -2602,8 +2668,7 @@ void SpdySession::OnPushPromise(SpdyStreamId stream_id, |
| &headers, stream_id, promised_stream_id)); |
| } |
| - // Any priority will do. TODO(baranovich): Pass parent stream id priority? |
| - TryCreatePushStream(promised_stream_id, stream_id, 0, std::move(headers)); |
| + TryCreatePushStream(promised_stream_id, stream_id, std::move(headers)); |
| } |
| void SpdySession::SendStreamWindowUpdate(SpdyStreamId stream_id, |