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

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

Issue 2113383002: More detailed implementation of the RequestPicker (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Simplify picker logic for multiple criteria Created 4 years, 5 months 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_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
11 namespace offline_pages { 11 namespace offline_pages {
12 12
13 RequestPicker::RequestPicker( 13 RequestPicker::RequestPicker(
14 RequestQueue* requestQueue) 14 RequestQueue* requestQueue, OfflinerPolicy* policy)
15 : queue_(requestQueue), 15 : queue_(requestQueue),
16 policy_(policy),
16 weak_ptr_factory_(this) {} 17 weak_ptr_factory_(this) {}
17 18
18 RequestPicker::~RequestPicker() {} 19 RequestPicker::~RequestPicker() {}
19 20
21 // Entry point for the async operation to choose the next request.
20 void RequestPicker::ChooseNextRequest( 22 void RequestPicker::ChooseNextRequest(
21 RequestCoordinator::RequestPickedCallback picked_callback, 23 RequestCoordinator::RequestPickedCallback picked_callback,
22 RequestCoordinator::RequestQueueEmptyCallback empty_callback) { 24 RequestCoordinator::RequestQueueEmptyCallback empty_callback,
25 DeviceConditions* device_conditions) {
23 picked_callback_ = picked_callback; 26 picked_callback_ = picked_callback;
24 empty_callback_ = empty_callback; 27 empty_callback_ = empty_callback;
28 current_conditions_.reset(new DeviceConditions(*device_conditions));
25 // Get all requests from queue (there is no filtering mechanism). 29 // Get all requests from queue (there is no filtering mechanism).
26 queue_->GetRequests(base::Bind(&RequestPicker::GetRequestResultCallback, 30 queue_->GetRequests(base::Bind(&RequestPicker::GetRequestResultCallback,
27 weak_ptr_factory_.GetWeakPtr())); 31 weak_ptr_factory_.GetWeakPtr()));
28 } 32 }
29 33
34 // When we get contents from the queue, use them to pick the next
35 // request to operate on (if any).
30 void RequestPicker::GetRequestResultCallback( 36 void RequestPicker::GetRequestResultCallback(
31 RequestQueue::GetRequestsResult, 37 RequestQueue::GetRequestsResult,
32 const std::vector<SavePageRequest>& requests) { 38 const std::vector<SavePageRequest>& requests) {
33 // If there is nothing to do, return right away. 39 // If there is nothing to do, return right away.
34 if (requests.size() == 0) { 40 if (requests.size() == 0) {
35 empty_callback_.Run(); 41 empty_callback_.Run();
36 return; 42 return;
37 } 43 }
38 44
39 // Pick the most deserving request for our conditions. 45 // Pick the most deserving request for our conditions.
40 const SavePageRequest& picked_request = requests[0]; 46 const SavePageRequest* picked_request = nullptr;
41 47
42 // When we have a best request to try next, get the request coodinator to 48 // Iterate once through the requests, keeping track of best candidate.
43 // start it. 49 for (unsigned i = 0; i < requests.size(); ++i) {
44 picked_callback_.Run(picked_request); 50 if (!RequestConditionsSatisfied(requests[i])) {
fgorski 2016/07/20 16:23:31 nit: {} not needed
Pete Williamson 2016/07/20 19:50:44 Done.
51 continue;
fgorski 2016/07/20 16:23:31 nit: indentation
Pete Williamson 2016/07/20 19:50:44 Done.
52 }
53 if (IsNewRequestBetter(picked_request, &(requests[i])))
54 picked_request = &(requests[i]);
55 }
56
57 // If we have a best request to try next, get the request coodinator to
58 // start it. Otherwise return that we have no candidates.
59 if (picked_request != nullptr) {
60 picked_callback_.Run(*picked_request);
61 } else {
62 empty_callback_.Run();
63 }
64 }
65
66 // Filter out requests that don't meet the current conditions. For instance, if
67 // this is a predictive request, and we are not on WiFi, it should be ignored
68 // this round.
69 bool RequestPicker::RequestConditionsSatisfied(const SavePageRequest& request) {
70 // If the user did not request the page directly, make sure we are connected
71 // to power and have WiFi and sufficient battery remaining before we take this
72 // reqeust.
73 // TODO(petewil): We may later want to configure whether to allow 2G for non
74 // user_requested items, add that to policy.
75 if (!request.user_requested()) {
76 if (!current_conditions_->IsPowerConnected())
77 return false;
78
79 if (current_conditions_->GetNetConnectionType() !=
80 net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI) {
81 return false;
82 }
83
84 if (current_conditions_->GetBatteryPercentage() <
85 policy_->GetMinimumBatteryPercentageForNonUserRequestOfflining()) {
86 return false;
87 }
88 }
89
90 // If we have already tried this page the max number of times, it is not
91 // eligible to try again.
92 // TODO(petewil): Instead, we should have code to remove the page from the
93 // queue after the last retry.
94 if (request.attempt_count() >= policy_->GetMaxRetries())
95 return false;
96
97 // If this request is not active yet, return false.
98 if (request.activation_time() > base::Time::Now())
99 return false;
100
101 return true;
102 }
103
104 // Look at policies to decide which requests to prefer.
105 bool RequestPicker::IsNewRequestBetter(
106 const SavePageRequest* oldRequest, const SavePageRequest* newRequest) {
107
108 // If there is no old request, the new one is better.
109 if (oldRequest == nullptr)
110 return true;
111
112 // User requested pages get priority.
113 if (newRequest->user_requested() && !oldRequest->user_requested())
114 return true;
115
116 ComparisonResult retryCountPreference =
117 IsNewRequestRetryCountBetter(oldRequest, newRequest);
118 ComparisonResult recencyPreference =
119 IsNewRequestRecencyBetter(oldRequest, newRequest);
120
121 // Check to see if we should prefer RetryCount or Recency as the primary
122 // deciding factor.
123 if (policy_->RetryCountIsMoreImportantThanRecency()) {
124 // Check retry count first, then recency.
125 if (retryCountPreference != Same) {
fgorski 2016/07/20 16:23:31 This use of result both here and below (specifical
Pete Williamson 2016/07/20 19:50:44 OK, per our discussion, I will try an alternate ap
126 return (retryCountPreference == Better);
127 } else {
128 return (recencyPreference == Better);
129 }
130 } else {
131 // Check recency first, then retry count.
132 if (recencyPreference != Same) {
133 return (recencyPreference == Better);
134 } else {
135 return (retryCountPreference == Better);
136 }
137 }
138
139 // If we have no preference, defailt to prefering the old request.
140 return false;
141 }
142
143 // Is the new request better as regards retry count?
144 ComparisonResult RequestPicker::IsNewRequestRetryCountBetter(
fgorski 2016/07/20 16:23:31 I have 2 concerns with these implementations. 1) T
145 const SavePageRequest* oldRequest, const SavePageRequest* newRequest) {
146 // If the retry counts are equal, we have no preference.
fgorski 2016/07/20 16:23:31 This is self evident in the code. (A lot of your c
Pete Williamson 2016/07/20 19:50:44 Done. (My thinking was that this is a bit convolu
147 if (newRequest->attempt_count() == oldRequest->attempt_count())
fgorski 2016/07/20 16:23:31 nit: aligment
Pete Williamson 2016/07/20 19:50:44 Done.
148 return Same;
149
150 // Check the policy to see if we should prefer more tried or less tried
151 // requests.
152 if (policy_->ShouldPreferTriedRequests()) {
153 // We prefer more-tried requests.
154 if (newRequest->attempt_count() > oldRequest->attempt_count())
155 return Better;
156 } else {
157 // We prefer less-tried requests.
158 if (newRequest->attempt_count() < oldRequest->attempt_count())
159 return Better;
160 }
161
162 // If we found that this wasn't as good in the area of request count,
163 // then we prefer the old request, and exit now.
164 return Worse;
165
fgorski 2016/07/20 16:23:31 nit: empty line is not needed here.
Pete Williamson 2016/07/20 19:50:44 Done.
166 }
167
168 // Is the new request better in regard to how long ago it was created?
169 ComparisonResult RequestPicker::IsNewRequestRecencyBetter(
170 const SavePageRequest* oldRequest, const SavePageRequest* newRequest) {
171 // In theory requests should not have the same creation time, but if they do,
172 // we call them equivalent.
173 if (newRequest->creation_time() == oldRequest->creation_time())
174 return Same;
175
176 // Should we prefer earlier requests or later ones?
177 if (policy_->ShouldPreferEarlierRequests()) {
178 // We prefer requests made earlier.
179 if (newRequest->creation_time() < oldRequest->creation_time()) {
180 return Better;
181 }
182 } else {
183 // We prefer requests made more recently.
184 if (newRequest->creation_time() < oldRequest->creation_time())
185 return Better;
186 }
187
188 return Worse;
45 } 189 }
46 190
47 } // namespace offline_pages 191 } // namespace offline_pages
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698