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

Side by Side Diff: components/offline_pages/background/request_coordinator.cc

Issue 2508213002: [OfflinePages] Fix Coordinator issue with lagging NetworkChangeNotifier (Closed)
Patch Set: Created 4 years, 1 month 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
« no previous file with comments | « components/offline_pages/background/request_coordinator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "components/offline_pages/background/request_coordinator.h" 5 #include "components/offline_pages/background/request_coordinator.h"
6 6
7 #include <limits> 7 #include <limits>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/callback.h" 11 #include "base/callback.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/metrics/histogram_macros.h" 13 #include "base/metrics/histogram_macros.h"
14 #include "base/rand_util.h" 14 #include "base/rand_util.h"
15 #include "base/sys_info.h" 15 #include "base/sys_info.h"
16 #include "base/time/time.h" 16 #include "base/time/time.h"
17 #include "components/offline_pages/background/offliner_factory.h" 17 #include "components/offline_pages/background/offliner_factory.h"
18 #include "components/offline_pages/background/offliner_policy.h" 18 #include "components/offline_pages/background/offliner_policy.h"
19 #include "components/offline_pages/background/save_page_request.h" 19 #include "components/offline_pages/background/save_page_request.h"
20 #include "components/offline_pages/client_policy_controller.h" 20 #include "components/offline_pages/client_policy_controller.h"
21 #include "components/offline_pages/offline_page_feature.h" 21 #include "components/offline_pages/offline_page_feature.h"
22 #include "components/offline_pages/offline_page_item.h" 22 #include "components/offline_pages/offline_page_item.h"
23 #include "components/offline_pages/offline_page_model.h" 23 #include "components/offline_pages/offline_page_model.h"
24 24
25 namespace offline_pages { 25 namespace offline_pages {
26 26
27 namespace { 27 namespace {
28 const bool kUserRequest = true; 28 const bool kUserRequest = true;
29 const bool kStartOfProcessing = true;
29 const int kMinDurationSeconds = 1; 30 const int kMinDurationSeconds = 1;
30 const int kMaxDurationSeconds = 7 * 24 * 60 * 60; // 7 days 31 const int kMaxDurationSeconds = 7 * 24 * 60 * 60; // 7 days
31 const int kDurationBuckets = 50; 32 const int kDurationBuckets = 50;
32 const int kDisabledTaskRecheckSeconds = 5; 33 const int kDisabledTaskRecheckSeconds = 5;
33 34
34 // TODO(dougarnett): Move to util location and share with model impl. 35 // TODO(dougarnett): Move to util location and share with model impl.
35 std::string AddHistogramSuffix(const ClientId& client_id, 36 std::string AddHistogramSuffix(const ClientId& client_id,
36 const char* histogram_name) { 37 const char* histogram_name) {
37 if (client_id.name_space.empty()) { 38 if (client_id.name_space.empty()) {
38 NOTREACHED(); 39 NOTREACHED();
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 365
365 // Record the network quality when this request is made. 366 // Record the network quality when this request is made.
366 if (network_quality_estimator_) { 367 if (network_quality_estimator_) {
367 UMA_HISTOGRAM_ENUMERATION( 368 UMA_HISTOGRAM_ENUMERATION(
368 "OfflinePages.Background.EffectiveConnectionType.RemoveRequests", 369 "OfflinePages.Background.EffectiveConnectionType.RemoveRequests",
369 network_quality_estimator_->GetEffectiveConnectionType(), 370 network_quality_estimator_->GetEffectiveConnectionType(),
370 net::EFFECTIVE_CONNECTION_TYPE_LAST); 371 net::EFFECTIVE_CONNECTION_TYPE_LAST);
371 } 372 }
372 373
373 if (canceled) 374 if (canceled)
374 TryNextRequest(); 375 TryNextRequest(!kStartOfProcessing);
375 } 376 }
376 377
377 void RequestCoordinator::PauseRequests( 378 void RequestCoordinator::PauseRequests(
378 const std::vector<int64_t>& request_ids) { 379 const std::vector<int64_t>& request_ids) {
379 bool canceled = CancelActiveRequestIfItMatches(request_ids); 380 bool canceled = CancelActiveRequestIfItMatches(request_ids);
380 queue_->ChangeRequestsState( 381 queue_->ChangeRequestsState(
381 request_ids, SavePageRequest::RequestState::PAUSED, 382 request_ids, SavePageRequest::RequestState::PAUSED,
382 base::Bind(&RequestCoordinator::UpdateMultipleRequestsCallback, 383 base::Bind(&RequestCoordinator::UpdateMultipleRequestsCallback,
383 weak_ptr_factory_.GetWeakPtr())); 384 weak_ptr_factory_.GetWeakPtr()));
384 385
385 // Record the network quality when this request is made. 386 // Record the network quality when this request is made.
386 if (network_quality_estimator_) { 387 if (network_quality_estimator_) {
387 UMA_HISTOGRAM_ENUMERATION( 388 UMA_HISTOGRAM_ENUMERATION(
388 "OfflinePages.Background.EffectiveConnectionType.PauseRequests", 389 "OfflinePages.Background.EffectiveConnectionType.PauseRequests",
389 network_quality_estimator_->GetEffectiveConnectionType(), 390 network_quality_estimator_->GetEffectiveConnectionType(),
390 net::EFFECTIVE_CONNECTION_TYPE_LAST); 391 net::EFFECTIVE_CONNECTION_TYPE_LAST);
391 } 392 }
392 393
393 if (canceled) 394 if (canceled)
394 TryNextRequest(); 395 TryNextRequest(!kStartOfProcessing);
395 } 396 }
396 397
397 void RequestCoordinator::ResumeRequests( 398 void RequestCoordinator::ResumeRequests(
398 const std::vector<int64_t>& request_ids) { 399 const std::vector<int64_t>& request_ids) {
399 queue_->ChangeRequestsState( 400 queue_->ChangeRequestsState(
400 request_ids, SavePageRequest::RequestState::AVAILABLE, 401 request_ids, SavePageRequest::RequestState::AVAILABLE,
401 base::Bind(&RequestCoordinator::UpdateMultipleRequestsCallback, 402 base::Bind(&RequestCoordinator::UpdateMultipleRequestsCallback,
402 weak_ptr_factory_.GetWeakPtr())); 403 weak_ptr_factory_.GetWeakPtr()));
403 404
404 // Record the network quality when this request is made. 405 // Record the network quality when this request is made.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 } 465 }
465 466
466 if (available_user_request) 467 if (available_user_request)
467 StartImmediatelyIfConnected(); 468 StartImmediatelyIfConnected();
468 } 469 }
469 470
470 // When we successfully remove a request that completed successfully, move on to 471 // When we successfully remove a request that completed successfully, move on to
471 // the next request. 472 // the next request.
472 void RequestCoordinator::CompletedRequestCallback( 473 void RequestCoordinator::CompletedRequestCallback(
473 const MultipleItemStatuses& status) { 474 const MultipleItemStatuses& status) {
474 TryNextRequest(); 475 TryNextRequest(!kStartOfProcessing);
475 } 476 }
476 477
477 void RequestCoordinator::HandleRemovedRequestsAndCallback( 478 void RequestCoordinator::HandleRemovedRequestsAndCallback(
478 const RemoveRequestsCallback& callback, 479 const RemoveRequestsCallback& callback,
479 RequestNotifier::BackgroundSavePageResult status, 480 RequestNotifier::BackgroundSavePageResult status,
480 std::unique_ptr<UpdateRequestsResult> result) { 481 std::unique_ptr<UpdateRequestsResult> result) {
481 // TODO(dougarnett): Define status code for user/api cancel and use here 482 // TODO(dougarnett): Define status code for user/api cancel and use here
482 // to determine whether to record cancel time UMA. 483 // to determine whether to record cancel time UMA.
483 for (const auto& request : result->updated_items) 484 for (const auto& request : result->updated_items)
484 RecordCancelTimeUMA(request); 485 RecordCancelTimeUMA(request);
(...skipping 21 matching lines...) Expand all
506 StopPrerendering(stop_status); 507 StopPrerendering(stop_status);
507 508
508 // Let the scheduler know we are done processing. 509 // Let the scheduler know we are done processing.
509 scheduler_callback_.Run(true); 510 scheduler_callback_.Run(true);
510 } 511 }
511 512
512 void RequestCoordinator::HandleWatchdogTimeout() { 513 void RequestCoordinator::HandleWatchdogTimeout() {
513 Offliner::RequestStatus watchdog_status = 514 Offliner::RequestStatus watchdog_status =
514 Offliner::REQUEST_COORDINATOR_TIMED_OUT; 515 Offliner::REQUEST_COORDINATOR_TIMED_OUT;
515 StopPrerendering(watchdog_status); 516 StopPrerendering(watchdog_status);
516 TryNextRequest(); 517 TryNextRequest(!kStartOfProcessing);
517 } 518 }
518 519
519 // Returns true if the caller should expect a callback, false otherwise. For 520 // Returns true if the caller should expect a callback, false otherwise. For
520 // instance, this would return false if a request is already in progress. 521 // instance, this would return false if a request is already in progress.
521 bool RequestCoordinator::StartProcessing( 522 bool RequestCoordinator::StartProcessing(
522 const DeviceConditions& device_conditions, 523 const DeviceConditions& device_conditions,
523 const base::Callback<void(bool)>& callback) { 524 const base::Callback<void(bool)>& callback) {
524 DVLOG(2) << "Scheduled " << __func__; 525 DVLOG(2) << "Scheduled " << __func__;
525 return StartProcessingInternal(ProcessingWindowState::SCHEDULED_WINDOW, 526 return StartProcessingInternal(ProcessingWindowState::SCHEDULED_WINDOW,
526 device_conditions, callback); 527 device_conditions, callback);
527 } 528 }
528 529
529 bool RequestCoordinator::StartProcessingInternal( 530 bool RequestCoordinator::StartProcessingInternal(
530 const ProcessingWindowState processing_state, 531 const ProcessingWindowState processing_state,
531 const DeviceConditions& device_conditions, 532 const DeviceConditions& device_conditions,
532 const base::Callback<void(bool)>& callback) { 533 const base::Callback<void(bool)>& callback) {
533 current_conditions_.reset(new DeviceConditions(device_conditions)); 534 current_conditions_.reset(new DeviceConditions(device_conditions));
534 if (is_starting_ || is_busy_) 535 if (is_starting_ || is_busy_)
535 return false; 536 return false;
536 processing_state_ = processing_state; 537 processing_state_ = processing_state;
537 scheduler_callback_ = callback; 538 scheduler_callback_ = callback;
538 539
539 // Mark the time at which we started processing so we can check our time 540 // Mark the time at which we started processing so we can check our time
540 // budget. 541 // budget.
541 operation_start_time_ = base::Time::Now(); 542 operation_start_time_ = base::Time::Now();
542 543
543 TryNextRequest(); 544 TryNextRequest(kStartOfProcessing);
544 545
545 return true; 546 return true;
546 } 547 }
547 548
548 void RequestCoordinator::StartImmediatelyIfConnected() { 549 void RequestCoordinator::StartImmediatelyIfConnected() {
549 OfflinerImmediateStartStatus immediate_start_status = TryImmediateStart(); 550 OfflinerImmediateStartStatus immediate_start_status = TryImmediateStart();
550 UMA_HISTOGRAM_ENUMERATION( 551 UMA_HISTOGRAM_ENUMERATION(
551 "OfflinePages.Background.ImmediateStartStatus", immediate_start_status, 552 "OfflinePages.Background.ImmediateStartStatus", immediate_start_status,
552 RequestCoordinator::OfflinerImmediateStartStatus::STATUS_COUNT); 553 RequestCoordinator::OfflinerImmediateStartStatus::STATUS_COUNT);
553 } 554 }
(...skipping 23 matching lines...) Expand all
577 // TODO(dougarnett): Obtain actual battery conditions (from Android/Java). 578 // TODO(dougarnett): Obtain actual battery conditions (from Android/Java).
578 579
579 DeviceConditions device_conditions(false, 0, GetConnectionType()); 580 DeviceConditions device_conditions(false, 0, GetConnectionType());
580 if (StartProcessingInternal(ProcessingWindowState::IMMEDIATE_WINDOW, 581 if (StartProcessingInternal(ProcessingWindowState::IMMEDIATE_WINDOW,
581 device_conditions, immediate_schedule_callback_)) 582 device_conditions, immediate_schedule_callback_))
582 return OfflinerImmediateStartStatus::STARTED; 583 return OfflinerImmediateStartStatus::STARTED;
583 else 584 else
584 return OfflinerImmediateStartStatus::NOT_ACCEPTED; 585 return OfflinerImmediateStartStatus::NOT_ACCEPTED;
585 } 586 }
586 587
587 void RequestCoordinator::TryNextRequest() { 588 void RequestCoordinator::TryNextRequest(bool is_start_of_processing) {
588 is_starting_ = true; 589 is_starting_ = true;
589 base::TimeDelta processing_time_budget; 590 base::TimeDelta processing_time_budget;
590 if (processing_state_ == ProcessingWindowState::SCHEDULED_WINDOW) { 591 if (processing_state_ == ProcessingWindowState::SCHEDULED_WINDOW) {
591 processing_time_budget = base::TimeDelta::FromSeconds( 592 processing_time_budget = base::TimeDelta::FromSeconds(
592 policy_->GetProcessingTimeBudgetWhenBackgroundScheduledInSeconds()); 593 policy_->GetProcessingTimeBudgetWhenBackgroundScheduledInSeconds());
593 } else { 594 } else {
594 DCHECK(processing_state_ == ProcessingWindowState::IMMEDIATE_WINDOW); 595 DCHECK(processing_state_ == ProcessingWindowState::IMMEDIATE_WINDOW);
595 processing_time_budget = base::TimeDelta::FromSeconds( 596 processing_time_budget = base::TimeDelta::FromSeconds(
596 policy_->GetProcessingTimeBudgetForImmediateLoadInSeconds()); 597 policy_->GetProcessingTimeBudgetForImmediateLoadInSeconds());
597 } 598 }
598 599
600 // Determine connection type. If just starting processing, the best source is
601 // from the current device conditions (they are fresh and motivated starting
602 // processing whereas NetworkChangeNotifier may lag reality).
603 net::NetworkChangeNotifier::ConnectionType connection_type;
604 if (is_start_of_processing)
605 connection_type = current_conditions_->GetNetConnectionType();
606 else
607 connection_type = GetConnectionType();
608
599 // If there is no network or no time left in the budget, return to the 609 // If there is no network or no time left in the budget, return to the
600 // scheduler. We do not remove the pending scheduler task that was set 610 // scheduler. We do not remove the pending scheduler task that was set
601 // up earlier in case we run out of time, so the background scheduler 611 // up earlier in case we run out of time, so the background scheduler
602 // will return to us at the next opportunity to run background tasks. 612 // will return to us at the next opportunity to run background tasks.
603 if (GetConnectionType() == 613 if (connection_type ==
604 net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE || 614 net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE ||
605 (base::Time::Now() - operation_start_time_) > processing_time_budget) { 615 (base::Time::Now() - operation_start_time_) > processing_time_budget) {
606 is_starting_ = false; 616 is_starting_ = false;
607 617
608 // Let the scheduler know we are done processing. 618 // Let the scheduler know we are done processing.
609 // TODO: Make sure the scheduler callback is valid before running it. 619 // TODO: Make sure the scheduler callback is valid before running it.
610 scheduler_callback_.Run(true); 620 scheduler_callback_.Run(true);
611 DVLOG(2) << " out of time, giving up. " << __func__; 621 DVLOG(2) << " out of time, giving up. " << __func__;
612 622
613 return; 623 return;
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
752 request.request_id()); 762 request.request_id());
753 last_offlining_status_ = status; 763 last_offlining_status_ = status;
754 RecordOfflinerResultUMA(request.client_id(), request.creation_time(), 764 RecordOfflinerResultUMA(request.client_id(), request.creation_time(),
755 last_offlining_status_); 765 last_offlining_status_);
756 watchdog_timer_.Stop(); 766 watchdog_timer_.Stop();
757 is_busy_ = false; 767 is_busy_ = false;
758 active_request_.reset(nullptr); 768 active_request_.reset(nullptr);
759 769
760 UpdateRequestForCompletedAttempt(request, status); 770 UpdateRequestForCompletedAttempt(request, status);
761 if (ShouldTryNextRequest(status)) 771 if (ShouldTryNextRequest(status))
762 TryNextRequest(); 772 TryNextRequest(!kStartOfProcessing);
763 else 773 else
764 scheduler_callback_.Run(true); 774 scheduler_callback_.Run(true);
765 } 775 }
766 776
767 void RequestCoordinator::UpdateRequestForCompletedAttempt( 777 void RequestCoordinator::UpdateRequestForCompletedAttempt(
768 const SavePageRequest& request, 778 const SavePageRequest& request,
769 Offliner::RequestStatus status) { 779 Offliner::RequestStatus status) {
770 if (status == Offliner::RequestStatus::FOREGROUND_CANCELED || 780 if (status == Offliner::RequestStatus::FOREGROUND_CANCELED ||
771 status == Offliner::RequestStatus::PRERENDERING_CANCELED) { 781 status == Offliner::RequestStatus::PRERENDERING_CANCELED) {
772 // Update the request for the canceled attempt. 782 // Update the request for the canceled attempt.
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
894 904
895 ClientPolicyController* RequestCoordinator::GetPolicyController() { 905 ClientPolicyController* RequestCoordinator::GetPolicyController() {
896 return policy_controller_.get(); 906 return policy_controller_.get();
897 } 907 }
898 908
899 void RequestCoordinator::Shutdown() { 909 void RequestCoordinator::Shutdown() {
900 network_quality_estimator_ = nullptr; 910 network_quality_estimator_ = nullptr;
901 } 911 }
902 912
903 } // namespace offline_pages 913 } // namespace offline_pages
OLDNEW
« no previous file with comments | « components/offline_pages/background/request_coordinator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698