| 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 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 // are similar. | 121 // are similar. |
| 123 int64_t GenerateOfflineId() { | 122 int64_t GenerateOfflineId() { |
| 124 return base::RandGenerator(std::numeric_limits<int64_t>::max()) + 1; | 123 return base::RandGenerator(std::numeric_limits<int64_t>::max()) + 1; |
| 125 } | 124 } |
| 126 | 125 |
| 127 // In case we start processing from SavePageLater, we need a callback, but there | 126 // In case we start processing from SavePageLater, we need a callback, but there |
| 128 // is nothing for it to do. | 127 // is nothing for it to do. |
| 129 void EmptySchedulerCallback(bool started) {} | 128 void EmptySchedulerCallback(bool started) {} |
| 130 | 129 |
| 131 // Returns whether |result| is a successful result for a single request. | 130 // Returns whether |result| is a successful result for a single request. |
| 132 bool IsSingleSuccessResult(const UpdateRequestsResult* result) { | 131 bool IsSingleSuccessResult(const QueueResults::UpdateRequestsResult* result) { |
| 133 return result->store_state == StoreState::LOADED && | 132 return result->store_state == StoreState::LOADED && |
| 134 result->item_statuses.size() == 1 && | 133 result->item_statuses.size() == 1 && |
| 135 result->item_statuses.at(0).second == ItemActionStatus::SUCCESS; | 134 result->item_statuses.at(0).second == ItemActionStatus::SUCCESS; |
| 136 } | 135 } |
| 137 | 136 |
| 138 } // namespace | 137 } // namespace |
| 139 | 138 |
| 140 RequestCoordinator::RequestCoordinator( | 139 RequestCoordinator::RequestCoordinator( |
| 141 std::unique_ptr<OfflinerPolicy> policy, | 140 std::unique_ptr<OfflinerPolicy> policy, |
| 142 std::unique_ptr<OfflinerFactory> factory, | 141 std::unique_ptr<OfflinerFactory> factory, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 156 queue_(std::move(queue)), | 155 queue_(std::move(queue)), |
| 157 scheduler_(std::move(scheduler)), | 156 scheduler_(std::move(scheduler)), |
| 158 policy_controller_(new ClientPolicyController()), | 157 policy_controller_(new ClientPolicyController()), |
| 159 network_quality_estimator_(network_quality_estimator), | 158 network_quality_estimator_(network_quality_estimator), |
| 160 active_request_(nullptr), | 159 active_request_(nullptr), |
| 161 last_offlining_status_(Offliner::RequestStatus::UNKNOWN), | 160 last_offlining_status_(Offliner::RequestStatus::UNKNOWN), |
| 162 scheduler_callback_(base::Bind(&EmptySchedulerCallback)), | 161 scheduler_callback_(base::Bind(&EmptySchedulerCallback)), |
| 163 immediate_schedule_callback_(base::Bind(&EmptySchedulerCallback)), | 162 immediate_schedule_callback_(base::Bind(&EmptySchedulerCallback)), |
| 164 weak_ptr_factory_(this) { | 163 weak_ptr_factory_(this) { |
| 165 DCHECK(policy_ != nullptr); | 164 DCHECK(policy_ != nullptr); |
| 166 picker_.reset( | 165 queue_->SetPickerBuilder( |
| 167 new RequestPicker(queue_.get(), policy_.get(), this, &event_logger_)); | 166 new PickRequestTaskBuilder(policy_.get(), this, &event_logger_)); |
| 168 } | 167 } |
| 169 | 168 |
| 170 RequestCoordinator::~RequestCoordinator() {} | 169 RequestCoordinator::~RequestCoordinator() {} |
| 171 | 170 |
| 172 int64_t RequestCoordinator::SavePageLater(const GURL& url, | 171 int64_t RequestCoordinator::SavePageLater(const GURL& url, |
| 173 const ClientId& client_id, | 172 const ClientId& client_id, |
| 174 bool user_requested, | 173 bool user_requested, |
| 175 RequestAvailability availability) { | 174 RequestAvailability availability) { |
| 176 DVLOG(2) << "URL is " << url << " " << __func__; | 175 DVLOG(2) << "URL is " << url << " " << __func__; |
| 177 | 176 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 200 void RequestCoordinator::GetAllRequests(const GetRequestsCallback& callback) { | 199 void RequestCoordinator::GetAllRequests(const GetRequestsCallback& callback) { |
| 201 // Get all matching requests from the request queue, send them to our | 200 // Get all matching requests from the request queue, send them to our |
| 202 // callback. We bind the namespace and callback to the front of the callback | 201 // callback. We bind the namespace and callback to the front of the callback |
| 203 // param set. | 202 // param set. |
| 204 queue_->GetRequests(base::Bind(&RequestCoordinator::GetQueuedRequestsCallback, | 203 queue_->GetRequests(base::Bind(&RequestCoordinator::GetQueuedRequestsCallback, |
| 205 weak_ptr_factory_.GetWeakPtr(), callback)); | 204 weak_ptr_factory_.GetWeakPtr(), callback)); |
| 206 } | 205 } |
| 207 | 206 |
| 208 void RequestCoordinator::GetQueuedRequestsCallback( | 207 void RequestCoordinator::GetQueuedRequestsCallback( |
| 209 const GetRequestsCallback& callback, | 208 const GetRequestsCallback& callback, |
| 210 RequestQueue::GetRequestsResult result, | 209 QueueResults::GetRequestsResult result, |
| 211 std::vector<std::unique_ptr<SavePageRequest>> requests) { | 210 std::vector<std::unique_ptr<SavePageRequest>> requests) { |
| 212 callback.Run(std::move(requests)); | 211 callback.Run(std::move(requests)); |
| 213 } | 212 } |
| 214 | 213 |
| 215 void RequestCoordinator::StopPrerendering(Offliner::RequestStatus stop_status) { | 214 void RequestCoordinator::StopPrerendering(Offliner::RequestStatus stop_status) { |
| 216 if (offliner_ && is_busy_) { | 215 if (offliner_ && is_busy_) { |
| 217 DCHECK(active_request_.get()); | 216 DCHECK(active_request_.get()); |
| 218 offliner_->Cancel(); | 217 offliner_->Cancel(); |
| 219 | 218 |
| 220 // If we timed out, let the offliner done callback handle it. | 219 // If we timed out, let the offliner done callback handle it. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 236 active_request_->request_id()); | 235 active_request_->request_id()); |
| 237 RecordOfflinerResultUMA(active_request_->client_id(), | 236 RecordOfflinerResultUMA(active_request_->client_id(), |
| 238 active_request_->creation_time(), | 237 active_request_->creation_time(), |
| 239 last_offlining_status_); | 238 last_offlining_status_); |
| 240 is_busy_ = false; | 239 is_busy_ = false; |
| 241 active_request_.reset(); | 240 active_request_.reset(); |
| 242 } | 241 } |
| 243 } | 242 } |
| 244 | 243 |
| 245 void RequestCoordinator::GetRequestsForSchedulingCallback( | 244 void RequestCoordinator::GetRequestsForSchedulingCallback( |
| 246 RequestQueue::GetRequestsResult result, | 245 QueueResults::GetRequestsResult result, |
| 247 std::vector<std::unique_ptr<SavePageRequest>> requests) { | 246 std::vector<std::unique_ptr<SavePageRequest>> requests) { |
| 248 bool user_requested = false; | 247 bool user_requested = false; |
| 249 | 248 |
| 250 // Examine all requests, if we find a user requested one, we will use the less | 249 // Examine all requests, if we find a user requested one, we will use the less |
| 251 // restrictive conditions for user_requested requests. Otherwise we will use | 250 // restrictive conditions for user_requested requests. Otherwise we will use |
| 252 // the more restrictive non-user-requested conditions. | 251 // the more restrictive non-user-requested conditions. |
| 253 for (const auto& request : requests) { | 252 for (const auto& request : requests) { |
| 254 if (request->user_requested()) { | 253 if (request->user_requested()) { |
| 255 user_requested = true; | 254 user_requested = true; |
| 256 break; | 255 break; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 274 active_request_.reset(nullptr); | 273 active_request_.reset(nullptr); |
| 275 return true; | 274 return true; |
| 276 } | 275 } |
| 277 } | 276 } |
| 278 | 277 |
| 279 return false; | 278 return false; |
| 280 } | 279 } |
| 281 | 280 |
| 282 void RequestCoordinator::AbortRequestAttempt(SavePageRequest* request) { | 281 void RequestCoordinator::AbortRequestAttempt(SavePageRequest* request) { |
| 283 if (request->started_attempt_count() >= policy_->GetMaxStartedTries()) { | 282 if (request->started_attempt_count() >= policy_->GetMaxStartedTries()) { |
| 284 const BackgroundSavePageResult result( | 283 const RequestNotifier::BackgroundSavePageResult result( |
| 285 BackgroundSavePageResult::START_COUNT_EXCEEDED); | 284 RequestNotifier::BackgroundSavePageResult::START_COUNT_EXCEEDED); |
| 286 event_logger_.RecordDroppedSavePageRequest(request->client_id().name_space, | 285 event_logger_.RecordDroppedSavePageRequest(request->client_id().name_space, |
| 287 result, request->request_id()); | 286 result, request->request_id()); |
| 288 RemoveAttemptedRequest(*request, result); | 287 RemoveAttemptedRequest(*request, result); |
| 289 } else { | 288 } else { |
| 290 queue_->MarkAttemptAborted( | 289 queue_->MarkAttemptAborted( |
| 291 request->request_id(), | 290 request->request_id(), |
| 292 base::Bind(&RequestCoordinator::MarkAttemptAbortedDone, | 291 base::Bind(&RequestCoordinator::MarkAttemptAbortedDone, |
| 293 weak_ptr_factory_.GetWeakPtr(), request->request_id(), | 292 weak_ptr_factory_.GetWeakPtr(), request->request_id(), |
| 294 request->client_id())); | 293 request->client_id())); |
| 295 } | 294 } |
| 296 } | 295 } |
| 297 | 296 |
| 298 void RequestCoordinator::RemoveAttemptedRequest( | 297 void RequestCoordinator::RemoveAttemptedRequest( |
| 299 const SavePageRequest& request, | 298 const SavePageRequest& request, |
| 300 BackgroundSavePageResult result) { | 299 RequestNotifier::BackgroundSavePageResult result) { |
| 301 std::vector<int64_t> remove_requests; | 300 std::vector<int64_t> remove_requests; |
| 302 remove_requests.push_back(request.request_id()); | 301 remove_requests.push_back(request.request_id()); |
| 303 queue_->RemoveRequests(remove_requests, | 302 queue_->RemoveRequests(remove_requests, |
| 304 base::Bind(&RequestCoordinator::HandleRemovedRequests, | 303 base::Bind(&RequestCoordinator::HandleRemovedRequests, |
| 305 weak_ptr_factory_.GetWeakPtr(), result)); | 304 weak_ptr_factory_.GetWeakPtr(), result)); |
| 306 RecordAttemptCount(request, result); | 305 RecordAttemptCount(request, result); |
| 307 } | 306 } |
| 308 | 307 |
| 309 void RequestCoordinator::MarkAttemptAbortedDone( | 308 void RequestCoordinator::MarkAttemptAbortedDone( |
| 310 int64_t request_id, | 309 int64_t request_id, |
| 311 const ClientId& client_id, | 310 const ClientId& client_id, |
| 312 std::unique_ptr<UpdateRequestsResult> result) { | 311 std::unique_ptr<QueueResults::UpdateRequestsResult> result) { |
| 313 // If the request succeeded, nothing to do. If it failed, we can't really do | 312 // If the request succeeded, nothing to do. If it failed, we can't really do |
| 314 // much, so just log it. | 313 // much, so just log it. |
| 315 if (!IsSingleSuccessResult(result.get())) { | 314 if (!IsSingleSuccessResult(result.get())) { |
| 316 DVLOG(1) << "Failed to mark request aborted: " << request_id; | 315 DVLOG(1) << "Failed to mark request aborted: " << request_id; |
| 317 RequestQueue::UpdateRequestResult request_result = | 316 QueueResults::UpdateRequestResult request_result = |
| 318 result->store_state != StoreState::LOADED | 317 result->store_state != StoreState::LOADED |
| 319 ? RequestQueue::UpdateRequestResult::STORE_FAILURE | 318 ? QueueResults::UpdateRequestResult::STORE_FAILURE |
| 320 : RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; | 319 : QueueResults::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; |
| 321 event_logger_.RecordUpdateRequestFailed(client_id.name_space, | 320 event_logger_.RecordUpdateRequestFailed(client_id.name_space, |
| 322 request_result); | 321 request_result); |
| 323 } | 322 } |
| 324 } | 323 } |
| 325 | 324 |
| 326 void RequestCoordinator::RemoveRequests( | 325 void RequestCoordinator::RemoveRequests( |
| 327 const std::vector<int64_t>& request_ids, | 326 const std::vector<int64_t>& request_ids, |
| 328 const RemoveRequestsCallback& callback) { | 327 const RemoveRequestsCallback& callback) { |
| 329 bool canceled = CancelActiveRequestIfItMatches(request_ids); | 328 bool canceled = CancelActiveRequestIfItMatches(request_ids); |
| 330 queue_->RemoveRequests( | 329 queue_->RemoveRequests( |
| 331 request_ids, | 330 request_ids, |
| 332 base::Bind(&RequestCoordinator::HandleRemovedRequestsAndCallback, | 331 base::Bind(&RequestCoordinator::HandleRemovedRequestsAndCallback, |
| 333 weak_ptr_factory_.GetWeakPtr(), callback, | 332 weak_ptr_factory_.GetWeakPtr(), callback, |
| 334 BackgroundSavePageResult::REMOVED)); | 333 RequestNotifier::BackgroundSavePageResult::REMOVED)); |
| 335 if (canceled) | 334 if (canceled) |
| 336 TryNextRequest(); | 335 TryNextRequest(); |
| 337 } | 336 } |
| 338 | 337 |
| 339 void RequestCoordinator::PauseRequests( | 338 void RequestCoordinator::PauseRequests( |
| 340 const std::vector<int64_t>& request_ids) { | 339 const std::vector<int64_t>& request_ids) { |
| 341 bool canceled = CancelActiveRequestIfItMatches(request_ids); | 340 bool canceled = CancelActiveRequestIfItMatches(request_ids); |
| 342 queue_->ChangeRequestsState( | 341 queue_->ChangeRequestsState( |
| 343 request_ids, SavePageRequest::RequestState::PAUSED, | 342 request_ids, SavePageRequest::RequestState::PAUSED, |
| 344 base::Bind(&RequestCoordinator::UpdateMultipleRequestsCallback, | 343 base::Bind(&RequestCoordinator::UpdateMultipleRequestsCallback, |
| (...skipping 16 matching lines...) Expand all Loading... |
| 361 net::NetworkChangeNotifier::ConnectionType | 360 net::NetworkChangeNotifier::ConnectionType |
| 362 RequestCoordinator::GetConnectionType() { | 361 RequestCoordinator::GetConnectionType() { |
| 363 // If we have a connection type set for test, use that. | 362 // If we have a connection type set for test, use that. |
| 364 if (use_test_connection_type_) | 363 if (use_test_connection_type_) |
| 365 return test_connection_type_; | 364 return test_connection_type_; |
| 366 | 365 |
| 367 return net::NetworkChangeNotifier::GetConnectionType(); | 366 return net::NetworkChangeNotifier::GetConnectionType(); |
| 368 } | 367 } |
| 369 | 368 |
| 370 void RequestCoordinator::AddRequestResultCallback( | 369 void RequestCoordinator::AddRequestResultCallback( |
| 371 RequestQueue::AddRequestResult result, | 370 QueueResults::AddRequestResult result, |
| 372 const SavePageRequest& request) { | 371 const SavePageRequest& request) { |
| 373 NotifyAdded(request); | 372 NotifyAdded(request); |
| 374 // Inform the scheduler that we have an outstanding task. | 373 // Inform the scheduler that we have an outstanding task. |
| 375 scheduler_->Schedule(GetTriggerConditions(kUserRequest)); | 374 scheduler_->Schedule(GetTriggerConditions(kUserRequest)); |
| 376 | 375 |
| 377 if (request.user_requested()) | 376 if (request.user_requested()) |
| 378 StartImmediatelyIfConnected(); | 377 StartImmediatelyIfConnected(); |
| 379 } | 378 } |
| 380 | 379 |
| 381 void RequestCoordinator::MarkAttemptCompletedDoneCallback( | 380 void RequestCoordinator::MarkAttemptCompletedDoneCallback( |
| 382 int64_t request_id, | 381 int64_t request_id, |
| 383 const ClientId& client_id, | 382 const ClientId& client_id, |
| 384 std::unique_ptr<UpdateRequestsResult> result) { | 383 std::unique_ptr<QueueResults::UpdateRequestsResult> result) { |
| 385 if (IsSingleSuccessResult(result.get())) { | 384 if (IsSingleSuccessResult(result.get())) { |
| 386 NotifyChanged(result->updated_items.at(0)); | 385 NotifyChanged(result->updated_items.at(0)); |
| 387 } else { | 386 } else { |
| 388 DVLOG(1) << "Failed to mark request completed " << request_id; | 387 DVLOG(1) << "Failed to mark request completed " << request_id; |
| 389 RequestQueue::UpdateRequestResult request_result = | 388 QueueResults::UpdateRequestResult request_result = |
| 390 result->store_state != StoreState::LOADED | 389 result->store_state != StoreState::LOADED |
| 391 ? RequestQueue::UpdateRequestResult::STORE_FAILURE | 390 ? QueueResults::UpdateRequestResult::STORE_FAILURE |
| 392 : RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; | 391 : QueueResults::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; |
| 393 event_logger_.RecordUpdateRequestFailed(client_id.name_space, | 392 event_logger_.RecordUpdateRequestFailed(client_id.name_space, |
| 394 request_result); | 393 request_result); |
| 395 } | 394 } |
| 396 } | 395 } |
| 397 | 396 |
| 398 void RequestCoordinator::UpdateMultipleRequestsCallback( | 397 void RequestCoordinator::UpdateMultipleRequestsCallback( |
| 399 std::unique_ptr<UpdateRequestsResult> result) { | 398 std::unique_ptr<QueueResults::UpdateRequestsResult> result) { |
| 400 for (const auto& request : result->updated_items) | 399 for (const auto& request : result->updated_items) |
| 401 NotifyChanged(request); | 400 NotifyChanged(request); |
| 402 | 401 |
| 403 bool available_user_request = false; | 402 bool available_user_request = false; |
| 404 for (const auto& request : result->updated_items) { | 403 for (const auto& request : result->updated_items) { |
| 405 if (!available_user_request && request.user_requested() && | 404 if (!available_user_request && request.user_requested() && |
| 406 request.request_state() == SavePageRequest::RequestState::AVAILABLE) { | 405 request.request_state() == SavePageRequest::RequestState::AVAILABLE) { |
| 407 available_user_request = true; | 406 available_user_request = true; |
| 408 } | 407 } |
| 409 } | 408 } |
| 410 | 409 |
| 411 if (available_user_request) | 410 if (available_user_request) |
| 412 StartImmediatelyIfConnected(); | 411 StartImmediatelyIfConnected(); |
| 413 } | 412 } |
| 414 | 413 |
| 415 // When we successfully remove a request that completed successfully, move on to | 414 // When we successfully remove a request that completed successfully, move on to |
| 416 // the next request. | 415 // the next request. |
| 417 void RequestCoordinator::CompletedRequestCallback( | 416 void RequestCoordinator::CompletedRequestCallback( |
| 418 const MultipleItemStatuses& status) { | 417 const MultipleItemStatuses& status) { |
| 419 TryNextRequest(); | 418 TryNextRequest(); |
| 420 } | 419 } |
| 421 | 420 |
| 422 void RequestCoordinator::HandleRemovedRequestsAndCallback( | 421 void RequestCoordinator::HandleRemovedRequestsAndCallback( |
| 423 const RemoveRequestsCallback& callback, | 422 const RemoveRequestsCallback& callback, |
| 424 BackgroundSavePageResult status, | 423 RequestNotifier::BackgroundSavePageResult status, |
| 425 std::unique_ptr<UpdateRequestsResult> result) { | 424 std::unique_ptr<QueueResults::UpdateRequestsResult> result) { |
| 426 // TODO(dougarnett): Define status code for user/api cancel and use here | 425 // TODO(dougarnett): Define status code for user/api cancel and use here |
| 427 // to determine whether to record cancel time UMA. | 426 // to determine whether to record cancel time UMA. |
| 428 for (const auto& request : result->updated_items) | 427 for (const auto& request : result->updated_items) |
| 429 RecordCancelTimeUMA(request); | 428 RecordCancelTimeUMA(request); |
| 430 callback.Run(result->item_statuses); | 429 callback.Run(result->item_statuses); |
| 431 HandleRemovedRequests(status, std::move(result)); | 430 HandleRemovedRequests(status, std::move(result)); |
| 432 } | 431 } |
| 433 | 432 |
| 434 void RequestCoordinator::HandleRemovedRequests( | 433 void RequestCoordinator::HandleRemovedRequests( |
| 435 BackgroundSavePageResult status, | 434 RequestNotifier::BackgroundSavePageResult status, |
| 436 std::unique_ptr<UpdateRequestsResult> result) { | 435 std::unique_ptr<QueueResults::UpdateRequestsResult> result) { |
| 437 for (const auto& request : result->updated_items) | 436 for (const auto& request : result->updated_items) |
| 438 NotifyCompleted(request, status); | 437 NotifyCompleted(request, status); |
| 439 } | 438 } |
| 440 | 439 |
| 441 void RequestCoordinator::ScheduleAsNeeded() { | 440 void RequestCoordinator::ScheduleAsNeeded() { |
| 442 // Get all requests from queue (there is no filtering mechanism). | 441 // Get all requests from queue (there is no filtering mechanism). |
| 443 queue_->GetRequests( | 442 queue_->GetRequests( |
| 444 base::Bind(&RequestCoordinator::GetRequestsForSchedulingCallback, | 443 base::Bind(&RequestCoordinator::GetRequestsForSchedulingCallback, |
| 445 weak_ptr_factory_.GetWeakPtr())); | 444 weak_ptr_factory_.GetWeakPtr())); |
| 446 } | 445 } |
| 447 | 446 |
| 448 void RequestCoordinator::StopProcessing( | 447 void RequestCoordinator::StopProcessing( |
| 449 Offliner::RequestStatus stop_status) { | 448 Offliner::RequestStatus stop_status) { |
| 450 processing_state_ = ProcessingWindowState::STOPPED; | 449 processing_state_ = ProcessingWindowState::STOPPED; |
| 451 StopPrerendering(stop_status); | 450 StopPrerendering(stop_status); |
| 452 | 451 |
| 453 // Let the scheduler know we are done processing. | 452 // Let the scheduler know we are done processing. |
| 454 scheduler_callback_.Run(true); | 453 scheduler_callback_.Run(true); |
| 455 } | 454 } |
| 456 | 455 |
| 457 void RequestCoordinator::HandleWatchdogTimeout() { | 456 void RequestCoordinator::HandleWatchdogTimeout() { |
| 458 StopProcessing(Offliner::REQUEST_COORDINATOR_TIMED_OUT); | 457 StopProcessing(Offliner::REQUEST_COORDINATOR_TIMED_OUT); |
| 459 } | 458 } |
| 460 | 459 |
| 461 // Returns true if the caller should expect a callback, false otherwise. For | 460 // Returns true if the caller should expect a callback, false otherwise. For |
| 462 // instance, this would return false if a request is already in progress. | 461 // instance, this would return false if a request is already in progress. |
| 463 bool RequestCoordinator::StartProcessing( | 462 bool RequestCoordinator::StartProcessing( |
| 464 const DeviceConditions& device_conditions, | 463 const DeviceConditions& device_conditions, |
| 465 const base::Callback<void(bool)>& callback) { | 464 const base::Callback<void(bool)>& callback) { |
| 465 DVLOG(2) << "Scheduled " << __func__; |
| 466 return StartProcessingInternal(ProcessingWindowState::SCHEDULED_WINDOW, | 466 return StartProcessingInternal(ProcessingWindowState::SCHEDULED_WINDOW, |
| 467 device_conditions, callback); | 467 device_conditions, callback); |
| 468 } | 468 } |
| 469 | 469 |
| 470 bool RequestCoordinator::StartProcessingInternal( | 470 bool RequestCoordinator::StartProcessingInternal( |
| 471 const ProcessingWindowState processing_state, | 471 const ProcessingWindowState processing_state, |
| 472 const DeviceConditions& device_conditions, | 472 const DeviceConditions& device_conditions, |
| 473 const base::Callback<void(bool)>& callback) { | 473 const base::Callback<void(bool)>& callback) { |
| 474 current_conditions_.reset(new DeviceConditions(device_conditions)); | 474 current_conditions_.reset(new DeviceConditions(device_conditions)); |
| 475 if (is_starting_ || is_busy_) | 475 if (is_starting_ || is_busy_) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 489 | 489 |
| 490 void RequestCoordinator::StartImmediatelyIfConnected() { | 490 void RequestCoordinator::StartImmediatelyIfConnected() { |
| 491 OfflinerImmediateStartStatus immediate_start_status = TryImmediateStart(); | 491 OfflinerImmediateStartStatus immediate_start_status = TryImmediateStart(); |
| 492 UMA_HISTOGRAM_ENUMERATION( | 492 UMA_HISTOGRAM_ENUMERATION( |
| 493 "OfflinePages.Background.ImmediateStartStatus", immediate_start_status, | 493 "OfflinePages.Background.ImmediateStartStatus", immediate_start_status, |
| 494 RequestCoordinator::OfflinerImmediateStartStatus::STATUS_COUNT); | 494 RequestCoordinator::OfflinerImmediateStartStatus::STATUS_COUNT); |
| 495 } | 495 } |
| 496 | 496 |
| 497 RequestCoordinator::OfflinerImmediateStartStatus | 497 RequestCoordinator::OfflinerImmediateStartStatus |
| 498 RequestCoordinator::TryImmediateStart() { | 498 RequestCoordinator::TryImmediateStart() { |
| 499 DVLOG(2) << "Immediate " << __func__; |
| 499 // Make sure not already busy processing. | 500 // Make sure not already busy processing. |
| 500 if (is_busy_) | 501 if (is_busy_) |
| 501 return OfflinerImmediateStartStatus::BUSY; | 502 return OfflinerImmediateStartStatus::BUSY; |
| 502 | 503 |
| 503 // Make sure we are not on svelte device to start immediately. | 504 // Make sure we are not on svelte device to start immediately. |
| 504 if (is_low_end_device_) { | 505 if (is_low_end_device_) { |
| 505 DVLOG(2) << "low end device, returning"; | 506 DVLOG(2) << "low end device, returning"; |
| 506 // Let the scheduler know we are done processing and failed due to svelte. | 507 // Let the scheduler know we are done processing and failed due to svelte. |
| 507 immediate_schedule_callback_.Run(false); | 508 immediate_schedule_callback_.Run(false); |
| 508 return OfflinerImmediateStartStatus::NOT_STARTED_ON_SVELTE; | 509 return OfflinerImmediateStartStatus::NOT_STARTED_ON_SVELTE; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 is_starting_ = false; | 552 is_starting_ = false; |
| 552 | 553 |
| 553 // Let the scheduler know we are done processing. | 554 // Let the scheduler know we are done processing. |
| 554 // TODO: Make sure the scheduler callback is valid before running it. | 555 // TODO: Make sure the scheduler callback is valid before running it. |
| 555 scheduler_callback_.Run(true); | 556 scheduler_callback_.Run(true); |
| 556 DVLOG(2) << " out of time, giving up. " << __func__; | 557 DVLOG(2) << " out of time, giving up. " << __func__; |
| 557 | 558 |
| 558 return; | 559 return; |
| 559 } | 560 } |
| 560 | 561 |
| 561 // Choose a request to process that meets the available conditions. | 562 // Ask request queue to make a new PickRequestTask object, then put it on the |
| 562 // This is an async call, and returns right away. | 563 // task queue. |
| 563 picker_->ChooseNextRequest(base::Bind(&RequestCoordinator::RequestPicked, | 564 queue_->PickNextRequest(base::Bind(&RequestCoordinator::RequestPicked, |
| 564 weak_ptr_factory_.GetWeakPtr()), | 565 weak_ptr_factory_.GetWeakPtr()), |
| 565 base::Bind(&RequestCoordinator::RequestNotPicked, | 566 base::Bind(&RequestCoordinator::RequestNotPicked, |
| 566 weak_ptr_factory_.GetWeakPtr()), | 567 weak_ptr_factory_.GetWeakPtr()), |
| 567 current_conditions_.get(), | 568 current_conditions_.get(), disabled_requests_); |
| 568 disabled_requests_); | 569 // TODO(petewil): Verify current_conditions has a good value on all calling |
| 570 // paths. It is really more of a "last known conditions" than "current |
| 571 // conditions". Consider having a call to Java to check the current |
| 572 // conditions. |
| 569 } | 573 } |
| 570 | 574 |
| 571 // Called by the request picker when a request has been picked. | 575 // Called by the request picker when a request has been picked. |
| 572 void RequestCoordinator::RequestPicked(const SavePageRequest& request) { | 576 void RequestCoordinator::RequestPicked(const SavePageRequest& request) { |
| 573 DVLOG(2) << request.url() << " " << __func__; | 577 DVLOG(2) << request.url() << " " << __func__; |
| 574 is_starting_ = false; | 578 is_starting_ = false; |
| 575 | 579 |
| 576 // Make sure we were not stopped while picking. | 580 // Make sure we were not stopped while picking. |
| 577 if (processing_state_ != ProcessingWindowState::STOPPED) { | 581 if (processing_state_ != ProcessingWindowState::STOPPED) { |
| 578 // Send the request on to the offliner. | 582 // Send the request on to the offliner. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 626 queue_->MarkAttemptStarted( | 630 queue_->MarkAttemptStarted( |
| 627 request.request_id(), | 631 request.request_id(), |
| 628 base::Bind(&RequestCoordinator::StartOffliner, | 632 base::Bind(&RequestCoordinator::StartOffliner, |
| 629 weak_ptr_factory_.GetWeakPtr(), request.request_id(), | 633 weak_ptr_factory_.GetWeakPtr(), request.request_id(), |
| 630 request.client_id().name_space)); | 634 request.client_id().name_space)); |
| 631 } | 635 } |
| 632 | 636 |
| 633 void RequestCoordinator::StartOffliner( | 637 void RequestCoordinator::StartOffliner( |
| 634 int64_t request_id, | 638 int64_t request_id, |
| 635 const std::string& client_namespace, | 639 const std::string& client_namespace, |
| 636 std::unique_ptr<UpdateRequestsResult> update_result) { | 640 std::unique_ptr<QueueResults::UpdateRequestsResult> update_result) { |
| 637 if (update_result->store_state != StoreState::LOADED || | 641 if (update_result->store_state != StoreState::LOADED || |
| 638 update_result->item_statuses.size() != 1 || | 642 update_result->item_statuses.size() != 1 || |
| 639 update_result->item_statuses.at(0).first != request_id || | 643 update_result->item_statuses.at(0).first != request_id || |
| 640 update_result->item_statuses.at(0).second != ItemActionStatus::SUCCESS) { | 644 update_result->item_statuses.at(0).second != ItemActionStatus::SUCCESS) { |
| 641 is_busy_ = false; | 645 is_busy_ = false; |
| 642 // TODO(fgorski): what is the best result? Do we create a new status? | 646 // TODO(fgorski): what is the best result? Do we create a new status? |
| 643 StopProcessing(Offliner::PRERENDERING_NOT_STARTED); | 647 StopProcessing(Offliner::PRERENDERING_NOT_STARTED); |
| 644 DVLOG(1) << "Failed to mark attempt started: " << request_id; | 648 DVLOG(1) << "Failed to mark attempt started: " << request_id; |
| 645 RequestQueue::UpdateRequestResult request_result = | 649 QueueResults::UpdateRequestResult request_result = |
| 646 update_result->store_state != StoreState::LOADED | 650 update_result->store_state != StoreState::LOADED |
| 647 ? RequestQueue::UpdateRequestResult::STORE_FAILURE | 651 ? QueueResults::UpdateRequestResult::STORE_FAILURE |
| 648 : RequestQueue::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; | 652 : QueueResults::UpdateRequestResult::REQUEST_DOES_NOT_EXIST; |
| 649 event_logger_.RecordUpdateRequestFailed(client_namespace, request_result); | 653 event_logger_.RecordUpdateRequestFailed(client_namespace, request_result); |
| 650 return; | 654 return; |
| 651 } | 655 } |
| 652 | 656 |
| 653 // TODO(fgorski): Switch to request_id only, so that this value is not written | 657 // TODO(fgorski): Switch to request_id only, so that this value is not written |
| 654 // back to the store. | 658 // back to the store. |
| 655 active_request_.reset( | 659 active_request_.reset( |
| 656 new SavePageRequest(update_result->updated_items.at(0))); | 660 new SavePageRequest(update_result->updated_items.at(0))); |
| 657 | 661 |
| 658 // Start the load and save process in the offliner (Async). | 662 // Start the load and save process in the offliner (Async). |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 if (status == Offliner::RequestStatus::FOREGROUND_CANCELED || | 704 if (status == Offliner::RequestStatus::FOREGROUND_CANCELED || |
| 701 status == Offliner::RequestStatus::PRERENDERING_CANCELED) { | 705 status == Offliner::RequestStatus::PRERENDERING_CANCELED) { |
| 702 // Update the request for the canceled attempt. | 706 // Update the request for the canceled attempt. |
| 703 // TODO(dougarnett): See if we can conclusively identify other attempt | 707 // TODO(dougarnett): See if we can conclusively identify other attempt |
| 704 // aborted cases to treat this way (eg, for Render Process Killed). | 708 // aborted cases to treat this way (eg, for Render Process Killed). |
| 705 SavePageRequest updated_request(request); | 709 SavePageRequest updated_request(request); |
| 706 AbortRequestAttempt(&updated_request); | 710 AbortRequestAttempt(&updated_request); |
| 707 NotifyChanged(updated_request); | 711 NotifyChanged(updated_request); |
| 708 } else if (status == Offliner::RequestStatus::SAVED) { | 712 } else if (status == Offliner::RequestStatus::SAVED) { |
| 709 // Remove the request from the queue if it succeeded. | 713 // Remove the request from the queue if it succeeded. |
| 710 RemoveAttemptedRequest(request, BackgroundSavePageResult::SUCCESS); | 714 RemoveAttemptedRequest(request, |
| 715 RequestNotifier::BackgroundSavePageResult::SUCCESS); |
| 711 } else if (status == Offliner::RequestStatus::PRERENDERING_FAILED_NO_RETRY) { | 716 } else if (status == Offliner::RequestStatus::PRERENDERING_FAILED_NO_RETRY) { |
| 712 RemoveAttemptedRequest(request, | 717 RemoveAttemptedRequest( |
| 713 BackgroundSavePageResult::PRERENDER_FAILURE); | 718 request, RequestNotifier::BackgroundSavePageResult::PRERENDER_FAILURE); |
| 714 } else if (request.completed_attempt_count() + 1 >= | 719 } else if (request.completed_attempt_count() + 1 >= |
| 715 policy_->GetMaxCompletedTries()) { | 720 policy_->GetMaxCompletedTries()) { |
| 716 // Remove from the request queue if we exceeded max retries. The +1 | 721 // Remove from the request queue if we exceeded max retries. The +1 |
| 717 // represents the request that just completed. Since we call | 722 // represents the request that just completed. Since we call |
| 718 // MarkAttemptCompleted within the if branches, the completed_attempt_count | 723 // MarkAttemptCompleted within the if branches, the completed_attempt_count |
| 719 // has not yet been updated when we are checking the if condition. | 724 // has not yet been updated when we are checking the if condition. |
| 720 const BackgroundSavePageResult result( | 725 const RequestNotifier::BackgroundSavePageResult result( |
| 721 BackgroundSavePageResult::RETRY_COUNT_EXCEEDED); | 726 RequestNotifier::BackgroundSavePageResult::RETRY_COUNT_EXCEEDED); |
| 722 event_logger_.RecordDroppedSavePageRequest(request.client_id().name_space, | 727 event_logger_.RecordDroppedSavePageRequest(request.client_id().name_space, |
| 723 result, request.request_id()); | 728 result, request.request_id()); |
| 724 RemoveAttemptedRequest(request, result); | 729 RemoveAttemptedRequest(request, result); |
| 725 } else { | 730 } else { |
| 726 // If we failed, but are not over the limit, update the request in the | 731 // If we failed, but are not over the limit, update the request in the |
| 727 // queue. | 732 // queue. |
| 728 queue_->MarkAttemptCompleted( | 733 queue_->MarkAttemptCompleted( |
| 729 request.request_id(), | 734 request.request_id(), |
| 730 base::Bind(&RequestCoordinator::MarkAttemptCompletedDoneCallback, | 735 base::Bind(&RequestCoordinator::MarkAttemptCompletedDoneCallback, |
| 731 weak_ptr_factory_.GetWeakPtr(), request.request_id(), | 736 weak_ptr_factory_.GetWeakPtr(), request.request_id(), |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 769 | 774 |
| 770 void RequestCoordinator::MarkRequestCompleted(int64_t request_id) { | 775 void RequestCoordinator::MarkRequestCompleted(int64_t request_id) { |
| 771 // Since the recent tab helper might call multiple times, ignore subsequent | 776 // Since the recent tab helper might call multiple times, ignore subsequent |
| 772 // calls for a particular request_id. | 777 // calls for a particular request_id. |
| 773 if (disabled_requests_.find(request_id) == disabled_requests_.end()) | 778 if (disabled_requests_.find(request_id) == disabled_requests_.end()) |
| 774 return; | 779 return; |
| 775 disabled_requests_.erase(request_id); | 780 disabled_requests_.erase(request_id); |
| 776 | 781 |
| 777 // Remove the request, but send out SUCCEEDED instead of removed. | 782 // Remove the request, but send out SUCCEEDED instead of removed. |
| 778 std::vector<int64_t> request_ids { request_id }; | 783 std::vector<int64_t> request_ids { request_id }; |
| 779 queue_->RemoveRequests( | 784 queue_->RemoveRequests( |
| 780 request_ids, | 785 request_ids, |
| 781 base::Bind(&RequestCoordinator::HandleRemovedRequestsAndCallback, | 786 base::Bind(&RequestCoordinator::HandleRemovedRequestsAndCallback, |
| 782 weak_ptr_factory_.GetWeakPtr(), | 787 weak_ptr_factory_.GetWeakPtr(), |
| 783 base::Bind(&RequestCoordinator::CompletedRequestCallback, | 788 base::Bind(&RequestCoordinator::CompletedRequestCallback, |
| 784 weak_ptr_factory_.GetWeakPtr()), | 789 weak_ptr_factory_.GetWeakPtr()), |
| 785 BackgroundSavePageResult::SUCCESS)); | 790 RequestNotifier::BackgroundSavePageResult::SUCCESS)); |
| 786 } | 791 } |
| 787 | 792 |
| 788 const Scheduler::TriggerConditions RequestCoordinator::GetTriggerConditions( | 793 const Scheduler::TriggerConditions RequestCoordinator::GetTriggerConditions( |
| 789 const bool user_requested) { | 794 const bool user_requested) { |
| 790 return Scheduler::TriggerConditions( | 795 return Scheduler::TriggerConditions( |
| 791 policy_->PowerRequired(user_requested), | 796 policy_->PowerRequired(user_requested), |
| 792 policy_->BatteryPercentageRequired(user_requested), | 797 policy_->BatteryPercentageRequired(user_requested), |
| 793 policy_->UnmeteredNetworkRequired(user_requested)); | 798 policy_->UnmeteredNetworkRequired(user_requested)); |
| 794 } | 799 } |
| 795 | 800 |
| 796 void RequestCoordinator::AddObserver(Observer* observer) { | 801 void RequestCoordinator::AddObserver(Observer* observer) { |
| 797 DCHECK(observer); | 802 DCHECK(observer); |
| 798 observers_.AddObserver(observer); | 803 observers_.AddObserver(observer); |
| 799 } | 804 } |
| 800 | 805 |
| 801 void RequestCoordinator::RemoveObserver(Observer* observer) { | 806 void RequestCoordinator::RemoveObserver(Observer* observer) { |
| 802 observers_.RemoveObserver(observer); | 807 observers_.RemoveObserver(observer); |
| 803 } | 808 } |
| 804 | 809 |
| 805 void RequestCoordinator::NotifyAdded(const SavePageRequest& request) { | 810 void RequestCoordinator::NotifyAdded(const SavePageRequest& request) { |
| 806 for (Observer& observer : observers_) | 811 for (Observer& observer : observers_) |
| 807 observer.OnAdded(request); | 812 observer.OnAdded(request); |
| 808 } | 813 } |
| 809 | 814 |
| 810 void RequestCoordinator::NotifyCompleted(const SavePageRequest& request, | 815 void RequestCoordinator::NotifyCompleted( |
| 811 BackgroundSavePageResult status) { | 816 const SavePageRequest& request, |
| 817 RequestNotifier::BackgroundSavePageResult status) { |
| 812 for (Observer& observer : observers_) | 818 for (Observer& observer : observers_) |
| 813 observer.OnCompleted(request, status); | 819 observer.OnCompleted(request, status); |
| 814 } | 820 } |
| 815 | 821 |
| 816 void RequestCoordinator::NotifyChanged(const SavePageRequest& request) { | 822 void RequestCoordinator::NotifyChanged(const SavePageRequest& request) { |
| 817 for (Observer& observer : observers_) | 823 for (Observer& observer : observers_) |
| 818 observer.OnChanged(request); | 824 observer.OnChanged(request); |
| 819 } | 825 } |
| 820 | 826 |
| 821 void RequestCoordinator::GetOffliner() { | 827 void RequestCoordinator::GetOffliner() { |
| 822 if (!offliner_) { | 828 if (!offliner_) { |
| 823 offliner_ = factory_->GetOffliner(policy_.get()); | 829 offliner_ = factory_->GetOffliner(policy_.get()); |
| 824 } | 830 } |
| 825 } | 831 } |
| 826 | 832 |
| 827 ClientPolicyController* RequestCoordinator::GetPolicyController() { | 833 ClientPolicyController* RequestCoordinator::GetPolicyController() { |
| 828 return policy_controller_.get(); | 834 return policy_controller_.get(); |
| 829 } | 835 } |
| 830 | 836 |
| 831 void RequestCoordinator::Shutdown() { | 837 void RequestCoordinator::Shutdown() { |
| 832 network_quality_estimator_ = nullptr; | 838 network_quality_estimator_ = nullptr; |
| 833 } | 839 } |
| 834 | 840 |
| 835 } // namespace offline_pages | 841 } // namespace offline_pages |
| OLD | NEW |