Index: components/offline_pages/core/background/pick_request_task.cc |
diff --git a/components/offline_pages/core/background/pick_request_task.cc b/components/offline_pages/core/background/pick_request_task.cc |
index 006d08b47aff2211d377e6869f8b95e49273185f..516b09947006278963bd09ad5b93df6de135d6ee 100644 |
--- a/components/offline_pages/core/background/pick_request_task.cc |
+++ b/components/offline_pages/core/background/pick_request_task.cc |
@@ -4,6 +4,8 @@ |
#include "components/offline_pages/core/background/pick_request_task.h" |
+#include <unordered_set> |
+ |
#include "base/bind.h" |
#include "base/logging.h" |
#include "base/time/time.h" |
@@ -35,13 +37,15 @@ PickRequestTask::PickRequestTask(RequestQueueStore* store, |
RequestNotPickedCallback not_picked_callback, |
RequestCountCallback request_count_callback, |
DeviceConditions& device_conditions, |
- const std::set<int64_t>& disabled_requests) |
+ const std::set<int64_t>& disabled_requests, |
+ std::deque<int64_t>& prioritized_requests) |
: store_(store), |
policy_(policy), |
picked_callback_(picked_callback), |
not_picked_callback_(not_picked_callback), |
request_count_callback_(request_count_callback), |
disabled_requests_(disabled_requests), |
+ prioritized_requests_(prioritized_requests), |
weak_ptr_factory_(this) { |
device_conditions_.reset(new DeviceConditions(device_conditions)); |
} |
@@ -85,19 +89,22 @@ void PickRequestTask::Choose( |
bool cleanup_needed = false; |
size_t available_request_count = 0; |
+ // Request ids which are available for picking. |
+ std::unordered_set<int64_t> available_request_ids; |
- // Iterate once through the requests, keeping track of best candidate. |
- for (unsigned i = 0; i < requests.size(); ++i) { |
+ // Iterate through the requests, filter out unavailable requests and get other |
+ // information (if cleanup is needed and number of non-user-requested |
+ // requests). |
+ for (const auto& request : requests) { |
// If the request is expired or has exceeded the retry count, skip it. |
- if (OfflinerPolicyUtils::CheckRequestExpirationStatus(requests[i].get(), |
+ if (OfflinerPolicyUtils::CheckRequestExpirationStatus(request.get(), |
policy_) != |
OfflinerPolicyUtils::RequestExpirationStatus::VALID) { |
cleanup_needed = true; |
continue; |
} |
- |
- // If the request is on the disabled list, skip it. |
- auto search = disabled_requests_.find(requests[i]->request_id()); |
+ // If the request is on the disabled list, skip it. |
+ auto search = disabled_requests_.find(request->request_id()); |
if (search != disabled_requests_.end()) |
continue; |
@@ -106,21 +113,50 @@ void PickRequestTask::Choose( |
// detect if any exist. If we don't find any user-requested tasks, we will |
// inform the "not_picked_callback_" that it needs to schedule a task for |
// non-user-requested items, which have different network and power needs. |
- if (!requests[i]->user_requested()) |
+ if (!request->user_requested()) |
non_user_requested_tasks_remaining = true; |
- if (requests[i]->request_state() == |
- SavePageRequest::RequestState::AVAILABLE) { |
+ if (request->request_state() == SavePageRequest::RequestState::AVAILABLE) { |
available_request_count++; |
} |
- if (!RequestConditionsSatisfied(requests[i].get())) |
+ if (!RequestConditionsSatisfied(request.get())) |
continue; |
- if (IsNewRequestBetter(picked_request, requests[i].get(), comparator)) |
- picked_request = requests[i].get(); |
+ available_request_ids.insert(request->request_id()); |
} |
- |
// Report the request queue counts. |
request_count_callback_.Run(requests.size(), available_request_count); |
+ // Search for and pick the prioritized request which is available for picking |
+ // from |available_request_ids|, the closer to the end means higher priority. |
+ // Also if a request in |prioritized_requests_| doesn't exist in |requests| |
+ // we're going to remove it. |
+ // For every ID in |available_request_ids|, there exists a corresponding |
+ // request in |requests|, so this won't be an infinite loop: either we pick a |
+ // request, or there's a request being poped from |prioritized_requests_|. |
+ while (!picked_request && !prioritized_requests_.empty()) { |
+ if (available_request_ids.count(prioritized_requests_.back()) > 0) { |
+ for (const auto& request : requests) { |
+ if (request->request_id() == prioritized_requests_.back()) { |
+ picked_request = request.get(); |
+ break; |
+ } |
+ } |
+ DCHECK(picked_request); |
+ } else { |
+ prioritized_requests_.pop_back(); |
+ } |
+ } |
+ |
+ // If no request was found from the priority list, find the best request |
+ // according to current policies. |
+ if (!picked_request) { |
+ for (const auto& request : requests) { |
+ if ((available_request_ids.count(request->request_id()) > 0) && |
+ (IsNewRequestBetter(picked_request, request.get(), comparator))) { |
+ picked_request = request.get(); |
+ } |
+ } |
+ } |
+ |
// If we have a best request to try next, get the request coodinator to |
// start it. Otherwise return that we have no candidates. |
if (picked_request != nullptr) { |