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_
|