blob: 460200fb5a8951771a11526cebfa3fbfbfcdf5cc [file] [log] [blame]
// Copyright 2023 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef COBALT_WORKER_SERVICE_WORKER_CONTEXT_H_
#define COBALT_WORKER_SERVICE_WORKER_CONTEXT_H_
#include <memory>
#include <set>
#include <string>
#include "base/memory/scoped_refptr.h"
#include "base/message_loop/message_loop.h"
#include "base/optional.h"
#include "base/synchronization/waitable_event.h"
#include "cobalt/network/network_module.h"
#include "cobalt/script/promise.h"
#include "cobalt/script/script_value.h"
#include "cobalt/script/script_value_factory.h"
#include "cobalt/web/context.h"
#include "cobalt/web/web_settings.h"
#include "cobalt/worker/client_query_options.h"
#include "cobalt/worker/service_worker_object.h"
#include "cobalt/worker/service_worker_registration_map.h"
#include "cobalt/worker/service_worker_registration_object.h"
#include "cobalt/worker/worker_type.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace cobalt {
namespace worker {
class ServiceWorkerJobs;
// Algorithms for Service Workers.
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#algorithms
class ServiceWorkerContext {
public:
enum RegistrationState { kInstalling, kWaiting, kActive };
ServiceWorkerContext(web::WebSettings* web_settings,
network::NetworkModule* network_module,
web::UserAgentPlatformInfo* platform_info,
base::MessageLoop* message_loop);
~ServiceWorkerContext();
base::MessageLoop* message_loop() { return message_loop_; }
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#start-register-algorithm
void StartRegister(const base::Optional<GURL>& scope_url,
const GURL& script_url,
std::unique_ptr<script::ValuePromiseWrappable::Reference>
promise_reference,
web::Context* client, const WorkerType& type,
const ServiceWorkerUpdateViaCache& update_via_cache);
void MaybeResolveReadyPromiseSubSteps(web::Context* client);
// Sub steps (8) of ServiceWorkerContainer.getRegistration().
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#navigator-service-worker-getRegistration
void GetRegistrationSubSteps(
const url::Origin& storage_key, const GURL& client_url,
web::Context* client,
std::unique_ptr<script::ValuePromiseWrappable::Reference>
promise_reference);
void GetRegistrationsSubSteps(
const url::Origin& storage_key, web::Context* client,
std::unique_ptr<script::ValuePromiseSequenceWrappable::Reference>
promise_reference);
// Sub steps (2) of ServiceWorkerGlobalScope.skipWaiting().
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#dom-serviceworkerglobalscope-skipwaiting
void SkipWaitingSubSteps(
web::Context* worker_context, ServiceWorkerObject* service_worker,
std::unique_ptr<script::ValuePromiseVoid::Reference> promise_reference);
// Sub steps for ExtendableEvent.WaitUntil().
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#dom-extendableevent-waituntil
void WaitUntilSubSteps(ServiceWorkerRegistrationObject* registration);
// Parallel sub steps (2) for algorithm for Clients.get(id):
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#clients-get
void ClientsGetSubSteps(
web::Context* worker_context,
ServiceWorkerObject* associated_service_worker,
std::unique_ptr<script::ValuePromiseWrappable::Reference>
promise_reference,
const std::string& id);
// Parallel sub steps (2) for algorithm for Clients.matchAll():
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#clients-matchall
void ClientsMatchAllSubSteps(
web::Context* worker_context,
ServiceWorkerObject* associated_service_worker,
std::unique_ptr<script::ValuePromiseSequenceWrappable::Reference>
promise_reference,
bool include_uncontrolled, ClientType type);
// Parallel sub steps (3) for algorithm for Clients.claim():
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#dom-clients-claim
void ClaimSubSteps(
web::Context* worker_context,
ServiceWorkerObject* associated_service_worker,
std::unique_ptr<script::ValuePromiseVoid::Reference> promise_reference);
// Parallel sub steps (6) for algorithm for ServiceWorker.postMessage():
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#service-worker-postmessage-options
void ServiceWorkerPostMessageSubSteps(
ServiceWorkerObject* service_worker, web::Context* incumbent_client,
std::unique_ptr<script::StructuredClone> structured_clone);
// Registration of web contexts that may have service workers.
void RegisterWebContext(web::Context* context);
void UnregisterWebContext(web::Context* context);
bool IsWebContextRegistered(web::Context* context) {
DCHECK(base::MessageLoop::current() == message_loop());
return web_context_registrations_.end() !=
web_context_registrations_.find(context);
}
// Ensure no references are kept to JS objects for a client that is about to
// be shutdown.
void PrepareForClientShutdown(web::Context* client);
// Set the active worker for a client if there is a matching service worker.
void SetActiveWorker(web::EnvironmentSettings* client);
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#activation-algorithm
void Activate(ServiceWorkerRegistrationObject* registration);
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#clear-registration-algorithm
void ClearRegistration(ServiceWorkerRegistrationObject* registration);
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#soft-update
void SoftUpdate(ServiceWorkerRegistrationObject* registration,
bool force_bypass_cache);
void EnsureServiceWorkerStarted(const url::Origin& storage_key,
const GURL& client_url,
base::WaitableEvent* done_event);
void EraseRegistrationMap();
ServiceWorkerJobs* jobs() { return jobs_.get(); }
ServiceWorkerRegistrationMap* registration_map() {
return scope_to_registration_map_.get();
}
const std::set<web::Context*>& web_context_registrations() const {
return web_context_registrations_;
}
private:
friend class ServiceWorkerJobs;
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#run-service-worker-algorithm
// The return value is a 'Completion or failure'.
// A failure is signaled by returning nullptr. Otherwise, the returned string
// points to the value of the Completion returned by the script runner
// abstraction.
std::string* RunServiceWorker(ServiceWorkerObject* worker,
bool force_bypass_cache = false);
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#try-activate-algorithm
void TryActivate(ServiceWorkerRegistrationObject* registration);
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#service-worker-has-no-pending-events
bool ServiceWorkerHasNoPendingEvents(ServiceWorkerObject* worker);
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#update-registration-state-algorithm
void UpdateRegistrationState(
ServiceWorkerRegistrationObject* registration, RegistrationState target,
const scoped_refptr<ServiceWorkerObject>& source);
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#update-state-algorithm
void UpdateWorkerState(ServiceWorkerObject* worker, ServiceWorkerState state);
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#on-client-unload-algorithm
void HandleServiceWorkerClientUnload(web::Context* client);
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#terminate-service-worker
void TerminateServiceWorker(ServiceWorkerObject* worker);
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#notify-controller-change-algorithm
void NotifyControllerChange(web::Context* client);
// https://www.w3.org/TR/2022/CRD-service-workers-20220712/#try-clear-registration-algorithm
void TryClearRegistration(ServiceWorkerRegistrationObject* registration);
bool IsAnyClientUsingRegistration(
ServiceWorkerRegistrationObject* registration);
// Returns false when the timeout is reached.
bool WaitForAsynchronousExtensions(
const scoped_refptr<ServiceWorkerRegistrationObject>& registration);
base::MessageLoop* message_loop_;
std::unique_ptr<ServiceWorkerRegistrationMap> scope_to_registration_map_;
std::unique_ptr<ServiceWorkerJobs> jobs_;
std::set<web::Context*> web_context_registrations_;
base::WaitableEvent web_context_registrations_cleared_ = {
base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED};
};
} // namespace worker
} // namespace cobalt
#endif // COBALT_WORKER_SERVICE_WORKER_CONTEXT_H_