Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / net / spdy / spdy_stream.cc
index 3988905..3a0d988 100644 (file)
@@ -85,7 +85,6 @@ SpdyStream::SpdyStream(SpdyStreamType type,
                        int32 initial_recv_window_size,
                        const BoundNetLog& net_log)
     : type_(type),
-      weak_ptr_factory_(this),
       stream_id_(0),
       url_(url),
       priority_(priority),
@@ -104,7 +103,8 @@ SpdyStream::SpdyStream(SpdyStreamType type,
       raw_received_bytes_(0),
       send_bytes_(0),
       recv_bytes_(0),
-      write_handler_guard_(false) {
+      write_handler_guard_(false),
+      weak_ptr_factory_(this) {
   CHECK(type_ == SPDY_BIDIRECTIONAL_STREAM ||
         type_ == SPDY_REQUEST_RESPONSE_STREAM ||
         type_ == SPDY_PUSH_STREAM);
@@ -123,7 +123,8 @@ void SpdyStream::SetDelegate(Delegate* delegate) {
   delegate_ = delegate;
 
   CHECK(io_state_ == STATE_IDLE ||
-        io_state_ == STATE_HALF_CLOSED_LOCAL_UNCLAIMED);
+        io_state_ == STATE_HALF_CLOSED_LOCAL_UNCLAIMED ||
+        io_state_ == STATE_RESERVED_REMOTE);
 
   if (io_state_ == STATE_HALF_CLOSED_LOCAL_UNCLAIMED) {
     DCHECK_EQ(type_, SPDY_PUSH_STREAM);
@@ -417,11 +418,12 @@ int SpdyStream::OnInitialResponseHeadersReceived(
       // Push streams transition to a locally half-closed state upon headers.
       // We must continue to buffer data while waiting for a call to
       // SetDelegate() (which may not ever happen).
-      // TODO(jgraettinger): When PUSH_PROMISE is added, Handle RESERVED_REMOTE
-      // cases here depending on whether the delegate is already set.
-      CHECK_EQ(io_state_, STATE_IDLE);
-      DCHECK(!delegate_);
-      io_state_ = STATE_HALF_CLOSED_LOCAL_UNCLAIMED;
+      CHECK_EQ(io_state_, STATE_RESERVED_REMOTE);
+      if (!delegate_) {
+        io_state_ = STATE_HALF_CLOSED_LOCAL_UNCLAIMED;
+      } else {
+        io_state_ = STATE_HALF_CLOSED_LOCAL;
+      }
       break;
   }
 
@@ -451,6 +453,16 @@ int SpdyStream::OnAdditionalResponseHeadersReceived(
   return MergeWithResponseHeaders(additional_response_headers);
 }
 
+void SpdyStream::OnPushPromiseHeadersReceived(const SpdyHeaderBlock& headers) {
+  CHECK(!request_headers_.get());
+  CHECK_EQ(io_state_, STATE_IDLE);
+  CHECK_EQ(type_, SPDY_PUSH_STREAM);
+  DCHECK(!delegate_);
+
+  io_state_ = STATE_RESERVED_REMOTE;
+  request_headers_.reset(new SpdyHeaderBlock(headers));
+}
+
 void SpdyStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) {
   DCHECK(session_->IsStreamActive(stream_id_));
 
@@ -718,6 +730,10 @@ bool SpdyStream::IsOpen() const {
   return io_state_ == STATE_OPEN;
 }
 
+bool SpdyStream::IsReservedRemote() const {
+  return io_state_ == STATE_RESERVED_REMOTE;
+}
+
 NextProto SpdyStream::GetProtocol() const {
   return session_->protocol();
 }
@@ -730,13 +746,11 @@ bool SpdyStream::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const {
 }
 
 GURL SpdyStream::GetUrlFromHeaders() const {
-  if (type_ != SPDY_PUSH_STREAM && !request_headers_)
+  if (!request_headers_)
     return GURL();
 
-  const SpdyHeaderBlock& headers =
-      (type_ == SPDY_PUSH_STREAM) ? response_headers_ : *request_headers_;
-  return GetUrlFromHeaderBlock(headers, GetProtocolVersion(),
-                               type_ == SPDY_PUSH_STREAM);
+  return GetUrlFromHeaderBlock(
+      *request_headers_, GetProtocolVersion(), type_ == SPDY_PUSH_STREAM);
 }
 
 bool SpdyStream::HasUrlFromHeaders() const {
@@ -780,7 +794,12 @@ void SpdyStream::QueueNextDataFrame() {
         io_state_ == STATE_HALF_CLOSED_REMOTE) << io_state_;
   CHECK_GT(stream_id_, 0u);
   CHECK(pending_send_data_.get());
-  CHECK_GT(pending_send_data_->BytesRemaining(), 0);
+  // Only the final fame may have a length of 0.
+  if (pending_send_status_ == NO_MORE_DATA_TO_SEND) {
+    CHECK_GE(pending_send_data_->BytesRemaining(), 0);
+  } else {
+    CHECK_GT(pending_send_data_->BytesRemaining(), 0);
+  }
 
   SpdyDataFlags flags =
       (pending_send_status_ == NO_MORE_DATA_TO_SEND) ?
@@ -800,13 +819,18 @@ void SpdyStream::QueueNextDataFrame() {
     size_t payload_size =
         data_buffer->GetRemainingSize() - session_->GetDataFrameMinimumSize();
     DCHECK_LE(payload_size, session_->GetDataFrameMaximumPayload());
-    DecreaseSendWindowSize(static_cast<int32>(payload_size));
-    // This currently isn't strictly needed, since write frames are
-    // discarded only if the stream is about to be closed. But have it
-    // here anyway just in case this changes.
-    data_buffer->AddConsumeCallback(
-        base::Bind(&SpdyStream::OnWriteBufferConsumed,
-                   GetWeakPtr(), payload_size));
+
+    // Send window size is based on payload size, so nothing to do if this is
+    // just a FIN with no payload.
+    if (payload_size != 0) {
+      DecreaseSendWindowSize(static_cast<int32>(payload_size));
+      // This currently isn't strictly needed, since write frames are
+      // discarded only if the stream is about to be closed. But have it
+      // here anyway just in case this changes.
+      data_buffer->AddConsumeCallback(
+          base::Bind(&SpdyStream::OnWriteBufferConsumed,
+                     GetWeakPtr(), payload_size));
+    }
   }
 
   session_->EnqueueStreamWrite(