| OLD | NEW | 
|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/async_resource_handler.h" | 5 #include "content/browser/loader/async_resource_handler.h" | 
| 6 | 6 | 
| 7 #include <algorithm> | 7 #include <algorithm> | 
| 8 #include <vector> | 8 #include <vector> | 
| 9 | 9 | 
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" | 
| 11 #include "base/containers/hash_tables.h" | 11 #include "base/containers/hash_tables.h" | 
| 12 #include "base/debug/alias.h" | 12 #include "base/debug/alias.h" | 
| 13 #include "base/feature_list.h" | 13 #include "base/feature_list.h" | 
| 14 #include "base/logging.h" | 14 #include "base/logging.h" | 
| 15 #include "base/macros.h" | 15 #include "base/macros.h" | 
| 16 #include "base/memory/shared_memory.h" | 16 #include "base/memory/shared_memory.h" | 
| 17 #include "base/metrics/histogram_macros.h" | 17 #include "base/metrics/histogram_macros.h" | 
| 18 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" | 
| 19 #include "base/time/time.h" | 19 #include "base/time/time.h" | 
| 20 #include "content/browser/loader/netlog_observer.h" | 20 #include "content/browser/loader/netlog_observer.h" | 
| 21 #include "content/browser/loader/resource_buffer.h" | 21 #include "content/browser/loader/resource_buffer.h" | 
| 22 #include "content/browser/loader/resource_dispatcher_host_impl.h" | 22 #include "content/browser/loader/resource_dispatcher_host_impl.h" | 
| 23 #include "content/browser/loader/resource_message_filter.h" | 23 #include "content/browser/loader/resource_message_filter.h" | 
| 24 #include "content/browser/loader/resource_request_info_impl.h" | 24 #include "content/browser/loader/resource_request_info_impl.h" | 
|  | 25 #include "content/browser/loader/upload_progress_tracker.h" | 
| 25 #include "content/common/resource_messages.h" | 26 #include "content/common/resource_messages.h" | 
| 26 #include "content/common/resource_request_completion_status.h" | 27 #include "content/common/resource_request_completion_status.h" | 
| 27 #include "content/common/view_messages.h" | 28 #include "content/common/view_messages.h" | 
| 28 #include "content/public/browser/resource_controller.h" | 29 #include "content/public/browser/resource_controller.h" | 
| 29 #include "content/public/browser/resource_dispatcher_host_delegate.h" | 30 #include "content/public/browser/resource_dispatcher_host_delegate.h" | 
| 30 #include "content/public/common/content_features.h" | 31 #include "content/public/common/content_features.h" | 
| 31 #include "content/public/common/resource_response.h" | 32 #include "content/public/common/resource_response.h" | 
| 32 #include "ipc/ipc_message_macros.h" | 33 #include "ipc/ipc_message_macros.h" | 
| 33 #include "net/base/io_buffer.h" | 34 #include "net/base/io_buffer.h" | 
| 34 #include "net/base/load_flags.h" | 35 #include "net/base/load_flags.h" | 
| 35 #include "net/url_request/redirect_info.h" | 36 #include "net/url_request/redirect_info.h" | 
| 36 | 37 | 
| 37 using base::TimeDelta; | 38 using base::TimeDelta; | 
| 38 using base::TimeTicks; | 39 using base::TimeTicks; | 
| 39 | 40 | 
| 40 namespace content { | 41 namespace content { | 
| 41 namespace { | 42 namespace { | 
| 42 | 43 | 
| 43 static int kBufferSize = 1024 * 512; | 44 static int kBufferSize = 1024 * 512; | 
| 44 static int kMinAllocationSize = 1024 * 4; | 45 static int kMinAllocationSize = 1024 * 4; | 
| 45 static int kMaxAllocationSize = 1024 * 32; | 46 static int kMaxAllocationSize = 1024 * 32; | 
| 46 // The interval for calls to ReportUploadProgress. |  | 
| 47 static int kUploadProgressIntervalMsec = 100; |  | 
| 48 | 47 | 
| 49 // Used when kOptimizeLoadingIPCForSmallResources is enabled. | 48 // Used when kOptimizeLoadingIPCForSmallResources is enabled. | 
| 50 // Small resource typically issues two Read call: one for the content itself | 49 // Small resource typically issues two Read call: one for the content itself | 
| 51 // and another for getting zero response to detect EOF. | 50 // and another for getting zero response to detect EOF. | 
| 52 // Inline these two into the IPC message to avoid allocating an expensive | 51 // Inline these two into the IPC message to avoid allocating an expensive | 
| 53 // SharedMemory for small resources. | 52 // SharedMemory for small resources. | 
| 54 const int kNumLeadingChunk = 2; | 53 const int kNumLeadingChunk = 2; | 
| 55 const int kInlinedLeadingChunkSize = 2048; | 54 const int kInlinedLeadingChunkSize = 2048; | 
| 56 | 55 | 
| 57 void GetNumericArg(const std::string& name, int* result) { | 56 void GetNumericArg(const std::string& name, int* result) { | 
| 58   const std::string& value = | 57   const std::string& value = | 
| 59       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(name); | 58       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(name); | 
| 60   if (!value.empty()) | 59   if (!value.empty()) | 
| 61     base::StringToInt(value, result); | 60     base::StringToInt(value, result); | 
| 62 } | 61 } | 
| 63 | 62 | 
| 64 void InitializeResourceBufferConstants() { | 63 void InitializeResourceBufferConstants() { | 
| 65   static bool did_init = false; | 64   static bool did_init = false; | 
| 66   if (did_init) | 65   if (did_init) | 
| 67     return; | 66     return; | 
| 68   did_init = true; | 67   did_init = true; | 
| 69 | 68 | 
| 70   GetNumericArg("resource-buffer-size", &kBufferSize); | 69   GetNumericArg("resource-buffer-size", &kBufferSize); | 
| 71   GetNumericArg("resource-buffer-min-allocation-size", &kMinAllocationSize); | 70   GetNumericArg("resource-buffer-min-allocation-size", &kMinAllocationSize); | 
| 72   GetNumericArg("resource-buffer-max-allocation-size", &kMaxAllocationSize); | 71   GetNumericArg("resource-buffer-max-allocation-size", &kMaxAllocationSize); | 
| 73 } | 72 } | 
| 74 | 73 | 
|  | 74 void SendUploadProgress(base::WeakPtr<ResourceMessageFilter> filter, | 
|  | 75                         int request_id, | 
|  | 76                         int64_t current_position, | 
|  | 77                         int64_t total_size) { | 
|  | 78   if (filter) { | 
|  | 79     filter->Send(new ResourceMsg_UploadProgress(request_id, current_position, | 
|  | 80                                                 total_size)); | 
|  | 81   } | 
|  | 82 } | 
|  | 83 | 
| 75 }  // namespace | 84 }  // namespace | 
| 76 | 85 | 
| 77 // Used when kOptimizeLoadingIPCForSmallResources is enabled. | 86 // Used when kOptimizeLoadingIPCForSmallResources is enabled. | 
| 78 // The instance hooks the buffer allocation of AsyncResourceHandler, and | 87 // The instance hooks the buffer allocation of AsyncResourceHandler, and | 
| 79 // determine if we should use SharedMemory or should inline the data into | 88 // determine if we should use SharedMemory or should inline the data into | 
| 80 // the IPC message. | 89 // the IPC message. | 
| 81 class AsyncResourceHandler::InliningHelper { | 90 class AsyncResourceHandler::InliningHelper { | 
| 82  public: | 91  public: | 
| 83 | 92 | 
| 84   InliningHelper() {} | 93   InliningHelper() {} | 
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 197     : ResourceHandler(request), | 206     : ResourceHandler(request), | 
| 198       ResourceMessageDelegate(request), | 207       ResourceMessageDelegate(request), | 
| 199       rdh_(rdh), | 208       rdh_(rdh), | 
| 200       pending_data_count_(0), | 209       pending_data_count_(0), | 
| 201       allocation_size_(0), | 210       allocation_size_(0), | 
| 202       did_defer_(false), | 211       did_defer_(false), | 
| 203       has_checked_for_sufficient_resources_(false), | 212       has_checked_for_sufficient_resources_(false), | 
| 204       sent_received_response_msg_(false), | 213       sent_received_response_msg_(false), | 
| 205       sent_data_buffer_msg_(false), | 214       sent_data_buffer_msg_(false), | 
| 206       inlining_helper_(new InliningHelper), | 215       inlining_helper_(new InliningHelper), | 
| 207       last_upload_position_(0), |  | 
| 208       waiting_for_upload_progress_ack_(false), |  | 
| 209       reported_transfer_size_(0) { | 216       reported_transfer_size_(0) { | 
| 210   DCHECK(GetRequestInfo()->requester_info()->IsRenderer()); | 217   DCHECK(GetRequestInfo()->requester_info()->IsRenderer()); | 
| 211   InitializeResourceBufferConstants(); | 218   InitializeResourceBufferConstants(); | 
| 212 } | 219 } | 
| 213 | 220 | 
| 214 AsyncResourceHandler::~AsyncResourceHandler() { | 221 AsyncResourceHandler::~AsyncResourceHandler() { | 
| 215   if (has_checked_for_sufficient_resources_) | 222   if (has_checked_for_sufficient_resources_) | 
| 216     rdh_->FinishedWithResourcesForRequest(request()); | 223     rdh_->FinishedWithResourcesForRequest(request()); | 
| 217 } | 224 } | 
| 218 | 225 | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 240   if (pending_data_count_) { | 247   if (pending_data_count_) { | 
| 241     --pending_data_count_; | 248     --pending_data_count_; | 
| 242 | 249 | 
| 243     buffer_->RecycleLeastRecentlyAllocated(); | 250     buffer_->RecycleLeastRecentlyAllocated(); | 
| 244     if (buffer_->CanAllocate()) | 251     if (buffer_->CanAllocate()) | 
| 245       ResumeIfDeferred(); | 252       ResumeIfDeferred(); | 
| 246   } | 253   } | 
| 247 } | 254 } | 
| 248 | 255 | 
| 249 void AsyncResourceHandler::OnUploadProgressACK(int request_id) { | 256 void AsyncResourceHandler::OnUploadProgressACK(int request_id) { | 
| 250   waiting_for_upload_progress_ack_ = false; | 257   if (upload_progress_tracker_) | 
| 251 } | 258     upload_progress_tracker_->OnAckReceived(); | 
| 252 |  | 
| 253 void AsyncResourceHandler::ReportUploadProgress() { |  | 
| 254   DCHECK(GetRequestInfo()->is_upload_progress_enabled()); |  | 
| 255   if (waiting_for_upload_progress_ack_) |  | 
| 256     return;  // Send one progress event at a time. |  | 
| 257 |  | 
| 258   net::UploadProgress progress = request()->GetUploadProgress(); |  | 
| 259   if (!progress.size()) |  | 
| 260     return;  // Nothing to upload. |  | 
| 261 |  | 
| 262   if (progress.position() == last_upload_position_) |  | 
| 263     return;  // No progress made since last time. |  | 
| 264 |  | 
| 265   const uint64_t kHalfPercentIncrements = 200; |  | 
| 266   const TimeDelta kOneSecond = TimeDelta::FromMilliseconds(1000); |  | 
| 267 |  | 
| 268   uint64_t amt_since_last = progress.position() - last_upload_position_; |  | 
| 269   TimeDelta time_since_last = TimeTicks::Now() - last_upload_ticks_; |  | 
| 270 |  | 
| 271   bool is_finished = (progress.size() == progress.position()); |  | 
| 272   bool enough_new_progress = |  | 
| 273       (amt_since_last > (progress.size() / kHalfPercentIncrements)); |  | 
| 274   bool too_much_time_passed = time_since_last > kOneSecond; |  | 
| 275 |  | 
| 276   if (is_finished || enough_new_progress || too_much_time_passed) { |  | 
| 277     ResourceMessageFilter* filter = GetFilter(); |  | 
| 278     if (filter) { |  | 
| 279       filter->Send( |  | 
| 280         new ResourceMsg_UploadProgress(GetRequestID(), |  | 
| 281                                        progress.position(), |  | 
| 282                                        progress.size())); |  | 
| 283     } |  | 
| 284     waiting_for_upload_progress_ack_ = true; |  | 
| 285     last_upload_ticks_ = TimeTicks::Now(); |  | 
| 286     last_upload_position_ = progress.position(); |  | 
| 287   } |  | 
| 288 } | 259 } | 
| 289 | 260 | 
| 290 bool AsyncResourceHandler::OnRequestRedirected( | 261 bool AsyncResourceHandler::OnRequestRedirected( | 
| 291     const net::RedirectInfo& redirect_info, | 262     const net::RedirectInfo& redirect_info, | 
| 292     ResourceResponse* response, | 263     ResourceResponse* response, | 
| 293     bool* defer) { | 264     bool* defer) { | 
| 294   ResourceMessageFilter* filter = GetFilter(); | 265   ResourceMessageFilter* filter = GetFilter(); | 
| 295   if (!filter) | 266   if (!filter) | 
| 296     return false; | 267     return false; | 
| 297 | 268 | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 314 bool AsyncResourceHandler::OnResponseStarted(ResourceResponse* response, | 285 bool AsyncResourceHandler::OnResponseStarted(ResourceResponse* response, | 
| 315                                              bool* defer) { | 286                                              bool* defer) { | 
| 316   // For changes to the main frame, inform the renderer of the new URL's | 287   // For changes to the main frame, inform the renderer of the new URL's | 
| 317   // per-host settings before the request actually commits.  This way the | 288   // per-host settings before the request actually commits.  This way the | 
| 318   // renderer will be able to set these precisely at the time the | 289   // renderer will be able to set these precisely at the time the | 
| 319   // request commits, avoiding the possibility of e.g. zooming the old content | 290   // request commits, avoiding the possibility of e.g. zooming the old content | 
| 320   // or of having to layout the new content twice. | 291   // or of having to layout the new content twice. | 
| 321 | 292 | 
| 322   response_started_ticks_ = base::TimeTicks::Now(); | 293   response_started_ticks_ = base::TimeTicks::Now(); | 
| 323 | 294 | 
| 324   progress_timer_.Stop(); |  | 
| 325   ResourceMessageFilter* filter = GetFilter(); |  | 
| 326   if (!filter) |  | 
| 327     return false; |  | 
| 328 |  | 
| 329   const ResourceRequestInfoImpl* info = GetRequestInfo(); |  | 
| 330   // We want to send a final upload progress message prior to sending the | 295   // We want to send a final upload progress message prior to sending the | 
| 331   // response complete message even if we're waiting for an ack to to a | 296   // response complete message even if we're waiting for an ack to to a | 
| 332   // previous upload progress message. | 297   // previous upload progress message. | 
| 333   if (info->is_upload_progress_enabled()) { | 298   if (upload_progress_tracker_) { | 
| 334     waiting_for_upload_progress_ack_ = false; | 299     upload_progress_tracker_->OnUploadCompleted(); | 
| 335     ReportUploadProgress(); | 300     upload_progress_tracker_ = nullptr; | 
| 336   } | 301   } | 
| 337 | 302 | 
|  | 303   const ResourceRequestInfoImpl* info = GetRequestInfo(); | 
| 338   if (rdh_->delegate()) { | 304   if (rdh_->delegate()) { | 
| 339     rdh_->delegate()->OnResponseStarted(request(), info->GetContext(), | 305     rdh_->delegate()->OnResponseStarted(request(), info->GetContext(), | 
| 340                                         response); | 306                                         response); | 
| 341   } | 307   } | 
| 342 | 308 | 
|  | 309   ResourceMessageFilter* filter = GetFilter(); | 
|  | 310   if (!filter) | 
|  | 311     return false; | 
|  | 312 | 
| 343   NetLogObserver::PopulateResponseInfo(request(), response); | 313   NetLogObserver::PopulateResponseInfo(request(), response); | 
| 344   response->head.encoded_data_length = request()->raw_header_size(); | 314   response->head.encoded_data_length = request()->raw_header_size(); | 
| 345 | 315 | 
| 346   // If the parent handler downloaded the resource to a file, grant the child | 316   // If the parent handler downloaded the resource to a file, grant the child | 
| 347   // read permissions on it. | 317   // read permissions on it. | 
| 348   if (!response->head.download_file_path.empty()) { | 318   if (!response->head.download_file_path.empty()) { | 
| 349     rdh_->RegisterDownloadedTempFile( | 319     rdh_->RegisterDownloadedTempFile( | 
| 350         info->GetChildID(), info->GetRequestID(), | 320         info->GetChildID(), info->GetRequestID(), | 
| 351         response->head.download_file_path); | 321         response->head.download_file_path); | 
| 352   } | 322   } | 
| 353 | 323 | 
| 354   response->head.request_start = request()->creation_time(); | 324   response->head.request_start = request()->creation_time(); | 
| 355   response->head.response_start = TimeTicks::Now(); | 325   response->head.response_start = TimeTicks::Now(); | 
| 356   filter->Send( | 326   filter->Send( | 
| 357       new ResourceMsg_ReceivedResponse(GetRequestID(), response->head)); | 327       new ResourceMsg_ReceivedResponse(GetRequestID(), response->head)); | 
| 358   sent_received_response_msg_ = true; | 328   sent_received_response_msg_ = true; | 
| 359 | 329 | 
| 360   if (request()->response_info().metadata.get()) { | 330   if (request()->response_info().metadata.get()) { | 
| 361     std::vector<char> copy(request()->response_info().metadata->data(), | 331     std::vector<char> copy(request()->response_info().metadata->data(), | 
| 362                            request()->response_info().metadata->data() + | 332                            request()->response_info().metadata->data() + | 
| 363                                request()->response_info().metadata->size()); | 333                                request()->response_info().metadata->size()); | 
| 364     filter->Send(new ResourceMsg_ReceivedCachedMetadata(GetRequestID(), copy)); | 334     filter->Send(new ResourceMsg_ReceivedCachedMetadata(GetRequestID(), copy)); | 
| 365   } | 335   } | 
| 366 | 336 | 
| 367   inlining_helper_->OnResponseReceived(*response); | 337   inlining_helper_->OnResponseReceived(*response); | 
| 368   return true; | 338   return true; | 
| 369 } | 339 } | 
| 370 | 340 | 
| 371 bool AsyncResourceHandler::OnWillStart(const GURL& url, bool* defer) { | 341 bool AsyncResourceHandler::OnWillStart(const GURL& url, bool* defer) { | 
|  | 342   ResourceMessageFilter* filter = GetFilter(); | 
|  | 343   if (!filter) | 
|  | 344     return false; | 
|  | 345 | 
| 372   if (GetRequestInfo()->is_upload_progress_enabled() && | 346   if (GetRequestInfo()->is_upload_progress_enabled() && | 
| 373       request()->has_upload()) { | 347       request()->has_upload()) { | 
| 374     ReportUploadProgress(); | 348     upload_progress_tracker_ = base::MakeUnique<UploadProgressTracker>( | 
| 375     progress_timer_.Start( | 349         base::BindRepeating(&SendUploadProgress, filter->GetWeakPtr(), | 
| 376         FROM_HERE, | 350                             GetRequestID()), | 
| 377         base::TimeDelta::FromMilliseconds(kUploadProgressIntervalMsec), | 351         request()); | 
| 378         this, | 352     upload_progress_tracker_->Start(FROM_HERE); | 
| 379         &AsyncResourceHandler::ReportUploadProgress); |  | 
| 380   } | 353   } | 
| 381   return true; | 354   return true; | 
| 382 } | 355 } | 
| 383 | 356 | 
| 384 bool AsyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, | 357 bool AsyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, | 
| 385                                       int* buf_size, | 358                                       int* buf_size, | 
| 386                                       int min_size) { | 359                                       int min_size) { | 
| 387   DCHECK_EQ(-1, min_size); | 360   DCHECK_EQ(-1, min_size); | 
| 388 | 361 | 
| 389   if (!CheckForSufficientResource()) | 362   if (!CheckForSufficientResource()) | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
| 402   CHECK(memory); | 375   CHECK(memory); | 
| 403 | 376 | 
| 404   *buf = new DependentIOBuffer(buffer_.get(), memory); | 377   *buf = new DependentIOBuffer(buffer_.get(), memory); | 
| 405   *buf_size = allocation_size_; | 378   *buf_size = allocation_size_; | 
| 406 | 379 | 
| 407   return true; | 380   return true; | 
| 408 } | 381 } | 
| 409 | 382 | 
| 410 bool AsyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { | 383 bool AsyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { | 
| 411   DCHECK_GE(bytes_read, 0); | 384   DCHECK_GE(bytes_read, 0); | 
|  | 385   DCHECK(!upload_progress_tracker_); | 
| 412 | 386 | 
| 413   if (!bytes_read) | 387   if (!bytes_read) | 
| 414     return true; | 388     return true; | 
| 415 | 389 | 
| 416   ResourceMessageFilter* filter = GetFilter(); | 390   ResourceMessageFilter* filter = GetFilter(); | 
| 417   if (!filter) | 391   if (!filter) | 
| 418     return false; | 392     return false; | 
| 419 | 393 | 
| 420   int encoded_data_length = CalculateEncodedDataLengthToReport(); | 394   int encoded_data_length = CalculateEncodedDataLengthToReport(); | 
| 421   if (!first_chunk_read_) | 395   if (!first_chunk_read_) | 
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 575   } else { | 549   } else { | 
| 576     UMA_HISTOGRAM_CUSTOM_COUNTS( | 550     UMA_HISTOGRAM_CUSTOM_COUNTS( | 
| 577         "Net.ResourceLoader.ResponseStartToEnd.Over_512kB", | 551         "Net.ResourceLoader.ResponseStartToEnd.Over_512kB", | 
| 578         elapsed_time, 1, 100000, 100); | 552         elapsed_time, 1, 100000, 100); | 
| 579   } | 553   } | 
| 580 | 554 | 
| 581   inlining_helper_->RecordHistogram(elapsed_time); | 555   inlining_helper_->RecordHistogram(elapsed_time); | 
| 582 } | 556 } | 
| 583 | 557 | 
| 584 }  // namespace content | 558 }  // namespace content | 
| OLD | NEW | 
|---|