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

content / browser / background_fetch / background_fetch_scheduler.h [blame]

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_SCHEDULER_H_
#define CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_SCHEDULER_H_

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

#include "base/containers/circular_deque.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/background_fetch/background_fetch_data_manager_observer.h"
#include "content/browser/background_fetch/background_fetch_event_dispatcher.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/browser/service_worker/service_worker_context_core_observer.h"
#include "content/common/content_export.h"
#include "third_party/blink/public/mojom/background_fetch/background_fetch.mojom.h"

namespace blink {
class StorageKey;
}  // namespace blink

namespace content {

class BackgroundFetchDataManager;
class BackgroundFetchDelegateProxy;
class BackgroundFetchJobController;
class BackgroundFetchRegistrationId;
class BackgroundFetchRegistrationNotifier;
class BackgroundFetchRequestInfo;
class DevToolsBackgroundServicesContextImpl;

// Maintains a list of Controllers and chooses which ones should launch new
// downloads.
class CONTENT_EXPORT BackgroundFetchScheduler
    : public BackgroundFetchDataManagerObserver,
      public ServiceWorkerContextCoreObserver {
 public:
  BackgroundFetchScheduler(
      BackgroundFetchContext* background_fetch_context,
      BackgroundFetchDataManager* data_manager,
      BackgroundFetchRegistrationNotifier* registration_notifier,
      BackgroundFetchDelegateProxy* delegate_proxy,
      DevToolsBackgroundServicesContextImpl& devtools_context,
      scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);

  BackgroundFetchScheduler(const BackgroundFetchScheduler&) = delete;
  BackgroundFetchScheduler& operator=(const BackgroundFetchScheduler&) = delete;

  ~BackgroundFetchScheduler() override;

  // Aborts the background fetch identified by |registration_id|.
  // Must only be used for background fetches aborted by the developer,
  // other cases are handled elsewhere.
  void Abort(
      const BackgroundFetchRegistrationId& registration_id,
      blink::mojom::BackgroundFetchFailureReason failure_reason,
      blink::mojom::BackgroundFetchRegistrationService::AbortCallback callback);

  // BackgroundFetchDataManagerObserver implementation.
  void OnRegistrationCreated(
      const BackgroundFetchRegistrationId& registration_id,
      const blink::mojom::BackgroundFetchRegistrationData& registration_data,
      blink::mojom::BackgroundFetchOptionsPtr options,
      const SkBitmap& icon,
      int num_requests,
      bool start_paused,
      net::IsolationInfo isolation_info) override;
  void OnRegistrationLoadedAtStartup(
      const BackgroundFetchRegistrationId& registration_id,
      const blink::mojom::BackgroundFetchRegistrationData& registration_data,
      blink::mojom::BackgroundFetchOptionsPtr options,
      const SkBitmap& icon,
      int num_completed_requests,
      int num_requests,
      std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
          active_fetch_requests,
      std::optional<net::IsolationInfo> isolation_info) override;
  void OnServiceWorkerDatabaseCorrupted(
      int64_t service_worker_registration_id) override;
  void OnRegistrationQueried(
      const BackgroundFetchRegistrationId& registration_id,
      blink::mojom::BackgroundFetchRegistrationData* registration_data)
      override;
  void OnRequestCompleted(const std::string& unique_id,
                          blink::mojom::FetchAPIRequestPtr request,
                          blink::mojom::FetchAPIResponsePtr response) override;

  // ServiceWorkerContextCoreObserver implementation.
  void OnRegistrationDeleted(int64_t registration_id,
                             const GURL& pattern,
                             const blink::StorageKey& key) override;
  void OnStorageWiped() override;

  // Called by BackgroundFetchContext during shutdown.
  void Shutdown();

 private:
  friend class BackgroundFetchJobControllerTest;
  friend class BackgroundFetchSchedulerTest;
  enum class Event;

  // Schedules a download, if possible, and returns whether successful.
  bool ScheduleDownload();

  // Helper method to abandon ongoing fetches for a given service worker.
  // Abandons all of them if |service_worker_registration_id| is set to
  // blink::mojom::kInvalidServiceWorkerRegistrationId.
  void AbortFetches(int64_t service_worker_registration_id);

  // Returns the active job controller, if any, for |registration_id| or
  // |unique_id|. Returns nullptr if the job isn't currently active.
  BackgroundFetchJobController* GetActiveController(
      const BackgroundFetchRegistrationId& registration_id);
  BackgroundFetchJobController* GetActiveController(
      const std::string& unique_id);

  std::unique_ptr<BackgroundFetchJobController> CreateInitializedController(
      const BackgroundFetchRegistrationId& registration_id,
      const blink::mojom::BackgroundFetchRegistrationData& registration_data,
      blink::mojom::BackgroundFetchOptionsPtr options,
      const SkBitmap& icon,
      int num_completed_requests,
      int num_requests,
      std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
          active_fetch_requests,
      bool start_paused,
      std::optional<net::IsolationInfo> isolation_info);

  void DidStartRequest(const BackgroundFetchRegistrationId& registration_id,
                       const BackgroundFetchRequestInfo* request_info);
  void DidCompleteRequest(
      const BackgroundFetchRegistrationId& registration_id,
      scoped_refptr<BackgroundFetchRequestInfo> request_info);

  void FinishJob(
      const BackgroundFetchRegistrationId& registration_id,
      blink::mojom::BackgroundFetchFailureReason failure_reason,
      base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback);

  void DidMarkForDeletion(
      const BackgroundFetchRegistrationId& registration_id,
      bool job_started,
      base::OnceCallback<void(blink::mojom::BackgroundFetchError)> callback,
      blink::mojom::BackgroundFetchError error,
      blink::mojom::BackgroundFetchFailureReason failure_reason);

  void CleanupRegistration(
      const BackgroundFetchRegistrationId& registration_id);

  void DispatchClickEvent(const std::string& unique_id);

  // Information needed to send over to the
  // DevToolsBackgroundServicesContextImpl. |event| is an enum describing the
  // stage of the fetch. |request_info| is nullptr if not available at the
  // moment. Any additional data to log can be passed through the |metadata|
  // map.
  void LogBackgroundFetchEventForDevTools(
      Event event,
      const BackgroundFetchRegistrationId& registration_id,
      const BackgroundFetchRequestInfo* request_info,
      std::map<std::string, std::string> metadata = {});

  // Owned by BackgroundFetchContext.
  raw_ptr<BackgroundFetchDataManager, DanglingUntriaged> data_manager_;
  raw_ptr<BackgroundFetchRegistrationNotifier> registration_notifier_;
  raw_ptr<BackgroundFetchDelegateProxy, DanglingUntriaged> delegate_proxy_;
  raw_ptr<DevToolsBackgroundServicesContextImpl> devtools_context_;

  BackgroundFetchEventDispatcher event_dispatcher_;

  // The order in which to process the job controllers.
  base::circular_deque<BackgroundFetchRegistrationId> controller_ids_;

  // Map from background fetch registration |unique_id|s to active job
  // controllers. Must be destroyed before |data_manager_|, |scheduler_| and
  // |registration_notifier_|.
  std::map<std::string, std::unique_ptr<BackgroundFetchJobController>>
      job_controllers_;

  // The current fetch job controllers that are being processed.
  base::circular_deque<BackgroundFetchJobController*> active_controllers_;

  struct RegistrationData {
    RegistrationData(
        const BackgroundFetchRegistrationId& registration_id,
        blink::mojom::BackgroundFetchRegistrationDataPtr registration);
    ~RegistrationData();

    BackgroundFetchRegistrationId registration_id;
    blink::mojom::BackgroundFetchRegistrationDataPtr registration;
    // Wheter all processing is completed and this data is safe to erase now.
    bool processing_completed = false;
  };

  // Map from |unique_id|s to the registration data.
  // An entry in here means the fetch has completed. This information is needed
  // after the fetch has completed to dispatch the backgroundfetchclick event.
  // TODO(crbug.com/41397180): Clean this up when the UI is no longer showing.
  std::map<std::string, std::unique_ptr<RegistrationData>> completed_fetches_;

  // Scheduling params - Finch configurable.
  int max_running_downloads_;
  int max_active_registrations_;
  int num_active_registrations_ = 0;
  int num_running_downloads_ = 0;

  base::WeakPtrFactory<BackgroundFetchScheduler> weak_ptr_factory_{this};
};

}  // namespace content

#endif  // CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_SCHEDULER_H_