| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/child/url_response_body_consumer.h" | 5 #include "content/child/url_response_body_consumer.h" |
| 6 | 6 |
| 7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| 11 #include "content/child/resource_dispatcher.h" | 11 #include "content/child/resource_dispatcher.h" |
| 12 #include "content/common/resource_messages.h" | 12 #include "content/common/resource_messages.h" |
| 13 #include "content/common/resource_request_completion_status.h" | 13 #include "content/common/resource_request_completion_status.h" |
| 14 #include "content/public/child/request_peer.h" | 14 #include "content/public/child/request_peer.h" |
| 15 | 15 |
| 16 namespace content { | 16 namespace content { |
| 17 | 17 |
| 18 constexpr uint32_t URLResponseBodyConsumer::kMaxNumConsumedBytesInTask; |
| 19 |
| 18 class URLResponseBodyConsumer::ReceivedData final | 20 class URLResponseBodyConsumer::ReceivedData final |
| 19 : public RequestPeer::ReceivedData { | 21 : public RequestPeer::ReceivedData { |
| 20 public: | 22 public: |
| 21 ReceivedData(const char* payload, | 23 ReceivedData(const char* payload, |
| 22 int length, | 24 int length, |
| 23 scoped_refptr<URLResponseBodyConsumer> consumer) | 25 scoped_refptr<URLResponseBodyConsumer> consumer) |
| 24 : payload_(payload), length_(length), consumer_(consumer) {} | 26 : payload_(payload), length_(length), consumer_(consumer) {} |
| 25 | 27 |
| 26 ~ReceivedData() override { consumer_->Reclaim(length_); } | 28 ~ReceivedData() override { consumer_->Reclaim(length_); } |
| 27 | 29 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 task_runner_->PostTask( | 93 task_runner_->PostTask( |
| 92 FROM_HERE, base::Bind(&URLResponseBodyConsumer::OnReadable, AsWeakPtr(), | 94 FROM_HERE, base::Bind(&URLResponseBodyConsumer::OnReadable, AsWeakPtr(), |
| 93 MOJO_RESULT_OK)); | 95 MOJO_RESULT_OK)); |
| 94 } | 96 } |
| 95 | 97 |
| 96 void URLResponseBodyConsumer::OnReadable(MojoResult unused) { | 98 void URLResponseBodyConsumer::OnReadable(MojoResult unused) { |
| 97 if (has_been_cancelled_ || has_seen_end_of_data_ || is_deferred_) | 99 if (has_been_cancelled_ || has_seen_end_of_data_ || is_deferred_) |
| 98 return; | 100 return; |
| 99 | 101 |
| 100 DCHECK(!is_in_on_readable_); | 102 DCHECK(!is_in_on_readable_); |
| 103 uint32_t num_bytes_consumed = 0; |
| 101 | 104 |
| 102 // Protect |this| as RequestPeer::OnReceivedData may call deref. | 105 // Protect |this| as RequestPeer::OnReceivedData may call deref. |
| 103 scoped_refptr<URLResponseBodyConsumer> protect(this); | 106 scoped_refptr<URLResponseBodyConsumer> protect(this); |
| 104 base::AutoReset<bool> is_in_on_readable(&is_in_on_readable_, true); | 107 base::AutoReset<bool> is_in_on_readable(&is_in_on_readable_, true); |
| 105 | 108 |
| 106 while (!has_been_cancelled_ && !is_deferred_) { | 109 while (!has_been_cancelled_ && !is_deferred_) { |
| 107 const void* buffer = nullptr; | 110 const void* buffer = nullptr; |
| 108 uint32_t available = 0; | 111 uint32_t available = 0; |
| 109 MojoResult result = mojo::BeginReadDataRaw( | 112 MojoResult result = mojo::BeginReadDataRaw( |
| 110 handle_.get(), &buffer, &available, MOJO_READ_DATA_FLAG_NONE); | 113 handle_.get(), &buffer, &available, MOJO_READ_DATA_FLAG_NONE); |
| 111 if (result == MOJO_RESULT_SHOULD_WAIT || result == MOJO_RESULT_BUSY) | 114 if (result == MOJO_RESULT_SHOULD_WAIT || result == MOJO_RESULT_BUSY) |
| 112 return; | 115 return; |
| 113 if (result == MOJO_RESULT_FAILED_PRECONDITION) { | 116 if (result == MOJO_RESULT_FAILED_PRECONDITION) { |
| 114 has_seen_end_of_data_ = true; | 117 has_seen_end_of_data_ = true; |
| 115 NotifyCompletionIfAppropriate(); | 118 NotifyCompletionIfAppropriate(); |
| 116 return; | 119 return; |
| 117 } | 120 } |
| 118 if (result != MOJO_RESULT_OK) { | 121 if (result != MOJO_RESULT_OK) { |
| 119 completion_status_.error_code = net::ERR_FAILED; | 122 completion_status_.error_code = net::ERR_FAILED; |
| 120 has_seen_end_of_data_ = true; | 123 has_seen_end_of_data_ = true; |
| 121 has_received_completion_ = true; | 124 has_received_completion_ = true; |
| 122 NotifyCompletionIfAppropriate(); | 125 NotifyCompletionIfAppropriate(); |
| 123 return; | 126 return; |
| 124 } | 127 } |
| 128 DCHECK_LE(num_bytes_consumed, kMaxNumConsumedBytesInTask); |
| 129 available = |
| 130 std::min(available, kMaxNumConsumedBytesInTask - num_bytes_consumed); |
| 131 if (available == 0) { |
| 132 // We've already consumed many bytes in this task. Defer the remaining |
| 133 // to the next task. |
| 134 result = mojo::EndReadDataRaw(handle_.get(), 0); |
| 135 DCHECK_EQ(result, MOJO_RESULT_OK); |
| 136 task_runner_->PostTask(FROM_HERE, |
| 137 base::Bind(&URLResponseBodyConsumer::OnReadable, |
| 138 AsWeakPtr(), MOJO_RESULT_OK)); |
| 139 return; |
| 140 } |
| 141 num_bytes_consumed += available; |
| 125 ResourceDispatcher::PendingRequestInfo* request_info = | 142 ResourceDispatcher::PendingRequestInfo* request_info = |
| 126 resource_dispatcher_->GetPendingRequestInfo(request_id_); | 143 resource_dispatcher_->GetPendingRequestInfo(request_id_); |
| 127 DCHECK(request_info); | 144 DCHECK(request_info); |
| 128 request_info->peer->OnReceivedData(base::MakeUnique<ReceivedData>( | 145 request_info->peer->OnReceivedData(base::MakeUnique<ReceivedData>( |
| 129 static_cast<const char*>(buffer), available, this)); | 146 static_cast<const char*>(buffer), available, this)); |
| 130 } | 147 } |
| 131 } | 148 } |
| 132 | 149 |
| 133 void URLResponseBodyConsumer::NotifyCompletionIfAppropriate() { | 150 void URLResponseBodyConsumer::NotifyCompletionIfAppropriate() { |
| 134 if (has_been_cancelled_) | 151 if (has_been_cancelled_) |
| 135 return; | 152 return; |
| 136 if (!has_received_completion_ || !has_seen_end_of_data_) | 153 if (!has_received_completion_ || !has_seen_end_of_data_) |
| 137 return; | 154 return; |
| 138 // Cancel this instance in order not to notify twice. | 155 // Cancel this instance in order not to notify twice. |
| 139 Cancel(); | 156 Cancel(); |
| 140 | 157 |
| 141 resource_dispatcher_->DispatchMessage( | 158 resource_dispatcher_->DispatchMessage( |
| 142 ResourceMsg_RequestComplete(request_id_, completion_status_)); | 159 ResourceMsg_RequestComplete(request_id_, completion_status_)); |
| 143 // |this| may be deleted. | 160 // |this| may be deleted. |
| 144 } | 161 } |
| 145 | 162 |
| 146 } // namespace content | 163 } // namespace content |
| OLD | NEW |