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) { |
fgorski
2016/08/15 17:51:44
nit: remove {}
Pete Williamson
2016/08/15 20:22:52
Done.
| |
158 if (result != RequestQueue::UpdateRequestResult::SUCCESS) { | 160 NotifyChanged(request); |
159 DVLOG(1) << "Failed to update request attempt details. " | |
160 << static_cast<int>(result); | |
161 } | 161 } |
162 } | 162 } |
163 | 163 |
164 void RequestCoordinator::RemoveRequestsCallback( | 164 void RequestCoordinator::RemoveRequestsCallback( |
165 const RequestQueue::UpdateMultipleRequestResults& results) { | 165 const RequestQueue::UpdateMultipleRequestResults& results, |
166 // TODO(petewil): Today the RemoveRequests API does not come with a callback. | 166 const std::vector<SavePageRequest>& requests) { |
167 // Should we add one? Perhaps the notifications from the observer will be | 167 for (SavePageRequest request : requests) { |
fgorski
2016/08/15 17:51:44
nit: remove {}
Pete Williamson
2016/08/15 20:22:52
Done.
| |
168 // sufficient. | 168 NotifyRemoved(request); |
169 } | |
169 } | 170 } |
170 | 171 |
171 void RequestCoordinator::StopProcessing() { | 172 void RequestCoordinator::StopProcessing() { |
172 is_canceled_ = true; | 173 is_canceled_ = true; |
173 if (offliner_ && is_busy_) { | 174 if (offliner_ && is_busy_) { |
174 // TODO(dougarnett): Find current request and mark attempt aborted. | 175 // TODO(dougarnett): Find current request and mark attempt aborted. |
175 offliner_->Cancel(); | 176 offliner_->Cancel(); |
176 } | 177 } |
177 | 178 |
178 // Stopping offliner means it will not call callback. | 179 // 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) { | 307 if (status == Offliner::RequestStatus::FOREGROUND_CANCELED) { |
307 // Update the request for the canceled attempt. | 308 // Update the request for the canceled attempt. |
308 // TODO(dougarnett): See if we can conclusively identify other attempt | 309 // TODO(dougarnett): See if we can conclusively identify other attempt |
309 // aborted cases to treat this way (eg, for Render Process Killed). | 310 // aborted cases to treat this way (eg, for Render Process Killed). |
310 SavePageRequest updated_request(request); | 311 SavePageRequest updated_request(request); |
311 updated_request.MarkAttemptAborted(); | 312 updated_request.MarkAttemptAborted(); |
312 queue_->UpdateRequest(updated_request, | 313 queue_->UpdateRequest(updated_request, |
313 base::Bind(&RequestCoordinator::UpdateRequestCallback, | 314 base::Bind(&RequestCoordinator::UpdateRequestCallback, |
314 weak_ptr_factory_.GetWeakPtr(), | 315 weak_ptr_factory_.GetWeakPtr(), |
315 updated_request.client_id())); | 316 updated_request.client_id())); |
317 NotifyFailed(updated_request, SavePageStatus::FOREGROUND_CANCELED); | |
316 | 318 |
317 } else if (status == Offliner::RequestStatus::SAVED || | 319 } else if (status == Offliner::RequestStatus::SAVED) { |
318 request.completed_attempt_count() + 1 >= | 320 // 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; | 321 std::vector<int64_t> remove_requests; |
326 remove_requests.push_back(request.request_id()); | 322 remove_requests.push_back(request.request_id()); |
327 queue_->RemoveRequests( | 323 queue_->RemoveRequests( |
328 remove_requests, base::Bind(&RequestCoordinator::RemoveRequestsCallback, | 324 remove_requests, base::Bind(&RequestCoordinator::RemoveRequestsCallback, |
329 weak_ptr_factory_.GetWeakPtr())); | 325 weak_ptr_factory_.GetWeakPtr())); |
326 NotifySucceeded(request); | |
327 } else if (request.completed_attempt_count() + 1 >= | |
328 policy_->GetMaxCompletedTries()) { | |
329 // Remove from the request queue if we exceeeded max retries. The +1 | |
330 // represents the request that just completed. Since we call | |
331 // MarkAttemptCompleted within the if branches, the completed_attempt_count | |
332 // has not yet been updated when we are checking the if condition. | |
333 std::vector<int64_t> remove_requests; | |
334 remove_requests.push_back(request.request_id()); | |
335 queue_->RemoveRequests( | |
336 remove_requests, base::Bind(&RequestCoordinator::RemoveRequestsCallback, | |
337 weak_ptr_factory_.GetWeakPtr())); | |
338 NotifyFailed(request, SavePageStatus::RETRY_COUNT_EXCEEDED); | |
330 } else { | 339 } else { |
331 // If we failed, but are not over the limit, update the request in the | 340 // If we failed, but are not over the limit, update the request in the |
332 // queue. | 341 // queue. |
333 SavePageRequest updated_request(request); | 342 SavePageRequest updated_request(request); |
334 updated_request.MarkAttemptCompleted(); | 343 updated_request.MarkAttemptCompleted(); |
335 queue_->UpdateRequest(updated_request, | 344 queue_->UpdateRequest(updated_request, |
336 base::Bind(&RequestCoordinator::UpdateRequestCallback, | 345 base::Bind(&RequestCoordinator::UpdateRequestCallback, |
337 weak_ptr_factory_.GetWeakPtr(), | 346 weak_ptr_factory_.GetWeakPtr(), |
338 updated_request.client_id())); | 347 updated_request.client_id())); |
348 NotifyChanged(updated_request); | |
339 } | 349 } |
340 | 350 |
341 // Determine whether we might try another request in this | 351 // Determine whether we might try another request in this |
342 // processing window based on how the previous request completed. | 352 // processing window based on how the previous request completed. |
343 // | 353 // |
344 // TODO(dougarnett): Need to split PRERENDERING_FAILED into separate | 354 // TODO(dougarnett): Need to split PRERENDERING_FAILED into separate |
345 // codes as to whether we should try another request or not. | 355 // codes as to whether we should try another request or not. |
346 switch (status) { | 356 switch (status) { |
347 case Offliner::RequestStatus::SAVED: | 357 case Offliner::RequestStatus::SAVED: |
348 case Offliner::RequestStatus::SAVE_FAILED: | 358 case Offliner::RequestStatus::SAVE_FAILED: |
(...skipping 15 matching lines...) Expand all Loading... | |
364 | 374 |
365 const Scheduler::TriggerConditions | 375 const Scheduler::TriggerConditions |
366 RequestCoordinator::GetTriggerConditionsForUserRequest() { | 376 RequestCoordinator::GetTriggerConditionsForUserRequest() { |
367 Scheduler::TriggerConditions trigger_conditions( | 377 Scheduler::TriggerConditions trigger_conditions( |
368 policy_->PowerRequiredForUserRequestedPage(), | 378 policy_->PowerRequiredForUserRequestedPage(), |
369 policy_->BatteryPercentageRequiredForUserRequestedPage(), | 379 policy_->BatteryPercentageRequiredForUserRequestedPage(), |
370 policy_->UnmeteredNetworkRequiredForUserRequestedPage()); | 380 policy_->UnmeteredNetworkRequiredForUserRequestedPage()); |
371 return trigger_conditions; | 381 return trigger_conditions; |
372 } | 382 } |
373 | 383 |
384 void RequestCoordinator::AddObserver(Observer* observer) { | |
385 DCHECK(observer); | |
386 observers_.AddObserver(observer); | |
387 } | |
388 | |
389 void RequestCoordinator::RemoveObserver(Observer* observer) { | |
390 observers_.RemoveObserver(observer); | |
391 } | |
392 | |
393 void RequestCoordinator::NotifyAdded(const SavePageRequest& request) { | |
394 FOR_EACH_OBSERVER(Observer, observers_, OnAdded(request)); | |
395 } | |
396 | |
397 void RequestCoordinator::NotifySucceeded(const SavePageRequest& request) { | |
398 FOR_EACH_OBSERVER(Observer, observers_, OnSucceeded(request)); | |
399 } | |
400 | |
401 void RequestCoordinator::NotifyFailed(const SavePageRequest& request, | |
402 SavePageStatus status) { | |
403 FOR_EACH_OBSERVER(Observer, observers_, OnFailed(request, status)); | |
404 } | |
405 | |
406 void RequestCoordinator::NotifyChanged(const SavePageRequest& request) { | |
407 FOR_EACH_OBSERVER(Observer, observers_, OnChanged(request)); | |
408 } | |
409 | |
410 void RequestCoordinator::NotifyRemoved(const SavePageRequest& request) { | |
411 FOR_EACH_OBSERVER(Observer, observers_, | |
412 OnRemoved(request, SavePageStatus::REMOVED_BY_CLIENT)); | |
413 } | |
414 | |
374 void RequestCoordinator::GetOffliner() { | 415 void RequestCoordinator::GetOffliner() { |
375 if (!offliner_) { | 416 if (!offliner_) { |
376 offliner_ = factory_->GetOffliner(policy_.get()); | 417 offliner_ = factory_->GetOffliner(policy_.get()); |
377 } | 418 } |
378 } | 419 } |
379 | 420 |
380 } // namespace offline_pages | 421 } // namespace offline_pages |
OLD | NEW |