| 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 <limits> | 7 #include <limits> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/callback.h" | 11 #include "base/callback.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
| 14 #include "base/rand_util.h" | 14 #include "base/rand_util.h" |
| 15 #include "base/sys_info.h" | 15 #include "base/sys_info.h" |
| 16 #include "base/time/time.h" | 16 #include "base/time/time.h" |
| 17 #include "components/offline_pages/background/offliner_factory.h" | 17 #include "components/offline_pages/background/offliner_factory.h" |
| 18 #include "components/offline_pages/background/offliner_policy.h" | 18 #include "components/offline_pages/background/offliner_policy.h" |
| 19 #include "components/offline_pages/background/request_picker.h" | |
| 20 #include "components/offline_pages/background/save_page_request.h" | 19 #include "components/offline_pages/background/save_page_request.h" |
| 21 #include "components/offline_pages/client_policy_controller.h" | 20 #include "components/offline_pages/client_policy_controller.h" |
| 22 #include "components/offline_pages/offline_page_item.h" | 21 #include "components/offline_pages/offline_page_item.h" |
| 23 #include "components/offline_pages/offline_page_model.h" | 22 #include "components/offline_pages/offline_page_model.h" |
| 24 | 23 |
| 25 namespace offline_pages { | 24 namespace offline_pages { |
| 26 | 25 |
| 27 namespace { | 26 namespace { |
| 28 const bool kUserRequest = true; | 27 const bool kUserRequest = true; |
| 29 const int kMinDurationSeconds = 1; | 28 const int kMinDurationSeconds = 1; |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 // are similar. | 138 // are similar. |
| 140 int64_t GenerateOfflineId() { | 139 int64_t GenerateOfflineId() { |
| 141 return base::RandGenerator(std::numeric_limits<int64_t>::max()) + 1; | 140 return base::RandGenerator(std::numeric_limits<int64_t>::max()) + 1; |
| 142 } | 141 } |
| 143 | 142 |
| 144 // In case we start processing from SavePageLater, we need a callback, but there | 143 // In case we start processing from SavePageLater, we need a callback, but there |
| 145 // is nothing for it to do. | 144 // is nothing for it to do. |
| 146 void EmptySchedulerCallback(bool started) {} | 145 void EmptySchedulerCallback(bool started) {} |
| 147 | 146 |
| 148 // Returns whether |result| is a successful result for a single request. | 147 // Returns whether |result| is a successful result for a single request. |
| 149 bool IsSingleSuccessResult(const UpdateRequestsResult* result) { | 148 bool IsSingleSuccessResult(const QueueResults::UpdateRequestsResult* result) { |
| 150 return result->store_state == StoreState::LOADED && | 149 return result->store_state == StoreState::LOADED && |
| 151 result->item_statuses.size() == 1 && | 150 result->item_statuses.size() == 1 && |
| 152 result->item_statuses.at(0).second == ItemActionStatus::SUCCESS; | 151 result->item_statuses.at(0).second == ItemActionStatus::SUCCESS; |
| 153 } | 152 } |
| 154 | 153 |
| 155 } // namespace | 154 } // namespace |
| 156 | 155 |
| 157 RequestCoordinator::RequestCoordinator( | 156 RequestCoordinator::RequestCoordinator( |
| 158 std::unique_ptr<OfflinerPolicy> policy, | 157 std::unique_ptr<OfflinerPolicy> policy, |
| 159 std::unique_ptr<OfflinerFactory> factory, | 158 std::unique_ptr<OfflinerFactory> factory, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 173 queue_(std::move(queue)), | 172 queue_(std::move(queue)), |
| 174 scheduler_(std::move(scheduler)), | 173 scheduler_(std::move(scheduler)), |
| 175 policy_controller_(new ClientPolicyController()), | 174 policy_controller_(new ClientPolicyController()), |
| 176 network_quality_estimator_(network_quality_estimator), | 175 network_quality_estimator_(network_quality_estimator), |
| 177 active_request_(nullptr), | 176 active_request_(nullptr), |
| 178 last_offlining_status_(Offliner::RequestStatus::UNKNOWN), | 177 last_offlining_status_(Offliner::RequestStatus::UNKNOWN), |
| 179 scheduler_callback_(base::Bind(&EmptySchedulerCallback)), | 178 scheduler_callback_(base::Bind(&EmptySchedulerCallback)), |
| 180 immediate_schedule_callback_(base::Bind(&EmptySchedulerCallback)), | 179 immediate_schedule_callback_(base::Bind(&EmptySchedulerCallback)), |
| 181 weak_ptr_factory_(this) { | 180 weak_ptr_factory_(this) { |
| 182 DCHECK(policy_ != nullptr); | 181 DCHECK(policy_ != nullptr); |
| 183 picker_.reset( | 182 std::unique_ptr<PickRequestTaskBuilder> builder( |
| 184 new RequestPicker(queue_.get(), policy_.get(), this, &event_logger_)); | 183 new PickRequestTaskBuilder(policy_.get(), this, &event_logger_)); |
| 184 queue_->SetPickerBuilder(builder); |
| 185 } | 185 } |
| 186 | 186 |
| 187 RequestCoordinator::~RequestCoordinator() {} | 187 RequestCoordinator::~RequestCoordinator() {} |
| 188 | 188 |
| 189 int64_t RequestCoordinator::SavePageLater(const GURL& url, | 189 int64_t RequestCoordinator::SavePageLater(const GURL& url, |
| 190 const ClientId& client_id, | 190 const ClientId& client_id, |
| 191 bool user_requested, | 191 bool user_requested, |
| 192 RequestAvailability availability) { | 192 RequestAvailability availability) { |
| 193 DVLOG(2) << "URL is " << url << " " << __func__; | 193 DVLOG(2) << "URL is " << url << " " << __func__; |
| 194 | 194 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 224 void RequestCoordinator::GetAllRequests(const GetRequestsCallback& callback) { | 224 void RequestCoordinator::GetAllRequests(const GetRequestsCallback& callback) { |
| 225 // Get all matching requests from the request queue, send them to our | 225 // Get all matching requests from the request queue, send them to our |
| 226 // callback. We bind the namespace and callback to the front of the callback | 226 // callback. We bind the namespace and callback to the front of the callback |
| 227 // param set. | 227 // param set. |
| 228 queue_->GetRequests(base::Bind(&RequestCoordinator::GetQueuedRequestsCallback, | 228 queue_->GetRequests(base::Bind(&RequestCoordinator::GetQueuedRequestsCallback, |
| 229 weak_ptr_factory_.GetWeakPtr(), callback)); | 229 weak_ptr_factory_.GetWeakPtr(), callback)); |
| 230 } | 230 } |
| 231 | 231 |
| 232 void RequestCoordinator::GetQueuedRequestsCallback( | 232 void RequestCoordinator::GetQueuedRequestsCallback( |
| 233 const GetRequestsCallback& callback, | 233 const GetRequestsCallback& callback, |
| 234 RequestQueue::GetRequestsResult result, | 234 QueueResults::GetRequestsResult result, |
| 235 std::vector<std::unique_ptr<SavePageRequest>> requests) { | 235 std::vector<std::unique_ptr<SavePageRequest>> requests) { |
| 236 callback.Run(std::move(requests)); | 236 callback.Run(std::move(requests)); |
| 237 } | 237 } |
| 238 | 238 |
| 239 void RequestCoordinator::StopPrerendering(Offliner::RequestStatus stop_status) { | 239 void RequestCoordinator::StopPrerendering(Offliner::RequestStatus stop_status) { |
| 240 if (offliner_ && is_busy_) { | 240 if (offliner_ && is_busy_) { |
| 241 DCHECK(active_request_.get()); | 241 DCHECK(active_request_.get()); |
| 242 offliner_->Cancel(); | 242 offliner_->Cancel(); |
| 243 | 243 |
| 244 // If we timed out, let the offliner done callback handle it. | 244 // If we timed out, let the offliner done callback handle it. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 260 active_request_->request_id()); | 260 active_request_->request_id()); |
| 261 RecordOfflinerResultUMA(active_request_->client_id(), | 261 RecordOfflinerResultUMA(active_request_->client_id(), |
| 262 active_request_->creation_time(), | 262 active_request_->creation_time(), |
| 263 last_offlining_status_); | 263 last_offlining_status_); |
| 264 is_busy_ = false; | 264 is_busy_ = false; |
| 265 active_request_.reset(); | 265 active_request_.reset(); |
| 266 } | 266 } |
| 267 } | 267 } |
| 268 | 268 |
| 269 void RequestCoordinator::GetRequestsForSchedulingCallback( | 269 void RequestCoordinator::GetRequestsForSchedulingCallback( |
| 270 RequestQueue::GetRequestsResult result, | 270 QueueResults::GetRequestsResult result, |
| 271 std::vector<std::unique_ptr<SavePageRequest>> requests) { | 271 std::vector<std::unique_ptr<SavePageRequest>> requests) { |
| 272 bool user_requested = false; | 272 bool user_requested = false; |
| 273 | 273 |
| 274 // Examine all requests, if we find a user requested one, we will use the less | 274 // Examine all requests, if we find a user requested one, we will use the less |
| 275 // restrictive conditions for user_requested requests. Otherwise we will use | 275 // restrictive conditions for user_requested requests. Otherwise we will use |
| 276 // the more restrictive non-user-requested conditions. | 276 // the more restrictive non-user-requested conditions. |
| 277 for (const auto& request : requests) { | 277 for (const auto& request : requests) { |
| 278 if (request->user_requested()) { | 278 if (request->user_requested()) { |
| 279 user_requested = true; | 279 user_requested = true; |
| 280 break; | 280 break; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 298 active_request_.reset(nullptr); | 298 active_request_.reset(nullptr); |
| 299 return true; | 299 return true; |
| 300 } | 300 } |
| 301 } | 301 } |
| 302 | 302 |
| 303 return false; | 303 return false; |
| 304 } | 304 } |
| 305 | 305 |
| 306 void RequestCoordinator::AbortRequestAttempt(SavePageRequest* request) { | 306 void RequestCoordinator::AbortRequestAttempt(SavePageRequest* request) { |
| 307 if (request->started_attempt_count() >= policy_->GetMaxStartedTries()) { | 307 if (request->started_attempt_count() >= policy_->GetMaxStartedTries()) { |
| 308 const BackgroundSavePageResult result( | 308 const RequestNotifier::BackgroundSavePageResult result( |
| 309 BackgroundSavePageResult::START_COUNT_EXCEEDED); | 309 RequestNotifier::BackgroundSavePageResult::START_COUNT_EXCEEDED); |
| 310 event_logger_.RecordDroppedSavePageRequest(request->client_id().name_space, | 310 event_logger_.RecordDroppedSavePageRequest(request->client_id().name_space, |
| 311 result, request->request_id()); | 311 result, request->request_id()); |
| 312 RemoveAttemptedRequest(*request, result); | 312 RemoveAttemptedRequest(*request, result); |
| 313 } else { | 313 } else { |
| 314 queue_->MarkAttemptAborted( | 314 queue_->MarkAttemptAborted( |
| 315 request->request_id(), | 315 request->request_id(), |
| 316 base::Bind(&RequestCoordinator::MarkAttemptAbortedDone, | 316 base::Bind(&RequestCoordinator::MarkAttemptAbortedDone, |
| 317 weak_ptr_factory_.GetWeakPtr(), request->request_id(), | 317 weak_ptr_factory_.GetWeakPtr(), request->request_id(), |
| 318 request->client_id())); | 318 request->client_id())); |
| 319 } | 319 } |
| 320 } | 320 } |
| 321 | 321 |
| 322 void RequestCoordinator::RemoveAttemptedRequest( | 322 void RequestCoordinator::RemoveAttemptedRequest( |
| 323 const SavePageRequest& request, | 323 const SavePageRequest& request, |
| 324 BackgroundSavePageResult result) { | 324 RequestNotifier::BackgroundSavePageResult result) { |
| 325 std::vector<int64_t> remove_requests; | 325 std::vector<int64_t> remove_requests; |
| 326 remove_requests.push_back(request.request_id()); | 326 remove_requests.push_back(request.request_id()); |
| 327 queue_->RemoveRequests(remove_requests, | 327 queue_->RemoveRequests(remove_requests, |
| 328 base::Bind(&RequestCoordinator::HandleRemovedRequests, | 328 base::Bind(&RequestCoordinator::HandleRemovedRequests, |
| 329 weak_ptr_factory_.GetWeakPtr(), result)); | 329 weak_ptr_factory_.GetWeakPtr(), result)); |
| 330 RecordAttemptCount(request, result); | 330 RecordAttemptCount(request, result); |
| 331 } | 331 } |
| 332 | 332 |
| 333 void RequestCoordinator::MarkAttemptAbortedDone( | 333 void RequestCoordinator::MarkAttemptAbortedDone( |
| 334 int64_t request_id, | 334 int64_t request_id, |
| 335 const ClientId& client_id, | 335 const ClientId& client_id, |
| 336 std::unique_ptr<UpdateRequestsResult> result) { | 336 std::unique_ptr<QueueResults::UpdateRequestsResult> result) { |
| 337 // If the request succeeded, nothing to do. If it failed, we can't really do | 337 // If the request succeeded, nothing to do. If it failed, we can't really do |
| 338 // much, so just log it. | 338 // much, so just log it. |
| 339 if (!IsSingleSuccessResult(result.get())) { | 339 if (!IsSingleSuccessResult(result.get())) { |
| 340 DVLOG(1) << "Failed to mark request aborted: " << request_id; | 340 DVLOG(1) << "Failed to mark request aborted: " << request_id; |
| 341 RequestQueue::UpdateRequestResult request_result = | 341 QueueResults::UpdateRequestResult request_result = |
| 342 result->store_state != StoreState::LOADED | 342 result->store_state != StoreState::LOADED |
| 343 ? RequestQueue::UpdateRequestResult::STORE_FAILURE | 343 ? QueueResults::UpdateRequestResult::STORE_FAILURE |
| 344 : RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; | 344 : QueueResults::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; |
| 345 event_logger_.RecordUpdateRequestFailed(client_id.name_space, | 345 event_logger_.RecordUpdateRequestFailed(client_id.name_space, |
| 346 request_result); | 346 request_result); |
| 347 } | 347 } |
| 348 } | 348 } |
| 349 | 349 |
| 350 void RequestCoordinator::RemoveRequests( | 350 void RequestCoordinator::RemoveRequests( |
| 351 const std::vector<int64_t>& request_ids, | 351 const std::vector<int64_t>& request_ids, |
| 352 const RemoveRequestsCallback& callback) { | 352 const RemoveRequestsCallback& callback) { |
| 353 bool canceled = CancelActiveRequestIfItMatches(request_ids); | 353 bool canceled = CancelActiveRequestIfItMatches(request_ids); |
| 354 queue_->RemoveRequests( | 354 queue_->RemoveRequests( |
| 355 request_ids, | 355 request_ids, |
| 356 base::Bind(&RequestCoordinator::HandleRemovedRequestsAndCallback, | 356 base::Bind(&RequestCoordinator::HandleRemovedRequestsAndCallback, |
| 357 weak_ptr_factory_.GetWeakPtr(), callback, | 357 weak_ptr_factory_.GetWeakPtr(), callback, |
| 358 BackgroundSavePageResult::REMOVED)); | 358 RequestNotifier::BackgroundSavePageResult::REMOVED)); |
| 359 | 359 |
| 360 // Record the network quality when this request is made. | 360 // Record the network quality when this request is made. |
| 361 if (network_quality_estimator_) { | 361 if (network_quality_estimator_) { |
| 362 UMA_HISTOGRAM_ENUMERATION( | 362 UMA_HISTOGRAM_ENUMERATION( |
| 363 "OfflinePages.Background.EffectiveConnectionType.RemoveRequests", | 363 "OfflinePages.Background.EffectiveConnectionType.RemoveRequests", |
| 364 network_quality_estimator_->GetEffectiveConnectionType(), | 364 network_quality_estimator_->GetEffectiveConnectionType(), |
| 365 net::EFFECTIVE_CONNECTION_TYPE_LAST); | 365 net::EFFECTIVE_CONNECTION_TYPE_LAST); |
| 366 } | 366 } |
| 367 | 367 |
| 368 if (canceled) | 368 if (canceled) |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 net::NetworkChangeNotifier::ConnectionType | 411 net::NetworkChangeNotifier::ConnectionType |
| 412 RequestCoordinator::GetConnectionType() { | 412 RequestCoordinator::GetConnectionType() { |
| 413 // If we have a connection type set for test, use that. | 413 // If we have a connection type set for test, use that. |
| 414 if (use_test_connection_type_) | 414 if (use_test_connection_type_) |
| 415 return test_connection_type_; | 415 return test_connection_type_; |
| 416 | 416 |
| 417 return net::NetworkChangeNotifier::GetConnectionType(); | 417 return net::NetworkChangeNotifier::GetConnectionType(); |
| 418 } | 418 } |
| 419 | 419 |
| 420 void RequestCoordinator::AddRequestResultCallback( | 420 void RequestCoordinator::AddRequestResultCallback( |
| 421 RequestQueue::AddRequestResult result, | 421 QueueResults::AddRequestResult result, |
| 422 const SavePageRequest& request) { | 422 const SavePageRequest& request) { |
| 423 NotifyAdded(request); | 423 NotifyAdded(request); |
| 424 // Inform the scheduler that we have an outstanding task. | 424 // Inform the scheduler that we have an outstanding task. |
| 425 scheduler_->Schedule(GetTriggerConditions(kUserRequest)); | 425 scheduler_->Schedule(GetTriggerConditions(kUserRequest)); |
| 426 | 426 |
| 427 if (request.user_requested()) | 427 if (request.user_requested()) |
| 428 StartImmediatelyIfConnected(); | 428 StartImmediatelyIfConnected(); |
| 429 } | 429 } |
| 430 | 430 |
| 431 void RequestCoordinator::MarkAttemptCompletedDoneCallback( | 431 void RequestCoordinator::MarkAttemptCompletedDoneCallback( |
| 432 int64_t request_id, | 432 int64_t request_id, |
| 433 const ClientId& client_id, | 433 const ClientId& client_id, |
| 434 std::unique_ptr<UpdateRequestsResult> result) { | 434 std::unique_ptr<QueueResults::UpdateRequestsResult> result) { |
| 435 if (IsSingleSuccessResult(result.get())) { | 435 if (IsSingleSuccessResult(result.get())) { |
| 436 NotifyChanged(result->updated_items.at(0)); | 436 NotifyChanged(result->updated_items.at(0)); |
| 437 } else { | 437 } else { |
| 438 DVLOG(1) << "Failed to mark request completed " << request_id; | 438 DVLOG(1) << "Failed to mark request completed " << request_id; |
| 439 RequestQueue::UpdateRequestResult request_result = | 439 QueueResults::UpdateRequestResult request_result = |
| 440 result->store_state != StoreState::LOADED | 440 result->store_state != StoreState::LOADED |
| 441 ? RequestQueue::UpdateRequestResult::STORE_FAILURE | 441 ? QueueResults::UpdateRequestResult::STORE_FAILURE |
| 442 : RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; | 442 : QueueResults::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; |
| 443 event_logger_.RecordUpdateRequestFailed(client_id.name_space, | 443 event_logger_.RecordUpdateRequestFailed(client_id.name_space, |
| 444 request_result); | 444 request_result); |
| 445 } | 445 } |
| 446 } | 446 } |
| 447 | 447 |
| 448 void RequestCoordinator::UpdateMultipleRequestsCallback( | 448 void RequestCoordinator::UpdateMultipleRequestsCallback( |
| 449 std::unique_ptr<UpdateRequestsResult> result) { | 449 std::unique_ptr<QueueResults::UpdateRequestsResult> result) { |
| 450 for (const auto& request : result->updated_items) | 450 for (const auto& request : result->updated_items) |
| 451 NotifyChanged(request); | 451 NotifyChanged(request); |
| 452 | 452 |
| 453 bool available_user_request = false; | 453 bool available_user_request = false; |
| 454 for (const auto& request : result->updated_items) { | 454 for (const auto& request : result->updated_items) { |
| 455 if (!available_user_request && request.user_requested() && | 455 if (!available_user_request && request.user_requested() && |
| 456 request.request_state() == SavePageRequest::RequestState::AVAILABLE) { | 456 request.request_state() == SavePageRequest::RequestState::AVAILABLE) { |
| 457 available_user_request = true; | 457 available_user_request = true; |
| 458 } | 458 } |
| 459 } | 459 } |
| 460 | 460 |
| 461 if (available_user_request) | 461 if (available_user_request) |
| 462 StartImmediatelyIfConnected(); | 462 StartImmediatelyIfConnected(); |
| 463 } | 463 } |
| 464 | 464 |
| 465 // When we successfully remove a request that completed successfully, move on to | 465 // When we successfully remove a request that completed successfully, move on to |
| 466 // the next request. | 466 // the next request. |
| 467 void RequestCoordinator::CompletedRequestCallback( | 467 void RequestCoordinator::CompletedRequestCallback( |
| 468 const MultipleItemStatuses& status) { | 468 const MultipleItemStatuses& status) { |
| 469 TryNextRequest(); | 469 TryNextRequest(); |
| 470 } | 470 } |
| 471 | 471 |
| 472 void RequestCoordinator::HandleRemovedRequestsAndCallback( | 472 void RequestCoordinator::HandleRemovedRequestsAndCallback( |
| 473 const RemoveRequestsCallback& callback, | 473 const RemoveRequestsCallback& callback, |
| 474 BackgroundSavePageResult status, | 474 RequestNotifier::BackgroundSavePageResult status, |
| 475 std::unique_ptr<UpdateRequestsResult> result) { | 475 std::unique_ptr<QueueResults::UpdateRequestsResult> result) { |
| 476 // TODO(dougarnett): Define status code for user/api cancel and use here | 476 // TODO(dougarnett): Define status code for user/api cancel and use here |
| 477 // to determine whether to record cancel time UMA. | 477 // to determine whether to record cancel time UMA. |
| 478 for (const auto& request : result->updated_items) | 478 for (const auto& request : result->updated_items) |
| 479 RecordCancelTimeUMA(request); | 479 RecordCancelTimeUMA(request); |
| 480 callback.Run(result->item_statuses); | 480 callback.Run(result->item_statuses); |
| 481 HandleRemovedRequests(status, std::move(result)); | 481 HandleRemovedRequests(status, std::move(result)); |
| 482 } | 482 } |
| 483 | 483 |
| 484 void RequestCoordinator::HandleRemovedRequests( | 484 void RequestCoordinator::HandleRemovedRequests( |
| 485 BackgroundSavePageResult status, | 485 RequestNotifier::BackgroundSavePageResult status, |
| 486 std::unique_ptr<UpdateRequestsResult> result) { | 486 std::unique_ptr<QueueResults::UpdateRequestsResult> result) { |
| 487 for (const auto& request : result->updated_items) | 487 for (const auto& request : result->updated_items) |
| 488 NotifyCompleted(request, status); | 488 NotifyCompleted(request, status); |
| 489 } | 489 } |
| 490 | 490 |
| 491 void RequestCoordinator::ScheduleAsNeeded() { | 491 void RequestCoordinator::ScheduleAsNeeded() { |
| 492 // Get all requests from queue (there is no filtering mechanism). | 492 // Get all requests from queue (there is no filtering mechanism). |
| 493 queue_->GetRequests( | 493 queue_->GetRequests( |
| 494 base::Bind(&RequestCoordinator::GetRequestsForSchedulingCallback, | 494 base::Bind(&RequestCoordinator::GetRequestsForSchedulingCallback, |
| 495 weak_ptr_factory_.GetWeakPtr())); | 495 weak_ptr_factory_.GetWeakPtr())); |
| 496 } | 496 } |
| 497 | 497 |
| 498 void RequestCoordinator::StopProcessing( | 498 void RequestCoordinator::StopProcessing( |
| 499 Offliner::RequestStatus stop_status) { | 499 Offliner::RequestStatus stop_status) { |
| 500 processing_state_ = ProcessingWindowState::STOPPED; | 500 processing_state_ = ProcessingWindowState::STOPPED; |
| 501 StopPrerendering(stop_status); | 501 StopPrerendering(stop_status); |
| 502 | 502 |
| 503 // Let the scheduler know we are done processing. | 503 // Let the scheduler know we are done processing. |
| 504 scheduler_callback_.Run(true); | 504 scheduler_callback_.Run(true); |
| 505 } | 505 } |
| 506 | 506 |
| 507 void RequestCoordinator::HandleWatchdogTimeout() { | 507 void RequestCoordinator::HandleWatchdogTimeout() { |
| 508 StopProcessing(Offliner::REQUEST_COORDINATOR_TIMED_OUT); | 508 StopProcessing(Offliner::REQUEST_COORDINATOR_TIMED_OUT); |
| 509 } | 509 } |
| 510 | 510 |
| 511 // Returns true if the caller should expect a callback, false otherwise. For | 511 // Returns true if the caller should expect a callback, false otherwise. For |
| 512 // instance, this would return false if a request is already in progress. | 512 // instance, this would return false if a request is already in progress. |
| 513 bool RequestCoordinator::StartProcessing( | 513 bool RequestCoordinator::StartProcessing( |
| 514 const DeviceConditions& device_conditions, | 514 const DeviceConditions& device_conditions, |
| 515 const base::Callback<void(bool)>& callback) { | 515 const base::Callback<void(bool)>& callback) { |
| 516 DVLOG(2) << "Scheduled " << __func__; |
| 516 return StartProcessingInternal(ProcessingWindowState::SCHEDULED_WINDOW, | 517 return StartProcessingInternal(ProcessingWindowState::SCHEDULED_WINDOW, |
| 517 device_conditions, callback); | 518 device_conditions, callback); |
| 518 } | 519 } |
| 519 | 520 |
| 520 bool RequestCoordinator::StartProcessingInternal( | 521 bool RequestCoordinator::StartProcessingInternal( |
| 521 const ProcessingWindowState processing_state, | 522 const ProcessingWindowState processing_state, |
| 522 const DeviceConditions& device_conditions, | 523 const DeviceConditions& device_conditions, |
| 523 const base::Callback<void(bool)>& callback) { | 524 const base::Callback<void(bool)>& callback) { |
| 524 current_conditions_.reset(new DeviceConditions(device_conditions)); | 525 current_conditions_.reset(new DeviceConditions(device_conditions)); |
| 525 if (is_starting_ || is_busy_) | 526 if (is_starting_ || is_busy_) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 539 | 540 |
| 540 void RequestCoordinator::StartImmediatelyIfConnected() { | 541 void RequestCoordinator::StartImmediatelyIfConnected() { |
| 541 OfflinerImmediateStartStatus immediate_start_status = TryImmediateStart(); | 542 OfflinerImmediateStartStatus immediate_start_status = TryImmediateStart(); |
| 542 UMA_HISTOGRAM_ENUMERATION( | 543 UMA_HISTOGRAM_ENUMERATION( |
| 543 "OfflinePages.Background.ImmediateStartStatus", immediate_start_status, | 544 "OfflinePages.Background.ImmediateStartStatus", immediate_start_status, |
| 544 RequestCoordinator::OfflinerImmediateStartStatus::STATUS_COUNT); | 545 RequestCoordinator::OfflinerImmediateStartStatus::STATUS_COUNT); |
| 545 } | 546 } |
| 546 | 547 |
| 547 RequestCoordinator::OfflinerImmediateStartStatus | 548 RequestCoordinator::OfflinerImmediateStartStatus |
| 548 RequestCoordinator::TryImmediateStart() { | 549 RequestCoordinator::TryImmediateStart() { |
| 550 DVLOG(2) << "Immediate " << __func__; |
| 549 // Make sure not already busy processing. | 551 // Make sure not already busy processing. |
| 550 if (is_busy_) | 552 if (is_busy_) |
| 551 return OfflinerImmediateStartStatus::BUSY; | 553 return OfflinerImmediateStartStatus::BUSY; |
| 552 | 554 |
| 553 // Make sure we are not on svelte device to start immediately. | 555 // Make sure we are not on svelte device to start immediately. |
| 554 if (is_low_end_device_) { | 556 if (is_low_end_device_) { |
| 555 DVLOG(2) << "low end device, returning"; | 557 DVLOG(2) << "low end device, returning"; |
| 556 // Let the scheduler know we are done processing and failed due to svelte. | 558 // Let the scheduler know we are done processing and failed due to svelte. |
| 557 immediate_schedule_callback_.Run(false); | 559 immediate_schedule_callback_.Run(false); |
| 558 return OfflinerImmediateStartStatus::NOT_STARTED_ON_SVELTE; | 560 return OfflinerImmediateStartStatus::NOT_STARTED_ON_SVELTE; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 is_starting_ = false; | 595 is_starting_ = false; |
| 594 | 596 |
| 595 // Let the scheduler know we are done processing. | 597 // Let the scheduler know we are done processing. |
| 596 // TODO: Make sure the scheduler callback is valid before running it. | 598 // TODO: Make sure the scheduler callback is valid before running it. |
| 597 scheduler_callback_.Run(true); | 599 scheduler_callback_.Run(true); |
| 598 DVLOG(2) << " out of time, giving up. " << __func__; | 600 DVLOG(2) << " out of time, giving up. " << __func__; |
| 599 | 601 |
| 600 return; | 602 return; |
| 601 } | 603 } |
| 602 | 604 |
| 603 // Choose a request to process that meets the available conditions. | 605 // Ask request queue to make a new PickRequestTask object, then put it on the |
| 604 // This is an async call, and returns right away. | 606 // task queue. |
| 605 picker_->ChooseNextRequest(base::Bind(&RequestCoordinator::RequestPicked, | 607 queue_->PickNextRequest(base::Bind(&RequestCoordinator::RequestPicked, |
| 606 weak_ptr_factory_.GetWeakPtr()), | 608 weak_ptr_factory_.GetWeakPtr()), |
| 607 base::Bind(&RequestCoordinator::RequestNotPicked, | 609 base::Bind(&RequestCoordinator::RequestNotPicked, |
| 608 weak_ptr_factory_.GetWeakPtr()), | 610 weak_ptr_factory_.GetWeakPtr()), |
| 609 current_conditions_.get(), | 611 current_conditions_.get(), disabled_requests_); |
| 610 disabled_requests_); | 612 // TODO(petewil): Verify current_conditions has a good value on all calling |
| 613 // paths. It is really more of a "last known conditions" than "current |
| 614 // conditions". Consider having a call to Java to check the current |
| 615 // conditions. |
| 611 } | 616 } |
| 612 | 617 |
| 613 // Called by the request picker when a request has been picked. | 618 // Called by the request picker when a request has been picked. |
| 614 void RequestCoordinator::RequestPicked(const SavePageRequest& request) { | 619 void RequestCoordinator::RequestPicked(const SavePageRequest& request) { |
| 615 DVLOG(2) << request.url() << " " << __func__; | 620 DVLOG(2) << request.url() << " " << __func__; |
| 616 is_starting_ = false; | 621 is_starting_ = false; |
| 617 | 622 |
| 618 // Make sure we were not stopped while picking. | 623 // Make sure we were not stopped while picking. |
| 619 if (processing_state_ != ProcessingWindowState::STOPPED) { | 624 if (processing_state_ != ProcessingWindowState::STOPPED) { |
| 620 // Send the request on to the offliner. | 625 // Send the request on to the offliner. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 queue_->MarkAttemptStarted( | 673 queue_->MarkAttemptStarted( |
| 669 request.request_id(), | 674 request.request_id(), |
| 670 base::Bind(&RequestCoordinator::StartOffliner, | 675 base::Bind(&RequestCoordinator::StartOffliner, |
| 671 weak_ptr_factory_.GetWeakPtr(), request.request_id(), | 676 weak_ptr_factory_.GetWeakPtr(), request.request_id(), |
| 672 request.client_id().name_space)); | 677 request.client_id().name_space)); |
| 673 } | 678 } |
| 674 | 679 |
| 675 void RequestCoordinator::StartOffliner( | 680 void RequestCoordinator::StartOffliner( |
| 676 int64_t request_id, | 681 int64_t request_id, |
| 677 const std::string& client_namespace, | 682 const std::string& client_namespace, |
| 678 std::unique_ptr<UpdateRequestsResult> update_result) { | 683 std::unique_ptr<QueueResults::UpdateRequestsResult> update_result) { |
| 679 if (update_result->store_state != StoreState::LOADED || | 684 if (update_result->store_state != StoreState::LOADED || |
| 680 update_result->item_statuses.size() != 1 || | 685 update_result->item_statuses.size() != 1 || |
| 681 update_result->item_statuses.at(0).first != request_id || | 686 update_result->item_statuses.at(0).first != request_id || |
| 682 update_result->item_statuses.at(0).second != ItemActionStatus::SUCCESS) { | 687 update_result->item_statuses.at(0).second != ItemActionStatus::SUCCESS) { |
| 683 is_busy_ = false; | 688 is_busy_ = false; |
| 684 // TODO(fgorski): what is the best result? Do we create a new status? | 689 // TODO(fgorski): what is the best result? Do we create a new status? |
| 685 StopProcessing(Offliner::PRERENDERING_NOT_STARTED); | 690 StopProcessing(Offliner::PRERENDERING_NOT_STARTED); |
| 686 DVLOG(1) << "Failed to mark attempt started: " << request_id; | 691 DVLOG(1) << "Failed to mark attempt started: " << request_id; |
| 687 RequestQueue::UpdateRequestResult request_result = | 692 QueueResults::UpdateRequestResult request_result = |
| 688 update_result->store_state != StoreState::LOADED | 693 update_result->store_state != StoreState::LOADED |
| 689 ? RequestQueue::UpdateRequestResult::STORE_FAILURE | 694 ? QueueResults::UpdateRequestResult::STORE_FAILURE |
| 690 : RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; | 695 : QueueResults::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; |
| 691 event_logger_.RecordUpdateRequestFailed(client_namespace, request_result); | 696 event_logger_.RecordUpdateRequestFailed(client_namespace, request_result); |
| 692 return; | 697 return; |
| 693 } | 698 } |
| 694 | 699 |
| 695 // TODO(fgorski): Switch to request_id only, so that this value is not written | 700 // TODO(fgorski): Switch to request_id only, so that this value is not written |
| 696 // back to the store. | 701 // back to the store. |
| 697 active_request_.reset( | 702 active_request_.reset( |
| 698 new SavePageRequest(update_result->updated_items.at(0))); | 703 new SavePageRequest(update_result->updated_items.at(0))); |
| 699 | 704 |
| 700 // Start the load and save process in the offliner (Async). | 705 // Start the load and save process in the offliner (Async). |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 742 if (status == Offliner::RequestStatus::FOREGROUND_CANCELED || | 747 if (status == Offliner::RequestStatus::FOREGROUND_CANCELED || |
| 743 status == Offliner::RequestStatus::PRERENDERING_CANCELED) { | 748 status == Offliner::RequestStatus::PRERENDERING_CANCELED) { |
| 744 // Update the request for the canceled attempt. | 749 // Update the request for the canceled attempt. |
| 745 // TODO(dougarnett): See if we can conclusively identify other attempt | 750 // TODO(dougarnett): See if we can conclusively identify other attempt |
| 746 // aborted cases to treat this way (eg, for Render Process Killed). | 751 // aborted cases to treat this way (eg, for Render Process Killed). |
| 747 SavePageRequest updated_request(request); | 752 SavePageRequest updated_request(request); |
| 748 AbortRequestAttempt(&updated_request); | 753 AbortRequestAttempt(&updated_request); |
| 749 NotifyChanged(updated_request); | 754 NotifyChanged(updated_request); |
| 750 } else if (status == Offliner::RequestStatus::SAVED) { | 755 } else if (status == Offliner::RequestStatus::SAVED) { |
| 751 // Remove the request from the queue if it succeeded. | 756 // Remove the request from the queue if it succeeded. |
| 752 RemoveAttemptedRequest(request, BackgroundSavePageResult::SUCCESS); | 757 RemoveAttemptedRequest(request, |
| 758 RequestNotifier::BackgroundSavePageResult::SUCCESS); |
| 753 } else if (status == Offliner::RequestStatus::PRERENDERING_FAILED_NO_RETRY) { | 759 } else if (status == Offliner::RequestStatus::PRERENDERING_FAILED_NO_RETRY) { |
| 754 RemoveAttemptedRequest(request, | 760 RemoveAttemptedRequest( |
| 755 BackgroundSavePageResult::PRERENDER_FAILURE); | 761 request, RequestNotifier::BackgroundSavePageResult::PRERENDER_FAILURE); |
| 756 } else if (request.completed_attempt_count() + 1 >= | 762 } else if (request.completed_attempt_count() + 1 >= |
| 757 policy_->GetMaxCompletedTries()) { | 763 policy_->GetMaxCompletedTries()) { |
| 758 // Remove from the request queue if we exceeded max retries. The +1 | 764 // Remove from the request queue if we exceeded max retries. The +1 |
| 759 // represents the request that just completed. Since we call | 765 // represents the request that just completed. Since we call |
| 760 // MarkAttemptCompleted within the if branches, the completed_attempt_count | 766 // MarkAttemptCompleted within the if branches, the completed_attempt_count |
| 761 // has not yet been updated when we are checking the if condition. | 767 // has not yet been updated when we are checking the if condition. |
| 762 const BackgroundSavePageResult result( | 768 const RequestNotifier::BackgroundSavePageResult result( |
| 763 BackgroundSavePageResult::RETRY_COUNT_EXCEEDED); | 769 RequestNotifier::BackgroundSavePageResult::RETRY_COUNT_EXCEEDED); |
| 764 event_logger_.RecordDroppedSavePageRequest(request.client_id().name_space, | 770 event_logger_.RecordDroppedSavePageRequest(request.client_id().name_space, |
| 765 result, request.request_id()); | 771 result, request.request_id()); |
| 766 RemoveAttemptedRequest(request, result); | 772 RemoveAttemptedRequest(request, result); |
| 767 } else { | 773 } else { |
| 768 // If we failed, but are not over the limit, update the request in the | 774 // If we failed, but are not over the limit, update the request in the |
| 769 // queue. | 775 // queue. |
| 770 queue_->MarkAttemptCompleted( | 776 queue_->MarkAttemptCompleted( |
| 771 request.request_id(), | 777 request.request_id(), |
| 772 base::Bind(&RequestCoordinator::MarkAttemptCompletedDoneCallback, | 778 base::Bind(&RequestCoordinator::MarkAttemptCompletedDoneCallback, |
| 773 weak_ptr_factory_.GetWeakPtr(), request.request_id(), | 779 weak_ptr_factory_.GetWeakPtr(), request.request_id(), |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 811 | 817 |
| 812 void RequestCoordinator::MarkRequestCompleted(int64_t request_id) { | 818 void RequestCoordinator::MarkRequestCompleted(int64_t request_id) { |
| 813 // Since the recent tab helper might call multiple times, ignore subsequent | 819 // Since the recent tab helper might call multiple times, ignore subsequent |
| 814 // calls for a particular request_id. | 820 // calls for a particular request_id. |
| 815 if (disabled_requests_.find(request_id) == disabled_requests_.end()) | 821 if (disabled_requests_.find(request_id) == disabled_requests_.end()) |
| 816 return; | 822 return; |
| 817 disabled_requests_.erase(request_id); | 823 disabled_requests_.erase(request_id); |
| 818 | 824 |
| 819 // Remove the request, but send out SUCCEEDED instead of removed. | 825 // Remove the request, but send out SUCCEEDED instead of removed. |
| 820 std::vector<int64_t> request_ids { request_id }; | 826 std::vector<int64_t> request_ids { request_id }; |
| 821 queue_->RemoveRequests( | 827 queue_->RemoveRequests( |
| 822 request_ids, | 828 request_ids, |
| 823 base::Bind(&RequestCoordinator::HandleRemovedRequestsAndCallback, | 829 base::Bind(&RequestCoordinator::HandleRemovedRequestsAndCallback, |
| 824 weak_ptr_factory_.GetWeakPtr(), | 830 weak_ptr_factory_.GetWeakPtr(), |
| 825 base::Bind(&RequestCoordinator::CompletedRequestCallback, | 831 base::Bind(&RequestCoordinator::CompletedRequestCallback, |
| 826 weak_ptr_factory_.GetWeakPtr()), | 832 weak_ptr_factory_.GetWeakPtr()), |
| 827 BackgroundSavePageResult::SUCCESS)); | 833 RequestNotifier::BackgroundSavePageResult::SUCCESS)); |
| 828 } | 834 } |
| 829 | 835 |
| 830 const Scheduler::TriggerConditions RequestCoordinator::GetTriggerConditions( | 836 const Scheduler::TriggerConditions RequestCoordinator::GetTriggerConditions( |
| 831 const bool user_requested) { | 837 const bool user_requested) { |
| 832 return Scheduler::TriggerConditions( | 838 return Scheduler::TriggerConditions( |
| 833 policy_->PowerRequired(user_requested), | 839 policy_->PowerRequired(user_requested), |
| 834 policy_->BatteryPercentageRequired(user_requested), | 840 policy_->BatteryPercentageRequired(user_requested), |
| 835 policy_->UnmeteredNetworkRequired(user_requested)); | 841 policy_->UnmeteredNetworkRequired(user_requested)); |
| 836 } | 842 } |
| 837 | 843 |
| 838 void RequestCoordinator::AddObserver(Observer* observer) { | 844 void RequestCoordinator::AddObserver(Observer* observer) { |
| 839 DCHECK(observer); | 845 DCHECK(observer); |
| 840 observers_.AddObserver(observer); | 846 observers_.AddObserver(observer); |
| 841 } | 847 } |
| 842 | 848 |
| 843 void RequestCoordinator::RemoveObserver(Observer* observer) { | 849 void RequestCoordinator::RemoveObserver(Observer* observer) { |
| 844 observers_.RemoveObserver(observer); | 850 observers_.RemoveObserver(observer); |
| 845 } | 851 } |
| 846 | 852 |
| 847 void RequestCoordinator::NotifyAdded(const SavePageRequest& request) { | 853 void RequestCoordinator::NotifyAdded(const SavePageRequest& request) { |
| 848 for (Observer& observer : observers_) | 854 for (Observer& observer : observers_) |
| 849 observer.OnAdded(request); | 855 observer.OnAdded(request); |
| 850 } | 856 } |
| 851 | 857 |
| 852 void RequestCoordinator::NotifyCompleted(const SavePageRequest& request, | 858 void RequestCoordinator::NotifyCompleted( |
| 853 BackgroundSavePageResult status) { | 859 const SavePageRequest& request, |
| 860 RequestNotifier::BackgroundSavePageResult status) { |
| 854 for (Observer& observer : observers_) | 861 for (Observer& observer : observers_) |
| 855 observer.OnCompleted(request, status); | 862 observer.OnCompleted(request, status); |
| 856 } | 863 } |
| 857 | 864 |
| 858 void RequestCoordinator::NotifyChanged(const SavePageRequest& request) { | 865 void RequestCoordinator::NotifyChanged(const SavePageRequest& request) { |
| 859 for (Observer& observer : observers_) | 866 for (Observer& observer : observers_) |
| 860 observer.OnChanged(request); | 867 observer.OnChanged(request); |
| 861 } | 868 } |
| 862 | 869 |
| 863 void RequestCoordinator::GetOffliner() { | 870 void RequestCoordinator::GetOffliner() { |
| 864 if (!offliner_) { | 871 if (!offliner_) { |
| 865 offliner_ = factory_->GetOffliner(policy_.get()); | 872 offliner_ = factory_->GetOffliner(policy_.get()); |
| 866 } | 873 } |
| 867 } | 874 } |
| 868 | 875 |
| 869 ClientPolicyController* RequestCoordinator::GetPolicyController() { | 876 ClientPolicyController* RequestCoordinator::GetPolicyController() { |
| 870 return policy_controller_.get(); | 877 return policy_controller_.get(); |
| 871 } | 878 } |
| 872 | 879 |
| 873 void RequestCoordinator::Shutdown() { | 880 void RequestCoordinator::Shutdown() { |
| 874 network_quality_estimator_ = nullptr; | 881 network_quality_estimator_ = nullptr; |
| 875 } | 882 } |
| 876 | 883 |
| 877 } // namespace offline_pages | 884 } // namespace offline_pages |
| OLD | NEW |