| 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" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/rand_util.h" | 13 #include "base/rand_util.h" |
| 14 #include "base/time/time.h" | 14 #include "base/time/time.h" |
| 15 #include "components/offline_pages/background/offliner_factory.h" | 15 #include "components/offline_pages/background/offliner_factory.h" |
| 16 #include "components/offline_pages/background/offliner_policy.h" | 16 #include "components/offline_pages/background/offliner_policy.h" |
| 17 #include "components/offline_pages/background/request_picker.h" | 17 #include "components/offline_pages/background/request_picker.h" |
| 18 #include "components/offline_pages/background/save_page_request.h" | 18 #include "components/offline_pages/background/save_page_request.h" |
| 19 #include "components/offline_pages/offline_page_item.h" | 19 #include "components/offline_pages/offline_page_item.h" |
| 20 #include "components/offline_pages/offline_page_model.h" | 20 #include "components/offline_pages/offline_page_model.h" |
| 21 | 21 |
| 22 namespace offline_pages { | 22 namespace offline_pages { |
| 23 | 23 |
| 24 namespace { | 24 namespace { |
| 25 const bool kUserRequest = true; |
| 25 | 26 |
| 26 // Records the final request status UMA for an offlining request. This should | 27 // Records the final request status UMA for an offlining request. This should |
| 27 // only be called once per Offliner::LoadAndSave request. | 28 // only be called once per Offliner::LoadAndSave request. |
| 28 void RecordOfflinerResultUMA(const ClientId& client_id, | 29 void RecordOfflinerResultUMA(const ClientId& client_id, |
| 29 Offliner::RequestStatus request_status) { | 30 Offliner::RequestStatus request_status) { |
| 30 // TODO(dougarnett): Consider exposing AddHistogramSuffix from | 31 // TODO(dougarnett): Consider exposing AddHistogramSuffix from |
| 31 // offline_page_model_impl.cc as visible utility method. | 32 // offline_page_model_impl.cc as visible utility method. |
| 32 std::string histogram_name("OfflinePages.Background.OfflinerRequestStatus"); | 33 std::string histogram_name("OfflinePages.Background.OfflinerRequestStatus"); |
| 33 if (!client_id.name_space.empty()) { | 34 if (!client_id.name_space.empty()) { |
| 34 histogram_name += "." + client_id.name_space; | 35 histogram_name += "." + client_id.name_space; |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 | 135 |
| 135 if (active_request_) { | 136 if (active_request_) { |
| 136 RecordOfflinerResultUMA(active_request_->client_id(), | 137 RecordOfflinerResultUMA(active_request_->client_id(), |
| 137 last_offlining_status_); | 138 last_offlining_status_); |
| 138 is_busy_ = false; | 139 is_busy_ = false; |
| 139 active_request_.reset(); | 140 active_request_.reset(); |
| 140 } | 141 } |
| 141 | 142 |
| 142 } | 143 } |
| 143 | 144 |
| 145 void RequestCoordinator::GetRequestsForSchedulingCallback( |
| 146 RequestQueue::GetRequestsResult result, |
| 147 const std::vector<SavePageRequest>& requests) { |
| 148 bool user_requested = false; |
| 149 |
| 150 // Examine all requests, if we find a user requested one, we will use the less |
| 151 // restrictive conditions for user_requested requests. Otherwise we will use |
| 152 // the more restrictive non-user-requested conditions. |
| 153 for (const SavePageRequest& request : requests) { |
| 154 if (request.user_requested()) { |
| 155 user_requested = true; |
| 156 break; |
| 157 } |
| 158 } |
| 159 |
| 160 // In the get callback, determine the least restrictive, and call |
| 161 // GetTriggerConditions based on that. |
| 162 scheduler_->Schedule(GetTriggerConditions(user_requested)); |
| 163 } |
| 164 |
| 144 bool RequestCoordinator::CancelActiveRequestIfItMatches( | 165 bool RequestCoordinator::CancelActiveRequestIfItMatches( |
| 145 const std::vector<int64_t>& request_ids) { | 166 const std::vector<int64_t>& request_ids) { |
| 146 // If we have a request in progress and need to cancel it, call the | 167 // If we have a request in progress and need to cancel it, call the |
| 147 // pre-renderer to cancel. TODO Make sure we remove any page created by the | 168 // pre-renderer to cancel. TODO Make sure we remove any page created by the |
| 148 // prerenderer if it doesn't get the cancel in time. | 169 // prerenderer if it doesn't get the cancel in time. |
| 149 if (active_request_ != nullptr) { | 170 if (active_request_ != nullptr) { |
| 150 if (request_ids.end() != std::find(request_ids.begin(), request_ids.end(), | 171 if (request_ids.end() != std::find(request_ids.begin(), request_ids.end(), |
| 151 active_request_->request_id())) { | 172 active_request_->request_id())) { |
| 152 StopPrerendering(); | 173 StopPrerendering(); |
| 153 return true; | 174 return true; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 181 if (canceled) | 202 if (canceled) |
| 182 TryNextRequest(); | 203 TryNextRequest(); |
| 183 } | 204 } |
| 184 | 205 |
| 185 void RequestCoordinator::ResumeRequests( | 206 void RequestCoordinator::ResumeRequests( |
| 186 const std::vector<int64_t>& request_ids) { | 207 const std::vector<int64_t>& request_ids) { |
| 187 queue_->ChangeRequestsState( | 208 queue_->ChangeRequestsState( |
| 188 request_ids, SavePageRequest::RequestState::AVAILABLE, | 209 request_ids, SavePageRequest::RequestState::AVAILABLE, |
| 189 base::Bind(&RequestCoordinator::UpdateMultipleRequestsCallback, | 210 base::Bind(&RequestCoordinator::UpdateMultipleRequestsCallback, |
| 190 weak_ptr_factory_.GetWeakPtr())); | 211 weak_ptr_factory_.GetWeakPtr())); |
| 191 scheduler_->Schedule(GetTriggerConditionsForUserRequest()); | 212 // Schedule a task, in case there is not one scheduled. |
| 213 ScheduleAsNeeded(); |
| 192 } | 214 } |
| 193 | 215 |
| 194 net::NetworkChangeNotifier::ConnectionType | 216 net::NetworkChangeNotifier::ConnectionType |
| 195 RequestCoordinator::GetConnectionType() { | 217 RequestCoordinator::GetConnectionType() { |
| 196 // If we have a connection type set for test, use that. | 218 // If we have a connection type set for test, use that. |
| 197 if (use_test_connection_type_) | 219 if (use_test_connection_type_) |
| 198 return test_connection_type_; | 220 return test_connection_type_; |
| 199 | 221 |
| 200 return net::NetworkChangeNotifier::GetConnectionType(); | 222 return net::NetworkChangeNotifier::GetConnectionType(); |
| 201 } | 223 } |
| 202 | 224 |
| 203 void RequestCoordinator::AddRequestResultCallback( | 225 void RequestCoordinator::AddRequestResultCallback( |
| 204 RequestQueue::AddRequestResult result, | 226 RequestQueue::AddRequestResult result, |
| 205 const SavePageRequest& request) { | 227 const SavePageRequest& request) { |
| 206 NotifyAdded(request); | 228 NotifyAdded(request); |
| 207 // Inform the scheduler that we have an outstanding task.. | 229 // Inform the scheduler that we have an outstanding task. |
| 208 scheduler_->Schedule(GetTriggerConditionsForUserRequest()); | 230 scheduler_->Schedule(GetTriggerConditions(kUserRequest)); |
| 209 | 231 |
| 210 if (request.user_requested()) | 232 if (request.user_requested()) |
| 211 StartProcessingIfConnected(); | 233 StartProcessingIfConnected(); |
| 212 } | 234 } |
| 213 | 235 |
| 214 // Called in response to updating a request in the request queue. | 236 // Called in response to updating a request in the request queue. |
| 215 void RequestCoordinator::UpdateRequestCallback( | 237 void RequestCoordinator::UpdateRequestCallback( |
| 216 const ClientId& client_id, | 238 const ClientId& client_id, |
| 217 RequestQueue::UpdateRequestResult result) { | 239 RequestQueue::UpdateRequestResult result) { |
| 218 // If the request succeeded, nothing to do. If it failed, we can't really do | 240 // If the request succeeded, nothing to do. If it failed, we can't really do |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 } | 283 } |
| 262 | 284 |
| 263 void RequestCoordinator::HandleRemovedRequests( | 285 void RequestCoordinator::HandleRemovedRequests( |
| 264 SavePageStatus status, | 286 SavePageStatus status, |
| 265 const RequestQueue::UpdateMultipleRequestResults& results, | 287 const RequestQueue::UpdateMultipleRequestResults& results, |
| 266 const std::vector<SavePageRequest>& requests) { | 288 const std::vector<SavePageRequest>& requests) { |
| 267 for (SavePageRequest request : requests) | 289 for (SavePageRequest request : requests) |
| 268 NotifyCompleted(request, status); | 290 NotifyCompleted(request, status); |
| 269 } | 291 } |
| 270 | 292 |
| 293 void RequestCoordinator::ScheduleAsNeeded() { |
| 294 // Get all requests from queue (there is no filtering mechanism). |
| 295 queue_->GetRequests( |
| 296 base::Bind(&RequestCoordinator::GetRequestsForSchedulingCallback, |
| 297 weak_ptr_factory_.GetWeakPtr())); |
| 298 } |
| 299 |
| 271 void RequestCoordinator::StopProcessing() { | 300 void RequestCoordinator::StopProcessing() { |
| 272 is_stopped_ = true; | 301 is_stopped_ = true; |
| 273 StopPrerendering(); | 302 StopPrerendering(); |
| 274 | 303 |
| 275 // Let the scheduler know we are done processing. | 304 // Let the scheduler know we are done processing. |
| 276 scheduler_callback_.Run(true); | 305 scheduler_callback_.Run(true); |
| 277 } | 306 } |
| 278 | 307 |
| 279 // Returns true if the caller should expect a callback, false otherwise. For | 308 // Returns true if the caller should expect a callback, false otherwise. For |
| 280 // instance, this would return false if a request is already in progress. | 309 // instance, this would return false if a request is already in progress. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 base::TimeDelta::FromSeconds( | 350 base::TimeDelta::FromSeconds( |
| 322 policy_->GetBackgroundProcessingTimeBudgetSeconds())) { | 351 policy_->GetBackgroundProcessingTimeBudgetSeconds())) { |
| 323 // Let the scheduler know we are done processing. | 352 // Let the scheduler know we are done processing. |
| 324 scheduler_callback_.Run(true); | 353 scheduler_callback_.Run(true); |
| 325 | 354 |
| 326 return; | 355 return; |
| 327 } | 356 } |
| 328 | 357 |
| 329 // Choose a request to process that meets the available conditions. | 358 // Choose a request to process that meets the available conditions. |
| 330 // This is an async call, and returns right away. | 359 // This is an async call, and returns right away. |
| 331 picker_->ChooseNextRequest( | 360 picker_->ChooseNextRequest(base::Bind(&RequestCoordinator::RequestPicked, |
| 332 base::Bind(&RequestCoordinator::RequestPicked, | 361 weak_ptr_factory_.GetWeakPtr()), |
| 333 weak_ptr_factory_.GetWeakPtr()), | 362 base::Bind(&RequestCoordinator::RequestNotPicked, |
| 334 base::Bind(&RequestCoordinator::RequestQueueEmpty, | 363 weak_ptr_factory_.GetWeakPtr()), |
| 335 weak_ptr_factory_.GetWeakPtr()), | 364 current_conditions_.get()); |
| 336 current_conditions_.get()); | |
| 337 } | 365 } |
| 338 | 366 |
| 339 // Called by the request picker when a request has been picked. | 367 // Called by the request picker when a request has been picked. |
| 340 void RequestCoordinator::RequestPicked(const SavePageRequest& request) { | 368 void RequestCoordinator::RequestPicked(const SavePageRequest& request) { |
| 341 // Send the request on to the offliner. | 369 // Send the request on to the offliner. |
| 342 SendRequestToOffliner(request); | 370 SendRequestToOffliner(request); |
| 343 } | 371 } |
| 344 | 372 |
| 345 void RequestCoordinator::RequestQueueEmpty() { | 373 void RequestCoordinator::RequestNotPicked( |
| 374 bool non_user_requested_tasks_remaining) { |
| 346 // Clear the outstanding "safety" task in the scheduler. | 375 // Clear the outstanding "safety" task in the scheduler. |
| 347 scheduler_->Unschedule(); | 376 scheduler_->Unschedule(); |
| 377 |
| 378 if (non_user_requested_tasks_remaining) |
| 379 scheduler_->Schedule(GetTriggerConditions(!kUserRequest)); |
| 348 // Let the scheduler know we are done processing. | 380 // Let the scheduler know we are done processing. |
| 349 scheduler_callback_.Run(true); | 381 scheduler_callback_.Run(true); |
| 350 } | 382 } |
| 351 | 383 |
| 352 void RequestCoordinator::SendRequestToOffliner(const SavePageRequest& request) { | 384 void RequestCoordinator::SendRequestToOffliner(const SavePageRequest& request) { |
| 353 // Check that offlining didn't get cancelled while performing some async | 385 // Check that offlining didn't get cancelled while performing some async |
| 354 // steps. | 386 // steps. |
| 355 if (is_stopped_) | 387 if (is_stopped_) |
| 356 return; | 388 return; |
| 357 | 389 |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 472 case Offliner::RequestStatus::PRERENDERING_FAILED: | 504 case Offliner::RequestStatus::PRERENDERING_FAILED: |
| 473 // No further processing in this service window. | 505 // No further processing in this service window. |
| 474 break; | 506 break; |
| 475 default: | 507 default: |
| 476 // Make explicit choice about new status codes that actually reach here. | 508 // Make explicit choice about new status codes that actually reach here. |
| 477 // Their default is no further processing in this service window. | 509 // Their default is no further processing in this service window. |
| 478 DCHECK(false); | 510 DCHECK(false); |
| 479 } | 511 } |
| 480 } | 512 } |
| 481 | 513 |
| 482 const Scheduler::TriggerConditions | 514 const Scheduler::TriggerConditions RequestCoordinator::GetTriggerConditions( |
| 483 RequestCoordinator::GetTriggerConditionsForUserRequest() { | 515 const bool user_requested) { |
| 484 Scheduler::TriggerConditions trigger_conditions( | 516 return Scheduler::TriggerConditions( |
| 485 policy_->PowerRequiredForUserRequestedPage(), | 517 policy_->PowerRequired(user_requested), |
| 486 policy_->BatteryPercentageRequiredForUserRequestedPage(), | 518 policy_->BatteryPercentageRequired(user_requested), |
| 487 policy_->UnmeteredNetworkRequiredForUserRequestedPage()); | 519 policy_->UnmeteredNetworkRequired(user_requested)); |
| 488 return trigger_conditions; | |
| 489 } | 520 } |
| 490 | 521 |
| 491 void RequestCoordinator::AddObserver(Observer* observer) { | 522 void RequestCoordinator::AddObserver(Observer* observer) { |
| 492 DCHECK(observer); | 523 DCHECK(observer); |
| 493 observers_.AddObserver(observer); | 524 observers_.AddObserver(observer); |
| 494 } | 525 } |
| 495 | 526 |
| 496 void RequestCoordinator::RemoveObserver(Observer* observer) { | 527 void RequestCoordinator::RemoveObserver(Observer* observer) { |
| 497 observers_.RemoveObserver(observer); | 528 observers_.RemoveObserver(observer); |
| 498 } | 529 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 510 FOR_EACH_OBSERVER(Observer, observers_, OnChanged(request)); | 541 FOR_EACH_OBSERVER(Observer, observers_, OnChanged(request)); |
| 511 } | 542 } |
| 512 | 543 |
| 513 void RequestCoordinator::GetOffliner() { | 544 void RequestCoordinator::GetOffliner() { |
| 514 if (!offliner_) { | 545 if (!offliner_) { |
| 515 offliner_ = factory_->GetOffliner(policy_.get()); | 546 offliner_ = factory_->GetOffliner(policy_.get()); |
| 516 } | 547 } |
| 517 } | 548 } |
| 518 | 549 |
| 519 } // namespace offline_pages | 550 } // namespace offline_pages |
| OLD | NEW |