| 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/time/time.h" |
| 12 #include "components/offline_pages/background/offliner_factory.h" | 13 #include "components/offline_pages/background/offliner_factory.h" |
| 13 #include "components/offline_pages/background/offliner_policy.h" | 14 #include "components/offline_pages/background/offliner_policy.h" |
| 14 #include "components/offline_pages/background/request_picker.h" | 15 #include "components/offline_pages/background/request_picker.h" |
| 15 #include "components/offline_pages/background/save_page_request.h" | 16 #include "components/offline_pages/background/save_page_request.h" |
| 16 #include "components/offline_pages/offline_page_item.h" | 17 #include "components/offline_pages/offline_page_item.h" |
| 17 | 18 |
| 18 namespace offline_pages { | 19 namespace offline_pages { |
| 19 | 20 |
| 20 namespace { | 21 namespace { |
| 21 // TODO(dougarnett/petewil): Move to Policy object. Also consider lower minimum | 22 // TODO(dougarnett/petewil): Move to Policy object. Also consider lower minimum |
| 22 // battery percentage once there is some processing time limits in place. | 23 // battery percentage once there is some processing time limits in place. |
| 23 const Scheduler::TriggerConditions kUserRequestTriggerConditions( | 24 const Scheduler::TriggerConditions kUserRequestTriggerConditions( |
| 24 false /* require_power_connected */, | 25 false /* require_power_connected */, |
| 25 50 /* minimum_battery_percentage */, | 26 50 /* minimum_battery_percentage */, |
| 26 false /* require_unmetered_network */); | 27 false /* require_unmetered_network */); |
| 28 |
| 29 // Timeout is 2.5 minutes based on the size of Marshmallow doze mode |
| 30 // maintenance window (3 minutes) |
| 31 // TODO(petewil): Find the optimal timeout based on data for 2G connections and |
| 32 // common EM websites. crbug.com/625204 |
| 33 // TODO(petewil): Move this value into the policy object. |
| 34 long OFFLINER_TIMEOUT_SECONDS = 150; |
| 35 |
| 27 } // namespace | 36 } // namespace |
| 28 | 37 |
| 29 RequestCoordinator::RequestCoordinator(std::unique_ptr<OfflinerPolicy> policy, | 38 RequestCoordinator::RequestCoordinator(std::unique_ptr<OfflinerPolicy> policy, |
| 30 std::unique_ptr<OfflinerFactory> factory, | 39 std::unique_ptr<OfflinerFactory> factory, |
| 31 std::unique_ptr<RequestQueue> queue, | 40 std::unique_ptr<RequestQueue> queue, |
| 32 std::unique_ptr<Scheduler> scheduler) | 41 std::unique_ptr<Scheduler> scheduler) |
| 33 : is_busy_(false), | 42 : is_busy_(false), |
| 34 is_canceled_(false), | 43 is_canceled_(false), |
| 44 offliner_timeout_(base::TimeDelta::FromSeconds(OFFLINER_TIMEOUT_SECONDS)), |
| 35 offliner_(nullptr), | 45 offliner_(nullptr), |
| 36 policy_(std::move(policy)), | 46 policy_(std::move(policy)), |
| 37 factory_(std::move(factory)), | 47 factory_(std::move(factory)), |
| 38 queue_(std::move(queue)), | 48 queue_(std::move(queue)), |
| 39 scheduler_(std::move(scheduler)), | 49 scheduler_(std::move(scheduler)), |
| 40 last_offlining_status_(Offliner::RequestStatus::UNKNOWN), | 50 last_offlining_status_(Offliner::RequestStatus::UNKNOWN), |
| 41 weak_ptr_factory_(this) { | 51 weak_ptr_factory_(this) { |
| 42 DCHECK(policy_ != nullptr); | 52 DCHECK(policy_ != nullptr); |
| 43 picker_.reset(new RequestPicker(queue_.get())); | 53 picker_.reset(new RequestPicker(queue_.get())); |
| 44 } | 54 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 74 } | 84 } |
| 75 | 85 |
| 76 // Called in response to updating a request in the request queue. | 86 // Called in response to updating a request in the request queue. |
| 77 void RequestCoordinator::UpdateRequestCallback( | 87 void RequestCoordinator::UpdateRequestCallback( |
| 78 RequestQueue::UpdateRequestResult result) {} | 88 RequestQueue::UpdateRequestResult result) {} |
| 79 | 89 |
| 80 void RequestCoordinator::StopProcessing() { | 90 void RequestCoordinator::StopProcessing() { |
| 81 is_canceled_ = true; | 91 is_canceled_ = true; |
| 82 if (offliner_ && is_busy_) | 92 if (offliner_ && is_busy_) |
| 83 offliner_->Cancel(); | 93 offliner_->Cancel(); |
| 94 |
| 95 // Let the scheduler know we are done processing. |
| 96 scheduler_callback_.Run(true); |
| 84 } | 97 } |
| 85 | 98 |
| 86 // Returns true if the caller should expect a callback, false otherwise. For | 99 // Returns true if the caller should expect a callback, false otherwise. For |
| 87 // instance, this would return false if a request is already in progress. | 100 // instance, this would return false if a request is already in progress. |
| 88 bool RequestCoordinator::StartProcessing( | 101 bool RequestCoordinator::StartProcessing( |
| 89 const DeviceConditions& device_conditions, | 102 const DeviceConditions& device_conditions, |
| 90 const base::Callback<void(bool)>& callback) { | 103 const base::Callback<void(bool)>& callback) { |
| 91 if (is_busy_) return false; | 104 if (is_busy_) return false; |
| 92 | 105 |
| 93 is_canceled_ = false; | 106 is_canceled_ = false; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 112 | 125 |
| 113 // Called by the request picker when a request has been picked. | 126 // Called by the request picker when a request has been picked. |
| 114 void RequestCoordinator::RequestPicked(const SavePageRequest& request) { | 127 void RequestCoordinator::RequestPicked(const SavePageRequest& request) { |
| 115 // Send the request on to the offliner. | 128 // Send the request on to the offliner. |
| 116 SendRequestToOffliner(request); | 129 SendRequestToOffliner(request); |
| 117 } | 130 } |
| 118 | 131 |
| 119 void RequestCoordinator::RequestQueueEmpty() { | 132 void RequestCoordinator::RequestQueueEmpty() { |
| 120 // Clear the outstanding "safety" task in the scheduler. | 133 // Clear the outstanding "safety" task in the scheduler. |
| 121 scheduler_->Unschedule(); | 134 scheduler_->Unschedule(); |
| 122 // Return control to the scheduler when there is no more to do. | 135 // Let the scheduler know we are done processing. |
| 123 scheduler_callback_.Run(true); | 136 scheduler_callback_.Run(true); |
| 124 } | 137 } |
| 125 | 138 |
| 126 void RequestCoordinator::SendRequestToOffliner(const SavePageRequest& request) { | 139 void RequestCoordinator::SendRequestToOffliner(const SavePageRequest& request) { |
| 127 // Check that offlining didn't get cancelled while performing some async | 140 // Check that offlining didn't get cancelled while performing some async |
| 128 // steps. | 141 // steps. |
| 129 if (is_canceled_) | 142 if (is_canceled_) |
| 130 return; | 143 return; |
| 131 | 144 |
| 132 GetOffliner(); | 145 GetOffliner(); |
| 133 if (!offliner_) { | 146 if (!offliner_) { |
| 134 DVLOG(0) << "Unable to create Offliner. " | 147 DVLOG(0) << "Unable to create Offliner. " |
| 135 << "Cannot background offline page."; | 148 << "Cannot background offline page."; |
| 136 return; | 149 return; |
| 137 } | 150 } |
| 138 | 151 |
| 139 DCHECK(!is_busy_); | 152 DCHECK(!is_busy_); |
| 140 is_busy_ = true; | 153 is_busy_ = true; |
| 141 | 154 |
| 142 // Start the load and save process in the offliner (Async). | 155 // Start the load and save process in the offliner (Async). |
| 143 offliner_->LoadAndSave(request, | 156 offliner_->LoadAndSave(request, |
| 144 base::Bind(&RequestCoordinator::OfflinerDoneCallback, | 157 base::Bind(&RequestCoordinator::OfflinerDoneCallback, |
| 145 weak_ptr_factory_.GetWeakPtr())); | 158 weak_ptr_factory_.GetWeakPtr())); |
| 159 |
| 160 // Start a watchdog timer to catch pre-renders running too long |
| 161 watchdog_timer_.Start(FROM_HERE, offliner_timeout_, this, |
| 162 &RequestCoordinator::StopProcessing); |
| 146 } | 163 } |
| 147 | 164 |
| 148 void RequestCoordinator::OfflinerDoneCallback(const SavePageRequest& request, | 165 void RequestCoordinator::OfflinerDoneCallback(const SavePageRequest& request, |
| 149 Offliner::RequestStatus status) { | 166 Offliner::RequestStatus status) { |
| 150 DVLOG(2) << "offliner finished, saved: " | 167 DVLOG(2) << "offliner finished, saved: " |
| 151 << (status == Offliner::RequestStatus::SAVED) << ", status: " | 168 << (status == Offliner::RequestStatus::SAVED) << ", status: " |
| 152 << (int) status << ", " << __FUNCTION__; | 169 << (int) status << ", " << __FUNCTION__; |
| 153 event_logger_.RecordSavePageRequestUpdated( | 170 event_logger_.RecordSavePageRequestUpdated( |
| 154 request.client_id().name_space, | 171 request.client_id().name_space, |
| 155 "Saved", | 172 "Saved", |
| 156 request.request_id()); | 173 request.request_id()); |
| 157 last_offlining_status_ = status; | 174 last_offlining_status_ = status; |
| 175 watchdog_timer_.Stop(); |
| 158 | 176 |
| 159 is_busy_ = false; | 177 is_busy_ = false; |
| 160 | 178 |
| 161 // If the request succeeded, remove it from the Queue and maybe schedule | 179 // If the request succeeded, remove it from the Queue and maybe schedule |
| 162 // another one. | 180 // another one. |
| 163 if (status == Offliner::RequestStatus::SAVED) { | 181 if (status == Offliner::RequestStatus::SAVED) { |
| 164 queue_->RemoveRequest(request.request_id(), | 182 queue_->RemoveRequest(request.request_id(), |
| 165 base::Bind(&RequestCoordinator::UpdateRequestCallback, | 183 base::Bind(&RequestCoordinator::UpdateRequestCallback, |
| 166 weak_ptr_factory_.GetWeakPtr())); | 184 weak_ptr_factory_.GetWeakPtr())); |
| 167 | 185 |
| 168 // TODO(petewil): Check time budget. Return to the scheduler if we are out. | 186 // TODO(petewil): Check time budget. Return to the scheduler if we are out. |
| 169 | 187 |
| 170 // Start another request if we have time. | 188 // Start another request if we have time. |
| 171 TryNextRequest(); | 189 TryNextRequest(); |
| 172 } | 190 } |
| 173 } | 191 } |
| 174 | 192 |
| 175 const Scheduler::TriggerConditions& | 193 const Scheduler::TriggerConditions& |
| 176 RequestCoordinator::GetTriggerConditionsForUserRequest() { | 194 RequestCoordinator::GetTriggerConditionsForUserRequest() { |
| 177 return kUserRequestTriggerConditions; | 195 return kUserRequestTriggerConditions; |
| 178 } | 196 } |
| 179 | 197 |
| 180 void RequestCoordinator::GetOffliner() { | 198 void RequestCoordinator::GetOffliner() { |
| 181 if (!offliner_) { | 199 if (!offliner_) { |
| 182 offliner_ = factory_->GetOffliner(policy_.get()); | 200 offliner_ = factory_->GetOffliner(policy_.get()); |
| 183 } | 201 } |
| 184 } | 202 } |
| 185 | 203 |
| 186 } // namespace offline_pages | 204 } // namespace offline_pages |
| OLD | NEW |