Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: components/offline_pages/background/request_coordinator.cc

Issue 2219393004: Adds an observer for the request coordinator. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@resumeAPI
Patch Set: Second batch of FGorski CR fixes Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698