| 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/message_loop/message_loop.h" | 7 #include "base/message_loop/message_loop.h" |
| 8 #include "mojo/common/common_type_converters.h" | 8 #include "mojo/common/common_type_converters.h" |
| 9 #include "mojo/services/network/network_context.h" | 9 #include "mojo/services/network/network_context.h" |
| 10 #include "net/base/io_buffer.h" | 10 #include "net/base/io_buffer.h" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 url_request->GetMimeType(&mime_type); | 39 url_request->GetMimeType(&mime_type); |
| 40 response->mime_type = mime_type; | 40 response->mime_type = mime_type; |
| 41 | 41 |
| 42 std::string charset; | 42 std::string charset; |
| 43 url_request->GetCharset(&charset); | 43 url_request->GetCharset(&charset); |
| 44 response->charset = charset; | 44 response->charset = charset; |
| 45 | 45 |
| 46 return response.Pass(); | 46 return response.Pass(); |
| 47 } | 47 } |
| 48 | 48 |
| 49 NetworkErrorPtr MakeNetworkError(int error_code) { |
| 50 NetworkErrorPtr error = NetworkError::New(); |
| 51 error->code = error_code; |
| 52 error->description = net::ErrorToString(error_code); |
| 53 return error.Pass(); |
| 54 } |
| 55 |
| 49 } // namespace | 56 } // namespace |
| 50 | 57 |
| 51 // Keeps track of a pending two-phase write on a DataPipeProducerHandle. | 58 // Keeps track of a pending two-phase write on a DataPipeProducerHandle. |
| 52 class URLLoaderImpl::PendingWriteToDataPipe : | 59 class URLLoaderImpl::PendingWriteToDataPipe : |
| 53 public base::RefCountedThreadSafe<PendingWriteToDataPipe> { | 60 public base::RefCountedThreadSafe<PendingWriteToDataPipe> { |
| 54 public: | 61 public: |
| 55 explicit PendingWriteToDataPipe(ScopedDataPipeProducerHandle handle) | 62 explicit PendingWriteToDataPipe(ScopedDataPipeProducerHandle handle) |
| 56 : handle_(handle.Pass()), | 63 : handle_(handle.Pass()), |
| 57 buffer_(NULL) { | 64 buffer_(NULL) { |
| 58 } | 65 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 : net::WrappedIOBuffer(pending_write->buffer()), | 103 : net::WrappedIOBuffer(pending_write->buffer()), |
| 97 pending_write_(pending_write) { | 104 pending_write_(pending_write) { |
| 98 } | 105 } |
| 99 private: | 106 private: |
| 100 virtual ~DependentIOBuffer() {} | 107 virtual ~DependentIOBuffer() {} |
| 101 scoped_refptr<PendingWriteToDataPipe> pending_write_; | 108 scoped_refptr<PendingWriteToDataPipe> pending_write_; |
| 102 }; | 109 }; |
| 103 | 110 |
| 104 URLLoaderImpl::URLLoaderImpl(NetworkContext* context) | 111 URLLoaderImpl::URLLoaderImpl(NetworkContext* context) |
| 105 : context_(context), | 112 : context_(context), |
| 113 response_body_buffer_size_(0), |
| 106 auto_follow_redirects_(true), | 114 auto_follow_redirects_(true), |
| 107 weak_ptr_factory_(this) { | 115 weak_ptr_factory_(this) { |
| 108 } | 116 } |
| 109 | 117 |
| 110 URLLoaderImpl::~URLLoaderImpl() { | 118 URLLoaderImpl::~URLLoaderImpl() { |
| 111 } | 119 } |
| 112 | 120 |
| 113 void URLLoaderImpl::OnConnectionError() { | 121 void URLLoaderImpl::OnConnectionError() { |
| 114 delete this; | 122 delete this; |
| 115 } | 123 } |
| 116 | 124 |
| 117 void URLLoaderImpl::Start(URLRequestPtr request, | 125 void URLLoaderImpl::Start(URLRequestPtr request, |
| 118 ScopedDataPipeProducerHandle response_body_stream) { | 126 const Callback<void(URLResponsePtr)>& callback) { |
| 119 // Do not allow starting another request. | |
| 120 if (url_request_) { | 127 if (url_request_) { |
| 121 SendError(net::ERR_UNEXPECTED); | 128 SendError(net::ERR_UNEXPECTED, callback); |
| 122 url_request_.reset(); | |
| 123 response_body_stream_.reset(); | |
| 124 return; | 129 return; |
| 125 } | 130 } |
| 126 | 131 |
| 127 if (!request) { | 132 if (!request) { |
| 128 SendError(net::ERR_INVALID_ARGUMENT); | 133 SendError(net::ERR_INVALID_ARGUMENT, callback); |
| 129 return; | 134 return; |
| 130 } | 135 } |
| 131 | 136 |
| 132 response_body_stream_ = response_body_stream.Pass(); | |
| 133 | |
| 134 GURL url(request->url); | |
| 135 url_request_.reset( | 137 url_request_.reset( |
| 136 new net::URLRequest(url, | 138 new net::URLRequest(GURL(request->url), |
| 137 net::DEFAULT_PRIORITY, | 139 net::DEFAULT_PRIORITY, |
| 138 this, | 140 this, |
| 139 context_->url_request_context())); | 141 context_->url_request_context())); |
| 140 url_request_->set_method(request->method); | 142 url_request_->set_method(request->method); |
| 141 if (request->headers) { | 143 if (request->headers) { |
| 142 net::HttpRequestHeaders headers; | 144 net::HttpRequestHeaders headers; |
| 143 for (size_t i = 0; i < request->headers.size(); ++i) | 145 for (size_t i = 0; i < request->headers.size(); ++i) |
| 144 headers.AddHeaderFromString(request->headers[i].To<base::StringPiece>()); | 146 headers.AddHeaderFromString(request->headers[i].To<base::StringPiece>()); |
| 145 url_request_->SetExtraRequestHeaders(headers); | 147 url_request_->SetExtraRequestHeaders(headers); |
| 146 } | 148 } |
| 147 if (request->bypass_cache) | 149 if (request->bypass_cache) |
| 148 url_request_->SetLoadFlags(net::LOAD_BYPASS_CACHE); | 150 url_request_->SetLoadFlags(net::LOAD_BYPASS_CACHE); |
| 149 // TODO(darin): Handle request body. | 151 // TODO(darin): Handle request body. |
| 150 | 152 |
| 153 callback_ = callback; |
| 154 response_body_buffer_size_ = request->response_body_buffer_size; |
| 151 auto_follow_redirects_ = request->auto_follow_redirects; | 155 auto_follow_redirects_ = request->auto_follow_redirects; |
| 152 | 156 |
| 153 url_request_->Start(); | 157 url_request_->Start(); |
| 154 } | 158 } |
| 155 | 159 |
| 156 void URLLoaderImpl::FollowRedirect() { | 160 void URLLoaderImpl::FollowRedirect( |
| 161 const Callback<void(URLResponsePtr)>& callback) { |
| 162 if (!url_request_) { |
| 163 SendError(net::ERR_UNEXPECTED, callback); |
| 164 return; |
| 165 } |
| 166 |
| 157 if (auto_follow_redirects_) { | 167 if (auto_follow_redirects_) { |
| 158 DLOG(ERROR) << "Spurious call to FollowRedirect"; | 168 DLOG(ERROR) << "Spurious call to FollowRedirect"; |
| 169 SendError(net::ERR_UNEXPECTED, callback); |
| 170 return; |
| 171 } |
| 172 |
| 173 // TODO(darin): Verify that it makes sense to call FollowDeferredRedirect. |
| 174 url_request_->FollowDeferredRedirect(); |
| 175 } |
| 176 |
| 177 void URLLoaderImpl::QueryStatus( |
| 178 const Callback<void(URLLoaderStatusPtr)>& callback) { |
| 179 URLLoaderStatusPtr status(URLLoaderStatus::New()); |
| 180 if (url_request_) { |
| 181 status->is_loading = url_request_->is_pending(); |
| 182 if (!url_request_->status().is_success()) |
| 183 status->error = MakeNetworkError(url_request_->status().error()); |
| 159 } else { | 184 } else { |
| 160 if (url_request_) | 185 status->is_loading = false; |
| 161 url_request_->FollowDeferredRedirect(); | |
| 162 } | 186 } |
| 187 // TODO(darin): Populate more status fields. |
| 188 callback.Run(status.Pass()); |
| 163 } | 189 } |
| 164 | 190 |
| 165 void URLLoaderImpl::OnReceivedRedirect(net::URLRequest* url_request, | 191 void URLLoaderImpl::OnReceivedRedirect(net::URLRequest* url_request, |
| 166 const GURL& new_url, | 192 const GURL& new_url, |
| 167 bool* defer_redirect) { | 193 bool* defer_redirect) { |
| 168 DCHECK(url_request == url_request_.get()); | 194 DCHECK(url_request == url_request_.get()); |
| 169 DCHECK(url_request->status().is_success()); | 195 DCHECK(url_request->status().is_success()); |
| 170 | 196 |
| 197 if (auto_follow_redirects_) |
| 198 return; |
| 199 |
| 200 // Send the redirect response to the client, allowing them to inspect it and |
| 201 // optionally follow the redirect. |
| 202 *defer_redirect = true; |
| 203 |
| 171 URLResponsePtr response = MakeURLResponse(url_request); | 204 URLResponsePtr response = MakeURLResponse(url_request); |
| 172 std::string redirect_method = | 205 response->redirect_method = |
| 173 net::URLRequest::ComputeMethodForRedirect(url_request->method(), | 206 net::URLRequest::ComputeMethodForRedirect(url_request->method(), |
| 174 response->status_code); | 207 response->status_code); |
| 175 client()->OnReceivedRedirect( | 208 response->redirect_url = new_url.spec(); |
| 176 response.Pass(), new_url.spec(), redirect_method); | |
| 177 | 209 |
| 178 *defer_redirect = !auto_follow_redirects_; | 210 SendResponse(response.Pass()); |
| 179 } | 211 } |
| 180 | 212 |
| 181 void URLLoaderImpl::OnResponseStarted(net::URLRequest* url_request) { | 213 void URLLoaderImpl::OnResponseStarted(net::URLRequest* url_request) { |
| 182 DCHECK(url_request == url_request_.get()); | 214 DCHECK(url_request == url_request_.get()); |
| 183 | 215 |
| 184 if (!url_request->status().is_success()) { | 216 if (!url_request->status().is_success()) { |
| 185 SendError(url_request->status().error()); | 217 SendError(url_request->status().error(), callback_); |
| 218 callback_ = Callback<void(URLResponsePtr)>(); |
| 186 return; | 219 return; |
| 187 } | 220 } |
| 188 | 221 |
| 189 // TODO(darin): Add support for optional MIME sniffing. | 222 // TODO(darin): Add support for optional MIME sniffing. |
| 190 | 223 |
| 191 client()->OnReceivedResponse(MakeURLResponse(url_request)); | 224 DataPipe data_pipe; |
| 225 // TODO(darin): Honor given buffer size. |
| 226 |
| 227 URLResponsePtr response = MakeURLResponse(url_request); |
| 228 response->body = data_pipe.consumer_handle.Pass(); |
| 229 response_body_stream_ = data_pipe.producer_handle.Pass(); |
| 230 |
| 231 SendResponse(response.Pass()); |
| 192 | 232 |
| 193 // Start reading... | 233 // Start reading... |
| 194 ReadMore(); | 234 ReadMore(); |
| 195 } | 235 } |
| 196 | 236 |
| 197 void URLLoaderImpl::OnReadCompleted(net::URLRequest* url_request, | 237 void URLLoaderImpl::OnReadCompleted(net::URLRequest* url_request, |
| 198 int bytes_read) { | 238 int bytes_read) { |
| 239 DCHECK(url_request == url_request_.get()); |
| 240 |
| 199 if (url_request->status().is_success()) { | 241 if (url_request->status().is_success()) { |
| 200 DidRead(static_cast<uint32_t>(bytes_read), false); | 242 DidRead(static_cast<uint32_t>(bytes_read), false); |
| 201 } else { | 243 } else { |
| 202 pending_write_ = NULL; // This closes the data pipe. | 244 pending_write_ = NULL; // This closes the data pipe. |
| 203 // TODO(darin): Perhaps we should communicate this error to our client. | |
| 204 } | 245 } |
| 205 } | 246 } |
| 206 | 247 |
| 207 void URLLoaderImpl::SendError(int error_code) { | 248 void URLLoaderImpl::SendError( |
| 208 NetworkErrorPtr error(NetworkError::New()); | 249 int error_code, |
| 209 error->code = error_code; | 250 const Callback<void(URLResponsePtr)>& callback) { |
| 210 error->description = net::ErrorToString(error_code); | 251 URLResponsePtr response(URLResponse::New()); |
| 211 client()->OnReceivedError(error.Pass()); | 252 if (url_request_) |
| 253 response->url = url_request_->url().spec(); |
| 254 response->error = MakeNetworkError(error_code); |
| 255 callback.Run(response.Pass()); |
| 256 } |
| 257 |
| 258 void URLLoaderImpl::SendResponse(URLResponsePtr response) { |
| 259 Callback<void(URLResponsePtr)> callback; |
| 260 std::swap(callback_, callback); |
| 261 callback.Run(response.Pass()); |
| 212 } | 262 } |
| 213 | 263 |
| 214 void URLLoaderImpl::OnResponseBodyStreamReady(MojoResult result) { | 264 void URLLoaderImpl::OnResponseBodyStreamReady(MojoResult result) { |
| 215 // TODO(darin): Handle a bad |result| value. | 265 // TODO(darin): Handle a bad |result| value. |
| 216 ReadMore(); | 266 ReadMore(); |
| 217 } | 267 } |
| 218 | 268 |
| 219 void URLLoaderImpl::WaitToReadMore() { | 269 void URLLoaderImpl::WaitToReadMore() { |
| 220 handle_watcher_.Start(response_body_stream_.get(), | 270 handle_watcher_.Start(response_body_stream_.get(), |
| 221 MOJO_HANDLE_SIGNAL_WRITABLE, | 271 MOJO_HANDLE_SIGNAL_WRITABLE, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 // Drop our reference to the buffer. | 303 // Drop our reference to the buffer. |
| 254 buf = NULL; | 304 buf = NULL; |
| 255 | 305 |
| 256 if (url_request_->status().is_io_pending()) { | 306 if (url_request_->status().is_io_pending()) { |
| 257 // Wait for OnReadCompleted. | 307 // Wait for OnReadCompleted. |
| 258 } else if (url_request_->status().is_success() && bytes_read > 0) { | 308 } else if (url_request_->status().is_success() && bytes_read > 0) { |
| 259 DidRead(static_cast<uint32_t>(bytes_read), true); | 309 DidRead(static_cast<uint32_t>(bytes_read), true); |
| 260 } else { | 310 } else { |
| 261 pending_write_->Complete(0); | 311 pending_write_->Complete(0); |
| 262 pending_write_ = NULL; // This closes the data pipe. | 312 pending_write_ = NULL; // This closes the data pipe. |
| 263 if (bytes_read == 0) { | |
| 264 client()->OnReceivedEndOfResponseBody(); | |
| 265 } else { | |
| 266 DCHECK(!url_request_->status().is_success()); | |
| 267 SendError(url_request_->status().error()); | |
| 268 } | |
| 269 } | 313 } |
| 270 } | 314 } |
| 271 | 315 |
| 272 void URLLoaderImpl::DidRead(uint32_t num_bytes, bool completed_synchronously) { | 316 void URLLoaderImpl::DidRead(uint32_t num_bytes, bool completed_synchronously) { |
| 273 DCHECK(url_request_->status().is_success()); | 317 DCHECK(url_request_->status().is_success()); |
| 274 | 318 |
| 275 response_body_stream_ = pending_write_->Complete(num_bytes); | 319 response_body_stream_ = pending_write_->Complete(num_bytes); |
| 276 pending_write_ = NULL; | 320 pending_write_ = NULL; |
| 277 | 321 |
| 278 if (completed_synchronously) { | 322 if (completed_synchronously) { |
| 279 base::MessageLoop::current()->PostTask( | 323 base::MessageLoop::current()->PostTask( |
| 280 FROM_HERE, | 324 FROM_HERE, |
| 281 base::Bind(&URLLoaderImpl::ReadMore, weak_ptr_factory_.GetWeakPtr())); | 325 base::Bind(&URLLoaderImpl::ReadMore, weak_ptr_factory_.GetWeakPtr())); |
| 282 } else { | 326 } else { |
| 283 ReadMore(); | 327 ReadMore(); |
| 284 } | 328 } |
| 285 } | 329 } |
| 286 | 330 |
| 287 } // namespace mojo | 331 } // namespace mojo |
| OLD | NEW |