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

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/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
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
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
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_->ForceReportUploadProgress();
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 FROM_HERE, base::BindRepeating(&SendUploadProgress,
376 FROM_HERE, 350 filter->GetWeakPtr(), GetRequestID()),
377 base::TimeDelta::FromMilliseconds(kUploadProgressIntervalMsec), 351 request());
378 this, 352 upload_progress_tracker_->ForceReportUploadProgress();
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 10 matching lines...) Expand all
400 DCHECK(buffer_->CanAllocate()); 373 DCHECK(buffer_->CanAllocate());
401 char* memory = buffer_->Allocate(&allocation_size_); 374 char* memory = buffer_->Allocate(&allocation_size_);
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) {
yhirano 2016/12/02 09:17:52 Is it good to nullify upload_progress_tracker_ in
tzik 2016/12/05 08:00:06 OnResponseStarted should clear it before OnReadCom
yhirano 2016/12/07 13:50:03 Oops, sorry, I wanted to comment at OnResponseComp
tzik 2016/12/08 05:57:54 That makes sense. Done.
411 DCHECK_GE(bytes_read, 0); 384 DCHECK_GE(bytes_read, 0);
412 385
413 if (!bytes_read) 386 if (!bytes_read)
414 return true; 387 return true;
415 388
416 ResourceMessageFilter* filter = GetFilter(); 389 ResourceMessageFilter* filter = GetFilter();
417 if (!filter) 390 if (!filter)
418 return false; 391 return false;
419 392
420 int encoded_data_length = CalculateEncodedDataLengthToReport(); 393 int encoded_data_length = CalculateEncodedDataLengthToReport();
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 } else { 548 } else {
576 UMA_HISTOGRAM_CUSTOM_COUNTS( 549 UMA_HISTOGRAM_CUSTOM_COUNTS(
577 "Net.ResourceLoader.ResponseStartToEnd.Over_512kB", 550 "Net.ResourceLoader.ResponseStartToEnd.Over_512kB",
578 elapsed_time, 1, 100000, 100); 551 elapsed_time, 1, 100000, 100);
579 } 552 }
580 553
581 inlining_helper_->RecordHistogram(elapsed_time); 554 inlining_helper_->RecordHistogram(elapsed_time);
582 } 555 }
583 556
584 } // namespace content 557 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698