Index: net/quic/chromium/quic_chromium_client_session.cc |
diff --git a/net/quic/chromium/quic_chromium_client_session.cc b/net/quic/chromium/quic_chromium_client_session.cc |
index d4fd7767f38b7563638e0aaacaa891c02a9e3ca2..11c56c58215616ee5f3bdbc0758b044d87c9e72c 100644 |
--- a/net/quic/chromium/quic_chromium_client_session.cc |
+++ b/net/quic/chromium/quic_chromium_client_session.cc |
@@ -31,6 +31,7 @@ |
#include "net/quic/core/quic_client_promised_info.h" |
#include "net/quic/core/quic_crypto_client_stream_factory.h" |
#include "net/quic/core/spdy_utils.h" |
+#include "net/spdy/spdy_http_utils.h" |
#include "net/spdy/spdy_session.h" |
#include "net/ssl/channel_id_service.h" |
#include "net/ssl/ssl_connection_status_flags.h" |
@@ -162,6 +163,26 @@ class HpackDecoderDebugVisitor : public QuicHeadersStream::HpackDebugVisitor { |
} |
}; |
+class QuicServerPushHelper : public ServerPushDelegate::ServerPushHelper { |
+ public: |
+ explicit QuicServerPushHelper( |
+ base::WeakPtr<QuicChromiumClientSession> session, |
+ const GURL& url) |
+ : session_(session), request_url_(url) {} |
+ |
+ void Cancel() override { |
+ if (session_) { |
+ session_->CancelPush(request_url_); |
+ } |
+ } |
+ |
+ const GURL& GetURL() override { return request_url_; } |
+ |
+ private: |
+ base::WeakPtr<QuicChromiumClientSession> session_; |
+ const GURL request_url_; |
+}; |
+ |
} // namespace |
QuicChromiumClientSession::StreamRequest::StreamRequest() : stream_(nullptr) {} |
@@ -242,6 +263,7 @@ QuicChromiumClientSession::QuicChromiumClientSession( |
going_away_(false), |
port_migration_detected_(false), |
token_binding_signatures_(kTokenBindingSignatureMapSize), |
+ push_delegate_(nullptr), |
streams_pushed_count_(0), |
streams_pushed_and_claimed_count_(0), |
bytes_pushed_count_(0), |
@@ -1418,13 +1440,23 @@ bool QuicChromiumClientSession::HasNonMigratableStreams() const { |
return false; |
} |
-void QuicChromiumClientSession::HandlePromised(QuicStreamId id, |
+bool QuicChromiumClientSession::HandlePromised(QuicStreamId id, |
QuicStreamId promised_id, |
const SpdyHeaderBlock& headers) { |
- QuicClientSessionBase::HandlePromised(id, promised_id, headers); |
+ bool result = QuicClientSessionBase::HandlePromised(id, promised_id, headers); |
+ if (result) { |
+ // The push promise is accepted, notify the push_delegate that a push |
+ // promise has been received. |
+ GURL pushed_url = GetUrlFromHeaderBlock(headers); |
+ if (push_delegate_) { |
+ push_delegate_->OnPush(base::MakeUnique<QuicServerPushHelper>( |
+ weak_factory_.GetWeakPtr(), pushed_url)); |
+ } |
+ } |
net_log_.AddEvent(NetLogEventType::QUIC_SESSION_PUSH_PROMISE_RECEIVED, |
base::Bind(&NetLogQuicPushPromiseReceivedCallback, &headers, |
id, promised_id)); |
+ return result; |
} |
void QuicChromiumClientSession::DeletePromised( |
@@ -1443,8 +1475,8 @@ void QuicChromiumClientSession::OnPushStreamTimedOut(QuicStreamId stream_id) { |
void QuicChromiumClientSession::CancelPush(const GURL& url) { |
QuicClientPromisedInfo* promised_info = |
QuicClientSessionBase::GetPromisedByUrl(url.spec()); |
- if (!promised_info) { |
- // Push stream has already been claimed. |
+ if (!promised_info || promised_info->is_validating()) { |
+ // Push stream has already been claimed or is pending matched to a request. |
return; |
} |