Chromium Code Reviews| 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/time/time.h" | 13 #include "base/time/time.h" |
| 14 #include "components/offline_pages/background/offliner_factory.h" | 14 #include "components/offline_pages/background/offliner_factory.h" |
| 15 #include "components/offline_pages/background/offliner_policy.h" | 15 #include "components/offline_pages/background/offliner_policy.h" |
| 16 #include "components/offline_pages/background/request_picker.h" | 16 #include "components/offline_pages/background/request_picker.h" |
| 17 #include "components/offline_pages/background/save_page_request.h" | 17 #include "components/offline_pages/background/save_page_request.h" |
| 18 #include "components/offline_pages/offline_page_item.h" | 18 #include "components/offline_pages/offline_page_item.h" |
| 19 #include "components/offline_pages/offline_page_model.h" | |
| 19 | 20 |
| 20 namespace offline_pages { | 21 namespace offline_pages { |
| 21 | 22 |
| 22 namespace { | 23 namespace { |
| 23 | 24 |
| 24 // Records the final request status UMA for an offlining request. This should | 25 // Records the final request status UMA for an offlining request. This should |
| 25 // only be called once per Offliner::LoadAndSave request. | 26 // only be called once per Offliner::LoadAndSave request. |
| 26 void RecordOfflinerResultUMA(Offliner::RequestStatus request_status) { | 27 void RecordOfflinerResultUMA(Offliner::RequestStatus request_status) { |
| 27 UMA_HISTOGRAM_ENUMERATION("OfflinePages.Background.OfflinerRequestStatus", | 28 UMA_HISTOGRAM_ENUMERATION("OfflinePages.Background.OfflinerRequestStatus", |
| 28 request_status, | 29 request_status, |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 49 DCHECK(policy_ != nullptr); | 50 DCHECK(policy_ != nullptr); |
| 50 picker_.reset(new RequestPicker(queue_.get(), policy_.get())); | 51 picker_.reset(new RequestPicker(queue_.get(), policy_.get())); |
| 51 } | 52 } |
| 52 | 53 |
| 53 RequestCoordinator::~RequestCoordinator() {} | 54 RequestCoordinator::~RequestCoordinator() {} |
| 54 | 55 |
| 55 bool RequestCoordinator::SavePageLater( | 56 bool RequestCoordinator::SavePageLater( |
| 56 const GURL& url, const ClientId& client_id, bool was_user_requested) { | 57 const GURL& url, const ClientId& client_id, bool was_user_requested) { |
| 57 DVLOG(2) << "URL is " << url << " " << __func__; | 58 DVLOG(2) << "URL is " << url << " " << __func__; |
| 58 | 59 |
| 60 if (!OfflinePageModel::CanSaveURL(url)) { | |
| 61 DVLOG(1) << "Not able to save page for requested url: " << url; | |
| 62 return false; | |
| 63 } | |
| 64 | |
| 59 // TODO(petewil): We need a robust scheme for allocating new IDs. | 65 // TODO(petewil): We need a robust scheme for allocating new IDs. |
| 60 static int64_t id = 0; | 66 static int64_t id = 0; |
| 61 | 67 |
| 62 // Build a SavePageRequest. | 68 // Build a SavePageRequest. |
| 63 offline_pages::SavePageRequest request( | 69 offline_pages::SavePageRequest request( |
| 64 id++, url, client_id, base::Time::Now(), was_user_requested); | 70 id++, url, client_id, base::Time::Now(), was_user_requested); |
| 65 | 71 |
| 66 // Put the request on the request queue. | 72 // Put the request on the request queue. |
| 67 queue_->AddRequest(request, | 73 queue_->AddRequest(request, |
| 68 base::Bind(&RequestCoordinator::AddRequestResultCallback, | 74 base::Bind(&RequestCoordinator::AddRequestResultCallback, |
| 69 weak_ptr_factory_.GetWeakPtr())); | 75 weak_ptr_factory_.GetWeakPtr())); |
| 70 return true; | 76 return true; |
| 71 } | 77 } |
| 72 | 78 |
| 73 void RequestCoordinator::RemoveRequests( | 79 void RequestCoordinator::RemoveRequests( |
| 74 const std::vector<ClientId>& client_ids) { | 80 const std::vector<ClientId>& client_ids) { |
| 75 queue_->RemoveRequestsByClientId( | 81 queue_->RemoveRequestsByClientId( |
| 76 client_ids, base::Bind(&RequestCoordinator::UpdateRequestCallback, | 82 client_ids, base::Bind(&RequestCoordinator::UpdateMultipleRequestCallback, |
| 77 weak_ptr_factory_.GetWeakPtr())); | 83 weak_ptr_factory_.GetWeakPtr())); |
| 78 } | 84 } |
| 79 | 85 |
| 80 void RequestCoordinator::AddRequestResultCallback( | 86 void RequestCoordinator::AddRequestResultCallback( |
| 81 RequestQueue::AddRequestResult result, | 87 RequestQueue::AddRequestResult result, |
| 82 const SavePageRequest& request) { | 88 const SavePageRequest& request) { |
| 83 | 89 |
| 84 // Inform the scheduler that we have an outstanding task.. | 90 // Inform the scheduler that we have an outstanding task.. |
| 85 scheduler_->Schedule(GetTriggerConditionsForUserRequest()); | 91 scheduler_->Schedule(GetTriggerConditionsForUserRequest()); |
| 86 } | 92 } |
| 87 | 93 |
| 88 // Called in response to updating a request in the request queue. | 94 // Called in response to updating a request in the request queue. |
| 89 void RequestCoordinator::UpdateRequestCallback( | 95 void RequestCoordinator::UpdateRequestCallback( |
| 96 const ClientId& client_id, RequestQueue::UpdateRequestResult result) { | |
|
fgorski
2016/08/04 06:01:34
please run git cl format.
dougarnett
2016/08/04 16:24:38
Done.
| |
| 97 // If the request succeeded, nothing to do. If it failed, we can't really do | |
| 98 // much, so just log it. | |
| 99 if (result != RequestQueue::UpdateRequestResult::SUCCESS) { | |
| 100 DLOG(WARNING) << "Failed to update request attempt details. " | |
|
fgorski
2016/08/04 06:01:34
nit: use DVLOG here too
dougarnett
2016/08/04 16:24:38
Done.
| |
| 101 << static_cast<int>(result); | |
| 102 event_logger_.RecordUpdateRequestFailed( | |
| 103 client_id.name_space, | |
| 104 RequestQueue::UpdateRequestResultToString(result)); | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 // Called in response to updating multiple requests in the request queue. | |
| 109 void RequestCoordinator::UpdateMultipleRequestCallback( | |
| 90 RequestQueue::UpdateRequestResult result) { | 110 RequestQueue::UpdateRequestResult result) { |
| 91 // If the request succeeded, nothing to do. If it failed, we can't really do | 111 // If the request succeeded, nothing to do. If it failed, we can't really do |
| 92 // much, so just log it. | 112 // much, so just log it. |
| 93 if (result != RequestQueue::UpdateRequestResult::SUCCESS) { | 113 if (result != RequestQueue::UpdateRequestResult::SUCCESS) { |
| 94 // TODO(petewil): Consider adding UMA or showing on offline-internals page. | 114 DLOG(WARNING) << "Failed to update request attempt details. " |
| 95 DLOG(WARNING) << "Failed to update a request retry count. " | |
| 96 << static_cast<int>(result); | 115 << static_cast<int>(result); |
| 97 } | 116 } |
| 98 } | 117 } |
| 99 | 118 |
| 100 void RequestCoordinator::StopProcessing() { | 119 void RequestCoordinator::StopProcessing() { |
| 101 is_canceled_ = true; | 120 is_canceled_ = true; |
| 102 if (offliner_ && is_busy_) | 121 if (offliner_ && is_busy_) { |
| 122 // TODO(dougarnett): Find current request and mark attempt aborted. | |
| 103 offliner_->Cancel(); | 123 offliner_->Cancel(); |
| 124 } | |
| 104 | 125 |
| 105 // Stopping offliner means it will not call callback. | 126 // Stopping offliner means it will not call callback. |
| 106 last_offlining_status_ = | 127 last_offlining_status_ = |
| 107 Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED; | 128 Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED; |
| 108 RecordOfflinerResultUMA(last_offlining_status_); | 129 RecordOfflinerResultUMA(last_offlining_status_); |
| 109 | 130 |
| 110 // Let the scheduler know we are done processing. | 131 // Let the scheduler know we are done processing. |
| 111 scheduler_callback_.Run(true); | 132 scheduler_callback_.Run(true); |
| 112 } | 133 } |
| 113 | 134 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 177 GetOffliner(); | 198 GetOffliner(); |
| 178 if (!offliner_) { | 199 if (!offliner_) { |
| 179 DVLOG(0) << "Unable to create Offliner. " | 200 DVLOG(0) << "Unable to create Offliner. " |
| 180 << "Cannot background offline page."; | 201 << "Cannot background offline page."; |
| 181 return; | 202 return; |
| 182 } | 203 } |
| 183 | 204 |
| 184 DCHECK(!is_busy_); | 205 DCHECK(!is_busy_); |
| 185 is_busy_ = true; | 206 is_busy_ = true; |
| 186 | 207 |
| 208 // Prepare an updated request to attempt. | |
| 209 SavePageRequest updated_request(request); | |
| 210 updated_request.MarkAttemptStarted(base::Time::Now()); | |
| 211 | |
| 187 // Start the load and save process in the offliner (Async). | 212 // Start the load and save process in the offliner (Async). |
| 188 offliner_->LoadAndSave(request, | 213 if (offliner_->LoadAndSave(updated_request, |
| 189 base::Bind(&RequestCoordinator::OfflinerDoneCallback, | 214 base::Bind(&RequestCoordinator::OfflinerDoneCallback, |
|
fgorski
2016/08/04 06:01:34
nit: alignment
dougarnett
2016/08/04 16:24:38
Done.
| |
| 190 weak_ptr_factory_.GetWeakPtr())); | 215 weak_ptr_factory_.GetWeakPtr()))) { |
| 216 // Offliner accepted request so update it in the queue. | |
| 217 queue_->UpdateRequest( | |
| 218 updated_request, | |
| 219 base::Bind(&RequestCoordinator::UpdateRequestCallback, | |
| 220 weak_ptr_factory_.GetWeakPtr(), | |
| 221 updated_request.client_id())); | |
| 191 | 222 |
| 192 // Start a watchdog timer to catch pre-renders running too long | 223 // Start a watchdog timer to catch pre-renders running too long |
| 193 watchdog_timer_.Start(FROM_HERE, offliner_timeout_, this, | 224 watchdog_timer_.Start(FROM_HERE, offliner_timeout_, this, |
| 194 &RequestCoordinator::StopProcessing); | 225 &RequestCoordinator::StopProcessing); |
| 226 } else { | |
| 227 is_busy_ = false; | |
| 228 DVLOG(0) << "Unable to start LoadAndSave"; | |
| 229 StopProcessing(); | |
| 230 } | |
| 195 } | 231 } |
| 196 | 232 |
| 197 void RequestCoordinator::OfflinerDoneCallback(const SavePageRequest& request, | 233 void RequestCoordinator::OfflinerDoneCallback(const SavePageRequest& request, |
| 198 Offliner::RequestStatus status) { | 234 Offliner::RequestStatus status) { |
| 199 DVLOG(2) << "offliner finished, saved: " | 235 DVLOG(2) << "offliner finished, saved: " |
| 200 << (status == Offliner::RequestStatus::SAVED) | 236 << (status == Offliner::RequestStatus::SAVED) |
| 201 << ", status: " << static_cast<int>(status) << ", " << __func__; | 237 << ", status: " << static_cast<int>(status) << ", " << __func__; |
| 202 DCHECK_NE(status, Offliner::RequestStatus::UNKNOWN); | 238 DCHECK_NE(status, Offliner::RequestStatus::UNKNOWN); |
| 203 DCHECK_NE(status, Offliner::RequestStatus::LOADED); | 239 DCHECK_NE(status, Offliner::RequestStatus::LOADED); |
| 204 event_logger_.RecordSavePageRequestUpdated( | 240 event_logger_.RecordSavePageRequestUpdated( |
| 205 request.client_id().name_space, | 241 request.client_id().name_space, |
| 206 "Saved", | 242 Offliner::RequestStatusToString(status), |
| 207 request.request_id()); | 243 request.request_id()); |
| 208 last_offlining_status_ = status; | 244 last_offlining_status_ = status; |
| 209 RecordOfflinerResultUMA(last_offlining_status_); | 245 RecordOfflinerResultUMA(last_offlining_status_); |
| 210 watchdog_timer_.Stop(); | 246 watchdog_timer_.Stop(); |
| 211 | 247 |
| 212 is_busy_ = false; | 248 is_busy_ = false; |
| 213 | 249 |
| 214 int64_t new_attempt_count = request.attempt_count() + 1; | 250 if (status == Offliner::RequestStatus::FOREGROUND_CANCELED) { |
| 251 // Update the request for the canceled attempt. | |
| 252 // TODO(dougarnett): See if we can conclusively identify other attempt | |
| 253 // aborted cases to treat this way (eg, for Render Process Killed). | |
| 254 SavePageRequest updated_request(request); | |
| 255 updated_request.MarkAttemptAborted(); | |
| 256 queue_->UpdateRequest( | |
| 257 updated_request, | |
| 258 base::Bind(&RequestCoordinator::UpdateRequestCallback, | |
| 259 weak_ptr_factory_.GetWeakPtr(), | |
| 260 updated_request.client_id())); | |
| 215 | 261 |
| 216 // Remove the request from the queue if it either succeeded or exceeded the | 262 } else if (status == Offliner::RequestStatus::SAVED |
| 217 // max number of retries. | 263 || request.attempt_count() >= policy_->GetMaxTries()) { |
| 218 if (status == Offliner::RequestStatus::SAVED | 264 // Remove the request from the queue if it either succeeded or exceeded the |
| 219 || new_attempt_count > policy_->GetMaxTries()) { | 265 // max number of retries. |
| 220 queue_->RemoveRequest(request.request_id(), | 266 queue_->RemoveRequest(request.request_id(), |
| 221 base::Bind(&RequestCoordinator::UpdateRequestCallback, | 267 base::Bind(&RequestCoordinator::UpdateRequestCallback, |
| 222 weak_ptr_factory_.GetWeakPtr())); | 268 weak_ptr_factory_.GetWeakPtr(), |
| 269 request.client_id())); | |
| 223 } else { | 270 } else { |
| 224 // If we failed, but are not over the limit, update the request in the | 271 // If we failed, but are not over the limit, update the request in the |
| 225 // queue. | 272 // queue. |
| 226 SavePageRequest updated_request(request); | 273 SavePageRequest updated_request(request); |
| 227 updated_request.set_attempt_count(new_attempt_count); | 274 updated_request.MarkAttemptCompleted(); |
| 228 updated_request.set_last_attempt_time(base::Time::Now()); | |
| 229 RequestQueue::UpdateRequestCallback update_callback = | |
| 230 base::Bind(&RequestCoordinator::UpdateRequestCallback, | |
| 231 weak_ptr_factory_.GetWeakPtr()); | |
| 232 queue_->UpdateRequest( | 275 queue_->UpdateRequest( |
| 233 updated_request, | 276 updated_request, |
| 234 base::Bind(&RequestCoordinator::UpdateRequestCallback, | 277 base::Bind(&RequestCoordinator::UpdateRequestCallback, |
| 235 weak_ptr_factory_.GetWeakPtr())); | 278 weak_ptr_factory_.GetWeakPtr(), |
| 279 updated_request.client_id())); | |
| 236 } | 280 } |
| 237 | 281 |
| 238 // Determine whether we might try another request in this | 282 // Determine whether we might try another request in this |
| 239 // processing window based on how the previous request completed. | 283 // processing window based on how the previous request completed. |
| 240 // | 284 // |
| 241 // TODO(dougarnett): Need to split PRERENDERING_FAILED into separate | 285 // TODO(dougarnett): Need to split PRERENDERING_FAILED into separate |
| 242 // codes as to whether we should try another request or not. | 286 // codes as to whether we should try another request or not. |
| 243 switch (status) { | 287 switch (status) { |
| 244 case Offliner::RequestStatus::SAVED: | 288 case Offliner::RequestStatus::SAVED: |
| 245 case Offliner::RequestStatus::SAVE_FAILED: | 289 case Offliner::RequestStatus::SAVE_FAILED: |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 268 return trigger_conditions; | 312 return trigger_conditions; |
| 269 } | 313 } |
| 270 | 314 |
| 271 void RequestCoordinator::GetOffliner() { | 315 void RequestCoordinator::GetOffliner() { |
| 272 if (!offliner_) { | 316 if (!offliner_) { |
| 273 offliner_ = factory_->GetOffliner(policy_.get()); | 317 offliner_ = factory_->GetOffliner(policy_.get()); |
| 274 } | 318 } |
| 275 } | 319 } |
| 276 | 320 |
| 277 } // namespace offline_pages | 321 } // namespace offline_pages |
| OLD | NEW |