Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(162)

Side by Side Diff: content/browser/loader/async_resource_handler.cc

Issue 2546653003: Factor out upload progress handling from AsyncResourceHandler (Closed)
Patch Set: . Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/ptr_util.h"
16 #include "base/memory/shared_memory.h" 17 #include "base/memory/shared_memory.h"
17 #include "base/metrics/histogram_macros.h" 18 #include "base/metrics/histogram_macros.h"
18 #include "base/strings/string_number_conversions.h" 19 #include "base/strings/string_number_conversions.h"
19 #include "base/time/time.h" 20 #include "base/time/time.h"
20 #include "content/browser/loader/netlog_observer.h" 21 #include "content/browser/loader/netlog_observer.h"
21 #include "content/browser/loader/resource_buffer.h" 22 #include "content/browser/loader/resource_buffer.h"
22 #include "content/browser/loader/resource_controller.h" 23 #include "content/browser/loader/resource_controller.h"
23 #include "content/browser/loader/resource_dispatcher_host_impl.h" 24 #include "content/browser/loader/resource_dispatcher_host_impl.h"
24 #include "content/browser/loader/resource_message_filter.h" 25 #include "content/browser/loader/resource_message_filter.h"
25 #include "content/browser/loader/resource_request_info_impl.h" 26 #include "content/browser/loader/resource_request_info_impl.h"
27 #include "content/browser/loader/upload_progress_tracker.h"
26 #include "content/common/resource_messages.h" 28 #include "content/common/resource_messages.h"
27 #include "content/common/resource_request_completion_status.h" 29 #include "content/common/resource_request_completion_status.h"
28 #include "content/common/view_messages.h" 30 #include "content/common/view_messages.h"
29 #include "content/public/browser/resource_dispatcher_host_delegate.h" 31 #include "content/public/browser/resource_dispatcher_host_delegate.h"
30 #include "content/public/common/content_features.h" 32 #include "content/public/common/content_features.h"
31 #include "content/public/common/resource_response.h" 33 #include "content/public/common/resource_response.h"
32 #include "ipc/ipc_message_macros.h" 34 #include "ipc/ipc_message_macros.h"
33 #include "net/base/io_buffer.h" 35 #include "net/base/io_buffer.h"
34 #include "net/base/load_flags.h" 36 #include "net/base/load_flags.h"
35 #include "net/url_request/redirect_info.h" 37 #include "net/url_request/redirect_info.h"
36 38
37 using base::TimeDelta; 39 using base::TimeDelta;
38 using base::TimeTicks; 40 using base::TimeTicks;
39 41
40 namespace content { 42 namespace content {
41 namespace { 43 namespace {
42 44
43 static int kBufferSize = 1024 * 512; 45 static int kBufferSize = 1024 * 512;
44 static int kMinAllocationSize = 1024 * 4; 46 static int kMinAllocationSize = 1024 * 4;
45 static int kMaxAllocationSize = 1024 * 32; 47 static int kMaxAllocationSize = 1024 * 32;
46 // The interval for calls to ReportUploadProgress.
47 static int kUploadProgressIntervalMsec = 100;
48 48
49 // Used when kOptimizeLoadingIPCForSmallResources is enabled. 49 // Used when kOptimizeLoadingIPCForSmallResources is enabled.
50 // Small resource typically issues two Read call: one for the content itself 50 // Small resource typically issues two Read call: one for the content itself
51 // and another for getting zero response to detect EOF. 51 // and another for getting zero response to detect EOF.
52 // Inline these two into the IPC message to avoid allocating an expensive 52 // Inline these two into the IPC message to avoid allocating an expensive
53 // SharedMemory for small resources. 53 // SharedMemory for small resources.
54 const int kNumLeadingChunk = 2; 54 const int kNumLeadingChunk = 2;
55 const int kInlinedLeadingChunkSize = 2048; 55 const int kInlinedLeadingChunkSize = 2048;
56 56
57 void GetNumericArg(const std::string& name, int* result) { 57 void GetNumericArg(const std::string& name, int* result) {
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 : ResourceHandler(request), 197 : ResourceHandler(request),
198 ResourceMessageDelegate(request), 198 ResourceMessageDelegate(request),
199 rdh_(rdh), 199 rdh_(rdh),
200 pending_data_count_(0), 200 pending_data_count_(0),
201 allocation_size_(0), 201 allocation_size_(0),
202 did_defer_(false), 202 did_defer_(false),
203 has_checked_for_sufficient_resources_(false), 203 has_checked_for_sufficient_resources_(false),
204 sent_received_response_msg_(false), 204 sent_received_response_msg_(false),
205 sent_data_buffer_msg_(false), 205 sent_data_buffer_msg_(false),
206 inlining_helper_(new InliningHelper), 206 inlining_helper_(new InliningHelper),
207 last_upload_position_(0),
208 waiting_for_upload_progress_ack_(false),
209 reported_transfer_size_(0) { 207 reported_transfer_size_(0) {
210 DCHECK(GetRequestInfo()->requester_info()->IsRenderer()); 208 DCHECK(GetRequestInfo()->requester_info()->IsRenderer());
211 InitializeResourceBufferConstants(); 209 InitializeResourceBufferConstants();
212 } 210 }
213 211
214 AsyncResourceHandler::~AsyncResourceHandler() { 212 AsyncResourceHandler::~AsyncResourceHandler() {
215 if (has_checked_for_sufficient_resources_) 213 if (has_checked_for_sufficient_resources_)
216 rdh_->FinishedWithResourcesForRequest(request()); 214 rdh_->FinishedWithResourcesForRequest(request());
217 } 215 }
218 216
(...skipping 21 matching lines...) Expand all
240 if (pending_data_count_) { 238 if (pending_data_count_) {
241 --pending_data_count_; 239 --pending_data_count_;
242 240
243 buffer_->RecycleLeastRecentlyAllocated(); 241 buffer_->RecycleLeastRecentlyAllocated();
244 if (buffer_->CanAllocate()) 242 if (buffer_->CanAllocate())
245 ResumeIfDeferred(); 243 ResumeIfDeferred();
246 } 244 }
247 } 245 }
248 246
249 void AsyncResourceHandler::OnUploadProgressACK(int request_id) { 247 void AsyncResourceHandler::OnUploadProgressACK(int request_id) {
250 waiting_for_upload_progress_ack_ = false; 248 if (upload_progress_tracker_)
251 } 249 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 } 250 }
289 251
290 bool AsyncResourceHandler::OnRequestRedirected( 252 bool AsyncResourceHandler::OnRequestRedirected(
291 const net::RedirectInfo& redirect_info, 253 const net::RedirectInfo& redirect_info,
292 ResourceResponse* response, 254 ResourceResponse* response,
293 bool* defer) { 255 bool* defer) {
294 ResourceMessageFilter* filter = GetFilter(); 256 ResourceMessageFilter* filter = GetFilter();
295 if (!filter) 257 if (!filter)
296 return false; 258 return false;
297 259
(...skipping 16 matching lines...) Expand all
314 bool AsyncResourceHandler::OnResponseStarted(ResourceResponse* response, 276 bool AsyncResourceHandler::OnResponseStarted(ResourceResponse* response,
315 bool* defer) { 277 bool* defer) {
316 // For changes to the main frame, inform the renderer of the new URL's 278 // 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 279 // per-host settings before the request actually commits. This way the
318 // renderer will be able to set these precisely at the time the 280 // 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 281 // request commits, avoiding the possibility of e.g. zooming the old content
320 // or of having to layout the new content twice. 282 // or of having to layout the new content twice.
321 283
322 response_started_ticks_ = base::TimeTicks::Now(); 284 response_started_ticks_ = base::TimeTicks::Now();
323 285
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 286 // 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 287 // response complete message even if we're waiting for an ack to to a
332 // previous upload progress message. 288 // previous upload progress message.
333 if (info->is_upload_progress_enabled()) { 289 if (upload_progress_tracker_) {
334 waiting_for_upload_progress_ack_ = false; 290 upload_progress_tracker_->OnUploadCompleted();
335 ReportUploadProgress(); 291 upload_progress_tracker_ = nullptr;
336 } 292 }
337 293
294 const ResourceRequestInfoImpl* info = GetRequestInfo();
338 if (rdh_->delegate()) { 295 if (rdh_->delegate()) {
339 rdh_->delegate()->OnResponseStarted(request(), info->GetContext(), 296 rdh_->delegate()->OnResponseStarted(request(), info->GetContext(),
340 response); 297 response);
341 } 298 }
342 299
300 ResourceMessageFilter* filter = GetFilter();
301 if (!filter)
302 return false;
303
343 NetLogObserver::PopulateResponseInfo(request(), response); 304 NetLogObserver::PopulateResponseInfo(request(), response);
344 response->head.encoded_data_length = request()->raw_header_size(); 305 response->head.encoded_data_length = request()->raw_header_size();
345 306
346 // If the parent handler downloaded the resource to a file, grant the child 307 // If the parent handler downloaded the resource to a file, grant the child
347 // read permissions on it. 308 // read permissions on it.
348 if (!response->head.download_file_path.empty()) { 309 if (!response->head.download_file_path.empty()) {
349 rdh_->RegisterDownloadedTempFile( 310 rdh_->RegisterDownloadedTempFile(
350 info->GetChildID(), info->GetRequestID(), 311 info->GetChildID(), info->GetRequestID(),
351 response->head.download_file_path); 312 response->head.download_file_path);
352 } 313 }
353 314
354 response->head.request_start = request()->creation_time(); 315 response->head.request_start = request()->creation_time();
355 response->head.response_start = TimeTicks::Now(); 316 response->head.response_start = TimeTicks::Now();
356 filter->Send( 317 filter->Send(
357 new ResourceMsg_ReceivedResponse(GetRequestID(), response->head)); 318 new ResourceMsg_ReceivedResponse(GetRequestID(), response->head));
358 sent_received_response_msg_ = true; 319 sent_received_response_msg_ = true;
359 320
360 if (request()->response_info().metadata.get()) { 321 if (request()->response_info().metadata.get()) {
361 std::vector<char> copy(request()->response_info().metadata->data(), 322 std::vector<char> copy(request()->response_info().metadata->data(),
362 request()->response_info().metadata->data() + 323 request()->response_info().metadata->data() +
363 request()->response_info().metadata->size()); 324 request()->response_info().metadata->size());
364 filter->Send(new ResourceMsg_ReceivedCachedMetadata(GetRequestID(), copy)); 325 filter->Send(new ResourceMsg_ReceivedCachedMetadata(GetRequestID(), copy));
365 } 326 }
366 327
367 inlining_helper_->OnResponseReceived(*response); 328 inlining_helper_->OnResponseReceived(*response);
368 return true; 329 return true;
369 } 330 }
370 331
371 bool AsyncResourceHandler::OnWillStart(const GURL& url, bool* defer) { 332 bool AsyncResourceHandler::OnWillStart(const GURL& url, bool* defer) {
333 ResourceMessageFilter* filter = GetFilter();
334 if (!filter)
335 return false;
336
372 if (GetRequestInfo()->is_upload_progress_enabled() && 337 if (GetRequestInfo()->is_upload_progress_enabled() &&
373 request()->has_upload()) { 338 request()->has_upload()) {
374 ReportUploadProgress(); 339 upload_progress_tracker_ = base::MakeUnique<UploadProgressTracker>(
375 progress_timer_.Start(
376 FROM_HERE, 340 FROM_HERE,
377 base::TimeDelta::FromMilliseconds(kUploadProgressIntervalMsec), 341 base::BindRepeating(&AsyncResourceHandler::SendUploadProgress,
378 this, 342 base::Unretained(this)),
379 &AsyncResourceHandler::ReportUploadProgress); 343 request());
380 } 344 }
381 return true; 345 return true;
382 } 346 }
383 347
384 bool AsyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, 348 bool AsyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
385 int* buf_size, 349 int* buf_size,
386 int min_size) { 350 int min_size) {
387 DCHECK_EQ(-1, min_size); 351 DCHECK_EQ(-1, min_size);
388 352
389 if (!CheckForSufficientResource()) 353 if (!CheckForSufficientResource())
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 } 430 }
467 } 431 }
468 432
469 void AsyncResourceHandler::OnResponseCompleted( 433 void AsyncResourceHandler::OnResponseCompleted(
470 const net::URLRequestStatus& status, 434 const net::URLRequestStatus& status,
471 bool* defer) { 435 bool* defer) {
472 ResourceMessageFilter* filter = GetFilter(); 436 ResourceMessageFilter* filter = GetFilter();
473 if (!filter) 437 if (!filter)
474 return; 438 return;
475 439
440 // Ensure sending the final upload progress message here, since
441 // OnResponseCompleted can be called without OnResponseStarted on cancellation
442 // or error cases.
443 if (upload_progress_tracker_) {
444 upload_progress_tracker_->OnUploadCompleted();
445 upload_progress_tracker_ = nullptr;
446 }
447
476 // If we crash here, figure out what URL the renderer was requesting. 448 // If we crash here, figure out what URL the renderer was requesting.
477 // http://crbug.com/107692 449 // http://crbug.com/107692
478 char url_buf[128]; 450 char url_buf[128];
479 base::strlcpy(url_buf, request()->url().spec().c_str(), arraysize(url_buf)); 451 base::strlcpy(url_buf, request()->url().spec().c_str(), arraysize(url_buf));
480 base::debug::Alias(url_buf); 452 base::debug::Alias(url_buf);
481 453
482 // TODO(gavinp): Remove this CHECK when we figure out the cause of 454 // TODO(gavinp): Remove this CHECK when we figure out the cause of
483 // http://crbug.com/124680 . This check mirrors closely check in 455 // http://crbug.com/124680 . This check mirrors closely check in
484 // WebURLLoaderImpl::OnCompletedRequest that routes this message to a WebCore 456 // WebURLLoaderImpl::OnCompletedRequest that routes this message to a WebCore
485 // ResourceHandleInternal which asserts on its state and crashes. By crashing 457 // ResourceHandleInternal which asserts on its state and crashes. By crashing
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 elapsed_time, 1, 100000, 100); 546 elapsed_time, 1, 100000, 100);
575 } else { 547 } else {
576 UMA_HISTOGRAM_CUSTOM_COUNTS( 548 UMA_HISTOGRAM_CUSTOM_COUNTS(
577 "Net.ResourceLoader.ResponseStartToEnd.Over_512kB", 549 "Net.ResourceLoader.ResponseStartToEnd.Over_512kB",
578 elapsed_time, 1, 100000, 100); 550 elapsed_time, 1, 100000, 100);
579 } 551 }
580 552
581 inlining_helper_->RecordHistogram(elapsed_time); 553 inlining_helper_->RecordHistogram(elapsed_time);
582 } 554 }
583 555
556 void AsyncResourceHandler::SendUploadProgress(int64_t current_position,
557 int64_t total_size) {
558 ResourceMessageFilter* filter = GetFilter();
559 if (!filter)
560 return;
561 filter->Send(new ResourceMsg_UploadProgress(
562 GetRequestID(), current_position, total_size));
563 }
564
584 } // namespace content 565 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/loader/async_resource_handler.h ('k') | content/browser/loader/upload_progress_tracker.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698