OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef COMPONENTS_OFFLINE_PAGES_BACKGROUND_REQUEST_COORDINATOR_H_ | |
6 #define COMPONENTS_OFFLINE_PAGES_BACKGROUND_REQUEST_COORDINATOR_H_ | |
7 | |
8 #include <memory> | |
9 #include <set> | |
10 #include <string> | |
11 #include <vector> | |
12 | |
13 #include "base/callback.h" | |
14 #include "base/macros.h" | |
15 #include "base/memory/weak_ptr.h" | |
16 #include "base/observer_list.h" | |
17 #include "base/supports_user_data.h" | |
18 #include "base/time/time.h" | |
19 #include "base/timer/timer.h" | |
20 #include "components/keyed_service/core/keyed_service.h" | |
21 #include "components/offline_pages/background/device_conditions.h" | |
22 #include "components/offline_pages/background/offliner.h" | |
23 #include "components/offline_pages/background/request_coordinator_event_logger.h
" | |
24 #include "components/offline_pages/background/request_notifier.h" | |
25 #include "components/offline_pages/background/request_queue.h" | |
26 #include "components/offline_pages/background/scheduler.h" | |
27 #include "net/nqe/network_quality_estimator.h" | |
28 #include "url/gurl.h" | |
29 | |
30 namespace offline_pages { | |
31 | |
32 struct ClientId; | |
33 class OfflinerPolicy; | |
34 class OfflinerFactory; | |
35 class Offliner; | |
36 class RequestQueue; | |
37 class SavePageRequest; | |
38 class Scheduler; | |
39 class ClientPolicyController; | |
40 | |
41 // Coordinates queueing and processing save page later requests. | |
42 class RequestCoordinator : public KeyedService, | |
43 public RequestNotifier, | |
44 public base::SupportsUserData { | |
45 public: | |
46 // Nested observer class. To make sure that no events are missed, the client | |
47 // code should first register for notifications, then |GetAllRequests|, and | |
48 // ignore all events before the return from |GetAllRequests|, and consume | |
49 // events after the return callback from |GetAllRequests|. | |
50 class Observer { | |
51 public: | |
52 virtual ~Observer() = default; | |
53 | |
54 virtual void OnAdded(const SavePageRequest& request) = 0; | |
55 virtual void OnCompleted( | |
56 const SavePageRequest& request, | |
57 RequestNotifier::BackgroundSavePageResult status) = 0; | |
58 virtual void OnChanged(const SavePageRequest& request) = 0; | |
59 }; | |
60 | |
61 enum class RequestAvailability { | |
62 ENABLED_FOR_OFFLINER, | |
63 DISABLED_FOR_OFFLINER, | |
64 }; | |
65 | |
66 // Callback specifying which request IDs were actually removed. | |
67 typedef base::Callback<void(const MultipleItemStatuses&)> | |
68 RemoveRequestsCallback; | |
69 | |
70 // Callback that receives the response for GetAllRequests. | |
71 typedef base::Callback<void(std::vector<std::unique_ptr<SavePageRequest>>)> | |
72 GetRequestsCallback; | |
73 | |
74 RequestCoordinator(std::unique_ptr<OfflinerPolicy> policy, | |
75 std::unique_ptr<OfflinerFactory> factory, | |
76 std::unique_ptr<RequestQueue> queue, | |
77 std::unique_ptr<Scheduler> scheduler, | |
78 net::NetworkQualityEstimator::NetworkQualityProvider* | |
79 network_quality_estimator); | |
80 | |
81 ~RequestCoordinator() override; | |
82 | |
83 // Queues |request| to later load and save when system conditions allow. | |
84 // Returns an id if the page could be queued successfully, 0L otherwise. | |
85 int64_t SavePageLater(const GURL& url, | |
86 const ClientId& client_id, | |
87 bool user_requested, | |
88 RequestAvailability availability); | |
89 | |
90 // Remove a list of requests by |request_id|. This removes requests from the | |
91 // request queue, and cancels an in-progress prerender. | |
92 void RemoveRequests(const std::vector<int64_t>& request_ids, | |
93 const RemoveRequestsCallback& callback); | |
94 | |
95 // Pause a list of requests by |request_id|. This will change the state | |
96 // in the request queue so the request cannot be started. | |
97 void PauseRequests(const std::vector<int64_t>& request_ids); | |
98 | |
99 // Resume a list of previously paused requests, making them available. | |
100 void ResumeRequests(const std::vector<int64_t>& request_ids); | |
101 | |
102 // Get all save page request items in the callback. | |
103 void GetAllRequests(const GetRequestsCallback& callback); | |
104 | |
105 // Starts processing of one or more queued save page later requests. | |
106 // Returns whether processing was started and that caller should expect | |
107 // a callback. If processing was already active, returns false. | |
108 bool StartProcessing(const DeviceConditions& device_conditions, | |
109 const base::Callback<void(bool)>& callback); | |
110 | |
111 // Stops the current request processing if active. This is a way for | |
112 // caller to abort processing; otherwise, processing will complete on | |
113 // its own. In either case, the callback will be called when processing | |
114 // is stopped or complete. | |
115 void StopProcessing(Offliner::RequestStatus stop_status); | |
116 | |
117 // Used to denote that the foreground thread is ready for the offliner | |
118 // to start work on a previously entered, but unavailable request. | |
119 void EnableForOffliner(int64_t request_id, const ClientId& client_id); | |
120 | |
121 // If a request that is unavailable to the offliner is finished elsewhere, | |
122 // (by the tab helper synchronous download), send a notificaiton that it | |
123 // succeeded through our notificaiton system. | |
124 void MarkRequestCompleted(int64_t request_id); | |
125 | |
126 const Scheduler::TriggerConditions GetTriggerConditions( | |
127 const bool user_requested); | |
128 | |
129 // A way for tests to set the callback in use when an operation is over. | |
130 void SetProcessingCallbackForTest(const base::Callback<void(bool)> callback) { | |
131 scheduler_callback_ = callback; | |
132 } | |
133 | |
134 // A way to set the callback which would be called if the request will be | |
135 // scheduled immediately. Used by testing harness to determine if a request | |
136 // has been processed. | |
137 void SetImmediateScheduleCallbackForTest( | |
138 const base::Callback<void(bool)> callback) { | |
139 immediate_schedule_callback_ = callback; | |
140 } | |
141 | |
142 void StartImmediatelyForTest() { StartImmediatelyIfConnected(); } | |
143 | |
144 // Observers implementing the RequestCoordinator::Observer interface can | |
145 // register here to get notifications of changes to request state. This | |
146 // pointer is not owned, and it is the callers responsibility to remove the | |
147 // observer before the observer is deleted. | |
148 void AddObserver(RequestCoordinator::Observer* observer); | |
149 | |
150 void RemoveObserver(RequestCoordinator::Observer* observer); | |
151 | |
152 // Implement RequestNotifier | |
153 void NotifyAdded(const SavePageRequest& request) override; | |
154 void NotifyCompleted( | |
155 const SavePageRequest& request, | |
156 RequestNotifier::BackgroundSavePageResult status) override; | |
157 void NotifyChanged(const SavePageRequest& request) override; | |
158 | |
159 // Returns the request queue used for requests. Coordinator keeps ownership. | |
160 RequestQueue* queue() { return queue_.get(); } | |
161 | |
162 // Return an unowned pointer to the Scheduler. | |
163 Scheduler* scheduler() { return scheduler_.get(); } | |
164 | |
165 OfflinerPolicy* policy() { return policy_.get(); } | |
166 | |
167 ClientPolicyController* GetPolicyController(); | |
168 | |
169 // Returns the status of the most recent offlining. | |
170 Offliner::RequestStatus last_offlining_status() { | |
171 return last_offlining_status_; | |
172 } | |
173 | |
174 bool is_busy() { | |
175 return is_busy_; | |
176 } | |
177 | |
178 // Returns whether processing is starting (before it is decided to actually | |
179 // process a request (is_busy()) at this time or not. | |
180 bool is_starting() { return is_starting_; } | |
181 | |
182 // Tracks whether the last offlining attempt got canceled. This is reset by | |
183 // the next StartProcessing() call. | |
184 bool is_canceled() { | |
185 return processing_state_ == ProcessingWindowState::STOPPED; | |
186 } | |
187 | |
188 RequestCoordinatorEventLogger* GetLogger() { return &event_logger_; } | |
189 | |
190 private: | |
191 // Immediate start attempt status code for UMA. | |
192 // These values are written to logs. New enum values can be added, but | |
193 // existing enums must never be renumbered or deleted and reused. | |
194 // For any additions, also update corresponding histogram in histograms.xml. | |
195 enum OfflinerImmediateStartStatus { | |
196 // Did start processing request. | |
197 STARTED = 0, | |
198 // Already busy processing a request. | |
199 BUSY = 1, | |
200 // The Offliner did not accept processing the request. | |
201 NOT_ACCEPTED = 2, | |
202 // No current network connection. | |
203 NO_CONNECTION = 3, | |
204 // Weak network connection (worse than 2G speed) | |
205 // according to network quality estimator. | |
206 WEAK_CONNECTION = 4, | |
207 // Did not start because this is svelte device. | |
208 NOT_STARTED_ON_SVELTE = 5, | |
209 // NOTE: insert new values above this line and update histogram enum too. | |
210 STATUS_COUNT = 6, | |
211 }; | |
212 | |
213 enum class ProcessingWindowState { | |
214 STOPPED, | |
215 SCHEDULED_WINDOW, | |
216 IMMEDIATE_WINDOW, | |
217 }; | |
218 | |
219 // Receives the results of a get from the request queue, and turns that into | |
220 // SavePageRequest objects for the caller of GetQueuedRequests. | |
221 void GetQueuedRequestsCallback( | |
222 const GetRequestsCallback& callback, | |
223 GetRequestsResult result, | |
224 std::vector<std::unique_ptr<SavePageRequest>> requests); | |
225 | |
226 // Receives the results of a get from the request queue, and turns that into | |
227 // SavePageRequest objects for the caller of GetQueuedRequests. | |
228 void GetRequestsForSchedulingCallback( | |
229 GetRequestsResult result, | |
230 std::vector<std::unique_ptr<SavePageRequest>> requests); | |
231 | |
232 // Receives the result of add requests to the request queue. | |
233 void AddRequestResultCallback(RequestAvailability availability, | |
234 AddRequestResult result, | |
235 const SavePageRequest& request); | |
236 | |
237 void UpdateMultipleRequestsCallback( | |
238 std::unique_ptr<UpdateRequestsResult> result); | |
239 | |
240 void HandleRemovedRequestsAndCallback( | |
241 const RemoveRequestsCallback& callback, | |
242 RequestNotifier::BackgroundSavePageResult status, | |
243 std::unique_ptr<UpdateRequestsResult> result); | |
244 | |
245 void HandleRemovedRequests(RequestNotifier::BackgroundSavePageResult status, | |
246 std::unique_ptr<UpdateRequestsResult> result); | |
247 | |
248 bool StartProcessingInternal(const ProcessingWindowState processing_state, | |
249 const DeviceConditions& device_conditions, | |
250 const base::Callback<void(bool)>& callback); | |
251 | |
252 // Start processing now if connected (but with conservative assumption | |
253 // as to other device conditions). | |
254 void StartImmediatelyIfConnected(); | |
255 | |
256 OfflinerImmediateStartStatus TryImmediateStart(); | |
257 | |
258 // Check the request queue, and schedule a task corresponding | |
259 // to the least restrictive type of request in the queue. | |
260 void ScheduleAsNeeded(); | |
261 | |
262 // Callback from the request picker when it has chosen our next request. | |
263 void RequestPicked(const SavePageRequest& request); | |
264 | |
265 // Callback from the request picker when no more requests are in the queue. | |
266 // The parameter is a signal for what (if any) conditions to schedule future | |
267 // processing for. | |
268 void RequestNotPicked(bool non_user_requested_tasks_remaining); | |
269 | |
270 // Callback from request picker that receives the current available queued | |
271 // request count as well as the total queued request count (which may be | |
272 // different if unavailable requests are queued such as paused requests). | |
273 // It also receives a flag as to whether this request picking is due to the | |
274 // start of a request processing window. | |
275 void RequestCounts(bool is_start_of_processing, | |
276 size_t total_requests, | |
277 size_t available_requests); | |
278 | |
279 void HandleWatchdogTimeout(); | |
280 | |
281 // Cancels an in progress pre-rendering, and updates state appropriately. | |
282 void StopPrerendering(Offliner::RequestStatus stop_status); | |
283 | |
284 // Marks attempt on the request and sends it to offliner in continuation. | |
285 void SendRequestToOffliner(const SavePageRequest& request); | |
286 | |
287 // Continuation of |SendRequestToOffliner| after the request is marked as | |
288 // started. | |
289 void StartOffliner(int64_t request_id, | |
290 const std::string& client_namespace, | |
291 std::unique_ptr<UpdateRequestsResult> update_result); | |
292 | |
293 // Called by the offliner when an offlining request is completed. (and by | |
294 // tests). | |
295 void OfflinerDoneCallback(const SavePageRequest& request, | |
296 Offliner::RequestStatus status); | |
297 | |
298 // Records a completed attempt for the request and update it in the queue | |
299 // (possibly removing it). | |
300 void UpdateRequestForCompletedAttempt(const SavePageRequest& request, | |
301 Offliner::RequestStatus status); | |
302 | |
303 // Returns whether we should try another request based on the outcome | |
304 // of the previous one. | |
305 bool ShouldTryNextRequest(Offliner::RequestStatus previous_request_status); | |
306 | |
307 // Try to find and start offlining an available request. | |
308 // |is_start_of_processing| identifies if this is the beginning of a | |
309 // processing window (vs. continuing within a current processing window). | |
310 void TryNextRequest(bool is_start_of_processing); | |
311 | |
312 // If there is an active request in the list, cancel that request. | |
313 bool CancelActiveRequestIfItMatches(const std::vector<int64_t>& request_ids); | |
314 | |
315 // Records an aborted attempt for the request and update it in the queue | |
316 // (possibly removing it). | |
317 void UpdateRequestForAbortedAttempt(const SavePageRequest& request); | |
318 | |
319 // Remove the attempted request from the queue with status to pass through to | |
320 // any observers and UMA histogram. | |
321 void RemoveAttemptedRequest(const SavePageRequest& request, | |
322 BackgroundSavePageResult status); | |
323 | |
324 // Marks the attempt as aborted. This makes the request available again | |
325 // for offlining. | |
326 void MarkAttemptAborted(int64_t request_id, const std::string& name_space); | |
327 | |
328 // Reports change from marking request, reports an error if it fails. | |
329 void MarkAttemptDone(int64_t request_id, | |
330 const std::string& name_space, | |
331 std::unique_ptr<UpdateRequestsResult> result); | |
332 | |
333 // Returns the appropriate offliner to use, getting a new one from the factory | |
334 // if needed. | |
335 void GetOffliner(); | |
336 | |
337 // Method to wrap calls to getting the connection type so it can be | |
338 // changed for tests. | |
339 net::NetworkChangeNotifier::ConnectionType GetConnectionType(); | |
340 | |
341 void SetNetworkConditionsForTest( | |
342 net::NetworkChangeNotifier::ConnectionType connection) { | |
343 use_test_connection_type_ = true; | |
344 test_connection_type_ = connection; | |
345 } | |
346 | |
347 void SetDeviceConditionsForTest(const DeviceConditions& current_conditions) { | |
348 current_conditions_.reset(new DeviceConditions(current_conditions)); | |
349 } | |
350 | |
351 // KeyedService implementation: | |
352 void Shutdown() override; | |
353 | |
354 friend class RequestCoordinatorTest; | |
355 | |
356 // Cached value of whether low end device. Overwritable for testing. | |
357 bool is_low_end_device_; | |
358 | |
359 // The offliner can only handle one request at a time - if the offliner is | |
360 // busy, prevent other requests. This flag marks whether the offliner is in | |
361 // use. | |
362 bool is_busy_; | |
363 // There is more than one path to start processing so this flag is used | |
364 // to avoid race conditions before is_busy_ is established. | |
365 bool is_starting_; | |
366 // Identifies the type of current processing window or if processing stopped. | |
367 ProcessingWindowState processing_state_; | |
368 // True if we should use the test connection type instead of the actual type. | |
369 bool use_test_connection_type_; | |
370 // For use by tests, a fake network connection type | |
371 net::NetworkChangeNotifier::ConnectionType test_connection_type_; | |
372 // Unowned pointer to the current offliner, if any. | |
373 Offliner* offliner_; | |
374 base::Time operation_start_time_; | |
375 // The observers. | |
376 base::ObserverList<Observer> observers_; | |
377 // Last known conditions for network, battery | |
378 std::unique_ptr<DeviceConditions> current_conditions_; | |
379 // RequestCoordinator takes over ownership of the policy | |
380 std::unique_ptr<OfflinerPolicy> policy_; | |
381 // OfflinerFactory. Used to create offline pages. Owned. | |
382 std::unique_ptr<OfflinerFactory> factory_; | |
383 // RequestQueue. Used to store incoming requests. Owned. | |
384 std::unique_ptr<RequestQueue> queue_; | |
385 // Scheduler. Used to request a callback when network is available. Owned. | |
386 std::unique_ptr<Scheduler> scheduler_; | |
387 // Controller of client policies. Owned. | |
388 std::unique_ptr<ClientPolicyController> policy_controller_; | |
389 // Unowned pointer to the Network Quality Estimator. | |
390 net::NetworkQualityEstimator::NetworkQualityProvider* | |
391 network_quality_estimator_; | |
392 // Holds copy of the active request, if any. | |
393 std::unique_ptr<SavePageRequest> active_request_; | |
394 // Status of the most recent offlining. | |
395 Offliner::RequestStatus last_offlining_status_; | |
396 // A set of request_ids that we are holding off until the download manager is | |
397 // done with them. | |
398 std::set<int64_t> disabled_requests_; | |
399 // Calling this returns to the scheduler across the JNI bridge. | |
400 base::Callback<void(bool)> scheduler_callback_; | |
401 // Logger to record events. | |
402 RequestCoordinatorEventLogger event_logger_; | |
403 // Timer to watch for pre-render attempts running too long. | |
404 base::OneShotTimer watchdog_timer_; | |
405 // Callback invoked when an immediate request is done (default empty). | |
406 base::Callback<void(bool)> immediate_schedule_callback_; | |
407 // Allows us to pass a weak pointer to callbacks. | |
408 base::WeakPtrFactory<RequestCoordinator> weak_ptr_factory_; | |
409 | |
410 DISALLOW_COPY_AND_ASSIGN(RequestCoordinator); | |
411 }; | |
412 | |
413 } // namespace offline_pages | |
414 | |
415 #endif // COMPONENTS_OFFLINE_PAGES_BACKGROUND_REQUEST_COORDINATOR_H_ | |
OLD | NEW |