| OLD | NEW |
| 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 <string> | |
| 9 #include <utility> | 8 #include <utility> |
| 10 #include <vector> | |
| 11 | 9 |
| 12 #include "base/bind.h" | 10 #include "base/bind.h" |
| 13 #include "base/callback.h" | 11 #include "base/callback.h" |
| 14 #include "base/logging.h" | 12 #include "base/logging.h" |
| 15 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
| 16 #include "base/rand_util.h" | 14 #include "base/rand_util.h" |
| 17 #include "base/sys_info.h" | 15 #include "base/sys_info.h" |
| 18 #include "base/time/time.h" | 16 #include "base/time/time.h" |
| 19 #include "components/offline_pages/background/offliner_factory.h" | 17 #include "components/offline_pages/background/offliner_factory.h" |
| 20 #include "components/offline_pages/background/offliner_policy.h" | 18 #include "components/offline_pages/background/offliner_policy.h" |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 // This should use the same algorithm as we use for OfflinePageItem, so the IDs | 121 // This should use the same algorithm as we use for OfflinePageItem, so the IDs |
| 124 // are similar. | 122 // are similar. |
| 125 int64_t GenerateOfflineId() { | 123 int64_t GenerateOfflineId() { |
| 126 return base::RandGenerator(std::numeric_limits<int64_t>::max()) + 1; | 124 return base::RandGenerator(std::numeric_limits<int64_t>::max()) + 1; |
| 127 } | 125 } |
| 128 | 126 |
| 129 // In case we start processing from SavePageLater, we need a callback, but there | 127 // In case we start processing from SavePageLater, we need a callback, but there |
| 130 // is nothing for it to do. | 128 // is nothing for it to do. |
| 131 void EmptySchedulerCallback(bool started) {} | 129 void EmptySchedulerCallback(bool started) {} |
| 132 | 130 |
| 131 // Returns whether |result| is a successful result for a single request. |
| 132 bool IsSingleSuccessResult(const UpdateRequestsResult* result) { |
| 133 return result->store_state == StoreState::LOADED && |
| 134 result->item_statuses.size() == 1 && |
| 135 result->item_statuses.at(0).second == ItemActionStatus::SUCCESS; |
| 136 } |
| 137 |
| 133 } // namespace | 138 } // namespace |
| 134 | 139 |
| 135 RequestCoordinator::RequestCoordinator( | 140 RequestCoordinator::RequestCoordinator( |
| 136 std::unique_ptr<OfflinerPolicy> policy, | 141 std::unique_ptr<OfflinerPolicy> policy, |
| 137 std::unique_ptr<OfflinerFactory> factory, | 142 std::unique_ptr<OfflinerFactory> factory, |
| 138 std::unique_ptr<RequestQueue> queue, | 143 std::unique_ptr<RequestQueue> queue, |
| 139 std::unique_ptr<Scheduler> scheduler, | 144 std::unique_ptr<Scheduler> scheduler, |
| 140 net::NetworkQualityEstimator::NetworkQualityProvider* | 145 net::NetworkQualityEstimator::NetworkQualityProvider* |
| 141 network_quality_estimator) | 146 network_quality_estimator) |
| 142 : is_low_end_device_(base::SysInfo::IsLowEndDevice()), | 147 : is_low_end_device_(base::SysInfo::IsLowEndDevice()), |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 weak_ptr_factory_.GetWeakPtr(), result)); | 298 weak_ptr_factory_.GetWeakPtr(), result)); |
| 294 RecordAttemptCount(request, result); | 299 RecordAttemptCount(request, result); |
| 295 } | 300 } |
| 296 | 301 |
| 297 void RequestCoordinator::MarkAttemptAbortedDone( | 302 void RequestCoordinator::MarkAttemptAbortedDone( |
| 298 int64_t request_id, | 303 int64_t request_id, |
| 299 const ClientId& client_id, | 304 const ClientId& client_id, |
| 300 std::unique_ptr<UpdateRequestsResult> result) { | 305 std::unique_ptr<UpdateRequestsResult> result) { |
| 301 // If the request succeeded, nothing to do. If it failed, we can't really do | 306 // If the request succeeded, nothing to do. If it failed, we can't really do |
| 302 // much, so just log it. | 307 // much, so just log it. |
| 303 if (result->store_state != StoreState::LOADED || | 308 if (!IsSingleSuccessResult(result.get())) { |
| 304 result->item_statuses.size() != 1 || | |
| 305 result->item_statuses.at(0).first != request_id || | |
| 306 result->item_statuses.at(0).second != ItemActionStatus::SUCCESS) { | |
| 307 DVLOG(1) << "Failed to mark request aborted: " << request_id; | 309 DVLOG(1) << "Failed to mark request aborted: " << request_id; |
| 308 event_logger_.RecordUpdateRequestFailed( | 310 RequestQueue::UpdateRequestResult request_result = |
| 309 client_id.name_space, | |
| 310 result->store_state != StoreState::LOADED | 311 result->store_state != StoreState::LOADED |
| 311 ? RequestQueue::UpdateRequestResult::STORE_FAILURE | 312 ? RequestQueue::UpdateRequestResult::STORE_FAILURE |
| 312 : RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST); | 313 : RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; |
| 314 event_logger_.RecordUpdateRequestFailed(client_id.name_space, |
| 315 request_result); |
| 313 } | 316 } |
| 314 } | 317 } |
| 315 | 318 |
| 316 void RequestCoordinator::RemoveRequests( | 319 void RequestCoordinator::RemoveRequests( |
| 317 const std::vector<int64_t>& request_ids, | 320 const std::vector<int64_t>& request_ids, |
| 318 const RemoveRequestsCallback& callback) { | 321 const RemoveRequestsCallback& callback) { |
| 319 bool canceled = CancelActiveRequestIfItMatches(request_ids); | 322 bool canceled = CancelActiveRequestIfItMatches(request_ids); |
| 320 queue_->RemoveRequests( | 323 queue_->RemoveRequests( |
| 321 request_ids, | 324 request_ids, |
| 322 base::Bind(&RequestCoordinator::HandleRemovedRequestsAndCallback, | 325 base::Bind(&RequestCoordinator::HandleRemovedRequestsAndCallback, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 RequestQueue::AddRequestResult result, | 364 RequestQueue::AddRequestResult result, |
| 362 const SavePageRequest& request) { | 365 const SavePageRequest& request) { |
| 363 NotifyAdded(request); | 366 NotifyAdded(request); |
| 364 // Inform the scheduler that we have an outstanding task. | 367 // Inform the scheduler that we have an outstanding task. |
| 365 scheduler_->Schedule(GetTriggerConditions(kUserRequest)); | 368 scheduler_->Schedule(GetTriggerConditions(kUserRequest)); |
| 366 | 369 |
| 367 if (request.user_requested()) | 370 if (request.user_requested()) |
| 368 StartImmediatelyIfConnected(); | 371 StartImmediatelyIfConnected(); |
| 369 } | 372 } |
| 370 | 373 |
| 371 // Called in response to updating a request in the request queue. | 374 void RequestCoordinator::MarkAttemptCompletedDoneCallback( |
| 372 void RequestCoordinator::UpdateRequestCallback( | 375 int64_t request_id, |
| 373 const ClientId& client_id, | 376 const ClientId& client_id, |
| 374 RequestQueue::UpdateRequestResult result) { | 377 std::unique_ptr<UpdateRequestsResult> result) { |
| 375 // If the request succeeded, nothing to do. If it failed, we can't really do | 378 if (IsSingleSuccessResult(result.get())) { |
| 376 // much, so just log it. | 379 NotifyChanged(result->updated_items.at(0)); |
| 377 if (result != RequestQueue::UpdateRequestResult::SUCCESS) { | 380 } else { |
| 378 DVLOG(1) << "Failed to update request attempt details. " | 381 DVLOG(1) << "Failed to mark request completed " << request_id; |
| 379 << static_cast<int>(result); | 382 RequestQueue::UpdateRequestResult request_result = |
| 380 event_logger_.RecordUpdateRequestFailed(client_id.name_space, result); | 383 result->store_state != StoreState::LOADED |
| 384 ? RequestQueue::UpdateRequestResult::STORE_FAILURE |
| 385 : RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; |
| 386 event_logger_.RecordUpdateRequestFailed(client_id.name_space, |
| 387 request_result); |
| 381 } | 388 } |
| 382 } | 389 } |
| 383 | 390 |
| 384 void RequestCoordinator::UpdateMultipleRequestsCallback( | 391 void RequestCoordinator::UpdateMultipleRequestsCallback( |
| 385 std::unique_ptr<UpdateRequestsResult> result) { | 392 std::unique_ptr<UpdateRequestsResult> result) { |
| 386 for (const auto& request : result->updated_items) | 393 for (const auto& request : result->updated_items) |
| 387 NotifyChanged(request); | 394 NotifyChanged(request); |
| 388 | 395 |
| 389 bool available_user_request = false; | 396 bool available_user_request = false; |
| 390 for (const auto& request : result->updated_items) { | 397 for (const auto& request : result->updated_items) { |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 621 const std::string& client_namespace, | 628 const std::string& client_namespace, |
| 622 std::unique_ptr<UpdateRequestsResult> update_result) { | 629 std::unique_ptr<UpdateRequestsResult> update_result) { |
| 623 if (update_result->store_state != StoreState::LOADED || | 630 if (update_result->store_state != StoreState::LOADED || |
| 624 update_result->item_statuses.size() != 1 || | 631 update_result->item_statuses.size() != 1 || |
| 625 update_result->item_statuses.at(0).first != request_id || | 632 update_result->item_statuses.at(0).first != request_id || |
| 626 update_result->item_statuses.at(0).second != ItemActionStatus::SUCCESS) { | 633 update_result->item_statuses.at(0).second != ItemActionStatus::SUCCESS) { |
| 627 is_busy_ = false; | 634 is_busy_ = false; |
| 628 // TODO(fgorski): what is the best result? Do we create a new status? | 635 // TODO(fgorski): what is the best result? Do we create a new status? |
| 629 StopProcessing(Offliner::PRERENDERING_NOT_STARTED); | 636 StopProcessing(Offliner::PRERENDERING_NOT_STARTED); |
| 630 DVLOG(1) << "Failed to mark attempt started: " << request_id; | 637 DVLOG(1) << "Failed to mark attempt started: " << request_id; |
| 631 event_logger_.RecordUpdateRequestFailed( | 638 RequestQueue::UpdateRequestResult request_result = |
| 632 client_namespace, | |
| 633 update_result->store_state != StoreState::LOADED | 639 update_result->store_state != StoreState::LOADED |
| 634 ? RequestQueue::UpdateRequestResult::STORE_FAILURE | 640 ? RequestQueue::UpdateRequestResult::STORE_FAILURE |
| 635 : RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST); | 641 : RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; |
| 642 event_logger_.RecordUpdateRequestFailed(client_namespace, request_result); |
| 636 return; | 643 return; |
| 637 } | 644 } |
| 638 | 645 |
| 639 // TODO(fgorski): Switch to request_id only, so that this value is not written | 646 // TODO(fgorski): Switch to request_id only, so that this value is not written |
| 640 // back to the store. | 647 // back to the store. |
| 641 active_request_.reset( | 648 active_request_.reset( |
| 642 new SavePageRequest(update_result->updated_items.at(0))); | 649 new SavePageRequest(update_result->updated_items.at(0))); |
| 643 | 650 |
| 644 // Start the load and save process in the offliner (Async). | 651 // Start the load and save process in the offliner (Async). |
| 645 if (offliner_->LoadAndSave( | 652 if (offliner_->LoadAndSave( |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 704 // MarkAttemptCompleted within the if branches, the completed_attempt_count | 711 // MarkAttemptCompleted within the if branches, the completed_attempt_count |
| 705 // has not yet been updated when we are checking the if condition. | 712 // has not yet been updated when we are checking the if condition. |
| 706 const BackgroundSavePageResult result( | 713 const BackgroundSavePageResult result( |
| 707 BackgroundSavePageResult::RETRY_COUNT_EXCEEDED); | 714 BackgroundSavePageResult::RETRY_COUNT_EXCEEDED); |
| 708 event_logger_.RecordDroppedSavePageRequest(request.client_id().name_space, | 715 event_logger_.RecordDroppedSavePageRequest(request.client_id().name_space, |
| 709 result, request.request_id()); | 716 result, request.request_id()); |
| 710 RemoveAttemptedRequest(request, result); | 717 RemoveAttemptedRequest(request, result); |
| 711 } else { | 718 } else { |
| 712 // If we failed, but are not over the limit, update the request in the | 719 // If we failed, but are not over the limit, update the request in the |
| 713 // queue. | 720 // queue. |
| 714 SavePageRequest updated_request(request); | 721 queue_->MarkAttemptCompleted( |
| 715 updated_request.MarkAttemptCompleted(); | 722 request.request_id(), |
| 716 queue_->UpdateRequest(updated_request, | 723 base::Bind(&RequestCoordinator::MarkAttemptCompletedDoneCallback, |
| 717 base::Bind(&RequestCoordinator::UpdateRequestCallback, | 724 weak_ptr_factory_.GetWeakPtr(), request.request_id(), |
| 718 weak_ptr_factory_.GetWeakPtr(), | 725 request.client_id())); |
| 719 updated_request.client_id())); | |
| 720 NotifyChanged(updated_request); | |
| 721 } | 726 } |
| 722 | 727 |
| 723 // Determine whether we might try another request in this | 728 // Determine whether we might try another request in this |
| 724 // processing window based on how the previous request completed. | 729 // processing window based on how the previous request completed. |
| 725 switch (status) { | 730 switch (status) { |
| 726 case Offliner::RequestStatus::SAVED: | 731 case Offliner::RequestStatus::SAVED: |
| 727 case Offliner::RequestStatus::SAVE_FAILED: | 732 case Offliner::RequestStatus::SAVE_FAILED: |
| 728 case Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED: | 733 case Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED: |
| 729 case Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT: | 734 case Offliner::RequestStatus::REQUEST_COORDINATOR_TIMED_OUT: |
| 730 case Offliner::RequestStatus::PRERENDERING_FAILED_NO_RETRY: | 735 case Offliner::RequestStatus::PRERENDERING_FAILED_NO_RETRY: |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 814 | 819 |
| 815 ClientPolicyController* RequestCoordinator::GetPolicyController() { | 820 ClientPolicyController* RequestCoordinator::GetPolicyController() { |
| 816 return policy_controller_.get(); | 821 return policy_controller_.get(); |
| 817 } | 822 } |
| 818 | 823 |
| 819 void RequestCoordinator::Shutdown() { | 824 void RequestCoordinator::Shutdown() { |
| 820 network_quality_estimator_ = nullptr; | 825 network_quality_estimator_ = nullptr; |
| 821 } | 826 } |
| 822 | 827 |
| 823 } // namespace offline_pages | 828 } // namespace offline_pages |
| OLD | NEW |