OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/browser/streams/stream_url_request_job.h" | 5 #include "content/browser/streams/stream_url_request_job.h" |
6 | 6 |
7 #include "base/location.h" | 7 #include "base/location.h" |
8 #include "base/single_thread_task_runner.h" | 8 #include "base/single_thread_task_runner.h" |
9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
10 #include "base/thread_task_runner_handle.h" | 10 #include "base/thread_task_runner_handle.h" |
(...skipping 22 matching lines...) Expand all Loading... |
33 weak_factory_(this) { | 33 weak_factory_(this) { |
34 DCHECK(stream_.get()); | 34 DCHECK(stream_.get()); |
35 stream_->SetReadObserver(this); | 35 stream_->SetReadObserver(this); |
36 } | 36 } |
37 | 37 |
38 StreamURLRequestJob::~StreamURLRequestJob() { | 38 StreamURLRequestJob::~StreamURLRequestJob() { |
39 ClearStream(); | 39 ClearStream(); |
40 } | 40 } |
41 | 41 |
42 void StreamURLRequestJob::OnDataAvailable(Stream* stream) { | 42 void StreamURLRequestJob::OnDataAvailable(Stream* stream) { |
| 43 // Clear the IO_PENDING status. |
| 44 SetStatus(net::URLRequestStatus()); |
43 // Do nothing if pending_buffer_ is empty, i.e. there's no ReadRawData() | 45 // Do nothing if pending_buffer_ is empty, i.e. there's no ReadRawData() |
44 // operation waiting for IO completion. | 46 // operation waiting for IO completion. |
45 if (!pending_buffer_.get()) | 47 if (!pending_buffer_.get()) |
46 return; | 48 return; |
47 | 49 |
48 // pending_buffer_ is set to the IOBuffer instance provided to ReadRawData() | 50 // pending_buffer_ is set to the IOBuffer instance provided to ReadRawData() |
49 // by URLRequestJob. | 51 // by URLRequestJob. |
50 | 52 |
51 int result = 0; | 53 int bytes_read; |
52 switch (stream_->ReadRawData(pending_buffer_.get(), pending_buffer_size_, | 54 switch (stream_->ReadRawData(pending_buffer_.get(), pending_buffer_size_, |
53 &result)) { | 55 &bytes_read)) { |
54 case Stream::STREAM_HAS_DATA: | 56 case Stream::STREAM_HAS_DATA: |
55 DCHECK_GT(result, 0); | 57 DCHECK_GT(bytes_read, 0); |
56 break; | 58 break; |
57 case Stream::STREAM_COMPLETE: | 59 case Stream::STREAM_COMPLETE: |
58 // Ensure ReadRawData gives net::OK. | 60 // Ensure this. Calling NotifyReadComplete call with 0 signals |
59 DCHECK_EQ(net::OK, result); | 61 // completion. |
| 62 bytes_read = 0; |
60 break; | 63 break; |
61 case Stream::STREAM_EMPTY: | 64 case Stream::STREAM_EMPTY: |
62 NOTREACHED(); | 65 NOTREACHED(); |
63 break; | 66 break; |
64 case Stream::STREAM_ABORTED: | 67 case Stream::STREAM_ABORTED: |
65 // Handle this as connection reset. | 68 // Handle this as connection reset. |
66 result = net::ERR_CONNECTION_RESET; | 69 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, |
| 70 net::ERR_CONNECTION_RESET)); |
67 break; | 71 break; |
68 } | 72 } |
69 | 73 |
70 // Clear the buffers before notifying the read is complete, so that it is | 74 // Clear the buffers before notifying the read is complete, so that it is |
71 // safe for the observer to read. | 75 // safe for the observer to read. |
72 pending_buffer_ = NULL; | 76 pending_buffer_ = NULL; |
73 pending_buffer_size_ = 0; | 77 pending_buffer_size_ = 0; |
74 | 78 |
75 if (result > 0) | 79 total_bytes_read_ += bytes_read; |
76 total_bytes_read_ += result; | 80 NotifyReadComplete(bytes_read); |
77 ReadRawDataComplete(result); | |
78 } | 81 } |
79 | 82 |
80 // net::URLRequestJob methods. | 83 // net::URLRequestJob methods. |
81 void StreamURLRequestJob::Start() { | 84 void StreamURLRequestJob::Start() { |
82 // Continue asynchronously. | 85 // Continue asynchronously. |
83 base::ThreadTaskRunnerHandle::Get()->PostTask( | 86 base::ThreadTaskRunnerHandle::Get()->PostTask( |
84 FROM_HERE, | 87 FROM_HERE, |
85 base::Bind(&StreamURLRequestJob::DidStart, weak_factory_.GetWeakPtr())); | 88 base::Bind(&StreamURLRequestJob::DidStart, weak_factory_.GetWeakPtr())); |
86 } | 89 } |
87 | 90 |
88 void StreamURLRequestJob::Kill() { | 91 void StreamURLRequestJob::Kill() { |
89 net::URLRequestJob::Kill(); | 92 net::URLRequestJob::Kill(); |
90 weak_factory_.InvalidateWeakPtrs(); | 93 weak_factory_.InvalidateWeakPtrs(); |
91 ClearStream(); | 94 ClearStream(); |
92 } | 95 } |
93 | 96 |
94 int StreamURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size) { | 97 bool StreamURLRequestJob::ReadRawData(net::IOBuffer* buf, |
95 // TODO(ellyjones): This is not right. The old code returned true here, but | 98 int buf_size, |
96 // ReadRawData's old contract was to return true only for synchronous | 99 int* bytes_read) { |
97 // successes, which had the effect of treating all errors as synchronous EOFs. | |
98 // See https://crbug.com/508957 | |
99 if (request_failed_) | 100 if (request_failed_) |
100 return 0; | 101 return true; |
101 | 102 |
102 DCHECK(buf); | 103 DCHECK(buf); |
| 104 DCHECK(bytes_read); |
103 int to_read = buf_size; | 105 int to_read = buf_size; |
104 if (max_range_ && to_read) { | 106 if (max_range_ && to_read) { |
105 if (to_read + total_bytes_read_ > max_range_) | 107 if (to_read + total_bytes_read_ > max_range_) |
106 to_read = max_range_ - total_bytes_read_; | 108 to_read = max_range_ - total_bytes_read_; |
107 | 109 |
108 if (to_read == 0) | 110 if (to_read <= 0) { |
109 return 0; | 111 *bytes_read = 0; |
| 112 return true; |
| 113 } |
110 } | 114 } |
111 | 115 |
112 int bytes_read = 0; | 116 switch (stream_->ReadRawData(buf, to_read, bytes_read)) { |
113 switch (stream_->ReadRawData(buf, to_read, &bytes_read)) { | |
114 case Stream::STREAM_HAS_DATA: | 117 case Stream::STREAM_HAS_DATA: |
115 case Stream::STREAM_COMPLETE: | 118 case Stream::STREAM_COMPLETE: |
116 total_bytes_read_ += bytes_read; | 119 total_bytes_read_ += *bytes_read; |
117 return bytes_read; | 120 return true; |
118 case Stream::STREAM_EMPTY: | 121 case Stream::STREAM_EMPTY: |
119 pending_buffer_ = buf; | 122 pending_buffer_ = buf; |
120 pending_buffer_size_ = to_read; | 123 pending_buffer_size_ = to_read; |
121 return net::ERR_IO_PENDING; | 124 SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); |
| 125 return false; |
122 case Stream::STREAM_ABORTED: | 126 case Stream::STREAM_ABORTED: |
123 // Handle this as connection reset. | 127 // Handle this as connection reset. |
124 return net::ERR_CONNECTION_RESET; | 128 NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, |
| 129 net::ERR_CONNECTION_RESET)); |
| 130 return false; |
125 } | 131 } |
126 NOTREACHED(); | 132 NOTREACHED(); |
127 return net::ERR_FAILED; | 133 return false; |
128 } | 134 } |
129 | 135 |
130 bool StreamURLRequestJob::GetMimeType(std::string* mime_type) const { | 136 bool StreamURLRequestJob::GetMimeType(std::string* mime_type) const { |
131 if (!response_info_) | 137 if (!response_info_) |
132 return false; | 138 return false; |
133 | 139 |
134 // TODO(zork): Support registered MIME types if needed. | 140 // TODO(zork): Support registered MIME types if needed. |
135 return response_info_->headers->GetMimeType(mime_type); | 141 return response_info_->headers->GetMimeType(mime_type); |
136 } | 142 } |
137 | 143 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED); | 182 NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED); |
177 return; | 183 return; |
178 } | 184 } |
179 | 185 |
180 HeadersCompleted(net::HTTP_OK); | 186 HeadersCompleted(net::HTTP_OK); |
181 } | 187 } |
182 | 188 |
183 void StreamURLRequestJob::NotifyFailure(int error_code) { | 189 void StreamURLRequestJob::NotifyFailure(int error_code) { |
184 request_failed_ = true; | 190 request_failed_ = true; |
185 | 191 |
186 // This method can only be called before headers are set. | 192 // If we already return the headers on success, we can't change the headers |
187 DCHECK(!headers_set_); | 193 // now. Instead, we just error out. |
| 194 if (headers_set_) { |
| 195 NotifyDone( |
| 196 net::URLRequestStatus(net::URLRequestStatus::FAILED, error_code)); |
| 197 return; |
| 198 } |
188 | 199 |
189 // TODO(zork): Share these with BlobURLRequestJob. | 200 // TODO(zork): Share these with BlobURLRequestJob. |
190 net::HttpStatusCode status_code = net::HTTP_INTERNAL_SERVER_ERROR; | 201 net::HttpStatusCode status_code = net::HTTP_INTERNAL_SERVER_ERROR; |
191 switch (error_code) { | 202 switch (error_code) { |
192 case net::ERR_ACCESS_DENIED: | 203 case net::ERR_ACCESS_DENIED: |
193 status_code = net::HTTP_FORBIDDEN; | 204 status_code = net::HTTP_FORBIDDEN; |
194 break; | 205 break; |
195 case net::ERR_FILE_NOT_FOUND: | 206 case net::ERR_FILE_NOT_FOUND: |
196 status_code = net::HTTP_NOT_FOUND; | 207 status_code = net::HTTP_NOT_FOUND; |
197 break; | 208 break; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 } | 242 } |
232 | 243 |
233 void StreamURLRequestJob::ClearStream() { | 244 void StreamURLRequestJob::ClearStream() { |
234 if (stream_.get()) { | 245 if (stream_.get()) { |
235 stream_->RemoveReadObserver(this); | 246 stream_->RemoveReadObserver(this); |
236 stream_ = NULL; | 247 stream_ = NULL; |
237 } | 248 } |
238 } | 249 } |
239 | 250 |
240 } // namespace content | 251 } // namespace content |
OLD | NEW |