summaryrefslogtreecommitdiff
path: root/chromium/content/browser/background_sync/background_sync_manager.h
blob: 797e632efd5033095d70d106f8c4404ed4a93cd3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_MANAGER_H_
#define CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_MANAGER_H_

#include <stddef.h>
#include <stdint.h>

#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/callback_forward.h"
#include "base/cancelable_callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/time/clock.h"
#include "content/browser/background_sync/background_sync.pb.h"
#include "content/browser/background_sync/background_sync_registration.h"
#include "content/browser/background_sync/background_sync_status.h"
#include "content/browser/cache_storage/cache_storage_scheduler.h"
#include "content/browser/service_worker/service_worker_context_core_observer.h"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/public/browser/background_sync_parameters.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/blink/public/platform/modules/background_sync/background_sync.mojom.h"
#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
#include "url/gurl.h"

namespace blink {
namespace mojom {
enum class PermissionStatus;
}
}

namespace content {

class BackgroundSyncNetworkObserver;
class ServiceWorkerContextWrapper;

// BackgroundSyncManager manages and stores the set of background sync
// registrations across all registered service workers for a profile.
// Registrations are stored along with their associated Service Worker
// registration in ServiceWorkerStorage. If the ServiceWorker is unregistered,
// the sync registrations are removed. This class must be run on the IO
// thread. The asynchronous methods are executed sequentially.
class CONTENT_EXPORT BackgroundSyncManager
    : public ServiceWorkerContextCoreObserver {
 public:
  using BoolCallback = base::OnceCallback<void(bool)>;
  using StatusAndRegistrationCallback =
      base::OnceCallback<void(BackgroundSyncStatus,
                              std::unique_ptr<BackgroundSyncRegistration>)>;
  using StatusAndRegistrationsCallback = base::OnceCallback<void(
      BackgroundSyncStatus,
      std::vector<std::unique_ptr<BackgroundSyncRegistration>>)>;

  static std::unique_ptr<BackgroundSyncManager> Create(
      scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
  ~BackgroundSyncManager() override;

  // Stores the given background sync registration and adds it to the scheduling
  // queue. It will overwrite an existing registration with the same tag unless
  // they're identical (save for the id). Calls |callback| with
  // BACKGROUND_SYNC_STATUS_OK and the accepted registration on success.
  // The accepted registration will have a unique id. It may also have altered
  // parameters if the user or UA chose different parameters than those
  // supplied.
  void Register(int64_t sw_registration_id,
                const BackgroundSyncRegistrationOptions& options,
                StatusAndRegistrationCallback callback);

  // Finds the background sync registrations associated with
  // |sw_registration_id|. Calls |callback| with BACKGROUND_SYNC_STATUS_OK on
  // success.
  void GetRegistrations(int64_t sw_registration_id,
                        StatusAndRegistrationsCallback callback);

  // ServiceWorkerContextCoreObserver overrides.
  void OnRegistrationDeleted(int64_t sw_registration_id,
                             const GURL& pattern) override;
  void OnStorageWiped() override;

  // Sets the max number of sync attempts after any pending operations have
  // completed.
  void SetMaxSyncAttemptsForTesting(int max_attempts);

  BackgroundSyncNetworkObserver* GetNetworkObserverForTesting() {
    return network_observer_.get();
  }

  void set_clock(base::Clock* clock) {
    DCHECK_CURRENTLY_ON(BrowserThread::IO);
    clock_ = clock;
  }

  // Called from DevTools
  void EmulateDispatchSyncEvent(
      const std::string& tag,
      scoped_refptr<ServiceWorkerVersion> active_version,
      bool last_chance,
      ServiceWorkerVersion::StatusCallback callback);

 protected:
  explicit BackgroundSyncManager(
      scoped_refptr<ServiceWorkerContextWrapper> context);

  // Init must be called before any public member function. Only call it once.
  void Init();

  // The following methods are virtual for testing.
  virtual void StoreDataInBackend(
      int64_t sw_registration_id,
      const GURL& origin,
      const std::string& backend_key,
      const std::string& data,
      ServiceWorkerStorage::StatusCallback callback);
  virtual void GetDataFromBackend(
      const std::string& backend_key,
      ServiceWorkerStorage::GetUserDataForAllRegistrationsCallback callback);
  virtual void DispatchSyncEvent(
      const std::string& tag,
      scoped_refptr<ServiceWorkerVersion> active_version,
      bool last_chance,
      ServiceWorkerVersion::StatusCallback callback);
  virtual void ScheduleDelayedTask(base::OnceClosure callback,
                                   base::TimeDelta delay);
  virtual void HasMainFrameProviderHost(const GURL& origin,
                                        BoolCallback callback);

 private:
  friend class TestBackgroundSyncManager;
  friend class BackgroundSyncManagerTest;

  struct BackgroundSyncRegistrations {
    using RegistrationMap = std::map<std::string, BackgroundSyncRegistration>;

    BackgroundSyncRegistrations();
    BackgroundSyncRegistrations(const BackgroundSyncRegistrations& other);
    ~BackgroundSyncRegistrations();

    RegistrationMap registration_map;
    BackgroundSyncRegistration::RegistrationId next_id;
    GURL origin;
  };

  using SWIdToRegistrationsMap = std::map<int64_t, BackgroundSyncRegistrations>;

  static const size_t kMaxTagLength = 10240;

  // Disable the manager. Already queued operations will abort once they start
  // to run (in their impl methods). Future operations will not queue.
  // The list of active registrations is cleared and the backend is also cleared
  // (if it's still functioning). The manager will reenable itself once it
  // receives the OnStorageWiped message or on browser restart.
  void DisableAndClearManager(base::OnceClosure callback);
  void DisableAndClearDidGetRegistrations(
      base::OnceClosure callback,
      const std::vector<std::pair<int64_t, std::string>>& user_data,
      ServiceWorkerStatusCode status);
  void DisableAndClearManagerClearedOne(base::OnceClosure barrier_closure,
                                        ServiceWorkerStatusCode status);

  // Returns the existing registration or nullptr if it cannot be found.
  BackgroundSyncRegistration* LookupActiveRegistration(
      int64_t sw_registration_id,
      const std::string& tag);

  // Write all registrations for a given |sw_registration_id| to persistent
  // storage.
  void StoreRegistrations(int64_t sw_registration_id,
                          ServiceWorkerStorage::StatusCallback callback);

  // Removes the active registration if it is in the map.
  void RemoveActiveRegistration(int64_t sw_registration_id,
                                const std::string& tag);

  void AddActiveRegistration(
      int64_t sw_registration_id,
      const GURL& origin,
      const BackgroundSyncRegistration& sync_registration);

  void InitImpl(base::OnceClosure callback);
  void InitDidGetControllerParameters(
      base::OnceClosure callback,
      std::unique_ptr<BackgroundSyncParameters> parameters);
  void InitDidGetDataFromBackend(
      base::OnceClosure callback,
      const std::vector<std::pair<int64_t, std::string>>& user_data,
      ServiceWorkerStatusCode status);

  // Register callbacks
  void RegisterCheckIfHasMainFrame(
      int64_t sw_registration_id,
      const BackgroundSyncRegistrationOptions& options,
      StatusAndRegistrationCallback callback);
  void RegisterDidCheckIfMainFrame(
      int64_t sw_registration_id,
      const BackgroundSyncRegistrationOptions& options,
      StatusAndRegistrationCallback callback,
      bool has_main_frame_client);
  void RegisterImpl(int64_t sw_registration_id,
                    const BackgroundSyncRegistrationOptions& options,
                    StatusAndRegistrationCallback callback);
  void RegisterDidAskForPermission(
      int64_t sw_registration_id,
      const BackgroundSyncRegistrationOptions& options,
      StatusAndRegistrationCallback callback,
      blink::mojom::PermissionStatus permission_status);
  void RegisterDidStore(int64_t sw_registration_id,
                        const BackgroundSyncRegistration& new_registration,
                        StatusAndRegistrationCallback callback,
                        ServiceWorkerStatusCode status);

  // GetRegistrations callbacks
  void GetRegistrationsImpl(int64_t sw_registration_id,
                            StatusAndRegistrationsCallback callback);

  bool AreOptionConditionsMet(const BackgroundSyncRegistrationOptions& options);
  bool IsRegistrationReadyToFire(
      const BackgroundSyncRegistration& registration);

  // Determines if the browser needs to be able to run in the background (e.g.,
  // to run a pending registration or verify that a firing registration
  // completed). If background processing is required it calls out to the
  // BackgroundSyncController to enable it.
  // Assumes that all registrations in the pending state are not currently ready
  // to fire. Therefore this should not be called directly and should only be
  // called by FireReadyEvents.
  void RunInBackgroundIfNecessary();

  // FireReadyEvents scans the list of available events and fires those that are
  // ready to fire. For those that can't yet be fired, wakeup alarms are set.
  void FireReadyEvents();
  void FireReadyEventsImpl(base::OnceClosure callback);
  void FireReadyEventsDidFindRegistration(
      const std::string& tag,
      BackgroundSyncRegistration::RegistrationId registration_id,
      base::OnceClosure event_fired_callback,
      base::OnceClosure event_completed_callback,
      ServiceWorkerStatusCode service_worker_status,
      scoped_refptr<ServiceWorkerRegistration> service_worker_registration);
  void FireReadyEventsAllEventsFiring(base::OnceClosure callback);

  // Called when a sync event has completed.
  void EventComplete(
      scoped_refptr<ServiceWorkerRegistration> service_worker_registration,
      int64_t service_worker_id,
      const std::string& tag,
      base::OnceClosure callback,
      ServiceWorkerStatusCode status_code);
  void EventCompleteImpl(int64_t service_worker_id,
                         const std::string& tag,
                         ServiceWorkerStatusCode status_code,
                         base::OnceClosure callback);
  void EventCompleteDidStore(int64_t service_worker_id,
                             base::OnceClosure callback,
                             ServiceWorkerStatusCode status_code);

  // Called when all sync events have completed.
  static void OnAllSyncEventsCompleted(const base::TimeTicks& start_time,
                                       int number_of_batched_sync_events);

  // OnRegistrationDeleted callbacks
  void OnRegistrationDeletedImpl(int64_t sw_registration_id,
                                 base::OnceClosure callback);

  // OnStorageWiped callbacks
  void OnStorageWipedImpl(base::OnceClosure callback);

  void OnNetworkChanged();

  // SetMaxSyncAttempts callback
  void SetMaxSyncAttemptsImpl(int max_sync_attempts,
                              base::OnceClosure callback);

  base::OnceClosure MakeEmptyCompletion();

  SWIdToRegistrationsMap active_registrations_;
  CacheStorageScheduler op_scheduler_;
  scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;

  std::unique_ptr<BackgroundSyncParameters> parameters_;

  // True if the manager is disabled and registrations should fail.
  bool disabled_;

  // The number of registrations currently in the firing state.
  int num_firing_registrations_;

  base::CancelableCallback<void()> delayed_sync_task_;

  std::unique_ptr<BackgroundSyncNetworkObserver> network_observer_;

  base::Clock* clock_;

  base::WeakPtrFactory<BackgroundSyncManager> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(BackgroundSyncManager);
};

}  // namespace content

#endif  // CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_MANAGER_H_