| 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_picker.h" | 5 #include "components/offline_pages/background/request_picker.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "components/offline_pages/background/save_page_request.h" | 9 #include "components/offline_pages/background/save_page_request.h" |
| 10 | 10 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 notifier_(notifier), | 27 notifier_(notifier), |
| 28 fewer_retries_better_(false), | 28 fewer_retries_better_(false), |
| 29 earlier_requests_better_(false), | 29 earlier_requests_better_(false), |
| 30 weak_ptr_factory_(this) {} | 30 weak_ptr_factory_(this) {} |
| 31 | 31 |
| 32 RequestPicker::~RequestPicker() {} | 32 RequestPicker::~RequestPicker() {} |
| 33 | 33 |
| 34 // Entry point for the async operation to choose the next request. | 34 // Entry point for the async operation to choose the next request. |
| 35 void RequestPicker::ChooseNextRequest( | 35 void RequestPicker::ChooseNextRequest( |
| 36 RequestCoordinator::RequestPickedCallback picked_callback, | 36 RequestCoordinator::RequestPickedCallback picked_callback, |
| 37 RequestCoordinator::RequestQueueEmptyCallback empty_callback, | 37 RequestCoordinator::RequestNotPickedCallback not_picked_callback, |
| 38 DeviceConditions* device_conditions) { | 38 DeviceConditions* device_conditions) { |
| 39 picked_callback_ = picked_callback; | 39 picked_callback_ = picked_callback; |
| 40 empty_callback_ = empty_callback; | 40 not_picked_callback_ = not_picked_callback; |
| 41 fewer_retries_better_ = policy_->ShouldPreferUntriedRequests(); | 41 fewer_retries_better_ = policy_->ShouldPreferUntriedRequests(); |
| 42 earlier_requests_better_ = policy_->ShouldPreferEarlierRequests(); | 42 earlier_requests_better_ = policy_->ShouldPreferEarlierRequests(); |
| 43 current_conditions_.reset(new DeviceConditions(*device_conditions)); | 43 current_conditions_.reset(new DeviceConditions(*device_conditions)); |
| 44 // Get all requests from queue (there is no filtering mechanism). | 44 // Get all requests from queue (there is no filtering mechanism). |
| 45 queue_->GetRequests(base::Bind(&RequestPicker::GetRequestResultCallback, | 45 queue_->GetRequests(base::Bind(&RequestPicker::GetRequestResultCallback, |
| 46 weak_ptr_factory_.GetWeakPtr())); | 46 weak_ptr_factory_.GetWeakPtr())); |
| 47 } | 47 } |
| 48 | 48 |
| 49 // When we get contents from the queue, use them to pick the next | 49 // When we get contents from the queue, use them to pick the next |
| 50 // request to operate on (if any). | 50 // request to operate on (if any). |
| 51 void RequestPicker::GetRequestResultCallback( | 51 void RequestPicker::GetRequestResultCallback( |
| 52 RequestQueue::GetRequestsResult, | 52 RequestQueue::GetRequestsResult, |
| 53 const std::vector<SavePageRequest>& requests) { | 53 const std::vector<SavePageRequest>& requests) { |
| 54 // If there is nothing to do, return right away. | 54 // If there is nothing to do, return right away. |
| 55 if (requests.size() == 0) { | 55 if (requests.size() == 0) { |
| 56 empty_callback_.Run(); | 56 not_picked_callback_.Run(false); |
| 57 return; | 57 return; |
| 58 } | 58 } |
| 59 | 59 |
| 60 // Get the expired requests to be removed from the queue, and the valid ones | 60 // Get the expired requests to be removed from the queue, and the valid ones |
| 61 // from which to pick the next request. | 61 // from which to pick the next request. |
| 62 std::vector<SavePageRequest> valid_requests; | 62 std::vector<SavePageRequest> valid_requests; |
| 63 std::vector<SavePageRequest> expired_requests; | 63 std::vector<SavePageRequest> expired_requests; |
| 64 SplitRequests(requests, valid_requests, expired_requests); | 64 SplitRequests(requests, valid_requests, expired_requests); |
| 65 std::vector<int64_t> expired_request_ids; | 65 std::vector<int64_t> expired_request_ids; |
| 66 for (auto request : expired_requests) | 66 for (auto request : expired_requests) |
| 67 expired_request_ids.push_back(request.request_id()); | 67 expired_request_ids.push_back(request.request_id()); |
| 68 | 68 |
| 69 queue_->RemoveRequests(expired_request_ids, | 69 queue_->RemoveRequests(expired_request_ids, |
| 70 base::Bind(&RequestPicker::OnRequestExpired, | 70 base::Bind(&RequestPicker::OnRequestExpired, |
| 71 weak_ptr_factory_.GetWeakPtr())); | 71 weak_ptr_factory_.GetWeakPtr())); |
| 72 | 72 |
| 73 // Pick the most deserving request for our conditions. | 73 // Pick the most deserving request for our conditions. |
| 74 const SavePageRequest* picked_request = nullptr; | 74 const SavePageRequest* picked_request = nullptr; |
| 75 | 75 |
| 76 RequestCompareFunction comparator = nullptr; | 76 RequestCompareFunction comparator = nullptr; |
| 77 | 77 |
| 78 // Choose which comparison function to use based on policy. | 78 // Choose which comparison function to use based on policy. |
| 79 if (policy_->RetryCountIsMoreImportantThanRecency()) | 79 if (policy_->RetryCountIsMoreImportantThanRecency()) |
| 80 comparator = &RequestPicker::RetryCountFirstCompareFunction; | 80 comparator = &RequestPicker::RetryCountFirstCompareFunction; |
| 81 else | 81 else |
| 82 comparator = &RequestPicker::RecencyFirstCompareFunction; | 82 comparator = &RequestPicker::RecencyFirstCompareFunction; |
| 83 | 83 |
| 84 // Iterate once through the requests, keeping track of best candidate. | 84 // Iterate once through the requests, keeping track of best candidate. |
| 85 bool non_user_requested_tasks_remaining = false; |
| 85 for (unsigned i = 0; i < valid_requests.size(); ++i) { | 86 for (unsigned i = 0; i < valid_requests.size(); ++i) { |
| 87 if (!valid_requests[i].user_requested()) |
| 88 non_user_requested_tasks_remaining = true; |
| 86 if (!RequestConditionsSatisfied(valid_requests[i])) | 89 if (!RequestConditionsSatisfied(valid_requests[i])) |
| 87 continue; | 90 continue; |
| 88 if (IsNewRequestBetter(picked_request, &(valid_requests[i]), comparator)) | 91 if (IsNewRequestBetter(picked_request, &(valid_requests[i]), comparator)) |
| 89 picked_request = &(valid_requests[i]); | 92 picked_request = &(valid_requests[i]); |
| 90 } | 93 } |
| 91 | 94 |
| 92 // If we have a best request to try next, get the request coodinator to | 95 // If we have a best request to try next, get the request coodinator to |
| 93 // start it. Otherwise return that we have no candidates. | 96 // start it. Otherwise return that we have no candidates. |
| 94 if (picked_request != nullptr) { | 97 if (picked_request != nullptr) { |
| 95 picked_callback_.Run(*picked_request); | 98 picked_callback_.Run(*picked_request); |
| 96 } else { | 99 } else { |
| 97 empty_callback_.Run(); | 100 not_picked_callback_.Run(non_user_requested_tasks_remaining); |
| 98 } | 101 } |
| 99 } | 102 } |
| 100 | 103 |
| 101 // Filter out requests that don't meet the current conditions. For instance, if | 104 // Filter out requests that don't meet the current conditions. For instance, if |
| 102 // this is a predictive request, and we are not on WiFi, it should be ignored | 105 // this is a predictive request, and we are not on WiFi, it should be ignored |
| 103 // this round. | 106 // this round. |
| 104 bool RequestPicker::RequestConditionsSatisfied(const SavePageRequest& request) { | 107 bool RequestPicker::RequestConditionsSatisfied(const SavePageRequest& request) { |
| 105 // If the user did not request the page directly, make sure we are connected | 108 // If the user did not request the page directly, make sure we are connected |
| 106 // to power and have WiFi and sufficient battery remaining before we take this | 109 // to power and have WiFi and sufficient battery remaining before we take this |
| 107 // request. | 110 // request. |
| 108 // TODO(petewil): We may later want to configure whether to allow 2G for non | |
| 109 // user_requested items, add that to policy. | |
| 110 if (!request.user_requested()) { | |
| 111 if (!current_conditions_->IsPowerConnected()) | |
| 112 return false; | |
| 113 | 111 |
| 114 if (current_conditions_->GetNetConnectionType() != | 112 if (!current_conditions_->IsPowerConnected() && |
| 115 net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI) { | 113 policy_->PowerRequired(request.user_requested())) { |
| 116 return false; | 114 return false; |
| 117 } | 115 } |
| 118 | 116 |
| 119 if (current_conditions_->GetBatteryPercentage() < | 117 if (current_conditions_->GetNetConnectionType() != |
| 120 policy_->GetMinimumBatteryPercentageForNonUserRequestOfflining()) { | 118 net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI && |
| 121 return false; | 119 policy_->UnmeteredNetworkRequired(request.user_requested())) { |
| 122 } | 120 return false; |
| 121 } |
| 122 |
| 123 if (current_conditions_->GetBatteryPercentage() < |
| 124 policy_->BatteryPercentageRequired(request.user_requested())) { |
| 125 return false; |
| 123 } | 126 } |
| 124 | 127 |
| 125 // If we have already started this page the max number of times, it is not | 128 // If we have already started this page the max number of times, it is not |
| 126 // eligible to try again. | 129 // eligible to try again. |
| 127 // TODO(petewil): We should have code to remove the page from the | 130 // TODO(petewil): We should have code to remove the page from the |
| 128 // queue after the last retry. | 131 // queue after the last retry. |
| 129 if (request.started_attempt_count() >= policy_->GetMaxStartedTries()) | 132 if (request.started_attempt_count() >= policy_->GetMaxStartedTries()) |
| 130 return false; | 133 return false; |
| 131 | 134 |
| 132 // If we have already completed trying this page the max number of times, it | 135 // If we have already completed trying this page the max number of times, it |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 // the coordinator. | 260 // the coordinator. |
| 258 void RequestPicker::OnRequestExpired( | 261 void RequestPicker::OnRequestExpired( |
| 259 const RequestQueue::UpdateMultipleRequestResults& results, | 262 const RequestQueue::UpdateMultipleRequestResults& results, |
| 260 const std::vector<SavePageRequest>& requests) { | 263 const std::vector<SavePageRequest>& requests) { |
| 261 for (auto request : requests) | 264 for (auto request : requests) |
| 262 notifier_->NotifyCompleted(request, | 265 notifier_->NotifyCompleted(request, |
| 263 RequestCoordinator::SavePageStatus::EXPIRED); | 266 RequestCoordinator::SavePageStatus::EXPIRED); |
| 264 } | 267 } |
| 265 | 268 |
| 266 } // namespace offline_pages | 269 } // namespace offline_pages |
| OLD | NEW |