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

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

Issue 2489443002: Move all components/offline_pages/ files into component/offline_pages/core (Closed)
Patch Set: rebase Created 4 years 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/offline_pages/background/pick_request_task.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/time/time.h"
10 #include "components/offline_pages/background/device_conditions.h"
11 #include "components/offline_pages/background/offliner_policy.h"
12 #include "components/offline_pages/background/offliner_policy_utils.h"
13 #include "components/offline_pages/background/request_coordinator_event_logger.h "
14 #include "components/offline_pages/background/request_notifier.h"
15 #include "components/offline_pages/background/request_queue_store.h"
16 #include "components/offline_pages/background/save_page_request.h"
17
18 namespace {
19 template <typename T>
20 int signum(T t) {
21 return (T(0) < t) - (t < T(0));
22 }
23
24 bool kCleanupNeeded = true;
25 bool kNonUserRequestsFound = true;
26
27 #define CALL_MEMBER_FUNCTION(object, ptrToMember) ((object)->*(ptrToMember))
28 } // namespace
29
30 namespace offline_pages {
31
32 PickRequestTask::PickRequestTask(RequestQueueStore* store,
33 OfflinerPolicy* policy,
34 RequestPickedCallback picked_callback,
35 RequestNotPickedCallback not_picked_callback,
36 RequestCountCallback request_count_callback,
37 DeviceConditions& device_conditions,
38 const std::set<int64_t>& disabled_requests)
39 : store_(store),
40 policy_(policy),
41 picked_callback_(picked_callback),
42 not_picked_callback_(not_picked_callback),
43 request_count_callback_(request_count_callback),
44 disabled_requests_(disabled_requests),
45 weak_ptr_factory_(this) {
46 device_conditions_.reset(new DeviceConditions(device_conditions));
47 }
48
49 PickRequestTask::~PickRequestTask() {}
50
51 void PickRequestTask::Run() {
52 GetRequests();
53 }
54
55 void PickRequestTask::GetRequests() {
56 // Get all the requests from the queue, we will classify them in the callback.
57 store_->GetRequests(
58 base::Bind(&PickRequestTask::Choose, weak_ptr_factory_.GetWeakPtr()));
59 }
60
61 void PickRequestTask::Choose(
62 bool success,
63 std::vector<std::unique_ptr<SavePageRequest>> requests) {
64 // If there is nothing to do, return right away.
65 if (requests.empty()) {
66 request_count_callback_.Run(requests.size(), 0);
67 not_picked_callback_.Run(!kNonUserRequestsFound, !kCleanupNeeded);
68 TaskComplete();
69 return;
70 }
71
72 // Pick the most deserving request for our conditions.
73 const SavePageRequest* picked_request = nullptr;
74
75 RequestCompareFunction comparator = nullptr;
76
77 // Choose which comparison function to use based on policy.
78 if (policy_->RetryCountIsMoreImportantThanRecency())
79 comparator = &PickRequestTask::RetryCountFirstCompareFunction;
80 else
81 comparator = &PickRequestTask::RecencyFirstCompareFunction;
82
83 // TODO(petewil): Consider replacing this bool with a better named enum.
84 bool non_user_requested_tasks_remaining = false;
85 bool cleanup_needed = false;
86
87 size_t available_request_count = 0;
88
89 // Iterate once through the requests, keeping track of best candidate.
90 for (unsigned i = 0; i < requests.size(); ++i) {
91 // If the request is expired or has exceeded the retry count, skip it.
92 if (OfflinerPolicyUtils::CheckRequestExpirationStatus(requests[i].get(),
93 policy_) !=
94 OfflinerPolicyUtils::RequestExpirationStatus::VALID) {
95 cleanup_needed = true;
96 continue;
97 }
98
99 // If the request is on the disabled list, skip it.
100 auto search = disabled_requests_.find(requests[i]->request_id());
101 if (search != disabled_requests_.end())
102 continue;
103
104 // If there are non-user-requested tasks remaining, we need to make sure
105 // that they are scheduled after we run out of user requested tasks. Here we
106 // detect if any exist. If we don't find any user-requested tasks, we will
107 // inform the "not_picked_callback_" that it needs to schedule a task for
108 // non-user-requested items, which have different network and power needs.
109 if (!requests[i]->user_requested())
110 non_user_requested_tasks_remaining = true;
111 if (requests[i]->request_state() ==
112 SavePageRequest::RequestState::AVAILABLE) {
113 available_request_count++;
114 }
115 if (!RequestConditionsSatisfied(requests[i].get()))
116 continue;
117 if (IsNewRequestBetter(picked_request, requests[i].get(), comparator))
118 picked_request = requests[i].get();
119 }
120
121 // Report the request queue counts.
122 request_count_callback_.Run(requests.size(), available_request_count);
123
124 // If we have a best request to try next, get the request coodinator to
125 // start it. Otherwise return that we have no candidates.
126 if (picked_request != nullptr) {
127 picked_callback_.Run(*picked_request, cleanup_needed);
128 } else {
129 not_picked_callback_.Run(non_user_requested_tasks_remaining,
130 cleanup_needed);
131 }
132
133 TaskComplete();
134 }
135
136 // Filter out requests that don't meet the current conditions. For instance, if
137 // this is a predictive request, and we are not on WiFi, it should be ignored
138 // this round.
139 bool PickRequestTask::RequestConditionsSatisfied(
140 const SavePageRequest* request) {
141 // If the user did not request the page directly, make sure we are connected
142 // to power and have WiFi and sufficient battery remaining before we take this
143 // request.
144 if (!device_conditions_->IsPowerConnected() &&
145 policy_->PowerRequired(request->user_requested())) {
146 return false;
147 }
148
149 if (device_conditions_->GetNetConnectionType() !=
150 net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI &&
151 policy_->UnmeteredNetworkRequired(request->user_requested())) {
152 return false;
153 }
154
155 if (device_conditions_->GetBatteryPercentage() <
156 policy_->BatteryPercentageRequired(request->user_requested())) {
157 return false;
158 }
159
160 // If the request is paused, do not consider it.
161 if (request->request_state() == SavePageRequest::RequestState::PAUSED)
162 return false;
163
164 // If this request is not active yet, return false.
165 // TODO(petewil): If the only reason we return nothing to do is that we have
166 // inactive requests, we still want to try again later after their activation
167 // time elapses, we shouldn't take ourselves completely off the scheduler.
168 if (request->activation_time() > base::Time::Now())
169 return false;
170
171 return true;
172 }
173
174 // Look at policies to decide which requests to prefer.
175 bool PickRequestTask::IsNewRequestBetter(const SavePageRequest* oldRequest,
176 const SavePageRequest* newRequest,
177 RequestCompareFunction comparator) {
178 // If there is no old request, the new one is better.
179 if (oldRequest == nullptr)
180 return true;
181
182 // User requested pages get priority.
183 if (newRequest->user_requested() && !oldRequest->user_requested())
184 return true;
185
186 // Otherwise, use the comparison function for the current policy, which
187 // returns true if the older request is better.
188 return !(CALL_MEMBER_FUNCTION(this, comparator)(oldRequest, newRequest));
189 }
190
191 // Compare the results, checking request count before recency. Returns true if
192 // left hand side is better, false otherwise.
193 bool PickRequestTask::RetryCountFirstCompareFunction(
194 const SavePageRequest* left,
195 const SavePageRequest* right) {
196 // Check the attempt count.
197 int result = CompareRetryCount(left, right);
198
199 if (result != 0)
200 return (result > 0);
201
202 // If we get here, the attempt counts were the same, so check recency.
203 result = CompareCreationTime(left, right);
204
205 return (result > 0);
206 }
207
208 // Compare the results, checking recency before request count. Returns true if
209 // left hand side is better, false otherwise.
210 bool PickRequestTask::RecencyFirstCompareFunction(
211 const SavePageRequest* left,
212 const SavePageRequest* right) {
213 // Check the recency.
214 int result = CompareCreationTime(left, right);
215
216 if (result != 0)
217 return (result > 0);
218
219 // If we get here, the recency was the same, so check the attempt count.
220 result = CompareRetryCount(left, right);
221
222 return (result > 0);
223 }
224
225 // Compare left and right side, returning 1 if the left side is better
226 // (preferred by policy), 0 if the same, and -1 if the right side is better.
227 int PickRequestTask::CompareRetryCount(const SavePageRequest* left,
228 const SavePageRequest* right) {
229 // Check the attempt count.
230 int result = signum(left->completed_attempt_count() -
231 right->completed_attempt_count());
232
233 // Flip the direction of comparison if policy prefers fewer retries.
234 if (policy_->ShouldPreferUntriedRequests())
235 result *= -1;
236
237 return result;
238 }
239
240 // Compare left and right side, returning 1 if the left side is better
241 // (preferred by policy), 0 if the same, and -1 if the right side is better.
242 int PickRequestTask::CompareCreationTime(const SavePageRequest* left,
243 const SavePageRequest* right) {
244 // Check the recency.
245 base::TimeDelta difference = left->creation_time() - right->creation_time();
246 int result = signum(difference.InMilliseconds());
247
248 // Flip the direction of comparison if policy prefers fewer retries.
249 if (policy_->ShouldPreferEarlierRequests())
250 result *= -1;
251
252 return result;
253 }
254
255 } // namespace offline_pages
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698