| 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/browser/loader/mojo_async_resource_handler.h" | 5 #include "content/browser/loader/mojo_async_resource_handler.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/containers/hash_tables.h" | 10 #include "base/containers/hash_tables.h" |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 // the callback will never be called after |this| is destroyed. | 118 // the callback will never be called after |this| is destroyed. |
| 119 binding_.set_connection_error_handler( | 119 binding_.set_connection_error_handler( |
| 120 base::Bind(&MojoAsyncResourceHandler::Cancel, base::Unretained(this))); | 120 base::Bind(&MojoAsyncResourceHandler::Cancel, base::Unretained(this))); |
| 121 } | 121 } |
| 122 | 122 |
| 123 MojoAsyncResourceHandler::~MojoAsyncResourceHandler() { | 123 MojoAsyncResourceHandler::~MojoAsyncResourceHandler() { |
| 124 if (has_checked_for_sufficient_resources_) | 124 if (has_checked_for_sufficient_resources_) |
| 125 rdh_->FinishedWithResourcesForRequest(request()); | 125 rdh_->FinishedWithResourcesForRequest(request()); |
| 126 } | 126 } |
| 127 | 127 |
| 128 bool MojoAsyncResourceHandler::OnRequestRedirected( | 128 void MojoAsyncResourceHandler::OnRequestRedirected( |
| 129 const net::RedirectInfo& redirect_info, | 129 const net::RedirectInfo& redirect_info, |
| 130 ResourceResponse* response, | 130 ResourceResponse* response, |
| 131 bool* defer) { | 131 std::unique_ptr<ResourceController> controller) { |
| 132 // Unlike OnResponseStarted, OnRequestRedirected will NOT be preceded by | 132 // Unlike OnResponseStarted, OnRequestRedirected will NOT be preceded by |
| 133 // OnWillRead. | 133 // OnWillRead. |
| 134 DCHECK(!has_controller()); |
| 134 DCHECK(!shared_writer_); | 135 DCHECK(!shared_writer_); |
| 135 | 136 |
| 136 *defer = true; | |
| 137 request()->LogBlockedBy("MojoAsyncResourceHandler"); | 137 request()->LogBlockedBy("MojoAsyncResourceHandler"); |
| 138 set_controller(std::move(controller)); |
| 138 did_defer_on_redirect_ = true; | 139 did_defer_on_redirect_ = true; |
| 139 | 140 |
| 140 NetLogObserver::PopulateResponseInfo(request(), response); | 141 NetLogObserver::PopulateResponseInfo(request(), response); |
| 141 response->head.encoded_data_length = request()->GetTotalReceivedBytes(); | 142 response->head.encoded_data_length = request()->GetTotalReceivedBytes(); |
| 142 response->head.request_start = request()->creation_time(); | 143 response->head.request_start = request()->creation_time(); |
| 143 response->head.response_start = base::TimeTicks::Now(); | 144 response->head.response_start = base::TimeTicks::Now(); |
| 144 // TODO(davidben): Is it necessary to pass the new first party URL for | 145 // TODO(davidben): Is it necessary to pass the new first party URL for |
| 145 // cookies? The only case where it can change is top-level navigation requests | 146 // cookies? The only case where it can change is top-level navigation requests |
| 146 // and hopefully those will eventually all be owned by the browser. It's | 147 // and hopefully those will eventually all be owned by the browser. It's |
| 147 // possible this is still needed while renderer-owned ones exist. | 148 // possible this is still needed while renderer-owned ones exist. |
| 148 url_loader_client_->OnReceiveRedirect(redirect_info, response->head); | 149 url_loader_client_->OnReceiveRedirect(redirect_info, response->head); |
| 149 return true; | |
| 150 } | 150 } |
| 151 | 151 |
| 152 bool MojoAsyncResourceHandler::OnResponseStarted(ResourceResponse* response, | 152 void MojoAsyncResourceHandler::OnResponseStarted( |
| 153 bool* defer) { | 153 ResourceResponse* response, |
| 154 std::unique_ptr<ResourceController> controller) { |
| 155 DCHECK(!has_controller()); |
| 156 |
| 154 const ResourceRequestInfoImpl* info = GetRequestInfo(); | 157 const ResourceRequestInfoImpl* info = GetRequestInfo(); |
| 155 | 158 |
| 156 if (rdh_->delegate()) { | 159 if (rdh_->delegate()) { |
| 157 rdh_->delegate()->OnResponseStarted(request(), info->GetContext(), | 160 rdh_->delegate()->OnResponseStarted(request(), info->GetContext(), |
| 158 response); | 161 response); |
| 159 } | 162 } |
| 160 | 163 |
| 161 NetLogObserver::PopulateResponseInfo(request(), response); | 164 NetLogObserver::PopulateResponseInfo(request(), response); |
| 162 | 165 |
| 163 response->head.request_start = request()->creation_time(); | 166 response->head.request_start = request()->creation_time(); |
| 164 response->head.response_start = base::TimeTicks::Now(); | 167 response->head.response_start = base::TimeTicks::Now(); |
| 165 sent_received_response_message_ = true; | 168 sent_received_response_message_ = true; |
| 166 url_loader_client_->OnReceiveResponse(response->head); | 169 url_loader_client_->OnReceiveResponse(response->head); |
| 167 return true; | 170 |
| 171 controller->Resume(); |
| 168 } | 172 } |
| 169 | 173 |
| 170 bool MojoAsyncResourceHandler::OnWillStart(const GURL& url, bool* defer) { | 174 void MojoAsyncResourceHandler::OnWillStart( |
| 171 return true; | 175 const GURL& url, |
| 176 std::unique_ptr<ResourceController> controller) { |
| 177 controller->Resume(); |
| 172 } | 178 } |
| 173 | 179 |
| 174 bool MojoAsyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, | 180 bool MojoAsyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, |
| 175 int* buf_size, | 181 int* buf_size, |
| 176 int min_size) { | 182 int min_size) { |
| 177 DCHECK_EQ(-1, min_size); | 183 DCHECK_EQ(-1, min_size); |
| 178 | 184 |
| 185 // TODO(mmenke): Cancel with net::ERR_INSUFFICIENT_RESOURCES instead. |
| 179 if (!CheckForSufficientResource()) | 186 if (!CheckForSufficientResource()) |
| 180 return false; | 187 return false; |
| 181 | 188 |
| 182 if (!shared_writer_) { | 189 if (!shared_writer_) { |
| 183 MojoCreateDataPipeOptions options; | 190 MojoCreateDataPipeOptions options; |
| 184 options.struct_size = sizeof(MojoCreateDataPipeOptions); | 191 options.struct_size = sizeof(MojoCreateDataPipeOptions); |
| 185 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; | 192 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; |
| 186 options.element_num_bytes = 1; | 193 options.element_num_bytes = 1; |
| 187 options.capacity_num_bytes = g_allocation_size; | 194 options.capacity_num_bytes = g_allocation_size; |
| 188 mojo::DataPipe data_pipe(options); | 195 mojo::DataPipe data_pipe(options); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 216 is_using_io_buffer_not_from_writer_ = true; | 223 is_using_io_buffer_not_from_writer_ = true; |
| 217 buffer_ = new net::IOBufferWithSize(kMinAllocationSize); | 224 buffer_ = new net::IOBufferWithSize(kMinAllocationSize); |
| 218 } | 225 } |
| 219 | 226 |
| 220 DCHECK_EQ(0u, buffer_offset_); | 227 DCHECK_EQ(0u, buffer_offset_); |
| 221 *buf = buffer_; | 228 *buf = buffer_; |
| 222 *buf_size = buffer_->size(); | 229 *buf_size = buffer_->size(); |
| 223 return true; | 230 return true; |
| 224 } | 231 } |
| 225 | 232 |
| 226 bool MojoAsyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { | 233 void MojoAsyncResourceHandler::OnReadCompleted( |
| 234 int bytes_read, |
| 235 std::unique_ptr<ResourceController> controller) { |
| 236 DCHECK(!has_controller()); |
| 227 DCHECK_GE(bytes_read, 0); | 237 DCHECK_GE(bytes_read, 0); |
| 228 DCHECK(buffer_); | 238 DCHECK(buffer_); |
| 229 | 239 |
| 230 if (!bytes_read) | 240 if (!bytes_read) { |
| 231 return true; | 241 controller->Resume(); |
| 242 return; |
| 243 } |
| 232 | 244 |
| 233 if (is_using_io_buffer_not_from_writer_) { | 245 if (is_using_io_buffer_not_from_writer_) { |
| 234 // Couldn't allocate a buffer on the data pipe in OnWillRead. | 246 // Couldn't allocate a buffer on the data pipe in OnWillRead. |
| 235 DCHECK_EQ(0u, buffer_bytes_read_); | 247 DCHECK_EQ(0u, buffer_bytes_read_); |
| 236 buffer_bytes_read_ = bytes_read; | 248 buffer_bytes_read_ = bytes_read; |
| 237 if (!CopyReadDataToDataPipe(defer)) | 249 bool defer = false; |
| 238 return false; | 250 if (!CopyReadDataToDataPipe(&defer)) { |
| 239 if (*defer) { | 251 controller->Cancel(); |
| 252 return; |
| 253 } |
| 254 if (defer) { |
| 240 request()->LogBlockedBy("MojoAsyncResourceHandler"); | 255 request()->LogBlockedBy("MojoAsyncResourceHandler"); |
| 241 did_defer_on_writing_ = true; | 256 did_defer_on_writing_ = true; |
| 257 set_controller(std::move(controller)); |
| 258 return; |
| 242 } | 259 } |
| 243 return true; | 260 controller->Resume(); |
| 261 return; |
| 244 } | 262 } |
| 245 | 263 |
| 246 if (EndWrite(bytes_read) != MOJO_RESULT_OK) | 264 if (EndWrite(bytes_read) != MOJO_RESULT_OK) { |
| 247 return false; | 265 controller->Cancel(); |
| 266 return; |
| 267 } |
| 248 // Allocate a buffer for the next OnWillRead call here, because OnWillRead | 268 // Allocate a buffer for the next OnWillRead call here, because OnWillRead |
| 249 // doesn't have |defer| parameter. | 269 // doesn't have |defer| parameter. |
| 250 if (!AllocateWriterIOBuffer(&buffer_, defer)) | 270 bool defer = false; |
| 251 return false; | 271 if (!AllocateWriterIOBuffer(&buffer_, &defer)) { |
| 252 if (*defer) { | 272 controller->Cancel(); |
| 273 return; |
| 274 } |
| 275 if (defer) { |
| 253 request()->LogBlockedBy("MojoAsyncResourceHandler"); | 276 request()->LogBlockedBy("MojoAsyncResourceHandler"); |
| 254 did_defer_on_writing_ = true; | 277 did_defer_on_writing_ = true; |
| 278 set_controller(std::move(controller)); |
| 279 return; |
| 255 } | 280 } |
| 256 return true; | 281 |
| 282 controller->Resume(); |
| 257 } | 283 } |
| 258 | 284 |
| 259 void MojoAsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) { | 285 void MojoAsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) { |
| 260 int64_t total_received_bytes = request()->GetTotalReceivedBytes(); | 286 int64_t total_received_bytes = request()->GetTotalReceivedBytes(); |
| 261 int64_t bytes_to_report = | 287 int64_t bytes_to_report = |
| 262 total_received_bytes - reported_total_received_bytes_; | 288 total_received_bytes - reported_total_received_bytes_; |
| 263 reported_total_received_bytes_ = total_received_bytes; | 289 reported_total_received_bytes_ = total_received_bytes; |
| 264 DCHECK_LE(0, bytes_to_report); | 290 DCHECK_LE(0, bytes_to_report); |
| 265 | 291 |
| 266 url_loader_client_->OnDataDownloaded(bytes_downloaded, bytes_to_report); | 292 url_loader_client_->OnDataDownloaded(bytes_downloaded, bytes_to_report); |
| 267 } | 293 } |
| 268 | 294 |
| 269 void MojoAsyncResourceHandler::FollowRedirect() { | 295 void MojoAsyncResourceHandler::FollowRedirect() { |
| 270 if (!request()->status().is_success()) { | 296 if (!request()->status().is_success()) { |
| 271 DVLOG(1) << "FollowRedirect for invalid request"; | 297 DVLOG(1) << "FollowRedirect for invalid request"; |
| 272 return; | 298 return; |
| 273 } | 299 } |
| 274 if (!did_defer_on_redirect_) { | 300 if (!did_defer_on_redirect_) { |
| 275 DVLOG(1) << "Malformed FollowRedirect request"; | 301 DVLOG(1) << "Malformed FollowRedirect request"; |
| 276 ReportBadMessage("Malformed FollowRedirect request"); | 302 ReportBadMessage("Malformed FollowRedirect request"); |
| 277 return; | 303 return; |
| 278 } | 304 } |
| 279 | 305 |
| 280 DCHECK(!did_defer_on_writing_); | 306 DCHECK(!did_defer_on_writing_); |
| 281 did_defer_on_redirect_ = false; | 307 did_defer_on_redirect_ = false; |
| 282 request()->LogUnblocked(); | 308 request()->LogUnblocked(); |
| 283 controller()->Resume(); | 309 Resume(); |
| 284 } | 310 } |
| 285 | 311 |
| 286 void MojoAsyncResourceHandler::OnWritableForTesting() { | 312 void MojoAsyncResourceHandler::OnWritableForTesting() { |
| 287 OnWritable(MOJO_RESULT_OK); | 313 OnWritable(MOJO_RESULT_OK); |
| 288 } | 314 } |
| 289 | 315 |
| 290 void MojoAsyncResourceHandler::SetAllocationSizeForTesting(size_t size) { | 316 void MojoAsyncResourceHandler::SetAllocationSizeForTesting(size_t size) { |
| 291 g_allocation_size = size; | 317 g_allocation_size = size; |
| 292 } | 318 } |
| 293 | 319 |
| 294 MojoResult MojoAsyncResourceHandler::BeginWrite(void** data, | 320 MojoResult MojoAsyncResourceHandler::BeginWrite(void** data, |
| 295 uint32_t* available) { | 321 uint32_t* available) { |
| 296 MojoResult result = mojo::BeginWriteDataRaw( | 322 MojoResult result = mojo::BeginWriteDataRaw( |
| 297 shared_writer_->writer(), data, available, MOJO_WRITE_DATA_FLAG_NONE); | 323 shared_writer_->writer(), data, available, MOJO_WRITE_DATA_FLAG_NONE); |
| 298 if (result == MOJO_RESULT_OK) | 324 if (result == MOJO_RESULT_OK) |
| 299 *available = std::min(*available, static_cast<uint32_t>(kMaxChunkSize)); | 325 *available = std::min(*available, static_cast<uint32_t>(kMaxChunkSize)); |
| 300 return result; | 326 return result; |
| 301 } | 327 } |
| 302 | 328 |
| 303 MojoResult MojoAsyncResourceHandler::EndWrite(uint32_t written) { | 329 MojoResult MojoAsyncResourceHandler::EndWrite(uint32_t written) { |
| 304 return mojo::EndWriteDataRaw(shared_writer_->writer(), written); | 330 return mojo::EndWriteDataRaw(shared_writer_->writer(), written); |
| 305 } | 331 } |
| 306 | 332 |
| 307 void MojoAsyncResourceHandler::OnResponseCompleted( | 333 void MojoAsyncResourceHandler::OnResponseCompleted( |
| 308 const net::URLRequestStatus& status, | 334 const net::URLRequestStatus& status, |
| 309 bool* defer) { | 335 std::unique_ptr<ResourceController> controller) { |
| 310 shared_writer_ = nullptr; | 336 shared_writer_ = nullptr; |
| 311 buffer_ = nullptr; | 337 buffer_ = nullptr; |
| 312 handle_watcher_.Cancel(); | 338 handle_watcher_.Cancel(); |
| 313 | 339 |
| 314 const ResourceRequestInfoImpl* info = GetRequestInfo(); | 340 const ResourceRequestInfoImpl* info = GetRequestInfo(); |
| 315 | 341 |
| 316 // TODO(gavinp): Remove this CHECK when we figure out the cause of | 342 // TODO(gavinp): Remove this CHECK when we figure out the cause of |
| 317 // http://crbug.com/124680 . This check mirrors closely check in | 343 // http://crbug.com/124680 . This check mirrors closely check in |
| 318 // WebURLLoaderImpl::OnCompletedRequest that routes this message to a WebCore | 344 // WebURLLoaderImpl::OnCompletedRequest that routes this message to a WebCore |
| 319 // ResourceHandleInternal which asserts on its state and crashes. By crashing | 345 // ResourceHandleInternal which asserts on its state and crashes. By crashing |
| (...skipping 12 matching lines...) Expand all Loading... |
| 332 | 358 |
| 333 ResourceRequestCompletionStatus request_complete_data; | 359 ResourceRequestCompletionStatus request_complete_data; |
| 334 request_complete_data.error_code = error_code; | 360 request_complete_data.error_code = error_code; |
| 335 request_complete_data.was_ignored_by_handler = was_ignored_by_handler; | 361 request_complete_data.was_ignored_by_handler = was_ignored_by_handler; |
| 336 request_complete_data.exists_in_cache = request()->response_info().was_cached; | 362 request_complete_data.exists_in_cache = request()->response_info().was_cached; |
| 337 request_complete_data.completion_time = base::TimeTicks::Now(); | 363 request_complete_data.completion_time = base::TimeTicks::Now(); |
| 338 request_complete_data.encoded_data_length = | 364 request_complete_data.encoded_data_length = |
| 339 request()->GetTotalReceivedBytes(); | 365 request()->GetTotalReceivedBytes(); |
| 340 | 366 |
| 341 url_loader_client_->OnComplete(request_complete_data); | 367 url_loader_client_->OnComplete(request_complete_data); |
| 368 controller->Resume(); |
| 342 } | 369 } |
| 343 | 370 |
| 344 bool MojoAsyncResourceHandler::CopyReadDataToDataPipe(bool* defer) { | 371 bool MojoAsyncResourceHandler::CopyReadDataToDataPipe(bool* defer) { |
| 345 while (true) { | 372 while (true) { |
| 346 scoped_refptr<net::IOBufferWithSize> dest; | 373 scoped_refptr<net::IOBufferWithSize> dest; |
| 347 if (!AllocateWriterIOBuffer(&dest, defer)) | 374 if (!AllocateWriterIOBuffer(&dest, defer)) |
| 348 return false; | 375 return false; |
| 349 if (*defer) | 376 if (*defer) |
| 350 return true; | 377 return true; |
| 351 if (buffer_bytes_read_ == 0) { | 378 if (buffer_bytes_read_ == 0) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 } | 414 } |
| 388 | 415 |
| 389 bool MojoAsyncResourceHandler::CheckForSufficientResource() { | 416 bool MojoAsyncResourceHandler::CheckForSufficientResource() { |
| 390 if (has_checked_for_sufficient_resources_) | 417 if (has_checked_for_sufficient_resources_) |
| 391 return true; | 418 return true; |
| 392 has_checked_for_sufficient_resources_ = true; | 419 has_checked_for_sufficient_resources_ = true; |
| 393 | 420 |
| 394 if (rdh_->HasSufficientResourcesForRequest(request())) | 421 if (rdh_->HasSufficientResourcesForRequest(request())) |
| 395 return true; | 422 return true; |
| 396 | 423 |
| 397 controller()->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES); | |
| 398 return false; | 424 return false; |
| 399 } | 425 } |
| 400 | 426 |
| 401 void MojoAsyncResourceHandler::OnWritable(MojoResult result) { | 427 void MojoAsyncResourceHandler::OnWritable(MojoResult result) { |
| 402 if (!did_defer_on_writing_) | 428 if (!did_defer_on_writing_) |
| 403 return; | 429 return; |
| 430 DCHECK(!has_controller()); |
| 404 DCHECK(!did_defer_on_redirect_); | 431 DCHECK(!did_defer_on_redirect_); |
| 405 did_defer_on_writing_ = false; | 432 did_defer_on_writing_ = false; |
| 406 | 433 |
| 407 if (is_using_io_buffer_not_from_writer_) { | 434 if (is_using_io_buffer_not_from_writer_) { |
| 408 // |buffer_| is set to a net::IOBufferWithSize. Write the buffer contents | 435 // |buffer_| is set to a net::IOBufferWithSize. Write the buffer contents |
| 409 // to the data pipe. | 436 // to the data pipe. |
| 410 DCHECK_GT(buffer_bytes_read_, 0u); | 437 DCHECK_GT(buffer_bytes_read_, 0u); |
| 411 if (!CopyReadDataToDataPipe(&did_defer_on_writing_)) { | 438 if (!CopyReadDataToDataPipe(&did_defer_on_writing_)) { |
| 412 controller()->CancelWithError(net::ERR_FAILED); | 439 CancelWithError(net::ERR_FAILED); |
| 413 return; | 440 return; |
| 414 } | 441 } |
| 415 } else { | 442 } else { |
| 416 // Allocate a buffer for the next OnWillRead call here. | 443 // Allocate a buffer for the next OnWillRead call here. |
| 417 if (!AllocateWriterIOBuffer(&buffer_, &did_defer_on_writing_)) { | 444 if (!AllocateWriterIOBuffer(&buffer_, &did_defer_on_writing_)) { |
| 418 controller()->CancelWithError(net::ERR_FAILED); | 445 CancelWithError(net::ERR_FAILED); |
| 419 return; | 446 return; |
| 420 } | 447 } |
| 421 } | 448 } |
| 422 | 449 |
| 423 if (did_defer_on_writing_) { | 450 if (did_defer_on_writing_) { |
| 424 // Continue waiting. | 451 // Continue waiting. |
| 425 return; | 452 return; |
| 426 } | 453 } |
| 427 request()->LogUnblocked(); | 454 request()->LogUnblocked(); |
| 428 controller()->Resume(); | 455 Resume(); |
| 429 } | 456 } |
| 430 | 457 |
| 431 void MojoAsyncResourceHandler::Cancel() { | 458 void MojoAsyncResourceHandler::Cancel() { |
| 432 const ResourceRequestInfoImpl* info = GetRequestInfo(); | 459 const ResourceRequestInfoImpl* info = GetRequestInfo(); |
| 433 ResourceDispatcherHostImpl::Get()->CancelRequestFromRenderer( | 460 ResourceDispatcherHostImpl::Get()->CancelRequestFromRenderer( |
| 434 GlobalRequestID(info->GetChildID(), info->GetRequestID())); | 461 GlobalRequestID(info->GetChildID(), info->GetRequestID())); |
| 435 } | 462 } |
| 436 | 463 |
| 437 void MojoAsyncResourceHandler::ReportBadMessage(const std::string& error) { | 464 void MojoAsyncResourceHandler::ReportBadMessage(const std::string& error) { |
| 438 mojo::ReportBadMessage(error); | 465 mojo::ReportBadMessage(error); |
| 439 } | 466 } |
| 440 | 467 |
| 441 } // namespace content | 468 } // namespace content |
| OLD | NEW |