OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "mojo/services/network/url_loader_impl.h" | 5 #include "mojo/services/network/url_loader_impl.h" |
6 | 6 |
7 #include "base/memory/scoped_vector.h" | 7 #include "base/memory/scoped_vector.h" |
8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
9 #include "mojo/common/common_type_converters.h" | 9 #include "mojo/common/common_type_converters.h" |
10 #include "mojo/services/network/net_adapters.h" | 10 #include "mojo/services/network/net_adapters.h" |
11 #include "mojo/services/network/network_context.h" | 11 #include "mojo/services/network/network_context.h" |
12 #include "net/base/io_buffer.h" | 12 #include "net/base/io_buffer.h" |
13 #include "net/base/load_flags.h" | 13 #include "net/base/load_flags.h" |
14 #include "net/base/upload_bytes_element_reader.h" | 14 #include "net/base/upload_bytes_element_reader.h" |
15 #include "net/base/upload_data_stream.h" | 15 #include "net/base/upload_data_stream.h" |
16 #include "net/http/http_response_headers.h" | 16 #include "net/http/http_response_headers.h" |
17 #include "net/url_request/redirect_info.h" | 17 #include "net/url_request/redirect_info.h" |
18 #include "net/url_request/url_request_context.h" | 18 #include "net/url_request/url_request_context.h" |
19 | 19 |
20 namespace mojo { | 20 namespace mojo { |
21 namespace { | 21 namespace { |
22 | 22 |
23 const uint32_t kMaxReadSize = 64 * 1024; | |
24 | |
25 // Generates an URLResponsePtr from the response state of a net::URLRequest. | 23 // Generates an URLResponsePtr from the response state of a net::URLRequest. |
26 URLResponsePtr MakeURLResponse(const net::URLRequest* url_request) { | 24 URLResponsePtr MakeURLResponse(const net::URLRequest* url_request) { |
27 URLResponsePtr response(URLResponse::New()); | 25 URLResponsePtr response(URLResponse::New()); |
28 response->url = String::From(url_request->url()); | 26 response->url = String::From(url_request->url()); |
29 | 27 |
30 const net::HttpResponseHeaders* headers = url_request->response_headers(); | 28 const net::HttpResponseHeaders* headers = url_request->response_headers(); |
31 if (headers) { | 29 if (headers) { |
32 response->status_code = headers->response_code(); | 30 response->status_code = headers->response_code(); |
33 response->status_line = headers->GetStatusLine(); | 31 response->status_line = headers->GetStatusLine(); |
34 | 32 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 private: | 90 private: |
93 ScopedDataPipeConsumerHandle pipe_; | 91 ScopedDataPipeConsumerHandle pipe_; |
94 uint32_t num_bytes_; | 92 uint32_t num_bytes_; |
95 uint32_t offset_; | 93 uint32_t offset_; |
96 | 94 |
97 DISALLOW_COPY_AND_ASSIGN(UploadDataPipeElementReader); | 95 DISALLOW_COPY_AND_ASSIGN(UploadDataPipeElementReader); |
98 }; | 96 }; |
99 | 97 |
100 } // namespace | 98 } // namespace |
101 | 99 |
102 // Keeps track of a pending two-phase write on a DataPipeProducerHandle. | |
103 class URLLoaderImpl::PendingWriteToDataPipe : | |
104 public base::RefCountedThreadSafe<PendingWriteToDataPipe> { | |
105 public: | |
106 explicit PendingWriteToDataPipe(ScopedDataPipeProducerHandle handle) | |
107 : handle_(handle.Pass()), | |
108 buffer_(NULL) { | |
109 } | |
110 | |
111 MojoResult BeginWrite(uint32_t* num_bytes) { | |
112 MojoResult result = BeginWriteDataRaw(handle_.get(), &buffer_, num_bytes, | |
113 MOJO_WRITE_DATA_FLAG_NONE); | |
114 if (*num_bytes > kMaxReadSize) | |
115 *num_bytes = kMaxReadSize; | |
116 | |
117 return result; | |
118 } | |
119 | |
120 ScopedDataPipeProducerHandle Complete(uint32_t num_bytes) { | |
121 EndWriteDataRaw(handle_.get(), num_bytes); | |
122 buffer_ = NULL; | |
123 return handle_.Pass(); | |
124 } | |
125 | |
126 char* buffer() { return static_cast<char*>(buffer_); } | |
127 | |
128 private: | |
129 friend class base::RefCountedThreadSafe<PendingWriteToDataPipe>; | |
130 | |
131 ~PendingWriteToDataPipe() { | |
132 if (handle_.is_valid()) | |
133 EndWriteDataRaw(handle_.get(), 0); | |
134 } | |
135 | |
136 ScopedDataPipeProducerHandle handle_; | |
137 void* buffer_; | |
138 | |
139 DISALLOW_COPY_AND_ASSIGN(PendingWriteToDataPipe); | |
140 }; | |
141 | |
142 // Takes ownership of a pending two-phase write on a DataPipeProducerHandle, | |
143 // and makes its buffer available as a net::IOBuffer. | |
144 class URLLoaderImpl::DependentIOBuffer : public net::WrappedIOBuffer { | |
145 public: | |
146 DependentIOBuffer(PendingWriteToDataPipe* pending_write) | |
147 : net::WrappedIOBuffer(pending_write->buffer()), | |
148 pending_write_(pending_write) { | |
149 } | |
150 private: | |
151 virtual ~DependentIOBuffer() {} | |
152 scoped_refptr<PendingWriteToDataPipe> pending_write_; | |
153 }; | |
154 | |
155 URLLoaderImpl::URLLoaderImpl(NetworkContext* context) | 100 URLLoaderImpl::URLLoaderImpl(NetworkContext* context) |
156 : context_(context), | 101 : context_(context), |
157 response_body_buffer_size_(0), | 102 response_body_buffer_size_(0), |
158 auto_follow_redirects_(true), | 103 auto_follow_redirects_(true), |
159 weak_ptr_factory_(this) { | 104 weak_ptr_factory_(this) { |
160 } | 105 } |
161 | 106 |
162 URLLoaderImpl::~URLLoaderImpl() { | 107 URLLoaderImpl::~URLLoaderImpl() { |
163 } | 108 } |
164 | 109 |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 Callback<void(URLResponsePtr)> callback; | 250 Callback<void(URLResponsePtr)> callback; |
306 std::swap(callback_, callback); | 251 std::swap(callback_, callback); |
307 callback.Run(response.Pass()); | 252 callback.Run(response.Pass()); |
308 } | 253 } |
309 | 254 |
310 void URLLoaderImpl::OnResponseBodyStreamReady(MojoResult result) { | 255 void URLLoaderImpl::OnResponseBodyStreamReady(MojoResult result) { |
311 // TODO(darin): Handle a bad |result| value. | 256 // TODO(darin): Handle a bad |result| value. |
312 ReadMore(); | 257 ReadMore(); |
313 } | 258 } |
314 | 259 |
315 void URLLoaderImpl::WaitToReadMore() { | |
316 handle_watcher_.Start(response_body_stream_.get(), | |
317 MOJO_HANDLE_SIGNAL_WRITABLE, | |
318 MOJO_DEADLINE_INDEFINITE, | |
319 base::Bind(&URLLoaderImpl::OnResponseBodyStreamReady, | |
320 weak_ptr_factory_.GetWeakPtr())); | |
321 } | |
322 | |
323 void URLLoaderImpl::ReadMore() { | 260 void URLLoaderImpl::ReadMore() { |
324 DCHECK(!pending_write_.get()); | 261 DCHECK(!pending_write_.get()); |
325 | 262 |
326 pending_write_ = new PendingWriteToDataPipe(response_body_stream_.Pass()); | 263 uint32_t num_bytes; |
| 264 MojoResult result = NetToMojoPendingBuffer::BeginWrite( |
| 265 &response_body_stream_, &pending_write_, &num_bytes); |
327 | 266 |
328 uint32_t num_bytes; | |
329 MojoResult result = pending_write_->BeginWrite(&num_bytes); | |
330 if (result == MOJO_RESULT_SHOULD_WAIT) { | 267 if (result == MOJO_RESULT_SHOULD_WAIT) { |
331 // The pipe is full. We need to wait for it to have more space. | 268 // The pipe is full. We need to wait for it to have more space. |
332 response_body_stream_ = pending_write_->Complete(num_bytes); | 269 handle_watcher_.Start(response_body_stream_.get(), |
333 pending_write_ = NULL; | 270 MOJO_HANDLE_SIGNAL_WRITABLE, |
334 WaitToReadMore(); | 271 MOJO_DEADLINE_INDEFINITE, |
| 272 base::Bind(&URLLoaderImpl::OnResponseBodyStreamReady, |
| 273 weak_ptr_factory_.GetWeakPtr())); |
335 return; | 274 return; |
336 } | 275 } else if (result != MOJO_RESULT_OK) { |
337 if (result != MOJO_RESULT_OK) { | |
338 // The response body stream is in a bad state. Bail. | 276 // The response body stream is in a bad state. Bail. |
339 // TODO(darin): How should this be communicated to our client? | 277 // TODO(darin): How should this be communicated to our client? |
340 return; | 278 return; |
341 } | 279 } |
342 CHECK_GT(static_cast<uint32_t>(std::numeric_limits<int>::max()), num_bytes); | 280 CHECK_GT(static_cast<uint32_t>(std::numeric_limits<int>::max()), num_bytes); |
343 | 281 |
344 scoped_refptr<net::IOBuffer> buf = | 282 scoped_refptr<net::IOBuffer> buf(new NetToMojoIOBuffer(pending_write_.get())); |
345 new DependentIOBuffer(pending_write_.get()); | |
346 | 283 |
347 int bytes_read; | 284 int bytes_read; |
348 url_request_->Read(buf.get(), static_cast<int>(num_bytes), &bytes_read); | 285 url_request_->Read(buf.get(), static_cast<int>(num_bytes), &bytes_read); |
349 | |
350 // Drop our reference to the buffer. | |
351 buf = NULL; | |
352 | |
353 if (url_request_->status().is_io_pending()) { | 286 if (url_request_->status().is_io_pending()) { |
354 // Wait for OnReadCompleted. | 287 // Wait for OnReadCompleted. |
355 } else if (url_request_->status().is_success() && bytes_read > 0) { | 288 } else if (url_request_->status().is_success() && bytes_read > 0) { |
356 DidRead(static_cast<uint32_t>(bytes_read), true); | 289 DidRead(static_cast<uint32_t>(bytes_read), true); |
357 } else { | 290 } else { |
358 pending_write_->Complete(0); | 291 pending_write_->Complete(0); |
359 pending_write_ = NULL; // This closes the data pipe. | 292 pending_write_ = NULL; // This closes the data pipe. |
360 } | 293 } |
361 } | 294 } |
362 | 295 |
363 void URLLoaderImpl::DidRead(uint32_t num_bytes, bool completed_synchronously) { | 296 void URLLoaderImpl::DidRead(uint32_t num_bytes, bool completed_synchronously) { |
364 DCHECK(url_request_->status().is_success()); | 297 DCHECK(url_request_->status().is_success()); |
365 | 298 |
366 response_body_stream_ = pending_write_->Complete(num_bytes); | 299 response_body_stream_ = pending_write_->Complete(num_bytes); |
367 pending_write_ = NULL; | 300 pending_write_ = NULL; |
368 | 301 |
369 if (completed_synchronously) { | 302 if (completed_synchronously) { |
370 base::MessageLoop::current()->PostTask( | 303 base::MessageLoop::current()->PostTask( |
371 FROM_HERE, | 304 FROM_HERE, |
372 base::Bind(&URLLoaderImpl::ReadMore, weak_ptr_factory_.GetWeakPtr())); | 305 base::Bind(&URLLoaderImpl::ReadMore, weak_ptr_factory_.GetWeakPtr())); |
373 } else { | 306 } else { |
374 ReadMore(); | 307 ReadMore(); |
375 } | 308 } |
376 } | 309 } |
377 | 310 |
378 } // namespace mojo | 311 } // namespace mojo |
OLD | NEW |