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

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

Issue 2493683002: [OfflinePages] Fixes RequestCoordinator bug not clearing state on timeout (Closed)
Patch Set: Broke out some OfflinerDoneCallback logic and reworked timeout handling 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
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"
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 RequestQueue::GetRequestsResult result, 234 RequestQueue::GetRequestsResult result,
235 std::vector<std::unique_ptr<SavePageRequest>> requests) { 235 std::vector<std::unique_ptr<SavePageRequest>> requests) {
236 callback.Run(std::move(requests)); 236 callback.Run(std::move(requests));
237 } 237 }
238 238
239 void RequestCoordinator::StopPrerendering(Offliner::RequestStatus stop_status) { 239 void RequestCoordinator::StopPrerendering(Offliner::RequestStatus stop_status) {
240 if (offliner_ && is_busy_) { 240 if (offliner_ && is_busy_) {
241 DCHECK(active_request_.get()); 241 DCHECK(active_request_.get());
242 offliner_->Cancel(); 242 offliner_->Cancel();
243 243
244 // If we timed out, let the offliner done callback handle it. 244 if (stop_status == Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT) {
245 if (stop_status == Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT) 245 // Consider watchdog timeout a completed attempt.
246 return; 246 SavePageRequest request(*active_request_.get());
247 247 UpdateRequestForCompletedAttempt(request,
248 // Otherwise, this attempt never really had a chance to run, mark it 248 Offliner::REQUEST_COORDINATOR_TIMED_OUT);
249 // aborted. 249 } else {
250 AbortRequestAttempt(*active_request_.get()); 250 // Otherwise consider this stop an aborted attempt.
251 UpdateRequestForAbortedAttempt(*active_request_.get());
252 }
251 } 253 }
252 254
253 // Stopping offliner means it will not call callback so set last status. 255 // Stopping offliner means it will not call callback so set last status.
254 last_offlining_status_ = stop_status; 256 last_offlining_status_ = stop_status;
255 257
256 if (active_request_) { 258 if (active_request_) {
257 event_logger_.RecordOfflinerResult(active_request_->client_id().name_space, 259 event_logger_.RecordOfflinerResult(active_request_->client_id().name_space,
258 last_offlining_status_, 260 last_offlining_status_,
259 active_request_->request_id()); 261 active_request_->request_id());
260 RecordOfflinerResultUMA(active_request_->client_id(), 262 RecordOfflinerResultUMA(active_request_->client_id(),
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 active_request_->request_id())) { 297 active_request_->request_id())) {
296 StopPrerendering(Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED); 298 StopPrerendering(Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED);
297 active_request_.reset(nullptr); 299 active_request_.reset(nullptr);
298 return true; 300 return true;
299 } 301 }
300 } 302 }
301 303
302 return false; 304 return false;
303 } 305 }
304 306
305 void RequestCoordinator::AbortRequestAttempt(const SavePageRequest& request) { 307 void RequestCoordinator::UpdateRequestForAbortedAttempt(
308 const SavePageRequest& request) {
306 if (request.started_attempt_count() >= policy_->GetMaxStartedTries()) { 309 if (request.started_attempt_count() >= policy_->GetMaxStartedTries()) {
307 const BackgroundSavePageResult result( 310 const BackgroundSavePageResult result(
308 BackgroundSavePageResult::START_COUNT_EXCEEDED); 311 BackgroundSavePageResult::START_COUNT_EXCEEDED);
309 event_logger_.RecordDroppedSavePageRequest(request.client_id().name_space, 312 event_logger_.RecordDroppedSavePageRequest(request.client_id().name_space,
310 result, request.request_id()); 313 result, request.request_id());
311 RemoveAttemptedRequest(request, result); 314 RemoveAttemptedRequest(request, result);
312 } else { 315 } else {
313 queue_->MarkAttemptAborted( 316 queue_->MarkAttemptAborted(
314 request.request_id(), 317 request.request_id(),
315 base::Bind(&RequestCoordinator::MarkAttemptAbortedDone, 318 base::Bind(&RequestCoordinator::MarkAttemptAbortedDone,
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 void RequestCoordinator::StopProcessing( 502 void RequestCoordinator::StopProcessing(
500 Offliner::RequestStatus stop_status) { 503 Offliner::RequestStatus stop_status) {
501 processing_state_ = ProcessingWindowState::STOPPED; 504 processing_state_ = ProcessingWindowState::STOPPED;
502 StopPrerendering(stop_status); 505 StopPrerendering(stop_status);
503 506
504 // Let the scheduler know we are done processing. 507 // Let the scheduler know we are done processing.
505 scheduler_callback_.Run(true); 508 scheduler_callback_.Run(true);
506 } 509 }
507 510
508 void RequestCoordinator::HandleWatchdogTimeout() { 511 void RequestCoordinator::HandleWatchdogTimeout() {
509 StopProcessing(Offliner::REQUEST_COORDINATOR_TIMED_OUT); 512 Offliner::RequestStatus watchdog_status =
513 Offliner::REQUEST_COORDINATOR_TIMED_OUT;
514 StopPrerendering(watchdog_status);
515 if (ShouldTryNextRequest(watchdog_status))
Pete Williamson 2016/11/11 00:24:04 Why call ShouldTryNextRequest() here? In this cas
dougarnett 2016/11/11 16:36:45 Yeah, almost did. The idea here was for the policy
516 TryNextRequest();
517 else
518 scheduler_callback_.Run(true);
510 } 519 }
511 520
512 // Returns true if the caller should expect a callback, false otherwise. For 521 // Returns true if the caller should expect a callback, false otherwise. For
513 // instance, this would return false if a request is already in progress. 522 // instance, this would return false if a request is already in progress.
514 bool RequestCoordinator::StartProcessing( 523 bool RequestCoordinator::StartProcessing(
515 const DeviceConditions& device_conditions, 524 const DeviceConditions& device_conditions,
516 const base::Callback<void(bool)>& callback) { 525 const base::Callback<void(bool)>& callback) {
517 return StartProcessingInternal(ProcessingWindowState::SCHEDULED_WINDOW, 526 return StartProcessingInternal(ProcessingWindowState::SCHEDULED_WINDOW,
518 device_conditions, callback); 527 device_conditions, callback);
519 } 528 }
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 << (status == Offliner::RequestStatus::SAVED) 743 << (status == Offliner::RequestStatus::SAVED)
735 << ", status: " << static_cast<int>(status) << ", " << __func__; 744 << ", status: " << static_cast<int>(status) << ", " << __func__;
736 DCHECK_NE(status, Offliner::RequestStatus::UNKNOWN); 745 DCHECK_NE(status, Offliner::RequestStatus::UNKNOWN);
737 DCHECK_NE(status, Offliner::RequestStatus::LOADED); 746 DCHECK_NE(status, Offliner::RequestStatus::LOADED);
738 event_logger_.RecordOfflinerResult(request.client_id().name_space, status, 747 event_logger_.RecordOfflinerResult(request.client_id().name_space, status,
739 request.request_id()); 748 request.request_id());
740 last_offlining_status_ = status; 749 last_offlining_status_ = status;
741 RecordOfflinerResultUMA(request.client_id(), request.creation_time(), 750 RecordOfflinerResultUMA(request.client_id(), request.creation_time(),
742 last_offlining_status_); 751 last_offlining_status_);
743 watchdog_timer_.Stop(); 752 watchdog_timer_.Stop();
744
745 is_busy_ = false; 753 is_busy_ = false;
746 active_request_.reset(nullptr); 754 active_request_.reset(nullptr);
747 755
756 UpdateRequestForCompletedAttempt(request, status);
757 if (ShouldTryNextRequest(status))
758 TryNextRequest();
759 else
760 scheduler_callback_.Run(true);
761 }
762
763 void RequestCoordinator::UpdateRequestForCompletedAttempt(
764 const SavePageRequest& request,
765 Offliner::RequestStatus status) {
748 if (status == Offliner::RequestStatus::FOREGROUND_CANCELED || 766 if (status == Offliner::RequestStatus::FOREGROUND_CANCELED ||
749 status == Offliner::RequestStatus::PRERENDERING_CANCELED) { 767 status == Offliner::RequestStatus::PRERENDERING_CANCELED) {
750 // Update the request for the canceled attempt. 768 // Update the request for the canceled attempt.
751 // TODO(dougarnett): See if we can conclusively identify other attempt 769 // TODO(dougarnett): See if we can conclusively identify other attempt
752 // aborted cases to treat this way (eg, for Render Process Killed). 770 // aborted cases to treat this way (eg, for Render Process Killed).
753 AbortRequestAttempt(request); 771 UpdateRequestForAbortedAttempt(request);
754 } else if (status == Offliner::RequestStatus::SAVED) { 772 } else if (status == Offliner::RequestStatus::SAVED) {
755 // Remove the request from the queue if it succeeded. 773 // Remove the request from the queue if it succeeded.
756 RemoveAttemptedRequest(request, BackgroundSavePageResult::SUCCESS); 774 RemoveAttemptedRequest(request, BackgroundSavePageResult::SUCCESS);
757 } else if (status == Offliner::RequestStatus::PRERENDERING_FAILED_NO_RETRY) { 775 } else if (status == Offliner::RequestStatus::PRERENDERING_FAILED_NO_RETRY) {
758 RemoveAttemptedRequest(request, 776 RemoveAttemptedRequest(request,
759 BackgroundSavePageResult::PRERENDER_FAILURE); 777 BackgroundSavePageResult::PRERENDER_FAILURE);
760 } else if (request.completed_attempt_count() + 1 >= 778 } else if (request.completed_attempt_count() + 1 >=
761 policy_->GetMaxCompletedTries()) { 779 policy_->GetMaxCompletedTries()) {
762 // Remove from the request queue if we exceeded max retries. The +1 780 // Remove from the request queue if we exceeded max retries. The +1
763 // represents the request that just completed. Since we call 781 // represents the request that just completed. Since we call
764 // MarkAttemptCompleted within the if branches, the completed_attempt_count 782 // MarkAttemptCompleted within the if branches, the completed_attempt_count
765 // has not yet been updated when we are checking the if condition. 783 // has not yet been updated when we are checking the if condition.
766 const BackgroundSavePageResult result( 784 const BackgroundSavePageResult result(
767 BackgroundSavePageResult::RETRY_COUNT_EXCEEDED); 785 BackgroundSavePageResult::RETRY_COUNT_EXCEEDED);
768 event_logger_.RecordDroppedSavePageRequest(request.client_id().name_space, 786 event_logger_.RecordDroppedSavePageRequest(request.client_id().name_space,
769 result, request.request_id()); 787 result, request.request_id());
770 RemoveAttemptedRequest(request, result); 788 RemoveAttemptedRequest(request, result);
771 } else { 789 } else {
772 // If we failed, but are not over the limit, update the request in the 790 // If we failed, but are not over the limit, update the request in the
773 // queue. 791 // queue.
774 queue_->MarkAttemptCompleted( 792 queue_->MarkAttemptCompleted(
775 request.request_id(), 793 request.request_id(),
776 base::Bind(&RequestCoordinator::MarkAttemptCompletedDoneCallback, 794 base::Bind(&RequestCoordinator::MarkAttemptCompletedDoneCallback,
777 weak_ptr_factory_.GetWeakPtr(), request.request_id(), 795 weak_ptr_factory_.GetWeakPtr(), request.request_id(),
778 request.client_id())); 796 request.client_id()));
779 } 797 }
798 }
780 799
781 // Determine whether we might try another request in this 800 bool RequestCoordinator::ShouldTryNextRequest(
782 // processing window based on how the previous request completed. 801 Offliner::RequestStatus previous_request_status) {
783 switch (status) { 802 switch (previous_request_status) {
784 case Offliner::RequestStatus::SAVED: 803 case Offliner::RequestStatus::SAVED:
785 case Offliner::RequestStatus::SAVE_FAILED: 804 case Offliner::RequestStatus::SAVE_FAILED:
786 case Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED: 805 case Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED:
787 case Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT: 806 case Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT:
788 case Offliner::RequestStatus::PRERENDERING_FAILED_NO_RETRY: 807 case Offliner::RequestStatus::PRERENDERING_FAILED_NO_RETRY:
789 // Consider processing another request in this service window. 808 return true;
790 TryNextRequest();
791 break;
792 case Offliner::RequestStatus::FOREGROUND_CANCELED: 809 case Offliner::RequestStatus::FOREGROUND_CANCELED:
793 case Offliner::RequestStatus::PRERENDERING_CANCELED: 810 case Offliner::RequestStatus::PRERENDERING_CANCELED:
794 case Offliner::RequestStatus::PRERENDERING_FAILED: 811 case Offliner::RequestStatus::PRERENDERING_FAILED:
795 // No further processing in this service window. 812 // No further processing in this service window.
796 // Let the scheduler know we are done processing. 813 return false;
797 scheduler_callback_.Run(true);
798 break;
799 default: 814 default:
800 // Make explicit choice about new status codes that actually reach here. 815 // Make explicit choice about new status codes that actually reach here.
801 // Their default is no further processing in this service window. 816 // Their default is no further processing in this service window.
802 NOTREACHED(); 817 NOTREACHED();
818 return false;
803 } 819 }
804 } 820 }
805 821
806 void RequestCoordinator::EnableForOffliner(int64_t request_id) { 822 void RequestCoordinator::EnableForOffliner(int64_t request_id) {
807 // Since the recent tab helper might call multiple times, ignore subsequent 823 // Since the recent tab helper might call multiple times, ignore subsequent
808 // calls for a particular request_id. 824 // calls for a particular request_id.
809 if (disabled_requests_.find(request_id) == disabled_requests_.end()) 825 if (disabled_requests_.find(request_id) == disabled_requests_.end())
810 return; 826 return;
811 disabled_requests_.erase(request_id); 827 disabled_requests_.erase(request_id);
812 // If we are not busy, start processing right away. 828 // If we are not busy, start processing right away.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
872 888
873 ClientPolicyController* RequestCoordinator::GetPolicyController() { 889 ClientPolicyController* RequestCoordinator::GetPolicyController() {
874 return policy_controller_.get(); 890 return policy_controller_.get();
875 } 891 }
876 892
877 void RequestCoordinator::Shutdown() { 893 void RequestCoordinator::Shutdown() {
878 network_quality_estimator_ = nullptr; 894 network_quality_estimator_ = nullptr;
879 } 895 }
880 896
881 } // namespace offline_pages 897 } // namespace offline_pages
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698