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

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: second round of CR comments 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 {
12 const int kEquiavalentRequest = 0;
dougarnett 2016/07/19 20:49:10 spelling
dougarnett 2016/07/19 20:49:11 Consider defining enum
Pete Williamson 2016/07/19 22:35:18 Changed to enum, renamed it.
Pete Williamson 2016/07/19 22:35:18 Done.
13 const int kBetterRequest = 1;
14 const int kWorseRequest = 2;
15 } // namespace
16
11 namespace offline_pages { 17 namespace offline_pages {
12 18
13 RequestPicker::RequestPicker( 19 RequestPicker::RequestPicker(
14 RequestQueue* requestQueue) 20 RequestQueue* requestQueue, OfflinerPolicy* policy)
15 : queue_(requestQueue), 21 : queue_(requestQueue),
22 policy_(policy),
16 weak_ptr_factory_(this) {} 23 weak_ptr_factory_(this) {}
17 24
18 RequestPicker::~RequestPicker() {} 25 RequestPicker::~RequestPicker() {}
19 26
27 // Entry point for the async operation to choose the next request.
20 void RequestPicker::ChooseNextRequest( 28 void RequestPicker::ChooseNextRequest(
21 RequestCoordinator::RequestPickedCallback picked_callback, 29 RequestCoordinator::RequestPickedCallback picked_callback,
22 RequestCoordinator::RequestQueueEmptyCallback empty_callback) { 30 RequestCoordinator::RequestQueueEmptyCallback empty_callback,
31 DeviceConditions* device_conditions) {
23 picked_callback_ = picked_callback; 32 picked_callback_ = picked_callback;
24 empty_callback_ = empty_callback; 33 empty_callback_ = empty_callback;
34 current_conditions_.reset(new DeviceConditions(*device_conditions));
25 // Get all requests from queue (there is no filtering mechanism). 35 // Get all requests from queue (there is no filtering mechanism).
26 queue_->GetRequests(base::Bind(&RequestPicker::GetRequestResultCallback, 36 queue_->GetRequests(base::Bind(&RequestPicker::GetRequestResultCallback,
27 weak_ptr_factory_.GetWeakPtr())); 37 weak_ptr_factory_.GetWeakPtr()));
28 } 38 }
29 39
40 // When we get contents from the queue, use them to pick the next
41 // request to operate on (if any).
30 void RequestPicker::GetRequestResultCallback( 42 void RequestPicker::GetRequestResultCallback(
31 RequestQueue::GetRequestsResult, 43 RequestQueue::GetRequestsResult,
32 const std::vector<SavePageRequest>& requests) { 44 const std::vector<SavePageRequest>& requests) {
33 // If there is nothing to do, return right away. 45 // If there is nothing to do, return right away.
34 if (requests.size() == 0) { 46 if (requests.size() == 0) {
35 empty_callback_.Run(); 47 empty_callback_.Run();
36 return; 48 return;
37 } 49 }
38 50
39 // Pick the most deserving request for our conditions. 51 // Pick the most deserving request for our conditions.
40 const SavePageRequest& picked_request = requests[0]; 52 const SavePageRequest* picked_request = nullptr;
41 53
42 // When we have a best request to try next, get the request coodinator to 54 // Iterate once through the requests, keeping track of best candidate.
43 // start it. 55 for (unsigned i = 0; i < requests.size(); ++i) {
44 picked_callback_.Run(picked_request); 56 if (!RequestConditionsSatisfied(requests[i])) {
57 continue;
58 }
59 if (IsNewRequestBetter(picked_request, &(requests[i])))
60 picked_request = &(requests[i]);
61 }
62
63 // If we have a best request to try next, get the request coodinator to
64 // start it. Otherwise return that we have no candidates.
65 if (picked_request != nullptr) {
66 picked_callback_.Run(*picked_request);
67 } else {
68 empty_callback_.Run();
69 }
70 }
71
72 // Filter out requests that don't meet the current conditions. For instance, if
73 // this is a predictive request, and we are not on WiFi, it should be ignored
74 // this round.
75 bool RequestPicker::RequestConditionsSatisfied(const SavePageRequest& request) {
76 // If the user did not request the page directly, make sure we are connected
77 // to power and have WiFi and sufficient battery remaining before we take this
78 // reqeust.
79 // TODO(petewil): We may later want to configure whether to allow 2G for non
80 // user_requested items, add that to policy.
81 if (!request.user_requested()) {
82 if (!current_conditions_->IsPowerConnected())
83 return false;
84
85 if (current_conditions_->GetNetConnectionType() !=
86 net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI) {
87 return false;
88 }
89
90 if (current_conditions_->GetBatteryPercentage() <
91 policy_->GetMinimumBatteryPercentageForNonUserRequestOfflining()) {
92 return false;
93 }
94 }
95
96 // If we have already tried this page the max number of times, it is not
97 // eligible to try again.
98 // TODO(petewil): Instead, we should have code to remove the page from the
99 // queue after the last retry.
100 if (request.attempt_count() >= policy_->GetMaxRetries())
101 return false;
102
103 // If this request is not active yet, return false.
104 if (request.activation_time() > base::Time::Now())
105 return false;
106
107 return true;
108 }
109
110 // Look at policies to decide which requests to prefer.
111 bool RequestPicker::IsNewRequestBetter(
112 const SavePageRequest* oldRequest, const SavePageRequest* newRequest) {
113
114 // If there is no old request, the new one is better.
115 if (oldRequest == nullptr)
116 return true;
117
118 // User requested pages get priority.
119 if (newRequest->user_requested() && !oldRequest->user_requested())
120 return true;
121
122 int preference = kEquiavalentRequest;
123 // First, see if we can decide based on the retry count.
124 if (policy_->RetryCountIsMoreImportantThanRecency()) {
dougarnett 2016/07/19 20:49:11 As we discussed, still more complicated than we'd
Pete Williamson 2016/07/19 22:35:18 Done.
125 // Check retry count first, then recency.
126 preference = IsNewRequestRetryCountBetter(oldRequest, newRequest);
127 if (preference == kBetterRequest) {
128 return true;
129 } else if (preference == kWorseRequest) {
130 return false;
131 } else {
132 preference = IsNewRequestRecencyBetter(oldRequest, newRequest);
133 if (preference == kBetterRequest) {
134 return true;
135 } else if (preference == kWorseRequest) {
136 return false;
137 }
138 }
139 } else {
140 // Check recency first, then retry count.
141 preference = IsNewRequestRecencyBetter(oldRequest, newRequest);
142 if (preference == kBetterRequest) {
143 return true;
144 } else if (preference == kWorseRequest) {
145 return false;
146 } else {
147 preference = IsNewRequestRetryCountBetter(oldRequest, newRequest);
148 if (preference == kBetterRequest) {
149 return true;
150 } else if (preference == kWorseRequest) {
151 return false;
152 }
153 }
154 }
155
156 // If we have no preference, defailt to prefering the old request.
157 return false;
158 }
159
160 // Is the new request better as regards retry count?
161 int RequestPicker::IsNewRequestRetryCountBetter(
162 const SavePageRequest* oldRequest, const SavePageRequest* newRequest) {
163 // If the retry counts are equal, we have no preference.
164 if (newRequest->attempt_count() == oldRequest->attempt_count())
165 return kEquiavalentRequest;
166
167 // Check the policy to see if we should prefer more tried or less tried
168 // requests.
169 if (policy_->ShouldPreferTriedRequests()) {
170 // We prefer more-tried requests.
171 if (newRequest->attempt_count() > oldRequest->attempt_count())
172 return kBetterRequest;
173 } else {
174 // We prefer less-tried requests.
175 if (newRequest->attempt_count() < oldRequest->attempt_count())
176 return kBetterRequest;
177 }
178
179 // If we found that this wasn't as good in the area of request count,
180 // then we prefer the old request, and exit now.
181 return kWorseRequest;
182
183 }
184
185 // Is the new request better in regard to how long ago it was created?
186 int RequestPicker::IsNewRequestRecencyBetter(
187 const SavePageRequest* oldRequest, const SavePageRequest* newRequest) {
188 // In theory requests should not have the same creation time, but if they do,
189 // we call them equivalent.
190 if (newRequest->creation_time() == oldRequest->creation_time())
191 return kEquiavalentRequest;
192
193 // Should we prefer earlier requests or later ones?
194 if (policy_->ShouldPreferEarlierRequests()) {
195 // We prefer requests made earlier.
196 if (newRequest->creation_time() < oldRequest->creation_time()) {
197 return kBetterRequest;
198 }
199 } else {
200 // We prefer requests made more recently.
201 if (newRequest->creation_time() < oldRequest->creation_time())
202 return kBetterRequest;
203 }
204
205 return kWorseRequest;
45 } 206 }
46 207
47 } // namespace offline_pages 208 } // namespace offline_pages
OLDNEW
« no previous file with comments | « components/offline_pages/background/request_picker.h ('k') | components/offline_pages/background/request_picker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698