File: service_worker_state.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (158 lines) | stat: -rw-r--r-- 6,538 bytes parent folder | download | duplicates (3)
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
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef EXTENSIONS_BROWSER_SERVICE_WORKER_SERVICE_WORKER_STATE_H_
#define EXTENSIONS_BROWSER_SERVICE_WORKER_SERVICE_WORKER_STATE_H_

#include <optional>

#include "base/auto_reset.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "content/public/browser/service_worker_context.h"
#include "extensions/browser/service_worker/sequenced_context_id.h"
#include "extensions/browser/service_worker/worker_id.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"

namespace extensions {
class ProcessManager;

// The current worker related state of an activated extension.
class ServiceWorkerState
    : public content::ServiceWorkerContextObserverSynchronous {
 public:
  // Browser process worker state of an activated extension.
  enum class BrowserState {
    // Worker has not started or has been stopped/terminated.
    kNotActive,
    // Worker has started (i.e. has seen DidStartWorkerForScope).
    kActive,
    // Worker has completed starting (i.e. has seen DidStartWorkerForScope and
    // DidStartServiceWorkerContext).
    kReady,
  };

  // Render process worker state of an activated extension.
  enum class RendererState {
    // Worker thread has not started or has been stopped/terminated.
    kNotActive,
    // Worker thread has started and it's running.
    kActive,
  };

  ServiceWorkerState(content::ServiceWorkerContext* service_worker_context,
                     const ProcessManager* process_manager);
  ~ServiceWorkerState() override;

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

  class Observer : public base::CheckedObserver {
   public:
    // Called when an extension service worker has started.
    virtual void OnWorkerStart(const SequencedContextId& context_id,
                               const WorkerId& worker_id) {}
    // Called when an extension service worker has failed to start.
    virtual void OnWorkerStartFail(const SequencedContextId& context_id,
                                   base::Time start_time,
                                   content::StatusCodeResponse status) {}
    // Called when an extension service worker is stopping or has stopped.
    virtual void OnWorkerStop(
        int64_t version_id,
        const content::ServiceWorkerRunningInfo& worker_info) {}
  };

  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  void SetBrowserState(BrowserState browser_state);
  void SetRendererState(RendererState renderer_state);
  void Reset();

  // Returns true if a request to start the worker has been made but the worker
  // is not ready yet.
  bool IsStarting() const;

  // Returns true if the worker is running and is ready to execute tasks.
  bool IsReady() const;

  // Starts the extension service worker. This method should only be called
  // if the service worker hasn't started yet. If this method is called while
  // the service worker is in the process of starting, it's a no-op.
  void StartWorker(const SequencedContextId& context_id);

  // Called when a service worker renderer process is running, has executed its
  // global JavaScript scope, and all its global event listeners have been
  // registered with the //extensions layer. It is considered the
  // "renderer-side" signal that the worker is ready.
  void DidStartServiceWorkerContext(const SequencedContextId& context_id,
                                    const WorkerId& worker_id);

  // Called when the worker was requested to start and it verified that a worker
  // registration exists at the //content layer. It is considered the
  // "browser-side" signal that the worker is ready.
  void DidStartWorkerForScope(const SequencedContextId& context_id,
                              base::Time start_time,
                              int64_t version_id,
                              int process_id,
                              int thread_id);
  // Called when the worker was requested to start, but failed.
  void DidStartWorkerFail(const SequencedContextId& context_id,
                          base::Time start_time,
                          content::StatusCodeResponse status);

  BrowserState browser_state() const { return browser_state_; }
  RendererState renderer_state() const { return renderer_state_; }
  const std::optional<WorkerId>& worker_id() const { return worker_id_; }

  static base::AutoReset<bool> AllowMultipleWorkersPerExtensionForTesting();
  void StopObservingContextForTest();

  // content::ServiceWorkerContextObserverSynchronous:
  // Called when an extension service worker has stopped.
  void OnStopped(int64_t version_id,
                 const content::ServiceWorkerRunningInfo& worker_info) override;
  // Called when an extension service worker is stopping.
  void OnStopping(
      int64_t version_id,
      const content::ServiceWorkerRunningInfo& worker_info) override;

 private:
  void SetWorkerId(const WorkerId& worker_id);
  void NotifyObserversIfReady(const SequencedContextId& context_id);

  BrowserState browser_state_ = BrowserState::kNotActive;
  RendererState renderer_state_ = RendererState::kNotActive;

  // Whether the service worker is in the process of starting.
  bool worker_starting_ = false;

  // Contains the worker's WorkerId associated with this ServiceWorkerState,
  // once we have discovered info about the worker.
  std::optional<WorkerId> worker_id_;

  // Holds a pointer to the service worker context associated with this worker.
  const raw_ptr<content::ServiceWorkerContext> service_worker_context_ =
      nullptr;

  // Holds a pointer to the ProcessManager associated with a profile /
  // BrowserContext. This ServiceWorkerState is owned by ServiceWorkerTaskQueue,
  // ensuring ProcessManager outlives this instance.
  const raw_ptr<const ProcessManager> process_manager_ = nullptr;

  base::ScopedObservation<content::ServiceWorkerContext,
                          content::ServiceWorkerContextObserverSynchronous>
      service_worker_context_observation_{this};

  base::ObserverList<Observer> observers_;

  base::WeakPtrFactory<ServiceWorkerState> weak_factory_{this};
};

}  // namespace extensions

#endif  // EXTENSIONS_BROWSER_SERVICE_WORKER_SERVICE_WORKER_STATE_H_