| 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_coordinator.h" | 5 #include "components/offline_pages/background/request_coordinator.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 return base::RandGenerator(std::numeric_limits<int64_t>::max()) + 1; | 51 return base::RandGenerator(std::numeric_limits<int64_t>::max()) + 1; |
| 52 } | 52 } |
| 53 | 53 |
| 54 } // namespace | 54 } // namespace |
| 55 | 55 |
| 56 RequestCoordinator::RequestCoordinator(std::unique_ptr<OfflinerPolicy> policy, | 56 RequestCoordinator::RequestCoordinator(std::unique_ptr<OfflinerPolicy> policy, |
| 57 std::unique_ptr<OfflinerFactory> factory, | 57 std::unique_ptr<OfflinerFactory> factory, |
| 58 std::unique_ptr<RequestQueue> queue, | 58 std::unique_ptr<RequestQueue> queue, |
| 59 std::unique_ptr<Scheduler> scheduler) | 59 std::unique_ptr<Scheduler> scheduler) |
| 60 : is_busy_(false), | 60 : is_busy_(false), |
| 61 is_canceled_(false), | 61 is_stopped_(false), |
| 62 offliner_(nullptr), | 62 offliner_(nullptr), |
| 63 policy_(std::move(policy)), | 63 policy_(std::move(policy)), |
| 64 factory_(std::move(factory)), | 64 factory_(std::move(factory)), |
| 65 queue_(std::move(queue)), | 65 queue_(std::move(queue)), |
| 66 scheduler_(std::move(scheduler)), | 66 scheduler_(std::move(scheduler)), |
| 67 active_request_(nullptr), | 67 active_request_(nullptr), |
| 68 last_offlining_status_(Offliner::RequestStatus::UNKNOWN), | 68 last_offlining_status_(Offliner::RequestStatus::UNKNOWN), |
| 69 offliner_timeout_(base::TimeDelta::FromSeconds( | 69 offliner_timeout_(base::TimeDelta::FromSeconds( |
| 70 policy_->GetSinglePageTimeLimitInSeconds())), | 70 policy_->GetSinglePageTimeLimitInSeconds())), |
| 71 weak_ptr_factory_(this) { | 71 weak_ptr_factory_(this) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 weak_ptr_factory_.GetWeakPtr(), callback)); | 105 weak_ptr_factory_.GetWeakPtr(), callback)); |
| 106 } | 106 } |
| 107 | 107 |
| 108 void RequestCoordinator::GetQueuedRequestsCallback( | 108 void RequestCoordinator::GetQueuedRequestsCallback( |
| 109 const GetRequestsCallback& callback, | 109 const GetRequestsCallback& callback, |
| 110 RequestQueue::GetRequestsResult result, | 110 RequestQueue::GetRequestsResult result, |
| 111 const std::vector<SavePageRequest>& requests) { | 111 const std::vector<SavePageRequest>& requests) { |
| 112 callback.Run(requests); | 112 callback.Run(requests); |
| 113 } | 113 } |
| 114 | 114 |
| 115 void RequestCoordinator::StopPrerendering() { |
| 116 if (offliner_ && is_busy_) { |
| 117 offliner_->Cancel(); |
| 118 // Find current request and mark attempt aborted. |
| 119 active_request_->MarkAttemptAborted(); |
| 120 queue_->UpdateRequest(*(active_request_.get()), |
| 121 base::Bind(&RequestCoordinator::UpdateRequestCallback, |
| 122 weak_ptr_factory_.GetWeakPtr(), |
| 123 active_request_->client_id())); |
| 124 } |
| 125 |
| 126 // Stopping offliner means it will not call callback. |
| 127 last_offlining_status_ = |
| 128 Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED; |
| 129 |
| 130 if (active_request_) { |
| 131 RecordOfflinerResultUMA(active_request_->client_id(), |
| 132 last_offlining_status_); |
| 133 active_request_.reset(); |
| 134 } |
| 135 |
| 136 } |
| 137 |
| 138 bool RequestCoordinator::CancelActiveRequestIfItMatches( |
| 139 const std::vector<int64_t>& request_ids) { |
| 140 // If we have a request in progress and need to cancel it, call the |
| 141 // pre-renderer to cancel. TODO Make sure we remove any page created by the |
| 142 // prerenderer if it doesn't get the cancel in time. |
| 143 if (active_request_ != nullptr) { |
| 144 if (request_ids.end() != std::find(request_ids.begin(), request_ids.end(), |
| 145 active_request_->request_id())) { |
| 146 StopPrerendering(); |
| 147 return true; |
| 148 } |
| 149 } |
| 150 |
| 151 return false; |
| 152 } |
| 153 |
| 115 void RequestCoordinator::RemoveRequests( | 154 void RequestCoordinator::RemoveRequests( |
| 116 const std::vector<int64_t>& request_ids) { | 155 const std::vector<int64_t>& request_ids) { |
| 156 bool canceled = CancelActiveRequestIfItMatches(request_ids); |
| 117 queue_->RemoveRequests(request_ids, | 157 queue_->RemoveRequests(request_ids, |
| 118 base::Bind(&RequestCoordinator::RemoveRequestsCallback, | 158 base::Bind(&RequestCoordinator::RemoveRequestsCallback, |
| 119 weak_ptr_factory_.GetWeakPtr())); | 159 weak_ptr_factory_.GetWeakPtr())); |
| 160 if (canceled) |
| 161 TryNextRequest(); |
| 120 } | 162 } |
| 121 | 163 |
| 122 void RequestCoordinator::PauseRequests( | 164 void RequestCoordinator::PauseRequests( |
| 123 const std::vector<int64_t>& request_ids) { | 165 const std::vector<int64_t>& request_ids) { |
| 166 bool canceled = CancelActiveRequestIfItMatches(request_ids); |
| 124 queue_->ChangeRequestsState( | 167 queue_->ChangeRequestsState( |
| 125 request_ids, SavePageRequest::RequestState::PAUSED, | 168 request_ids, SavePageRequest::RequestState::PAUSED, |
| 126 base::Bind(&RequestCoordinator::UpdateMultipleRequestsCallback, | 169 base::Bind(&RequestCoordinator::UpdateMultipleRequestsCallback, |
| 127 weak_ptr_factory_.GetWeakPtr())); | 170 weak_ptr_factory_.GetWeakPtr())); |
| 171 |
| 172 if (canceled) |
| 173 TryNextRequest(); |
| 128 } | 174 } |
| 129 | 175 |
| 130 void RequestCoordinator::ResumeRequests( | 176 void RequestCoordinator::ResumeRequests( |
| 131 const std::vector<int64_t>& request_ids) { | 177 const std::vector<int64_t>& request_ids) { |
| 132 queue_->ChangeRequestsState( | 178 queue_->ChangeRequestsState( |
| 133 request_ids, SavePageRequest::RequestState::AVAILABLE, | 179 request_ids, SavePageRequest::RequestState::AVAILABLE, |
| 134 base::Bind(&RequestCoordinator::UpdateMultipleRequestsCallback, | 180 base::Bind(&RequestCoordinator::UpdateMultipleRequestsCallback, |
| 135 weak_ptr_factory_.GetWeakPtr())); | 181 weak_ptr_factory_.GetWeakPtr())); |
| 136 // TODO: Should we also schedule a task, in case there is not one scheduled? | 182 // TODO: Should we also schedule a task, in case there is not one scheduled? |
| 137 } | 183 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 165 } | 211 } |
| 166 | 212 |
| 167 void RequestCoordinator::RemoveRequestsCallback( | 213 void RequestCoordinator::RemoveRequestsCallback( |
| 168 const RequestQueue::UpdateMultipleRequestResults& results, | 214 const RequestQueue::UpdateMultipleRequestResults& results, |
| 169 const std::vector<SavePageRequest>& requests) { | 215 const std::vector<SavePageRequest>& requests) { |
| 170 for (SavePageRequest request : requests) | 216 for (SavePageRequest request : requests) |
| 171 NotifyCompleted(request, SavePageStatus::REMOVED); | 217 NotifyCompleted(request, SavePageStatus::REMOVED); |
| 172 } | 218 } |
| 173 | 219 |
| 174 void RequestCoordinator::StopProcessing() { | 220 void RequestCoordinator::StopProcessing() { |
| 175 is_canceled_ = true; | 221 is_stopped_ = true; |
| 176 if (offliner_ && is_busy_) { | 222 StopPrerendering(); |
| 177 // TODO(dougarnett): Find current request and mark attempt aborted. | |
| 178 offliner_->Cancel(); | |
| 179 } | |
| 180 | |
| 181 // Stopping offliner means it will not call callback. | |
| 182 last_offlining_status_ = | |
| 183 Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED; | |
| 184 | |
| 185 if (active_request_) { | |
| 186 RecordOfflinerResultUMA(active_request_->client_id(), | |
| 187 last_offlining_status_); | |
| 188 active_request_.reset(); | |
| 189 } | |
| 190 | 223 |
| 191 // Let the scheduler know we are done processing. | 224 // Let the scheduler know we are done processing. |
| 192 scheduler_callback_.Run(true); | 225 scheduler_callback_.Run(true); |
| 193 } | 226 } |
| 194 | 227 |
| 195 // Returns true if the caller should expect a callback, false otherwise. For | 228 // Returns true if the caller should expect a callback, false otherwise. For |
| 196 // instance, this would return false if a request is already in progress. | 229 // instance, this would return false if a request is already in progress. |
| 197 bool RequestCoordinator::StartProcessing( | 230 bool RequestCoordinator::StartProcessing( |
| 198 const DeviceConditions& device_conditions, | 231 const DeviceConditions& device_conditions, |
| 199 const base::Callback<void(bool)>& callback) { | 232 const base::Callback<void(bool)>& callback) { |
| 200 current_conditions_.reset(new DeviceConditions(device_conditions)); | 233 current_conditions_.reset(new DeviceConditions(device_conditions)); |
| 201 if (is_busy_) return false; | 234 if (is_busy_) return false; |
| 202 | 235 |
| 203 // Mark the time at which we started processing so we can check our time | 236 // Mark the time at which we started processing so we can check our time |
| 204 // budget. | 237 // budget. |
| 205 operation_start_time_ = base::Time::Now(); | 238 operation_start_time_ = base::Time::Now(); |
| 206 | 239 |
| 207 is_canceled_ = false; | 240 is_stopped_ = false; |
| 208 scheduler_callback_ = callback; | 241 scheduler_callback_ = callback; |
| 209 | 242 |
| 210 TryNextRequest(); | 243 TryNextRequest(); |
| 211 | 244 |
| 212 return true; | 245 return true; |
| 213 } | 246 } |
| 214 | 247 |
| 215 void RequestCoordinator::TryNextRequest() { | 248 void RequestCoordinator::TryNextRequest() { |
| 216 // If there is no time left in the budget, return to the scheduler. | 249 // If there is no time left in the budget, return to the scheduler. |
| 217 // We do not remove the pending task that was set up earlier in case | 250 // We do not remove the pending task that was set up earlier in case |
| (...skipping 27 matching lines...) Expand all Loading... |
| 245 void RequestCoordinator::RequestQueueEmpty() { | 278 void RequestCoordinator::RequestQueueEmpty() { |
| 246 // Clear the outstanding "safety" task in the scheduler. | 279 // Clear the outstanding "safety" task in the scheduler. |
| 247 scheduler_->Unschedule(); | 280 scheduler_->Unschedule(); |
| 248 // Let the scheduler know we are done processing. | 281 // Let the scheduler know we are done processing. |
| 249 scheduler_callback_.Run(true); | 282 scheduler_callback_.Run(true); |
| 250 } | 283 } |
| 251 | 284 |
| 252 void RequestCoordinator::SendRequestToOffliner(const SavePageRequest& request) { | 285 void RequestCoordinator::SendRequestToOffliner(const SavePageRequest& request) { |
| 253 // Check that offlining didn't get cancelled while performing some async | 286 // Check that offlining didn't get cancelled while performing some async |
| 254 // steps. | 287 // steps. |
| 255 if (is_canceled_) | 288 if (is_stopped_) |
| 256 return; | 289 return; |
| 257 | 290 |
| 258 GetOffliner(); | 291 GetOffliner(); |
| 259 if (!offliner_) { | 292 if (!offliner_) { |
| 260 DVLOG(0) << "Unable to create Offliner. " | 293 DVLOG(0) << "Unable to create Offliner. " |
| 261 << "Cannot background offline page."; | 294 << "Cannot background offline page."; |
| 262 return; | 295 return; |
| 263 } | 296 } |
| 264 | 297 |
| 265 DCHECK(!is_busy_); | 298 DCHECK(!is_busy_); |
| 266 is_busy_ = true; | 299 is_busy_ = true; |
| 267 active_request_.reset(new SavePageRequest(request)); | |
| 268 | 300 |
| 269 // Prepare an updated request to attempt. | 301 // Prepare an updated request to attempt. |
| 270 SavePageRequest updated_request(request); | 302 SavePageRequest updated_request(request); |
| 271 updated_request.MarkAttemptStarted(base::Time::Now()); | 303 updated_request.MarkAttemptStarted(base::Time::Now()); |
| 304 active_request_.reset(new SavePageRequest(updated_request)); |
| 272 | 305 |
| 273 // Start the load and save process in the offliner (Async). | 306 // Start the load and save process in the offliner (Async). |
| 274 if (offliner_->LoadAndSave( | 307 if (offliner_->LoadAndSave( |
| 275 updated_request, base::Bind(&RequestCoordinator::OfflinerDoneCallback, | 308 updated_request, base::Bind(&RequestCoordinator::OfflinerDoneCallback, |
| 276 weak_ptr_factory_.GetWeakPtr()))) { | 309 weak_ptr_factory_.GetWeakPtr()))) { |
| 277 // Offliner accepted request so update it in the queue. | 310 // Offliner accepted request so update it in the queue. |
| 278 queue_->UpdateRequest(updated_request, | 311 queue_->UpdateRequest(updated_request, |
| 279 base::Bind(&RequestCoordinator::UpdateRequestCallback, | 312 base::Bind(&RequestCoordinator::UpdateRequestCallback, |
| 280 weak_ptr_factory_.GetWeakPtr(), | 313 weak_ptr_factory_.GetWeakPtr(), |
| 281 updated_request.client_id())); | 314 updated_request.client_id())); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 FOR_EACH_OBSERVER(Observer, observers_, OnChanged(request)); | 438 FOR_EACH_OBSERVER(Observer, observers_, OnChanged(request)); |
| 406 } | 439 } |
| 407 | 440 |
| 408 void RequestCoordinator::GetOffliner() { | 441 void RequestCoordinator::GetOffliner() { |
| 409 if (!offliner_) { | 442 if (!offliner_) { |
| 410 offliner_ = factory_->GetOffliner(policy_.get()); | 443 offliner_ = factory_->GetOffliner(policy_.get()); |
| 411 } | 444 } |
| 412 } | 445 } |
| 413 | 446 |
| 414 } // namespace offline_pages | 447 } // namespace offline_pages |
| OLD | NEW |