[Net] Propagate priority changes from HttpNetworkTransaction to its stream

BUG=166689
[email protected]

Review URL: https://codereview.chromium.org/19691003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@217596 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/net/http/http_basic_stream.cc b/net/http/http_basic_stream.cc
index d70ac02b..c30e17d 100644
--- a/net/http/http_basic_stream.cc
+++ b/net/http/http_basic_stream.cc
@@ -127,4 +127,8 @@
   // |drainer| will delete itself.
 }
 
+void HttpBasicStream::SetPriority(RequestPriority priority) {
+  // TODO(akalin): Plumb this through to |connection_|.
+}
+
 }  // namespace net
diff --git a/net/http/http_basic_stream.h b/net/http/http_basic_stream.h
index 2d4bb65a..2057837e 100644
--- a/net/http/http_basic_stream.h
+++ b/net/http/http_basic_stream.h
@@ -81,6 +81,8 @@
 
   virtual void Drain(HttpNetworkSession* session) OVERRIDE;
 
+  virtual void SetPriority(RequestPriority priority) OVERRIDE;
+
  private:
   scoped_refptr<GrowableIOBuffer> read_buf_;
 
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 4d1cf65..a63a2aa 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -421,7 +421,8 @@
   priority_ = priority;
   if (stream_request_)
     stream_request_->SetPriority(priority);
-  // TODO(akalin): Plumb this through to |stream_| also.
+  if (stream_)
+    stream_->SetPriority(priority);
 }
 
 void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config,
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index e59333e..0968b14 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -46,6 +46,7 @@
 #include "net/http/http_stream_factory.h"
 #include "net/http/http_transaction_unittest.h"
 #include "net/proxy/proxy_config_service_fixed.h"
+#include "net/proxy/proxy_info.h"
 #include "net/proxy/proxy_resolver.h"
 #include "net/proxy/proxy_service.h"
 #include "net/socket/client_socket_factory.h"
@@ -59,6 +60,7 @@
 #include "net/spdy/spdy_session_pool.h"
 #include "net/spdy/spdy_test_util_common.h"
 #include "net/ssl/ssl_cert_request_info.h"
+#include "net/ssl/ssl_config_service.h"
 #include "net/ssl/ssl_config_service_defaults.h"
 #include "net/ssl/ssl_info.h"
 #include "net/test/cert_test_util.h"
@@ -11683,15 +11685,129 @@
 
 namespace {
 
-// Fake HttpStreamRequest that simply records calls to SetPriority().
+// Fake HttpStreamBase that simply records calls to SetPriority().
+class FakeStream : public HttpStreamBase,
+                   public base::SupportsWeakPtr<FakeStream> {
+ public:
+  explicit FakeStream(RequestPriority priority) : priority_(priority) {}
+  virtual ~FakeStream() {}
+
+  RequestPriority priority() const { return priority_; }
+
+  virtual int InitializeStream(const HttpRequestInfo* request_info,
+                               RequestPriority priority,
+                               const BoundNetLog& net_log,
+                               const CompletionCallback& callback) OVERRIDE {
+    return ERR_IO_PENDING;
+  }
+
+  virtual int SendRequest(const HttpRequestHeaders& request_headers,
+                          HttpResponseInfo* response,
+                          const CompletionCallback& callback) OVERRIDE {
+    ADD_FAILURE();
+    return ERR_UNEXPECTED;
+  }
+
+  virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE {
+    ADD_FAILURE();
+    return ERR_UNEXPECTED;
+  }
+
+  virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE {
+    ADD_FAILURE();
+    return NULL;
+  }
+
+  virtual int ReadResponseBody(IOBuffer* buf, int buf_len,
+                               const CompletionCallback& callback) OVERRIDE {
+    ADD_FAILURE();
+    return ERR_UNEXPECTED;
+  }
+
+  virtual void Close(bool not_reusable) OVERRIDE {}
+
+  virtual bool IsResponseBodyComplete() const OVERRIDE {
+    ADD_FAILURE();
+    return false;
+  }
+
+  virtual bool CanFindEndOfResponse() const OVERRIDE {
+    return false;
+  }
+
+  virtual bool IsConnectionReused() const OVERRIDE {
+    ADD_FAILURE();
+    return false;
+  }
+
+  virtual void SetConnectionReused() OVERRIDE {
+    ADD_FAILURE();
+  }
+
+  virtual bool IsConnectionReusable() const OVERRIDE {
+    ADD_FAILURE();
+    return false;
+  }
+
+  virtual bool GetLoadTimingInfo(
+      LoadTimingInfo* load_timing_info) const OVERRIDE {
+    ADD_FAILURE();
+    return false;
+  }
+
+  virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE {
+    ADD_FAILURE();
+  }
+
+  virtual void GetSSLCertRequestInfo(
+      SSLCertRequestInfo* cert_request_info) OVERRIDE {
+    ADD_FAILURE();
+  }
+
+  virtual bool IsSpdyHttpStream() const OVERRIDE {
+    ADD_FAILURE();
+    return false;
+  }
+
+  virtual void Drain(HttpNetworkSession* session) OVERRIDE {
+    ADD_FAILURE();
+  }
+
+  virtual void SetPriority(RequestPriority priority) OVERRIDE {
+    priority_ = priority;
+  }
+
+ private:
+  RequestPriority priority_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeStream);
+};
+
+// Fake HttpStreamRequest that simply records calls to SetPriority()
+// and vends FakeStreams with its current priority.
 class FakeStreamRequest : public HttpStreamRequest,
                           public base::SupportsWeakPtr<FakeStreamRequest> {
  public:
-  explicit FakeStreamRequest(RequestPriority priority) : priority_(priority) {}
+  FakeStreamRequest(RequestPriority priority,
+                    HttpStreamRequest::Delegate* delegate)
+      : priority_(priority),
+        delegate_(delegate) {}
+
   virtual ~FakeStreamRequest() {}
 
   RequestPriority priority() const { return priority_; }
 
+  // Create a new FakeStream and pass it to the request's
+  // delegate. Returns a weak pointer to the FakeStream.
+  base::WeakPtr<FakeStream> FinishStreamRequest() {
+    FakeStream* fake_stream = new FakeStream(priority_);
+    // Do this before calling OnStreamReady() as OnStreamReady() may
+    // immediately delete |fake_stream|.
+    base::WeakPtr<FakeStream> weak_stream = fake_stream->AsWeakPtr();
+    delegate_->OnStreamReady(SSLConfig(), ProxyInfo(), fake_stream);
+    return weak_stream;
+  }
+
   virtual int RestartTunnelWithProxyAuth(
       const AuthCredentials& credentials) OVERRIDE {
     ADD_FAILURE();
@@ -11708,22 +11824,20 @@
   }
 
   virtual bool was_npn_negotiated() const OVERRIDE {
-    ADD_FAILURE();
     return false;
   }
 
   virtual NextProto protocol_negotiated() const OVERRIDE {
-    ADD_FAILURE();
     return kProtoUnknown;
   }
 
   virtual bool using_spdy() const OVERRIDE {
-    ADD_FAILURE();
     return false;
   }
 
  private:
   RequestPriority priority_;
+  HttpStreamRequest::Delegate* const delegate_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
 };
@@ -11747,7 +11861,7 @@
       const SSLConfig& proxy_ssl_config,
       HttpStreamRequest::Delegate* delegate,
       const BoundNetLog& net_log) OVERRIDE {
-    FakeStreamRequest* fake_request = new FakeStreamRequest(priority);
+    FakeStreamRequest* fake_request = new FakeStreamRequest(priority, delegate);
     last_stream_request_ = fake_request->AsWeakPtr();
     return fake_request;
   }
@@ -11838,4 +11952,30 @@
   EXPECT_EQ(LOWEST, fake_request->priority());
 }
 
+// Make sure that HttpNetworkTransaction passes on its priority
+// updates to its stream.
+TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
+  scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+  HttpNetworkSessionPeer peer(session);
+  FakeStreamFactory* fake_factory = new FakeStreamFactory();
+  peer.SetHttpStreamFactory(fake_factory);
+
+  HttpNetworkTransaction trans(LOW, session);
+
+  HttpRequestInfo request;
+  TestCompletionCallback callback;
+  EXPECT_EQ(ERR_IO_PENDING,
+            trans.Start(&request, callback.callback(), BoundNetLog()));
+
+  base::WeakPtr<FakeStreamRequest> fake_request =
+      fake_factory->last_stream_request();
+  ASSERT_TRUE(fake_request != NULL);
+  base::WeakPtr<FakeStream> fake_stream = fake_request->FinishStreamRequest();
+  ASSERT_TRUE(fake_stream != NULL);
+  EXPECT_EQ(LOW, fake_stream->priority());
+
+  trans.SetPriority(LOWEST);
+  EXPECT_EQ(LOWEST, fake_stream->priority());
+}
+
 }  // namespace net
diff --git a/net/http/http_pipelined_stream.cc b/net/http/http_pipelined_stream.cc
index 951c2f9..df574355 100644
--- a/net/http/http_pipelined_stream.cc
+++ b/net/http/http_pipelined_stream.cc
@@ -121,6 +121,11 @@
   pipeline_->Drain(this, session);
 }
 
+void HttpPipelinedStream::SetPriority(RequestPriority priority) {
+  // TODO(akalin): Plumb this through to |pipeline_| and its
+  // underlying ClientSocketHandle.
+}
+
 const SSLConfig& HttpPipelinedStream::used_ssl_config() const {
   return pipeline_->used_ssl_config();
 }
diff --git a/net/http/http_pipelined_stream.h b/net/http/http_pipelined_stream.h
index 675d8f0..d3a7991 100644
--- a/net/http/http_pipelined_stream.h
+++ b/net/http/http_pipelined_stream.h
@@ -81,6 +81,8 @@
 
   virtual void Drain(HttpNetworkSession* session) OVERRIDE;
 
+  virtual void SetPriority(RequestPriority priority) OVERRIDE;
+
   // The SSLConfig used to establish this stream's pipeline.
   const SSLConfig& used_ssl_config() const;
 
diff --git a/net/http/http_response_body_drainer_unittest.cc b/net/http/http_response_body_drainer_unittest.cc
index 5d9fcc46..70134cce 100644
--- a/net/http/http_response_body_drainer_unittest.cc
+++ b/net/http/http_response_body_drainer_unittest.cc
@@ -127,6 +127,8 @@
 
   virtual void Drain(HttpNetworkSession*) OVERRIDE {}
 
+  virtual void SetPriority(RequestPriority priority) OVERRIDE {}
+
   // Methods to tweak/observer mock behavior:
   void set_stall_reads_forever() { stall_reads_forever_ = true; }
 
diff --git a/net/http/http_stream_base.h b/net/http/http_stream_base.h
index 6dce6d2..596ed75 100644
--- a/net/http/http_stream_base.h
+++ b/net/http/http_stream_base.h
@@ -141,6 +141,9 @@
   // draining is complete.
   virtual void Drain(HttpNetworkSession* session) = 0;
 
+  // Called when the priority of the parent transaction changes.
+  virtual void SetPriority(RequestPriority priority) = 0;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(HttpStreamBase);
 };
diff --git a/net/http/proxy_connect_redirect_http_stream.cc b/net/http/proxy_connect_redirect_http_stream.cc
index f30f33c..59bb0146 100644
--- a/net/http/proxy_connect_redirect_http_stream.cc
+++ b/net/http/proxy_connect_redirect_http_stream.cc
@@ -109,6 +109,10 @@
   NOTREACHED();
 }
 
+void ProxyConnectRedirectHttpStream::SetPriority(RequestPriority priority) {
+  // Nothing to do.
+}
+
 UploadProgress ProxyConnectRedirectHttpStream::GetUploadProgress() const {
   NOTREACHED();
   return UploadProgress();
diff --git a/net/http/proxy_connect_redirect_http_stream.h b/net/http/proxy_connect_redirect_http_stream.h
index f39ec76..c335c21 100644
--- a/net/http/proxy_connect_redirect_http_stream.h
+++ b/net/http/proxy_connect_redirect_http_stream.h
@@ -59,6 +59,10 @@
       SSLCertRequestInfo* cert_request_info) OVERRIDE;
   virtual bool IsSpdyHttpStream() const OVERRIDE;
   virtual void Drain(HttpNetworkSession* session) OVERRIDE;
+
+  // This function may be called.
+  virtual void SetPriority(RequestPriority priority) OVERRIDE;
+
   virtual UploadProgress GetUploadProgress() const OVERRIDE;
   virtual HttpStream* RenewStreamForAuth() OVERRIDE;
 
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc
index 94d1a2e5..73581248 100644
--- a/net/quic/quic_http_stream.cc
+++ b/net/quic/quic_http_stream.cc
@@ -257,6 +257,10 @@
   delete this;
 }
 
+void QuicHttpStream::SetPriority(RequestPriority priority) {
+  // Nothing to do here (yet).
+}
+
 int QuicHttpStream::OnSendData() {
   // TODO(rch): Change QUIC IO to provide notifications to the streams.
   NOTREACHED();
diff --git a/net/quic/quic_http_stream.h b/net/quic/quic_http_stream.h
index 85dc553..cc2b973 100644
--- a/net/quic/quic_http_stream.h
+++ b/net/quic/quic_http_stream.h
@@ -54,6 +54,7 @@
       SSLCertRequestInfo* cert_request_info) OVERRIDE;
   virtual bool IsSpdyHttpStream() const OVERRIDE;
   virtual void Drain(HttpNetworkSession* session) OVERRIDE;
+  virtual void SetPriority(RequestPriority priority) OVERRIDE;
 
   // QuicReliableClientStream::Delegate implementation
   virtual int OnSendData() OVERRIDE;
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc
index 08e8b58..4d911751 100644
--- a/net/spdy/spdy_http_stream.cc
+++ b/net/spdy/spdy_http_stream.cc
@@ -524,4 +524,9 @@
   delete this;
 }
 
+void SpdyHttpStream::SetPriority(RequestPriority priority) {
+  // TODO(akalin): Plumb this through to |stream_request_| and
+  // |stream_|.
+}
+
 }  // namespace net
diff --git a/net/spdy/spdy_http_stream.h b/net/spdy/spdy_http_stream.h
index 65d98784..f6e39cd 100644
--- a/net/spdy/spdy_http_stream.h
+++ b/net/spdy/spdy_http_stream.h
@@ -73,6 +73,7 @@
       SSLCertRequestInfo* cert_request_info) OVERRIDE;
   virtual bool IsSpdyHttpStream() const OVERRIDE;
   virtual void Drain(HttpNetworkSession* session) OVERRIDE;
+  virtual void SetPriority(RequestPriority priority) OVERRIDE;
 
   // SpdyStream::Delegate implementation.
   virtual void OnRequestHeadersSent() OVERRIDE;