| Index: net/spdy/spdy_session.cc | 
| diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc | 
| index 80e24c6dd79ebf42ec56f304563a9581be9efe6a..28bab83f51e3b78b0b419be874bcf4d751ad47c8 100644 | 
| --- a/net/spdy/spdy_session.cc | 
| +++ b/net/spdy/spdy_session.cc | 
| @@ -59,6 +59,14 @@ const int kHungIntervalSeconds = 10; | 
| // Minimum seconds that unclaimed pushed streams will be kept in memory. | 
| const int kMinPushedStreamLifetimeSeconds = 300; | 
|  | 
| +// Field trial constants | 
| +const char kSpdyDependenciesFieldTrial[] = "SpdyEnableDependencies"; | 
| +const char kSpdyDepencenciesFieldTrialEnable[] = "Enable"; | 
| + | 
| +// Whether the creation of SPDY dependencies based on priority is | 
| +// enabled by default. | 
| +static bool priority_dependency_enabled_default = false; | 
| + | 
| scoped_ptr<base::ListValue> SpdyHeaderBlockToListValue( | 
| const SpdyHeaderBlock& headers, | 
| NetLogCaptureMode capture_mode) { | 
| @@ -691,6 +699,7 @@ SpdySession::SpdySession( | 
| hung_interval_(base::TimeDelta::FromSeconds(kHungIntervalSeconds)), | 
| trusted_spdy_proxy_(trusted_spdy_proxy), | 
| time_func_(time_func), | 
| +      send_priority_dependency_(priority_dependency_enabled_default), | 
| weak_factory_(this) { | 
| DCHECK_GE(protocol_, kProtoSPDYMinimumVersion); | 
| DCHECK_LE(protocol_, kProtoSPDYMaximumVersion); | 
| @@ -700,6 +709,10 @@ SpdySession::SpdySession( | 
| base::Bind(&NetLogSpdySessionCallback, &host_port_proxy_pair())); | 
| next_unclaimed_push_stream_sweep_time_ = time_func_() + | 
| base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); | 
| +  if (base::FieldTrialList::FindFullName(kSpdyDependenciesFieldTrial) == | 
| +      kSpdyDepencenciesFieldTrialEnable) { | 
| +    send_priority_dependency_ = true; | 
| +  } | 
| // TODO(mbelshe): consider randomization of the stream_hi_water_mark. | 
| } | 
|  | 
| @@ -1045,6 +1058,11 @@ bool SpdySession::CloseOneIdleConnection() { | 
| return false; | 
| } | 
|  | 
| +// static | 
| +void SpdySession::SetPriorityDependencyDefaultForTesting(bool enable) { | 
| +  priority_dependency_enabled_default = enable; | 
| +} | 
| + | 
| void SpdySession::EnqueueStreamWrite( | 
| const base::WeakPtr<SpdyStream>& stream, | 
| SpdyFrameType frame_type, | 
| @@ -1085,6 +1103,41 @@ scoped_ptr<SpdyFrame> SpdySession::CreateSynStream( | 
| SpdyHeadersIR headers(stream_id); | 
| headers.set_priority(spdy_priority); | 
| headers.set_has_priority(true); | 
| + | 
| +    if (send_priority_dependency_) { | 
| +      // Set dependencies to reflect request priority.  A newly created | 
| +      // stream should be dependent on the most recent previously created | 
| +      // stream of the same priority level.  The newly created stream | 
| +      // should also have all streams of a lower priority level dependent | 
| +      // on it, which is guaranteed by setting the exclusive bit. | 
| +      // | 
| +      // Note that this depends on stream ids being allocated in a monotonically | 
| +      // increasing fashion, and on all streams in | 
| +      // active_streams_{,by_priority_} having stream ids set. | 
| +      for (int i = priority; i >= IDLE; --i) { | 
| +        if (active_streams_by_priority_[i].empty()) | 
| +          continue; | 
| + | 
| +        auto candidate_it = active_streams_by_priority_[i].rbegin(); | 
| + | 
| +        // |active_streams_by_priority_| is updated before the | 
| +        // SYN stream frame is created, so the current streams | 
| +        // id is already on the list.  Skip over it, skipping this | 
| +        // priority level if it's singular. | 
| +        if (candidate_it->second->stream_id() == stream_id) | 
| +          ++candidate_it; | 
| +        if (candidate_it == active_streams_by_priority_[i].rend()) | 
| +          continue; | 
| + | 
| +        headers.set_parent_stream_id(candidate_it->second->stream_id()); | 
| +        break; | 
| +      } | 
| + | 
| +      // If there are no streams of priority <= the current stream, the | 
| +      // current stream will default to a child of the idle node (0). | 
| +      headers.set_exclusive(true); | 
| +    } | 
| + | 
| headers.set_fin((flags & CONTROL_FLAG_FIN) != 0); | 
| headers.set_header_block(block); | 
| syn_frame.reset(buffered_spdy_framer_->SerializeFrame(headers)); | 
| @@ -1291,6 +1344,8 @@ void SpdySession::CloseActiveStreamIterator(ActiveStreamMap::iterator it, | 
|  | 
| scoped_ptr<SpdyStream> owned_stream(it->second.stream); | 
| active_streams_.erase(it); | 
| +  active_streams_by_priority_[owned_stream->priority()].erase( | 
| +      owned_stream->stream_id()); | 
|  | 
| // TODO(akalin): When SpdyStream was ref-counted (and | 
| // |unclaimed_pushed_streams_| held scoped_refptr<SpdyStream>), this | 
| @@ -1952,6 +2007,8 @@ void SpdySession::InsertActivatedStream(scoped_ptr<SpdyStream> stream) { | 
| std::pair<ActiveStreamMap::iterator, bool> result = | 
| active_streams_.insert( | 
| std::make_pair(stream_id, ActiveStreamInfo(stream.get()))); | 
| +  active_streams_by_priority_[stream->priority()].insert( | 
| +      std::make_pair(stream_id, stream.get())); | 
| CHECK(result.second); | 
| ignore_result(stream.release()); | 
| } | 
|  |