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::GetQueuedRequests( | 96 void RequestCoordinator::GetQueuedRequests( |
94 const std::string& client_namespace, | 97 const std::string& client_namespace, |
95 const QueuedRequestCallback& callback) { | 98 const QueuedRequestCallback& callback) { |
96 // Get all matching requests from the request queue, send them to our | 99 // Get all matching requests from the request queue, send them to our |
97 // callback. We bind the namespace and callback to the front of the callback | 100 // callback. We bind the namespace and callback to the front of the callback |
98 // param set. | 101 // param set. |
99 queue_->GetRequests(base::Bind(&RequestCoordinator::GetQueuedRequestsCallback, | 102 queue_->GetRequests(base::Bind(&RequestCoordinator::GetQueuedRequestsCallback, |
100 weak_ptr_factory_.GetWeakPtr(), | 103 weak_ptr_factory_.GetWeakPtr(), |
(...skipping 11 matching lines...) Expand all Loading... | |
112 for (const auto& request : requests) { | 115 for (const auto& request : requests) { |
113 if (client_namespace == request.client_id().name_space) | 116 if (client_namespace == request.client_id().name_space) |
114 client_ids.push_back(request.client_id()); | 117 client_ids.push_back(request.client_id()); |
115 } | 118 } |
116 | 119 |
117 callback.Run(client_ids); | 120 callback.Run(client_ids); |
118 } | 121 } |
119 | 122 |
120 void RequestCoordinator::RemoveRequests( | 123 void RequestCoordinator::RemoveRequests( |
121 const std::vector<ClientId>& client_ids) { | 124 const std::vector<ClientId>& client_ids) { |
125 std::vector<int64_t> placeholder; | |
122 queue_->RemoveRequestsByClientId( | 126 queue_->RemoveRequestsByClientId( |
123 client_ids, base::Bind(&RequestCoordinator::UpdateMultipleRequestCallback, | 127 client_ids, base::Bind(&RequestCoordinator::UpdateMultipleRequestCallback, |
124 weak_ptr_factory_.GetWeakPtr())); | 128 weak_ptr_factory_.GetWeakPtr(), placeholder)); |
125 } | 129 } |
126 | 130 |
127 void RequestCoordinator::PauseRequests( | 131 void RequestCoordinator::PauseRequests( |
128 const std::vector<int64_t>& request_ids) { | 132 const std::vector<int64_t>& request_ids) { |
129 queue_->ChangeRequestsState( | 133 queue_->ChangeRequestsState( |
130 request_ids, SavePageRequest::RequestState::PAUSED, | 134 request_ids, SavePageRequest::RequestState::PAUSED, |
131 base::Bind(&RequestCoordinator::UpdateMultipleRequestCallback, | 135 base::Bind(&RequestCoordinator::UpdateMultipleRequestCallback, |
132 weak_ptr_factory_.GetWeakPtr())); | 136 weak_ptr_factory_.GetWeakPtr(), request_ids)); |
133 } | 137 } |
134 | 138 |
135 void RequestCoordinator::ResumeRequests( | 139 void RequestCoordinator::ResumeRequests( |
136 const std::vector<int64_t>& request_ids) { | 140 const std::vector<int64_t>& request_ids) { |
137 queue_->ChangeRequestsState( | 141 queue_->ChangeRequestsState( |
138 request_ids, SavePageRequest::RequestState::AVAILABLE, | 142 request_ids, SavePageRequest::RequestState::AVAILABLE, |
139 base::Bind(&RequestCoordinator::UpdateMultipleRequestCallback, | 143 base::Bind(&RequestCoordinator::UpdateMultipleRequestCallback, |
140 weak_ptr_factory_.GetWeakPtr())); | 144 weak_ptr_factory_.GetWeakPtr(), request_ids)); |
141 // TODO: Should we also schedule a task, in case there is not one scheduled? | 145 // TODO: Should we also schedule a task, in case there is not one scheduled? |
142 } | 146 } |
143 | 147 |
144 void RequestCoordinator::AddRequestResultCallback( | 148 void RequestCoordinator::AddRequestResultCallback( |
145 RequestQueue::AddRequestResult result, | 149 RequestQueue::AddRequestResult result, |
146 const SavePageRequest& request) { | 150 const SavePageRequest& request) { |
147 | |
148 // Inform the scheduler that we have an outstanding task.. | 151 // Inform the scheduler that we have an outstanding task.. |
149 scheduler_->Schedule(GetTriggerConditionsForUserRequest()); | 152 scheduler_->Schedule(GetTriggerConditionsForUserRequest()); |
150 } | 153 } |
151 | 154 |
152 // Called in response to updating a request in the request queue. | 155 // Called in response to updating a request in the request queue. |
153 void RequestCoordinator::UpdateRequestCallback( | 156 void RequestCoordinator::UpdateRequestCallback( |
154 const ClientId& client_id, | 157 const ClientId& client_id, |
155 RequestQueue::UpdateRequestResult result) { | 158 RequestQueue::UpdateRequestResult result) { |
156 // If the request succeeded, nothing to do. If it failed, we can't really do | 159 // If the request succeeded, nothing to do. If it failed, we can't really do |
157 // much, so just log it. | 160 // much, so just log it. |
158 if (result != RequestQueue::UpdateRequestResult::SUCCESS) { | 161 if (result != RequestQueue::UpdateRequestResult::SUCCESS) { |
159 DVLOG(1) << "Failed to update request attempt details. " | 162 DVLOG(1) << "Failed to update request attempt details. " |
160 << static_cast<int>(result); | 163 << static_cast<int>(result); |
161 event_logger_.RecordUpdateRequestFailed(client_id.name_space, result); | 164 event_logger_.RecordUpdateRequestFailed(client_id.name_space, result); |
162 } | 165 } |
163 } | 166 } |
164 | 167 |
165 // Called in response to updating multiple requests in the request queue. | 168 // Called in response to updating multiple requests in the request queue. |
166 void RequestCoordinator::UpdateMultipleRequestCallback( | 169 void RequestCoordinator::UpdateMultipleRequestCallback( |
Dmitry Titov
2016/08/11 03:41:55
UpdateMultipleRequestCallback and SendNotifyChange
Pete Williamson
2016/08/13 03:20:34
Done.
| |
170 const std::vector<int64_t>& request_ids, | |
167 RequestQueue::UpdateRequestResult result) { | 171 RequestQueue::UpdateRequestResult result) { |
168 // If the request succeeded, nothing to do. If it failed, we can't really do | 172 // If the request succeeded, nothing to do. If it failed, we can't really do |
Dmitry Titov
2016/08/11 03:41:55
This comment seems needs updating, because "nothin
Pete Williamson
2016/08/13 03:20:34
Done.
| |
169 // much, so just log it. | 173 // much, so just log it. |
170 if (result != RequestQueue::UpdateRequestResult::SUCCESS) { | 174 if (result != RequestQueue::UpdateRequestResult::SUCCESS) { |
171 DVLOG(1) << "Failed to update request attempt details. " | 175 DVLOG(1) << "Failed to update request attempt details. " |
172 << static_cast<int>(result); | 176 << static_cast<int>(result); |
177 } else { | |
178 SendNotifyChangeForRequestIdList(request_ids); | |
173 } | 179 } |
174 } | 180 } |
175 | 181 |
182 // Called in response to updating multiple requests in the request queue. | |
183 void RequestCoordinator::NotifyChangedListCallback( | |
184 const std::vector<int64_t>& request_ids, | |
185 RequestQueue::GetRequestsResult result, | |
186 const std::vector<SavePageRequest>& requests) { | |
187 std::vector<ClientId> client_ids; | |
188 | |
189 // For each item in request_ids, find it in requests and send a changed | |
190 // notification for that request. | |
191 std::unordered_set<int64_t> changed_ids(request_ids.begin(), | |
192 request_ids.end()); | |
193 for (const SavePageRequest& request : requests) { | |
194 // If we find a match, send a notification. | |
195 if (changed_ids.count(request.request_id()) > 0) | |
196 NotifyChanged(request); | |
197 } | |
198 } | |
199 | |
176 void RequestCoordinator::StopProcessing() { | 200 void RequestCoordinator::StopProcessing() { |
177 is_canceled_ = true; | 201 is_canceled_ = true; |
178 if (offliner_ && is_busy_) { | 202 if (offliner_ && is_busy_) { |
179 // TODO(dougarnett): Find current request and mark attempt aborted. | 203 // TODO(dougarnett): Find current request and mark attempt aborted. |
180 offliner_->Cancel(); | 204 offliner_->Cancel(); |
181 } | 205 } |
182 | 206 |
183 // Stopping offliner means it will not call callback. | 207 // Stopping offliner means it will not call callback. |
184 last_offlining_status_ = | 208 last_offlining_status_ = |
185 Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED; | 209 Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED; |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
311 if (status == Offliner::RequestStatus::FOREGROUND_CANCELED) { | 335 if (status == Offliner::RequestStatus::FOREGROUND_CANCELED) { |
312 // Update the request for the canceled attempt. | 336 // Update the request for the canceled attempt. |
313 // TODO(dougarnett): See if we can conclusively identify other attempt | 337 // TODO(dougarnett): See if we can conclusively identify other attempt |
314 // aborted cases to treat this way (eg, for Render Process Killed). | 338 // aborted cases to treat this way (eg, for Render Process Killed). |
315 SavePageRequest updated_request(request); | 339 SavePageRequest updated_request(request); |
316 updated_request.MarkAttemptAborted(); | 340 updated_request.MarkAttemptAborted(); |
317 queue_->UpdateRequest(updated_request, | 341 queue_->UpdateRequest(updated_request, |
318 base::Bind(&RequestCoordinator::UpdateRequestCallback, | 342 base::Bind(&RequestCoordinator::UpdateRequestCallback, |
319 weak_ptr_factory_.GetWeakPtr(), | 343 weak_ptr_factory_.GetWeakPtr(), |
320 updated_request.client_id())); | 344 updated_request.client_id())); |
345 NotifyFailed(updated_request, SavePageStatus::FOREGROUND_CANCELED); | |
321 | 346 |
322 } else if (status == Offliner::RequestStatus::SAVED || | 347 } else if (status == Offliner::RequestStatus::SAVED) { |
323 request.completed_attempt_count() + 1 >= | 348 // Remove the request from the queue if it succeeded. |
324 policy_->GetMaxCompletedTries()) { | |
325 // Remove the request from the queue if it either succeeded or exceeded the | |
326 // max number of retries. The +1 represents the request that just | |
327 // completed. Since we call MarkAttemptCompleted within the if branches, | |
328 // the completed_attempt_count has not yet been updated when we are checking | |
329 // the if condition. | |
330 queue_->RemoveRequest( | 349 queue_->RemoveRequest( |
331 request.request_id(), | 350 request.request_id(), |
332 base::Bind(&RequestCoordinator::UpdateRequestCallback, | 351 base::Bind(&RequestCoordinator::UpdateRequestCallback, |
333 weak_ptr_factory_.GetWeakPtr(), request.client_id())); | 352 weak_ptr_factory_.GetWeakPtr(), request.client_id())); |
353 // TODO: We don't have an offline ID to return. Modify the prerenderer | |
354 // callback to pass it. | |
355 NotifySucceeded(request, 0); | |
356 } else if (request.completed_attempt_count() + 1 >= | |
357 policy_->GetMaxCompletedTries()) { | |
358 // Remove from the request queue if we exceeeded max retries. The +1 | |
359 // represents the request that just completed. Since we call | |
360 // MarkAttemptCompleted within the if branches, the completed_attempt_count | |
361 // has not yet been updated when we are checking the if condition. | |
362 queue_->RemoveRequest( | |
363 request.request_id(), | |
364 base::Bind(&RequestCoordinator::UpdateRequestCallback, | |
365 weak_ptr_factory_.GetWeakPtr(), request.client_id())); | |
366 NotifyFailed(request, SavePageStatus::RETRY_COUNT_EXCEEDED); | |
334 } else { | 367 } else { |
335 // If we failed, but are not over the limit, update the request in the | 368 // If we failed, but are not over the limit, update the request in the |
336 // queue. | 369 // queue. |
337 SavePageRequest updated_request(request); | 370 SavePageRequest updated_request(request); |
338 updated_request.MarkAttemptCompleted(); | 371 updated_request.MarkAttemptCompleted(); |
339 queue_->UpdateRequest(updated_request, | 372 queue_->UpdateRequest(updated_request, |
340 base::Bind(&RequestCoordinator::UpdateRequestCallback, | 373 base::Bind(&RequestCoordinator::UpdateRequestCallback, |
341 weak_ptr_factory_.GetWeakPtr(), | 374 weak_ptr_factory_.GetWeakPtr(), |
342 updated_request.client_id())); | 375 updated_request.client_id())); |
376 NotifyChanged(updated_request); | |
343 } | 377 } |
344 | 378 |
345 // Determine whether we might try another request in this | 379 // Determine whether we might try another request in this |
346 // processing window based on how the previous request completed. | 380 // processing window based on how the previous request completed. |
347 // | 381 // |
348 // TODO(dougarnett): Need to split PRERENDERING_FAILED into separate | 382 // TODO(dougarnett): Need to split PRERENDERING_FAILED into separate |
349 // codes as to whether we should try another request or not. | 383 // codes as to whether we should try another request or not. |
350 switch (status) { | 384 switch (status) { |
351 case Offliner::RequestStatus::SAVED: | 385 case Offliner::RequestStatus::SAVED: |
352 case Offliner::RequestStatus::SAVE_FAILED: | 386 case Offliner::RequestStatus::SAVE_FAILED: |
(...skipping 15 matching lines...) Expand all Loading... | |
368 | 402 |
369 const Scheduler::TriggerConditions | 403 const Scheduler::TriggerConditions |
370 RequestCoordinator::GetTriggerConditionsForUserRequest() { | 404 RequestCoordinator::GetTriggerConditionsForUserRequest() { |
371 Scheduler::TriggerConditions trigger_conditions( | 405 Scheduler::TriggerConditions trigger_conditions( |
372 policy_->PowerRequiredForUserRequestedPage(), | 406 policy_->PowerRequiredForUserRequestedPage(), |
373 policy_->BatteryPercentageRequiredForUserRequestedPage(), | 407 policy_->BatteryPercentageRequiredForUserRequestedPage(), |
374 policy_->UnmeteredNetworkRequiredForUserRequestedPage()); | 408 policy_->UnmeteredNetworkRequiredForUserRequestedPage()); |
375 return trigger_conditions; | 409 return trigger_conditions; |
376 } | 410 } |
377 | 411 |
412 void RequestCoordinator::AddObserver(Observer* observer) { | |
413 DCHECK(observer); | |
414 observers_.AddObserver(observer); | |
415 } | |
416 | |
417 void RequestCoordinator::RemoveObserver(Observer* observer) { | |
418 observers_.RemoveObserver(observer); | |
419 } | |
420 | |
421 void RequestCoordinator::NotifyAdded(const SavePageRequest& request) { | |
422 FOR_EACH_OBSERVER(Observer, observers_, OnAdded(request)); | |
423 } | |
424 | |
425 void RequestCoordinator::NotifySucceeded(const SavePageRequest& request, | |
426 int64_t offline_id) { | |
427 FOR_EACH_OBSERVER(Observer, observers_, OnSucceeded(request, offline_id)); | |
428 } | |
429 | |
430 void RequestCoordinator::NotifyFailed(const SavePageRequest& request, | |
431 SavePageStatus status) { | |
432 FOR_EACH_OBSERVER(Observer, observers_, OnFailed(request, status)); | |
433 } | |
434 | |
435 void RequestCoordinator::NotifyChanged(const SavePageRequest& request) { | |
436 FOR_EACH_OBSERVER(Observer, observers_, OnChanged(request)); | |
437 } | |
438 | |
439 void RequestCoordinator::SendNotifyChangeForRequestIdList( | |
440 const std::vector<int64_t> request_ids) { | |
441 // Bind the request_ids onto our callback parameter list, the work will be | |
442 // done in the callback. | |
443 queue_->GetRequests(base::Bind(&RequestCoordinator::NotifyChangedListCallback, | |
Dmitry Titov
2016/08/11 03:41:55
It is unfortunate that we need to go do the SQL qu
Pete Williamson
2016/08/13 03:20:34
Done.
| |
444 weak_ptr_factory_.GetWeakPtr(), request_ids)); | |
445 } | |
446 | |
378 void RequestCoordinator::GetOffliner() { | 447 void RequestCoordinator::GetOffliner() { |
379 if (!offliner_) { | 448 if (!offliner_) { |
380 offliner_ = factory_->GetOffliner(policy_.get()); | 449 offliner_ = factory_->GetOffliner(policy_.get()); |
381 } | 450 } |
382 } | 451 } |
383 | 452 |
384 } // namespace offline_pages | 453 } // namespace offline_pages |
OLD | NEW |