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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 std::vector<std::unique_ptr<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 empty_callback_.Run(); |
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<std::unique_ptr<SavePageRequest>> valid_requests; |
63 std::vector<SavePageRequest> expired_requests; | 63 std::vector<std::unique_ptr<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 std::vector<std::unique_ptr<SavePageRequest>>::iterator request; |
67 expired_request_ids.push_back(request.request_id()); | 67 for (request = expired_requests.begin(); request != expired_requests.end(); |
| 68 ++request) |
| 69 expired_request_ids.push_back(request->get()->request_id()); |
68 | 70 |
69 queue_->RemoveRequests(expired_request_ids, | 71 queue_->RemoveRequests(expired_request_ids, |
70 base::Bind(&RequestPicker::OnRequestExpired, | 72 base::Bind(&RequestPicker::OnRequestExpired, |
71 weak_ptr_factory_.GetWeakPtr())); | 73 weak_ptr_factory_.GetWeakPtr())); |
72 | 74 |
73 // Pick the most deserving request for our conditions. | 75 // Pick the most deserving request for our conditions. |
74 const SavePageRequest* picked_request = nullptr; | 76 const SavePageRequest* picked_request = nullptr; |
75 | 77 |
76 RequestCompareFunction comparator = nullptr; | 78 RequestCompareFunction comparator = nullptr; |
77 | 79 |
78 // Choose which comparison function to use based on policy. | 80 // Choose which comparison function to use based on policy. |
79 if (policy_->RetryCountIsMoreImportantThanRecency()) | 81 if (policy_->RetryCountIsMoreImportantThanRecency()) |
80 comparator = &RequestPicker::RetryCountFirstCompareFunction; | 82 comparator = &RequestPicker::RetryCountFirstCompareFunction; |
81 else | 83 else |
82 comparator = &RequestPicker::RecencyFirstCompareFunction; | 84 comparator = &RequestPicker::RecencyFirstCompareFunction; |
83 | 85 |
84 // Iterate once through the requests, keeping track of best candidate. | 86 // Iterate once through the requests, keeping track of best candidate. |
85 for (unsigned i = 0; i < valid_requests.size(); ++i) { | 87 for (unsigned i = 0; i < valid_requests.size(); ++i) { |
86 if (!RequestConditionsSatisfied(valid_requests[i])) | 88 if (!RequestConditionsSatisfied(valid_requests[i].get())) |
87 continue; | 89 continue; |
88 if (IsNewRequestBetter(picked_request, &(valid_requests[i]), comparator)) | 90 if (IsNewRequestBetter(picked_request, valid_requests[i].get(), comparator)) |
89 picked_request = &(valid_requests[i]); | 91 picked_request = valid_requests[i].get(); |
90 } | 92 } |
91 | 93 |
92 // If we have a best request to try next, get the request coodinator to | 94 // If we have a best request to try next, get the request coodinator to |
93 // start it. Otherwise return that we have no candidates. | 95 // start it. Otherwise return that we have no candidates. |
94 if (picked_request != nullptr) { | 96 if (picked_request != nullptr) { |
95 picked_callback_.Run(*picked_request); | 97 picked_callback_.Run(*picked_request); |
96 } else { | 98 } else { |
97 empty_callback_.Run(); | 99 empty_callback_.Run(); |
98 } | 100 } |
99 } | 101 } |
100 | 102 |
101 // Filter out requests that don't meet the current conditions. For instance, if | 103 // 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 | 104 // this is a predictive request, and we are not on WiFi, it should be ignored |
103 // this round. | 105 // this round. |
104 bool RequestPicker::RequestConditionsSatisfied(const SavePageRequest& request) { | 106 bool RequestPicker::RequestConditionsSatisfied(const SavePageRequest* request) { |
105 // If the user did not request the page directly, make sure we are connected | 107 // 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 | 108 // to power and have WiFi and sufficient battery remaining before we take this |
107 // request. | 109 // request. |
108 // TODO(petewil): We may later want to configure whether to allow 2G for non | 110 // TODO(petewil): We may later want to configure whether to allow 2G for non |
109 // user_requested items, add that to policy. | 111 // user_requested items, add that to policy. |
110 if (!request.user_requested()) { | 112 if (!request->user_requested()) { |
111 if (!current_conditions_->IsPowerConnected()) | 113 if (!current_conditions_->IsPowerConnected()) |
112 return false; | 114 return false; |
113 | 115 |
114 if (current_conditions_->GetNetConnectionType() != | 116 if (current_conditions_->GetNetConnectionType() != |
115 net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI) { | 117 net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI) { |
116 return false; | 118 return false; |
117 } | 119 } |
118 | 120 |
119 if (current_conditions_->GetBatteryPercentage() < | 121 if (current_conditions_->GetBatteryPercentage() < |
120 policy_->GetMinimumBatteryPercentageForNonUserRequestOfflining()) { | 122 policy_->GetMinimumBatteryPercentageForNonUserRequestOfflining()) { |
121 return false; | 123 return false; |
122 } | 124 } |
123 } | 125 } |
124 | 126 |
125 // If we have already started this page the max number of times, it is not | 127 // If we have already started this page the max number of times, it is not |
126 // eligible to try again. | 128 // eligible to try again. |
127 // TODO(petewil): We should have code to remove the page from the | 129 // TODO(petewil): We should have code to remove the page from the |
128 // queue after the last retry. | 130 // queue after the last retry. |
129 if (request.started_attempt_count() >= policy_->GetMaxStartedTries()) | 131 if (request->started_attempt_count() >= policy_->GetMaxStartedTries()) |
130 return false; | 132 return false; |
131 | 133 |
132 // If we have already completed trying this page the max number of times, it | 134 // If we have already completed trying this page the max number of times, it |
133 // is not eligible to try again. | 135 // is not eligible to try again. |
134 // TODO(petewil): We should have code to remove the page from the | 136 // TODO(petewil): We should have code to remove the page from the |
135 // queue after the last retry. | 137 // queue after the last retry. |
136 if (request.completed_attempt_count() >= policy_->GetMaxCompletedTries()) | 138 if (request->completed_attempt_count() >= policy_->GetMaxCompletedTries()) |
137 return false; | 139 return false; |
138 | 140 |
139 // If the request is paused, do not consider it. | 141 // If the request is paused, do not consider it. |
140 if (request.request_state() == SavePageRequest::RequestState::PAUSED) | 142 if (request->request_state() == SavePageRequest::RequestState::PAUSED) |
141 return false; | 143 return false; |
142 | 144 |
143 // If the request is expired, do not consider it. | 145 // If the request is expired, do not consider it. |
144 // TODO(petewil): We need to remove this from the queue. | 146 // TODO(petewil): We need to remove this from the queue. |
145 base::TimeDelta requestAge = base::Time::Now() - request.creation_time(); | 147 base::TimeDelta requestAge = base::Time::Now() - request->creation_time(); |
146 if (requestAge > | 148 if (requestAge > |
147 base::TimeDelta::FromSeconds( | 149 base::TimeDelta::FromSeconds( |
148 policy_->GetRequestExpirationTimeInSeconds())) | 150 policy_->GetRequestExpirationTimeInSeconds())) |
149 return false; | 151 return false; |
150 | 152 |
151 // If this request is not active yet, return false. | 153 // If this request is not active yet, return false. |
152 // TODO(petewil): If the only reason we return nothing to do is that we have | 154 // TODO(petewil): If the only reason we return nothing to do is that we have |
153 // inactive requests, we still want to try again later after their activation | 155 // inactive requests, we still want to try again later after their activation |
154 // time elapses, we shouldn't take ourselves completely off the scheduler. | 156 // time elapses, we shouldn't take ourselves completely off the scheduler. |
155 if (request.activation_time() > base::Time::Now()) | 157 if (request->activation_time() > base::Time::Now()) |
156 return false; | 158 return false; |
157 | 159 |
158 return true; | 160 return true; |
159 } | 161 } |
160 | 162 |
161 // Look at policies to decide which requests to prefer. | 163 // Look at policies to decide which requests to prefer. |
162 bool RequestPicker::IsNewRequestBetter(const SavePageRequest* oldRequest, | 164 bool RequestPicker::IsNewRequestBetter(const SavePageRequest* oldRequest, |
163 const SavePageRequest* newRequest, | 165 const SavePageRequest* newRequest, |
164 RequestCompareFunction comparator) { | 166 RequestCompareFunction comparator) { |
165 | 167 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 base::TimeDelta difference = left->creation_time() - right->creation_time(); | 233 base::TimeDelta difference = left->creation_time() - right->creation_time(); |
232 int result = signum(difference.InMilliseconds()); | 234 int result = signum(difference.InMilliseconds()); |
233 | 235 |
234 // Flip the direction of comparison if policy prefers fewer retries. | 236 // Flip the direction of comparison if policy prefers fewer retries. |
235 if (earlier_requests_better_) | 237 if (earlier_requests_better_) |
236 result *= -1; | 238 result *= -1; |
237 | 239 |
238 return result; | 240 return result; |
239 } | 241 } |
240 | 242 |
241 // Split all requests into expired ones and still valid ones. | |
242 void RequestPicker::SplitRequests( | 243 void RequestPicker::SplitRequests( |
243 const std::vector<SavePageRequest>& requests, | 244 std::vector<std::unique_ptr<SavePageRequest>>& requests, |
244 std::vector<SavePageRequest>& valid_requests, | 245 std::vector<std::unique_ptr<SavePageRequest>>& valid_requests, |
245 std::vector<SavePageRequest>& expired_requests) { | 246 std::vector<std::unique_ptr<SavePageRequest>>& expired_requests) { |
246 for (SavePageRequest request : requests) { | 247 std::vector<std::unique_ptr<SavePageRequest>>::iterator request; |
247 if (base::Time::Now() - request.creation_time() >= | 248 for (request = requests.begin(); request != requests.end(); ++request) { |
| 249 if (base::Time::Now() - request->get()->creation_time() >= |
248 base::TimeDelta::FromSeconds(kRequestExpirationTimeInSeconds)) { | 250 base::TimeDelta::FromSeconds(kRequestExpirationTimeInSeconds)) { |
249 expired_requests.push_back(request); | 251 expired_requests.push_back(std::move(*request)); |
250 } else { | 252 } else { |
251 valid_requests.push_back(request); | 253 valid_requests.push_back(std::move(*request)); |
252 } | 254 } |
253 } | 255 } |
254 } | 256 } |
255 | 257 |
256 // Callback used after expired requests are deleted from the queue and notifies | 258 // Callback used after expired requests are deleted from the queue and notifies |
257 // the coordinator. | 259 // the coordinator. |
258 void RequestPicker::OnRequestExpired( | 260 void RequestPicker::OnRequestExpired( |
259 const RequestQueue::UpdateMultipleRequestResults& results, | 261 const RequestQueue::UpdateMultipleRequestResults& results, |
260 const std::vector<SavePageRequest>& requests) { | 262 const std::vector<std::unique_ptr<SavePageRequest>> requests) { |
261 for (auto request : requests) | 263 std::vector<std::unique_ptr<SavePageRequest>>::const_iterator request; |
262 notifier_->NotifyCompleted(request, | 264 for (request = requests.begin(); request != requests.end(); ++request) |
| 265 notifier_->NotifyCompleted(*(request->get()), |
263 RequestCoordinator::SavePageStatus::EXPIRED); | 266 RequestCoordinator::SavePageStatus::EXPIRED); |
264 } | 267 } |
265 | 268 |
266 } // namespace offline_pages | 269 } // namespace offline_pages |
OLD | NEW |