OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/offline_pages/background/request_coordinator.h" | 5 #include "components/offline_pages/background/request_coordinator.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 | 70 |
71 bool RequestCoordinator::SavePageLater( | 71 bool RequestCoordinator::SavePageLater( |
72 const GURL& url, const ClientId& client_id, bool user_requested) { | 72 const GURL& url, const ClientId& client_id, bool user_requested) { |
73 DVLOG(2) << "URL is " << url << " " << __func__; | 73 DVLOG(2) << "URL is " << url << " " << __func__; |
74 | 74 |
75 if (!OfflinePageModel::CanSaveURL(url)) { | 75 if (!OfflinePageModel::CanSaveURL(url)) { |
76 DVLOG(1) << "Not able to save page for requested url: " << url; | 76 DVLOG(1) << "Not able to save page for requested url: " << url; |
77 return false; | 77 return false; |
78 } | 78 } |
79 | 79 |
80 // TODO(petewil): We need a robust scheme for allocating new IDs. | 80 // TODO(petewil): Use an int64_t random number for this, pass it to the |
| 81 // offliner, and eventually use it as the offline_id - that way the client |
| 82 // uses offline_id everywhere. |
81 static int64_t id = 0; | 83 static int64_t id = 0; |
82 | 84 |
83 // Build a SavePageRequest. | 85 // Build a SavePageRequest. |
84 offline_pages::SavePageRequest request( | 86 offline_pages::SavePageRequest request( |
85 id++, url, client_id, base::Time::Now(), user_requested); | 87 id++, url, client_id, base::Time::Now(), user_requested); |
86 | 88 |
87 // Put the request on the request queue. | 89 // Put the request on the request queue. |
88 queue_->AddRequest(request, | 90 queue_->AddRequest(request, |
89 base::Bind(&RequestCoordinator::AddRequestResultCallback, | 91 base::Bind(&RequestCoordinator::AddRequestResultCallback, |
90 weak_ptr_factory_.GetWeakPtr())); | 92 weak_ptr_factory_.GetWeakPtr())); |
| 93 NotifyAdded(request); |
91 return true; | 94 return true; |
92 } | 95 } |
93 void RequestCoordinator::GetAllRequests(const GetRequestsCallback& callback) { | 96 void RequestCoordinator::GetAllRequests(const GetRequestsCallback& callback) { |
94 // Get all matching requests from the request queue, send them to our | 97 // Get all matching requests from the request queue, send them to our |
95 // callback. We bind the namespace and callback to the front of the callback | 98 // callback. We bind the namespace and callback to the front of the callback |
96 // param set. | 99 // param set. |
97 queue_->GetRequests(base::Bind(&RequestCoordinator::GetQueuedRequestsCallback, | 100 queue_->GetRequests(base::Bind(&RequestCoordinator::GetQueuedRequestsCallback, |
98 weak_ptr_factory_.GetWeakPtr(), callback)); | 101 weak_ptr_factory_.GetWeakPtr(), callback)); |
99 } | 102 } |
100 | 103 |
101 void RequestCoordinator::GetQueuedRequestsCallback( | 104 void RequestCoordinator::GetQueuedRequestsCallback( |
102 const GetRequestsCallback& callback, | 105 const GetRequestsCallback& callback, |
103 RequestQueue::GetRequestsResult result, | 106 RequestQueue::GetRequestsResult result, |
104 const std::vector<SavePageRequest>& requests) { | 107 const std::vector<SavePageRequest>& requests) { |
105 callback.Run(requests); | 108 callback.Run(requests); |
106 } | 109 } |
107 | 110 |
108 void RequestCoordinator::RemoveRequests( | 111 void RequestCoordinator::RemoveRequests( |
109 const std::vector<int64_t>& request_ids) { | 112 const std::vector<int64_t>& request_ids) { |
110 queue_->RemoveRequests(request_ids, | 113 queue_->RemoveRequests(request_ids, |
111 base::Bind(&RequestCoordinator::RemoveRequestsCallback, | 114 base::Bind(&RequestCoordinator::RemoveRequestsCallback, |
112 weak_ptr_factory_.GetWeakPtr())); | 115 weak_ptr_factory_.GetWeakPtr())); |
113 } | 116 } |
114 | 117 |
115 void RequestCoordinator::PauseRequests( | 118 void RequestCoordinator::PauseRequests( |
116 const std::vector<int64_t>& request_ids) { | 119 const std::vector<int64_t>& request_ids) { |
117 queue_->ChangeRequestsState( | 120 queue_->ChangeRequestsState( |
118 request_ids, SavePageRequest::RequestState::PAUSED, | 121 request_ids, SavePageRequest::RequestState::PAUSED, |
119 base::Bind(&RequestCoordinator::UpdateMultipleRequestCallback, | 122 base::Bind(&RequestCoordinator::UpdateMultipleRequestsCallback, |
120 weak_ptr_factory_.GetWeakPtr())); | 123 weak_ptr_factory_.GetWeakPtr())); |
121 } | 124 } |
122 | 125 |
123 void RequestCoordinator::ResumeRequests( | 126 void RequestCoordinator::ResumeRequests( |
124 const std::vector<int64_t>& request_ids) { | 127 const std::vector<int64_t>& request_ids) { |
125 queue_->ChangeRequestsState( | 128 queue_->ChangeRequestsState( |
126 request_ids, SavePageRequest::RequestState::AVAILABLE, | 129 request_ids, SavePageRequest::RequestState::AVAILABLE, |
127 base::Bind(&RequestCoordinator::UpdateMultipleRequestCallback, | 130 base::Bind(&RequestCoordinator::UpdateMultipleRequestsCallback, |
128 weak_ptr_factory_.GetWeakPtr())); | 131 weak_ptr_factory_.GetWeakPtr())); |
129 // TODO: Should we also schedule a task, in case there is not one scheduled? | 132 // TODO: Should we also schedule a task, in case there is not one scheduled? |
130 } | 133 } |
131 | 134 |
132 void RequestCoordinator::AddRequestResultCallback( | 135 void RequestCoordinator::AddRequestResultCallback( |
133 RequestQueue::AddRequestResult result, | 136 RequestQueue::AddRequestResult result, |
134 const SavePageRequest& request) { | 137 const SavePageRequest& request) { |
135 | |
136 // Inform the scheduler that we have an outstanding task.. | 138 // Inform the scheduler that we have an outstanding task.. |
137 scheduler_->Schedule(GetTriggerConditionsForUserRequest()); | 139 scheduler_->Schedule(GetTriggerConditionsForUserRequest()); |
138 } | 140 } |
139 | 141 |
140 // Called in response to updating a request in the request queue. | 142 // Called in response to updating a request in the request queue. |
141 void RequestCoordinator::UpdateRequestCallback( | 143 void RequestCoordinator::UpdateRequestCallback( |
142 const ClientId& client_id, | 144 const ClientId& client_id, |
143 RequestQueue::UpdateRequestResult result) { | 145 RequestQueue::UpdateRequestResult result) { |
144 // If the request succeeded, nothing to do. If it failed, we can't really do | 146 // If the request succeeded, nothing to do. If it failed, we can't really do |
145 // much, so just log it. | 147 // much, so just log it. |
146 if (result != RequestQueue::UpdateRequestResult::SUCCESS) { | 148 if (result != RequestQueue::UpdateRequestResult::SUCCESS) { |
147 DVLOG(1) << "Failed to update request attempt details. " | 149 DVLOG(1) << "Failed to update request attempt details. " |
148 << static_cast<int>(result); | 150 << static_cast<int>(result); |
149 event_logger_.RecordUpdateRequestFailed(client_id.name_space, result); | 151 event_logger_.RecordUpdateRequestFailed(client_id.name_space, result); |
150 } | 152 } |
151 } | 153 } |
152 | 154 |
153 // Called in response to updating multiple requests in the request queue. | 155 // Called in response to updating multiple requests in the request queue. |
154 void RequestCoordinator::UpdateMultipleRequestCallback( | 156 void RequestCoordinator::UpdateMultipleRequestsCallback( |
155 RequestQueue::UpdateRequestResult result) { | 157 const RequestQueue::UpdateMultipleRequestResults& results, |
156 // If the request succeeded, nothing to do. If it failed, we can't really do | 158 const std::vector<SavePageRequest>& requests) { |
157 // much, so just log it. | 159 for (SavePageRequest request : requests) |
158 if (result != RequestQueue::UpdateRequestResult::SUCCESS) { | 160 NotifyChanged(request); |
159 DVLOG(1) << "Failed to update request attempt details. " | |
160 << static_cast<int>(result); | |
161 } | |
162 } | 161 } |
163 | 162 |
164 void RequestCoordinator::RemoveRequestsCallback( | 163 void RequestCoordinator::RemoveRequestsCallback( |
165 const RequestQueue::UpdateMultipleRequestResults& results) { | 164 const RequestQueue::UpdateMultipleRequestResults& results, |
166 // TODO(petewil): Today the RemoveRequests API does not come with a callback. | 165 const std::vector<SavePageRequest>& requests) { |
167 // Should we add one? Perhaps the notifications from the observer will be | 166 for (SavePageRequest request : requests) |
168 // sufficient. | 167 NotifyRemoved(request); |
169 } | 168 } |
170 | 169 |
171 void RequestCoordinator::StopProcessing() { | 170 void RequestCoordinator::StopProcessing() { |
172 is_canceled_ = true; | 171 is_canceled_ = true; |
173 if (offliner_ && is_busy_) { | 172 if (offliner_ && is_busy_) { |
174 // TODO(dougarnett): Find current request and mark attempt aborted. | 173 // TODO(dougarnett): Find current request and mark attempt aborted. |
175 offliner_->Cancel(); | 174 offliner_->Cancel(); |
176 } | 175 } |
177 | 176 |
178 // Stopping offliner means it will not call callback. | 177 // Stopping offliner means it will not call callback. |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 if (status == Offliner::RequestStatus::FOREGROUND_CANCELED) { | 305 if (status == Offliner::RequestStatus::FOREGROUND_CANCELED) { |
307 // Update the request for the canceled attempt. | 306 // Update the request for the canceled attempt. |
308 // TODO(dougarnett): See if we can conclusively identify other attempt | 307 // TODO(dougarnett): See if we can conclusively identify other attempt |
309 // aborted cases to treat this way (eg, for Render Process Killed). | 308 // aborted cases to treat this way (eg, for Render Process Killed). |
310 SavePageRequest updated_request(request); | 309 SavePageRequest updated_request(request); |
311 updated_request.MarkAttemptAborted(); | 310 updated_request.MarkAttemptAborted(); |
312 queue_->UpdateRequest(updated_request, | 311 queue_->UpdateRequest(updated_request, |
313 base::Bind(&RequestCoordinator::UpdateRequestCallback, | 312 base::Bind(&RequestCoordinator::UpdateRequestCallback, |
314 weak_ptr_factory_.GetWeakPtr(), | 313 weak_ptr_factory_.GetWeakPtr(), |
315 updated_request.client_id())); | 314 updated_request.client_id())); |
| 315 NotifyFailed(updated_request, SavePageStatus::FOREGROUND_CANCELED); |
316 | 316 |
317 } else if (status == Offliner::RequestStatus::SAVED || | 317 } else if (status == Offliner::RequestStatus::SAVED) { |
318 request.completed_attempt_count() + 1 >= | 318 // Remove the request from the queue if it succeeded. |
319 policy_->GetMaxCompletedTries()) { | |
320 // Remove the request from the queue if it either succeeded or exceeded the | |
321 // max number of retries. The +1 represents the request that just | |
322 // completed. Since we call MarkAttemptCompleted within the if branches, | |
323 // the completed_attempt_count has not yet been updated when we are checking | |
324 // the if condition. | |
325 std::vector<int64_t> remove_requests; | 319 std::vector<int64_t> remove_requests; |
326 remove_requests.push_back(request.request_id()); | 320 remove_requests.push_back(request.request_id()); |
327 queue_->RemoveRequests( | 321 queue_->RemoveRequests( |
328 remove_requests, base::Bind(&RequestCoordinator::RemoveRequestsCallback, | 322 remove_requests, base::Bind(&RequestCoordinator::RemoveRequestsCallback, |
329 weak_ptr_factory_.GetWeakPtr())); | 323 weak_ptr_factory_.GetWeakPtr())); |
| 324 NotifySucceeded(request); |
| 325 } else if (request.completed_attempt_count() + 1 >= |
| 326 policy_->GetMaxCompletedTries()) { |
| 327 // Remove from the request queue if we exceeeded max retries. The +1 |
| 328 // represents the request that just completed. Since we call |
| 329 // MarkAttemptCompleted within the if branches, the completed_attempt_count |
| 330 // has not yet been updated when we are checking the if condition. |
| 331 std::vector<int64_t> remove_requests; |
| 332 remove_requests.push_back(request.request_id()); |
| 333 queue_->RemoveRequests( |
| 334 remove_requests, base::Bind(&RequestCoordinator::RemoveRequestsCallback, |
| 335 weak_ptr_factory_.GetWeakPtr())); |
| 336 NotifyFailed(request, SavePageStatus::RETRY_COUNT_EXCEEDED); |
330 } else { | 337 } else { |
331 // If we failed, but are not over the limit, update the request in the | 338 // If we failed, but are not over the limit, update the request in the |
332 // queue. | 339 // queue. |
333 SavePageRequest updated_request(request); | 340 SavePageRequest updated_request(request); |
334 updated_request.MarkAttemptCompleted(); | 341 updated_request.MarkAttemptCompleted(); |
335 queue_->UpdateRequest(updated_request, | 342 queue_->UpdateRequest(updated_request, |
336 base::Bind(&RequestCoordinator::UpdateRequestCallback, | 343 base::Bind(&RequestCoordinator::UpdateRequestCallback, |
337 weak_ptr_factory_.GetWeakPtr(), | 344 weak_ptr_factory_.GetWeakPtr(), |
338 updated_request.client_id())); | 345 updated_request.client_id())); |
| 346 NotifyChanged(updated_request); |
339 } | 347 } |
340 | 348 |
341 // Determine whether we might try another request in this | 349 // Determine whether we might try another request in this |
342 // processing window based on how the previous request completed. | 350 // processing window based on how the previous request completed. |
343 // | 351 // |
344 // TODO(dougarnett): Need to split PRERENDERING_FAILED into separate | 352 // TODO(dougarnett): Need to split PRERENDERING_FAILED into separate |
345 // codes as to whether we should try another request or not. | 353 // codes as to whether we should try another request or not. |
346 switch (status) { | 354 switch (status) { |
347 case Offliner::RequestStatus::SAVED: | 355 case Offliner::RequestStatus::SAVED: |
348 case Offliner::RequestStatus::SAVE_FAILED: | 356 case Offliner::RequestStatus::SAVE_FAILED: |
(...skipping 15 matching lines...) Expand all Loading... |
364 | 372 |
365 const Scheduler::TriggerConditions | 373 const Scheduler::TriggerConditions |
366 RequestCoordinator::GetTriggerConditionsForUserRequest() { | 374 RequestCoordinator::GetTriggerConditionsForUserRequest() { |
367 Scheduler::TriggerConditions trigger_conditions( | 375 Scheduler::TriggerConditions trigger_conditions( |
368 policy_->PowerRequiredForUserRequestedPage(), | 376 policy_->PowerRequiredForUserRequestedPage(), |
369 policy_->BatteryPercentageRequiredForUserRequestedPage(), | 377 policy_->BatteryPercentageRequiredForUserRequestedPage(), |
370 policy_->UnmeteredNetworkRequiredForUserRequestedPage()); | 378 policy_->UnmeteredNetworkRequiredForUserRequestedPage()); |
371 return trigger_conditions; | 379 return trigger_conditions; |
372 } | 380 } |
373 | 381 |
| 382 void RequestCoordinator::AddObserver(Observer* observer) { |
| 383 DCHECK(observer); |
| 384 observers_.AddObserver(observer); |
| 385 } |
| 386 |
| 387 void RequestCoordinator::RemoveObserver(Observer* observer) { |
| 388 observers_.RemoveObserver(observer); |
| 389 } |
| 390 |
| 391 void RequestCoordinator::NotifyAdded(const SavePageRequest& request) { |
| 392 FOR_EACH_OBSERVER(Observer, observers_, OnAdded(request)); |
| 393 } |
| 394 |
| 395 void RequestCoordinator::NotifySucceeded(const SavePageRequest& request) { |
| 396 FOR_EACH_OBSERVER(Observer, observers_, OnSucceeded(request)); |
| 397 } |
| 398 |
| 399 void RequestCoordinator::NotifyFailed(const SavePageRequest& request, |
| 400 SavePageStatus status) { |
| 401 FOR_EACH_OBSERVER(Observer, observers_, OnFailed(request, status)); |
| 402 } |
| 403 |
| 404 void RequestCoordinator::NotifyChanged(const SavePageRequest& request) { |
| 405 FOR_EACH_OBSERVER(Observer, observers_, OnChanged(request)); |
| 406 } |
| 407 |
| 408 void RequestCoordinator::NotifyRemoved(const SavePageRequest& request) { |
| 409 FOR_EACH_OBSERVER(Observer, observers_, |
| 410 OnRemoved(request, SavePageStatus::REMOVED_BY_CLIENT)); |
| 411 } |
| 412 |
374 void RequestCoordinator::GetOffliner() { | 413 void RequestCoordinator::GetOffliner() { |
375 if (!offliner_) { | 414 if (!offliner_) { |
376 offliner_ = factory_->GetOffliner(policy_.get()); | 415 offliner_ = factory_->GetOffliner(policy_.get()); |
377 } | 416 } |
378 } | 417 } |
379 | 418 |
380 } // namespace offline_pages | 419 } // namespace offline_pages |
OLD | NEW |