// 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.

#include "cobalt/worker/service_worker_context.h"

#include <list>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/message_loop/message_loop_current.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/web/dom_exception.h"
#include "cobalt/web/environment_settings.h"
#include "cobalt/worker/extendable_event.h"
#include "cobalt/worker/extendable_message_event.h"
#include "cobalt/worker/service_worker_container.h"
#include "cobalt/worker/service_worker_jobs.h"
#include "cobalt/worker/window_client.h"

namespace cobalt {
namespace worker {

namespace {

const base::TimeDelta kWaitForAsynchronousExtensionsTimeout =
    base::TimeDelta::FromSeconds(3);

const base::TimeDelta kShutdownWaitTimeoutSecs =
    base::TimeDelta::FromSeconds(5);

bool PathContainsEscapedSlash(const GURL& url) {
  const std::string path = url.path();
  return (path.find("%2f") != std::string::npos ||
          path.find("%2F") != std::string::npos ||
          path.find("%5c") != std::string::npos ||
          path.find("%5C") != std::string::npos);
}

void ResolveGetClientPromise(
    web::Context* client, web::Context* worker_context,
    std::unique_ptr<script::ValuePromiseWrappable::Reference>
        promise_reference) {
  TRACE_EVENT0("cobalt::worker", "ResolveGetClientPromise()");
  // Algorithm for Resolve Get Client Promise:
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#resolve-get-client-promise

  // 1. If client is an environment settings object, then:
  // 1.1. If client is not a secure context, queue a task to reject promise with
  //      a "SecurityError" DOMException, on promise’s relevant settings
  //      object's responsible event loop using the DOM manipulation task
  //      source, and abort these steps.
  // 2. Else:
  // 2.1. If client’s creation URL is not a potentially trustworthy URL, queue
  //      a task to reject promise with a "SecurityError" DOMException, on
  //      promise’s relevant settings object's responsible event loop using the
  //      DOM manipulation task source, and abort these steps.
  // In production, Cobalt requires https, therefore all clients are secure
  // contexts.

  // 3. If client is an environment settings object and is not a window client,
  //    then:
  if (!client->GetWindowOrWorkerGlobalScope()->IsWindow()) {
    // 3.1. Let clientObject be the result of running Create Client algorithm
    //      with client as the argument.
    scoped_refptr<Client> client_object =
        Client::Create(client->environment_settings());

    // 3.2. Queue a task to resolve promise with clientObject, on promise’s
    //      relevant settings object's responsible event loop using the DOM
    //      manipulation task source, and abort these steps.
    worker_context->message_loop()->task_runner()->PostTask(
        FROM_HERE,
        base::BindOnce(
            [](std::unique_ptr<script::ValuePromiseWrappable::Reference>
                   promise_reference,
               scoped_refptr<Client> client_object) {
              TRACE_EVENT0("cobalt::worker",
                           "ResolveGetClientPromise() Resolve");
              promise_reference->value().Resolve(client_object);
            },
            std::move(promise_reference), client_object));
    return;
  }
  // 4. Else:
  // 4.1. Let browsingContext be null.
  // 4.2. If client is an environment settings object, set browsingContext to
  //      client’s global object's browsing context.
  // 4.3. Else, set browsingContext to client’s target browsing context.
  // Note: Cobalt does not implement a distinction between environments and
  // environment settings objects.
  // 4.4. Queue a task to run the following steps on browsingContext’s event
  //      loop using the user interaction task source:
  // Note: The task below does not currently perform any actual
  // functionality in the client context. It is included however to help future
  // implementation for fetching values for WindowClient properties, with
  // similar logic existing in ClientsMatchAllSubSteps.
  client->message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(
          [](web::Context* client, web::Context* worker_context,
             std::unique_ptr<script::ValuePromiseWrappable::Reference>
                 promise_reference) {
            // 4.4.1. Let frameType be the result of running Get Frame Type with
            //        browsingContext.
            // Cobalt does not support nested or auxiliary browsing contexts.
            // 4.4.2. Let visibilityState be browsingContext’s active document's
            //        visibilityState attribute value.
            // 4.4.3. Let focusState be the result of running the has focus
            //        steps with browsingContext’s active document as the
            //        argument.
            // Handled in the WindowData constructor.
            std::unique_ptr<WindowData> window_data(
                new WindowData(client->environment_settings()));

            // 4.4.4. Let ancestorOriginsList be the empty list.
            // 4.4.5. If client is a window client, set ancestorOriginsList to
            //        browsingContext’s active document's relevant global
            //        object's Location object’s ancestor origins list's
            //        associated list.
            // Cobalt does not implement Location.ancestorOrigins.

            // 4.4.6. Queue a task to run the following steps on promise’s
            //        relevant settings object's responsible event loop using
            //        the DOM manipulation task source:
            worker_context->message_loop()->task_runner()->PostTask(
                FROM_HERE,
                base::BindOnce(
                    [](std::unique_ptr<script::ValuePromiseWrappable::Reference>
                           promise_reference,
                       std::unique_ptr<WindowData> window_data) {
                      // 4.4.6.1. If client’s discarded flag is set, resolve
                      //          promise with undefined and abort these
                      //          steps.
                      // 4.4.6.2. Let windowClient be the result of running
                      //          Create Window Client with client,
                      //          frameType, visibilityState, focusState,
                      //          and ancestorOriginsList.
                      scoped_refptr<Client> window_client =
                          WindowClient::Create(*window_data);
                      // 4.4.6.3. Resolve promise with windowClient.
                      promise_reference->value().Resolve(window_client);
                    },
                    std::move(promise_reference), std::move(window_data)));
          },
          client, worker_context, std::move(promise_reference)));
  DCHECK_EQ(nullptr, promise_reference.get());
}

}  // namespace

ServiceWorkerContext::ServiceWorkerContext(
    web::WebSettings* web_settings, network::NetworkModule* network_module,
    web::UserAgentPlatformInfo* platform_info, base::MessageLoop* message_loop,
    const GURL& url)
    : message_loop_(message_loop) {
  DCHECK_EQ(message_loop_, base::MessageLoop::current());
  jobs_ =
      std::make_unique<ServiceWorkerJobs>(this, network_module, message_loop);

  ServiceWorkerPersistentSettings::Options options(web_settings, network_module,
                                                   platform_info, this, url);
  scope_to_registration_map_.reset(new ServiceWorkerRegistrationMap(options));
  DCHECK(scope_to_registration_map_);
}

ServiceWorkerContext::~ServiceWorkerContext() {
  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  scope_to_registration_map_->HandleUserAgentShutdown(this);
  scope_to_registration_map_->AbortAllActive();
  scope_to_registration_map_.reset();
  if (!web_context_registrations_.empty()) {
    // Abort any Service Workers that remain.
    for (auto& context : web_context_registrations_) {
      DCHECK(context);
      if (context->GetWindowOrWorkerGlobalScope()->IsServiceWorker()) {
        ServiceWorkerGlobalScope* service_worker =
            context->GetWindowOrWorkerGlobalScope()->AsServiceWorker();
        if (service_worker && service_worker->service_worker_object()) {
          service_worker->service_worker_object()->Abort();
        }
      }
    }

    // Wait for web context registrations to be cleared.
    web_context_registrations_cleared_.TimedWait(kShutdownWaitTimeoutSecs);
  }
}

void ServiceWorkerContext::StartRegister(
    const base::Optional<GURL>& maybe_scope_url,
    const GURL& script_url_with_fragment,
    std::unique_ptr<script::ValuePromiseWrappable::Reference> promise_reference,
    web::Context* client, const WorkerType& type,
    const ServiceWorkerUpdateViaCache& update_via_cache) {
  TRACE_EVENT2("cobalt::worker", "ServiceWorkerContext::StartRegister()",
               "scope", maybe_scope_url.value_or(GURL()).spec(), "script",
               script_url_with_fragment.spec());
  DCHECK_NE(message_loop(), base::MessageLoop::current());
  DCHECK_EQ(client->message_loop(), base::MessageLoop::current());
  // Algorithm for Start Register:
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#start-register-algorithm
  // 1. If scriptURL is failure, reject promise with a TypeError and abort these
  //    steps.
  if (script_url_with_fragment.is_empty()) {
    promise_reference->value().Reject(script::kTypeError);
    return;
  }

  // 2. Set scriptURL’s fragment to null.
  url::Replacements<char> replacements;
  replacements.ClearRef();
  GURL script_url = script_url_with_fragment.ReplaceComponents(replacements);
  DCHECK(!script_url.has_ref() || script_url.ref().empty());
  DCHECK(!script_url.is_empty());

  // 3. If scriptURL’s scheme is not one of "http" and "https", reject promise
  //    with a TypeError and abort these steps.
  if (!script_url.SchemeIsHTTPOrHTTPS()) {
    promise_reference->value().Reject(script::kTypeError);
    return;
  }

  // 4. If any of the strings in scriptURL’s path contains either ASCII
  //    case-insensitive "%2f" or ASCII case-insensitive "%5c", reject promise
  //    with a TypeError and abort these steps.
  if (PathContainsEscapedSlash(script_url)) {
    promise_reference->value().Reject(script::kTypeError);
    return;
  }

  DCHECK(client);
  web::WindowOrWorkerGlobalScope* window_or_worker_global_scope =
      client->GetWindowOrWorkerGlobalScope();
  DCHECK(window_or_worker_global_scope);
  web::CspDelegate* csp_delegate =
      window_or_worker_global_scope->csp_delegate();
  DCHECK(csp_delegate);
  if (!csp_delegate->CanLoad(web::CspDelegate::kWorker, script_url,
                             /* did_redirect*/ false)) {
    promise_reference->value().Reject(new web::DOMException(
        web::DOMException::kSecurityErr,
        "Failed to register a ServiceWorker: The provided scriptURL ('" +
            script_url.spec() + "') violates the Content Security Policy."));
    return;
  }

  // 5. If scopeURL is null, set scopeURL to the result of parsing the string
  //    "./" with scriptURL.
  GURL scope_url = maybe_scope_url.value_or(script_url.Resolve("./"));

  // 6. If scopeURL is failure, reject promise with a TypeError and abort these
  //    steps.
  if (scope_url.is_empty()) {
    promise_reference->value().Reject(script::kTypeError);
    return;
  }

  // 7. Set scopeURL’s fragment to null.
  scope_url = scope_url.ReplaceComponents(replacements);
  DCHECK(!scope_url.has_ref() || scope_url.ref().empty());
  DCHECK(!scope_url.is_empty());

  // 8. If scopeURL’s scheme is not one of "http" and "https", reject promise
  //    with a TypeError and abort these steps.
  if (!scope_url.SchemeIsHTTPOrHTTPS()) {
    promise_reference->value().Reject(script::kTypeError);
    return;
  }

  // 9. If any of the strings in scopeURL’s path contains either ASCII
  //    case-insensitive "%2f" or ASCII case-insensitive "%5c", reject promise
  //    with a TypeError and abort these steps.
  if (PathContainsEscapedSlash(scope_url)) {
    promise_reference->value().Reject(script::kTypeError);
    return;
  }

  // 10. Let storage key be the result of running obtain a storage key given
  //     client.
  url::Origin storage_key = client->environment_settings()->ObtainStorageKey();

  // 11. Let job be the result of running Create Job with register, storage key,
  //     scopeURL, scriptURL, promise, and client.
  std::unique_ptr<ServiceWorkerJobs::Job> job = jobs_->CreateJob(
      ServiceWorkerJobs::kRegister, storage_key, scope_url, script_url,
      ServiceWorkerJobs::JobPromiseType::Create(std::move(promise_reference)),
      client);

  // 12. Set job’s worker type to workerType.
  // Cobalt only supports 'classic' worker type.

  // 13. Set job’s update via cache mode to updateViaCache.
  job->update_via_cache = update_via_cache;

  // 14. Set job’s referrer to referrer.
  // This is the same value as set in CreateJob().

  // 15. Invoke Schedule Job with job.
  jobs_->ScheduleJob(std::move(job));
}

void ServiceWorkerContext::SoftUpdate(
    ServiceWorkerRegistrationObject* registration, bool force_bypass_cache) {
  TRACE_EVENT0("cobalt::worker", "ServiceWorkerContext::SoftUpdate()");
  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  DCHECK(registration);
  // Algorithm for SoftUpdate:
  //    https://www.w3.org/TR/2022/CRD-service-workers-20220712/#soft-update
  // 1. Let newestWorker be the result of running Get Newest Worker algorithm
  // passing registration as its argument.
  ServiceWorkerObject* newest_worker = registration->GetNewestWorker();

  // 2. If newestWorker is null, abort these steps.
  if (newest_worker == nullptr) {
    return;
  }

  // 3. Let job be the result of running Create Job with update, registration’s
  // storage key, registration’s scope url, newestWorker’s script url, null, and
  // null.
  std::unique_ptr<ServiceWorkerJobs::Job> job = jobs_->CreateJobWithoutPromise(
      ServiceWorkerJobs::kUpdate, registration->storage_key(),
      registration->scope_url(), newest_worker->script_url());

  // 4. Set job’s worker type to newestWorker’s type.
  // Cobalt only supports 'classic' worker type.

  // 5. Set job’s force bypass cache flag if forceBypassCache is true.
  job->force_bypass_cache_flag = force_bypass_cache;

  // 6. Invoke Schedule Job with job.
  message_loop()->task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&ServiceWorkerJobs::ScheduleJob,
                                base::Unretained(jobs_.get()), std::move(job)));
  DCHECK(!job.get());
}

void ServiceWorkerContext::EnsureServiceWorkerStarted(
    const url::Origin& storage_key, const GURL& client_url,
    base::WaitableEvent* done_event) {
  if (message_loop() != base::MessageLoop::current()) {
    message_loop()->task_runner()->PostTask(
        FROM_HERE,
        base::BindOnce(&ServiceWorkerContext::EnsureServiceWorkerStarted,
                       base::Unretained(this), storage_key, client_url,
                       done_event));
    return;
  }
  base::ScopedClosureRunner signal_done(base::BindOnce(
      [](base::WaitableEvent* done_event) { done_event->Signal(); },
      done_event));
  base::TimeTicks start = base::TimeTicks::Now();
  auto registration =
      scope_to_registration_map_->MatchServiceWorkerRegistration(storage_key,
                                                                 client_url);
  if (!registration) {
    return;
  }
  auto service_worker_object = registration->active_worker();
  if (!service_worker_object || service_worker_object->is_running()) {
    return;
  }
  service_worker_object->ObtainWebAgentAndWaitUntilDone();
}

void ServiceWorkerContext::EraseRegistrationMap() {
  if (message_loop() != base::MessageLoop::current()) {
    message_loop()->task_runner()->PostTask(
        FROM_HERE, base::BindOnce(&ServiceWorkerContext::EraseRegistrationMap,
                                  base::Unretained(this)));
    return;
  }
  scope_to_registration_map_->DeletePersistentSettings();
}

std::string* ServiceWorkerContext::RunServiceWorker(ServiceWorkerObject* worker,
                                                    bool force_bypass_cache) {
  TRACE_EVENT0("cobalt::worker", "ServiceWorkerContext::RunServiceWorker()");

  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  DCHECK(worker);
  // Algorithm for "Run Service Worker"
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#run-service-worker-algorithm

  // 1. Let unsafeCreationTime be the unsafe shared current time.
  auto unsafe_creation_time = base::TimeTicks::Now();
  // 2. If serviceWorker is running, then return serviceWorker’s start status.
  if (worker->is_running()) {
    return worker->start_status();
  }
  // 3. If serviceWorker’s state is "redundant", then return failure.
  if (worker->state() == kServiceWorkerStateRedundant) {
    return nullptr;
  }
  // 4. Assert: serviceWorker’s start status is null.
  DCHECK(worker->start_status() == nullptr);
  // 5. Let script be serviceWorker’s script resource.
  // 6. Assert: script is not null.
  DCHECK(worker->HasScriptResource());
  // 7. Let startFailed be false.
  worker->store_start_failed(false);
  // 8. Let agent be the result of obtaining a service worker agent, and run the
  //    following steps in that context:
  // 9. Wait for serviceWorker to be running, or for startFailed to be true.
  worker->ObtainWebAgentAndWaitUntilDone();
  // 10. If startFailed is true, then return failure.
  if (worker->load_start_failed()) {
    return nullptr;
  }
  // 11. Return serviceWorker’s start status.
  return worker->start_status();
}

bool ServiceWorkerContext::WaitForAsynchronousExtensions(
    const scoped_refptr<ServiceWorkerRegistrationObject>& registration) {
  // TODO(b/240164388): Investigate a better approach for combining waiting
  // for the ExtendableEvent while also allowing use of algorithms that run
  // on the same thread from the event handler.
  base::TimeTicks wait_start_time = base::TimeTicks::Now();
  do {
    if (registration->done_event()->TimedWait(
            base::TimeDelta::FromMilliseconds(100)))
      break;
    base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
    base::RunLoop().RunUntilIdle();
  } while ((base::TimeTicks::Now() - wait_start_time) <
           kWaitForAsynchronousExtensionsTimeout);
  return registration->done_event()->IsSignaled();
}

bool ServiceWorkerContext::IsAnyClientUsingRegistration(
    ServiceWorkerRegistrationObject* registration) {
  bool any_client_is_using = false;
  for (auto& context : web_context_registrations_) {
    // When a service worker client is controlled by a service worker, it is
    // said that the service worker client is using the service worker’s
    // containing service worker registration.
    //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#dfn-control
    if (context->GetWindowOrWorkerGlobalScope()->IsServiceWorker()) continue;
    if (context->is_controlled_by(registration->active_worker())) {
      any_client_is_using = true;
      break;
    }
  }
  return any_client_is_using;
}

void ServiceWorkerContext::TryActivate(
    ServiceWorkerRegistrationObject* registration) {
  TRACE_EVENT0("cobalt::worker", "ServiceWorkerContext::TryActivate()");
  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  // Algorithm for Try Activate:
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#try-activate-algorithm

  // 1. If registration’s waiting worker is null, return.
  if (!registration) return;
  if (!registration->waiting_worker()) return;

  // 2. If registration’s active worker is not null and registration’s active
  //    worker's state is "activating", return.
  if (registration->active_worker() &&
      (registration->active_worker()->state() == kServiceWorkerStateActivating))
    return;

  // 3. Invoke Activate with registration if either of the following is true:

  //    - registration’s active worker is null.
  bool invoke_activate = registration->active_worker() == nullptr;

  if (!invoke_activate) {
    //    - The result of running Service Worker Has No Pending Events with
    //      registration’s active worker is true...
    if (ServiceWorkerHasNoPendingEvents(registration->active_worker())) {
      //      ... and no service worker client is using registration...
      bool any_client_using = IsAnyClientUsingRegistration(registration);
      invoke_activate = !any_client_using;
      //      ... or registration’s waiting worker's skip waiting flag is
      //      set.
      if (!invoke_activate && registration->waiting_worker()->skip_waiting())
        invoke_activate = true;
    }
  }

  if (invoke_activate) Activate(registration);
}

void ServiceWorkerContext::Activate(
    ServiceWorkerRegistrationObject* registration) {
  TRACE_EVENT0("cobalt::worker", "ServiceWorkerContext::Activate()");
  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  // Algorithm for Activate:
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#activation-algorithm

  // 1. If registration’s waiting worker is null, abort these steps.
  if (registration->waiting_worker() == nullptr) return;
  // 2. If registration’s active worker is not null, then:
  if (registration->active_worker()) {
    // 2.1. Terminate registration’s active worker.
    TerminateServiceWorker(registration->active_worker());
    // 2.2. Run the Update Worker State algorithm passing registration’s active
    //      worker and "redundant" as the arguments.
    UpdateWorkerState(registration->active_worker(),
                      kServiceWorkerStateRedundant);
  }
  // 3. Run the Update Registration State algorithm passing registration,
  //    "active" and registration’s waiting worker as the arguments.
  UpdateRegistrationState(registration, kActive,
                          registration->waiting_worker());
  // 4. Run the Update Registration State algorithm passing registration,
  //    "waiting" and null as the arguments.
  UpdateRegistrationState(registration, kWaiting, nullptr);
  // 5. Run the Update Worker State algorithm passing registration’s active
  //    worker and "activating" as the arguments.
  UpdateWorkerState(registration->active_worker(),
                    kServiceWorkerStateActivating);
  // 6. Let matchedClients be a list of service worker clients whose creation
  //    URL matches registration’s storage key and registration’s scope url.
  std::list<web::Context*> matched_clients;
  for (auto& context : web_context_registrations_) {
    url::Origin context_storage_key =
        url::Origin::Create(context->environment_settings()->creation_url());
    scoped_refptr<ServiceWorkerRegistrationObject> matched_registration =
        scope_to_registration_map_->MatchServiceWorkerRegistration(
            context_storage_key, registration->scope_url());
    if (matched_registration == registration) {
      matched_clients.push_back(context);
    }
  }
  // 7. For each client of matchedClients, queue a task on client’s  responsible
  //    event loop, using the DOM manipulation task source, to run the following
  //    substeps:
  for (auto& client : matched_clients) {
    // 7.1. Let readyPromise be client’s global object's
    //      ServiceWorkerContainer object’s ready
    //      promise.
    // 7.2. If readyPromise is null, then continue.
    // 7.3. If readyPromise is pending, resolve
    //      readyPromise with the the result of getting
    //      the service worker registration object that
    //      represents registration in readyPromise’s
    //      relevant settings object.
    client->message_loop()->task_runner()->PostTask(
        FROM_HERE,
        base::BindOnce(&ServiceWorkerContainer::MaybeResolveReadyPromise,
                       base::Unretained(client->GetWindowOrWorkerGlobalScope()
                                            ->navigator_base()
                                            ->service_worker()
                                            .get()),
                       base::Unretained(registration)));
  }
  // 8. For each client of matchedClients:
  // 8.1. If client is a window client, unassociate client’s responsible
  //      document from its application cache, if it has one.
  // 8.2. Else if client is a shared worker client, unassociate client’s
  //      global object from its application cache, if it has one.
  // Cobalt doesn't implement 'application cache':
  //   https://www.w3.org/TR/2011/WD-html5-20110525/offline.html#applicationcache
  // 9. For each service worker client client who is using registration:
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#dfn-use
  for (const auto& client : web_context_registrations_) {
    // When a service worker client is controlled by a service worker, it is
    // said that the service worker client is using the service worker’s
    // containing service worker registration.
    //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#dfn-control
    if (client->active_service_worker() &&
        client->active_service_worker()
                ->containing_service_worker_registration() == registration) {
      // 9.1. Set client’s active worker to registration’s active worker.
      client->set_active_service_worker(registration->active_worker());
      // 9.2. Invoke Notify Controller Change algorithm with client as the
      //      argument.
      NotifyControllerChange(client);
    }
  }
  // 10. Let activeWorker be registration’s active worker.
  ServiceWorkerObject* active_worker = registration->active_worker();
  bool activated = true;
  // 11. If the result of running the Should Skip Event algorithm with
  //     activeWorker and "activate" is false, then:
  DCHECK(active_worker);
  if (!active_worker->ShouldSkipEvent(base::Tokens::activate())) {
    // 11.1. If the result of running the Run Service Worker algorithm with
    //       activeWorker is not failure, then:
    auto* run_result = RunServiceWorker(active_worker);
    if (run_result) {
      // 11.1.1. Queue a task task on activeWorker’s event loop using the DOM
      //         manipulation task source to run the following steps:
      DCHECK_EQ(active_worker->web_agent()->context(),
                active_worker->worker_global_scope()
                    ->environment_settings()
                    ->context());
      DCHECK(registration->done_event()->IsSignaled());
      registration->done_event()->Reset();
      active_worker->web_agent()
          ->context()
          ->message_loop()
          ->task_runner()
          ->PostBlockingTask(
              FROM_HERE,
              base::Bind(
                  [](ServiceWorkerObject* active_worker,
                     base::WaitableEvent* done_event) {
                    auto done_callback =
                        base::BindOnce([](base::WaitableEvent* done_event,
                                          bool) { done_event->Signal(); },
                                       done_event);
                    auto* settings = active_worker->web_agent()
                                         ->context()
                                         ->environment_settings();
                    scoped_refptr<ExtendableEvent> event(
                        new ExtendableEvent(settings, base::Tokens::activate(),
                                            std::move(done_callback)));
                    // 11.1.1.1. Let e be the result of creating an event with
                    //           ExtendableEvent.
                    // 11.1.1.2. Initialize e’s type attribute to activate.
                    // 11.1.1.3. Dispatch e at activeWorker’s global object.
                    active_worker->worker_global_scope()->DispatchEvent(event);
                    // 11.1.1.4. WaitForAsynchronousExtensions: Wait, in
                    //           parallel, until e is not active.
                    if (!event->IsActive()) {
                      // If the event handler doesn't use waitUntil(), it will
                      // already no longer be active, and there will never be a
                      // callback to signal the done event.
                      done_event->Signal();
                    }
                  },
                  base::Unretained(active_worker), registration->done_event()));
      // 11.1.2. Wait for task to have executed or been discarded.
      // This waiting is done inside PostBlockingTask above.
      // 11.1.3. Wait for the step labeled WaitForAsynchronousExtensions to
      //         complete.
      // TODO(b/240164388): Investigate a better approach for combining waiting
      // for the ExtendableEvent while also allowing use of algorithms that run
      // on the same thread from the event handler.
      if (!WaitForAsynchronousExtensions(registration)) {
        // Timeout
        activated = false;
      }
    } else {
      activated = false;
    }
  }
  // 12. Run the Update Worker State algorithm passing registration’s active
  //     worker and "activated" as the arguments.
  if (activated && registration->active_worker()) {
    UpdateWorkerState(registration->active_worker(),
                      kServiceWorkerStateActivated);

    // Persist registration since the waiting_worker has been updated to nullptr
    // and the active_worker has been updated to the previous waiting_worker.
    scope_to_registration_map_->PersistRegistration(registration->storage_key(),
                                                    registration->scope_url());
  }
}

void ServiceWorkerContext::NotifyControllerChange(web::Context* client) {
  // Algorithm for Notify Controller Change:
  // https://www.w3.org/TR/2022/CRD-service-workers-20220712/#notify-controller-change-algorithm
  // 1. Assert: client is not null.
  DCHECK(client);

  // 2. If client is an environment settings object, queue a task to fire an
  //    event named controllerchange at the ServiceWorkerContainer object that
  //    client is associated with.
  client->message_loop()->task_runner()->PostTask(
      FROM_HERE, base::Bind(
                     [](web::Context* client) {
                       client->GetWindowOrWorkerGlobalScope()
                           ->navigator_base()
                           ->service_worker()
                           ->DispatchEvent(new web::Event(
                               base::Tokens::controllerchange()));
                     },
                     client));
}

bool ServiceWorkerContext::ServiceWorkerHasNoPendingEvents(
    ServiceWorkerObject* worker) {
  // Algorithm for Service Worker Has No Pending Events
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#service-worker-has-no-pending-events
  // TODO(b/240174245): Implement this using the 'set of extended events'.
  NOTIMPLEMENTED();

  // 1. For each event of worker’s set of extended events:
  // 1.1. If event is active, return false.
  // 2. Return true.
  return true;
}

void ServiceWorkerContext::ClearRegistration(
    ServiceWorkerRegistrationObject* registration) {
  TRACE_EVENT0("cobalt::worker", "ServiceWorkerContext::ClearRegistration()");
  // Algorithm for Clear Registration:
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#clear-registration-algorithm
  // 1. Run the following steps atomically.
  DCHECK_EQ(message_loop(), base::MessageLoop::current());

  // 2. If registration’s installing worker is not null, then:
  ServiceWorkerObject* installing_worker = registration->installing_worker();
  if (installing_worker) {
    // 2.1. Terminate registration’s installing worker.
    TerminateServiceWorker(installing_worker);
    // 2.2. Run the Update Worker State algorithm passing registration’s
    //      installing worker and "redundant" as the arguments.
    UpdateWorkerState(installing_worker, kServiceWorkerStateRedundant);
    // 2.3. Run the Update Registration State algorithm passing registration,
    //      "installing" and null as the arguments.
    UpdateRegistrationState(registration, kInstalling, nullptr);
  }

  // 3. If registration’s waiting worker is not null, then:
  ServiceWorkerObject* waiting_worker = registration->waiting_worker();
  if (waiting_worker) {
    // 3.1. Terminate registration’s waiting worker.
    TerminateServiceWorker(waiting_worker);
    // 3.2. Run the Update Worker State algorithm passing registration’s
    //      waiting worker and "redundant" as the arguments.
    UpdateWorkerState(waiting_worker, kServiceWorkerStateRedundant);
    // 3.3. Run the Update Registration State algorithm passing registration,
    //      "waiting" and null as the arguments.
    UpdateRegistrationState(registration, kWaiting, nullptr);
  }

  // 4. If registration’s active worker is not null, then:
  ServiceWorkerObject* active_worker = registration->active_worker();
  if (active_worker) {
    // 4.1. Terminate registration’s active worker.
    TerminateServiceWorker(active_worker);
    // 4.2. Run the Update Worker State algorithm passing registration’s
    //      active worker and "redundant" as the arguments.
    UpdateWorkerState(active_worker, kServiceWorkerStateRedundant);
    // 4.3. Run the Update Registration State algorithm passing registration,
    //      "active" and null as the arguments.
    UpdateRegistrationState(registration, kActive, nullptr);
  }

  // Persist registration since the waiting_worker and active_worker have
  // been updated to nullptr. This will remove any persisted registration
  // if one exists.
  scope_to_registration_map_->PersistRegistration(registration->storage_key(),
                                                  registration->scope_url());
}

void ServiceWorkerContext::TryClearRegistration(
    ServiceWorkerRegistrationObject* registration) {
  TRACE_EVENT0("cobalt::worker",
               "ServiceWorkerContext::TryClearRegistration()");
  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  // Algorithm for Try Clear Registration:
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#try-clear-registration-algorithm

  // 1. Invoke Clear Registration with registration if no service worker client
  // is using registration and all of the following conditions are true:
  if (IsAnyClientUsingRegistration(registration)) return;

  //    . registration’s installing worker is null or the result of running
  //      Service Worker Has No Pending Events with registration’s installing
  //      worker is true.
  if (registration->installing_worker() &&
      !ServiceWorkerHasNoPendingEvents(registration->installing_worker()))
    return;

  //    . registration’s waiting worker is null or the result of running
  //      Service Worker Has No Pending Events with registration’s waiting
  //      worker is true.
  if (registration->waiting_worker() &&
      !ServiceWorkerHasNoPendingEvents(registration->waiting_worker()))
    return;

  //    . registration’s active worker is null or the result of running
  //      ServiceWorker Has No Pending Events with registration’s active worker
  //      is true.
  if (registration->active_worker() &&
      !ServiceWorkerHasNoPendingEvents(registration->active_worker()))
    return;

  ClearRegistration(registration);
}

void ServiceWorkerContext::UpdateRegistrationState(
    ServiceWorkerRegistrationObject* registration, RegistrationState target,
    const scoped_refptr<ServiceWorkerObject>& source) {
  TRACE_EVENT2("cobalt::worker",
               "ServiceWorkerContext::UpdateRegistrationState()", "target",
               target, "source", source);
  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  DCHECK(registration);
  // Algorithm for Update Registration State:
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#update-registration-state-algorithm

  // 1. Let registrationObjects be an array containing all the
  //    ServiceWorkerRegistration objects associated with registration.
  // This is implemented with a call to LookupServiceWorkerRegistration for each
  // registered web context.

  switch (target) {
    // 2. If target is "installing", then:
    case kInstalling: {
      // 2.1. Set registration’s installing worker to source.
      registration->set_installing_worker(source);
      // 2.2. For each registrationObject in registrationObjects:
      for (auto& context : web_context_registrations_) {
        // 2.2.1. Queue a task to...
        context->message_loop()->task_runner()->PostBlockingTask(
            FROM_HERE,
            base::Bind(
                [](web::Context* context,
                   ServiceWorkerRegistrationObject* registration) {
                  // 2.2.1. ... set the installing attribute of
                  //        registrationObject to null if registration’s
                  //        installing worker is null, or the result of getting
                  //        the service worker object that represents
                  //        registration’s installing worker in
                  //        registrationObject’s relevant settings object.
                  auto registration_object =
                      context->LookupServiceWorkerRegistration(registration);
                  if (registration_object) {
                    registration_object->set_installing(
                        context->GetServiceWorker(
                            registration->installing_worker()));
                  }
                },
                context, base::Unretained(registration)));
      }
      break;
    }
    // 3. Else if target is "waiting", then:
    case kWaiting: {
      // 3.1. Set registration’s waiting worker to source.
      registration->set_waiting_worker(source);
      // 3.2. For each registrationObject in registrationObjects:
      for (auto& context : web_context_registrations_) {
        // 3.2.1. Queue a task to...
        context->message_loop()->task_runner()->PostBlockingTask(
            FROM_HERE,
            base::Bind(
                [](web::Context* context,
                   ServiceWorkerRegistrationObject* registration) {
                  // 3.2.1. ... set the waiting attribute of registrationObject
                  //        to null if registration’s waiting worker is null, or
                  //        the result of getting the service worker object that
                  //        represents registration’s waiting worker in
                  //        registrationObject’s relevant settings object.
                  auto registration_object =
                      context->LookupServiceWorkerRegistration(registration);
                  if (registration_object) {
                    registration_object->set_waiting(context->GetServiceWorker(
                        registration->waiting_worker()));
                  }
                },
                context, base::Unretained(registration)));
      }
      break;
    }
    // 4. Else if target is "active", then:
    case kActive: {
      // 4.1. Set registration’s active worker to source.
      registration->set_active_worker(source);
      // 4.2. For each registrationObject in registrationObjects:
      for (auto& context : web_context_registrations_) {
        // 4.2.1. Queue a task to...
        context->message_loop()->task_runner()->PostBlockingTask(
            FROM_HERE,
            base::Bind(
                [](web::Context* context,
                   ServiceWorkerRegistrationObject* registration) {
                  // 4.2.1. ... set the active attribute of registrationObject
                  //        to null if registration’s active worker is null, or
                  //        the result of getting the service worker object that
                  //        represents registration’s active worker in
                  //        registrationObject’s relevant settings object.
                  auto registration_object =
                      context->LookupServiceWorkerRegistration(registration);
                  if (registration_object) {
                    registration_object->set_active(context->GetServiceWorker(
                        registration->active_worker()));
                  }
                },
                context, base::Unretained(registration)));
      }
      break;
    }
    default:
      NOTREACHED();
  }
}

void ServiceWorkerContext::UpdateWorkerState(ServiceWorkerObject* worker,
                                             ServiceWorkerState state) {
  TRACE_EVENT1("cobalt::worker", "ServiceWorkerContext::UpdateWorkerState()",
               "state", state);
  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  DCHECK(worker);
  if (!worker) {
    return;
  }
  // Algorithm for Update Worker State:
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#update-state-algorithm
  // 1. Assert: state is not "parsed".
  DCHECK_NE(kServiceWorkerStateParsed, state);
  // 2. Set worker's state to state.
  worker->set_state(state);
  auto worker_origin = loader::Origin(worker->script_url());
  // 3. Let settingsObjects be all environment settings objects whose origin is
  //    worker's script url's origin.
  // 4. For each settingsObject of settingsObjects...
  for (auto& context : web_context_registrations_) {
    if (context->environment_settings()->GetOrigin() == worker_origin) {
      // 4. ... queue a task on
      //    settingsObject's responsible event loop in the DOM manipulation task
      //    source to run the following steps:
      context->message_loop()->task_runner()->PostBlockingTask(
          FROM_HERE, base::Bind(
                         [](web::Context* context, ServiceWorkerObject* worker,
                            ServiceWorkerState state) {
                           DCHECK_EQ(context->message_loop(),
                                     base::MessageLoop::current());
                           // 4.1. Let objectMap be settingsObject's service
                           // worker object
                           //      map.
                           // 4.2. If objectMap[worker] does not exist, then
                           // abort these
                           //      steps.
                           // 4.3. Let  workerObj be objectMap[worker].
                           auto worker_obj =
                               context->LookupServiceWorker(worker);
                           if (worker_obj) {
                             // 4.4. Set workerObj's state to state.
                             worker_obj->set_state(state);
                             // 4.5. Fire an event named statechange at
                             // workerObj.
                             worker_obj->DispatchEvent(
                                 new web::Event(base::Tokens::statechange()));
                           }
                         },
                         context, base::Unretained(worker), state));
    }
  }
}

void ServiceWorkerContext::HandleServiceWorkerClientUnload(
    web::Context* client) {
  TRACE_EVENT0("cobalt::worker",
               "ServiceWorkerContext::HandleServiceWorkerClientUnload()");
  // Algorithm for Handle Servicer Worker Client Unload:
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#on-client-unload-algorithm
  DCHECK(client);
  // 1. Run the following steps atomically.
  DCHECK_EQ(message_loop(), base::MessageLoop::current());

  // 2. Let registration be the service worker registration used by client.
  // 3. If registration is null, abort these steps.
  ServiceWorkerObject* active_service_worker = client->active_service_worker();
  if (!active_service_worker) return;
  ServiceWorkerRegistrationObject* registration =
      active_service_worker->containing_service_worker_registration();
  if (!registration) return;

  // 4. If any other service worker client is using registration, abort these
  //    steps.
  if (IsAnyClientUsingRegistration(registration)) return;

  // 5. If registration is unregistered, invoke Try Clear Registration with
  //    registration.
  if (scope_to_registration_map_ &&
      scope_to_registration_map_->IsUnregistered(registration)) {
    TryClearRegistration(registration);
  }

  // 6. Invoke Try Activate with registration.
  TryActivate(registration);
}

void ServiceWorkerContext::TerminateServiceWorker(ServiceWorkerObject* worker) {
  TRACE_EVENT0("cobalt::worker",
               "ServiceWorkerContext::TerminateServiceWorker()");
  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  // Algorithm for Terminate Service Worker:
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#terminate-service-worker
  // 1. Run the following steps in parallel with serviceWorker’s main loop:
  // This runs in the ServiceWorkerRegistry thread.
  DCHECK_EQ(message_loop(), base::MessageLoop::current());

  // 1.1. Let serviceWorkerGlobalScope be serviceWorker’s global object.
  WorkerGlobalScope* service_worker_global_scope =
      worker->worker_global_scope();

  // 1.2. Set serviceWorkerGlobalScope’s closing flag to true.
  if (service_worker_global_scope != nullptr)
    service_worker_global_scope->set_closing_flag(true);

  // 1.3. Remove all the items from serviceWorker’s set of extended events.
  // TODO(b/240174245): Implement 'set of extended events'.

  // 1.4. If there are any tasks, whose task source is either the handle fetch
  //      task source or the handle functional event task source, queued in
  //      serviceWorkerGlobalScope’s event loop’s task queues, queue them to
  //      serviceWorker’s containing service worker registration’s corresponding
  //      task queues in the same order using their original task sources, and
  //      discard all the tasks (including tasks whose task source is neither
  //      the handle fetch task source nor the handle functional event task
  //      source) from serviceWorkerGlobalScope’s event loop’s task queues
  //      without processing them.
  // TODO(b/234787641): Queue tasks to the registration.

  // Note: This step is not in the spec, but without this step the service
  // worker object map will always keep an entry with a service worker instance
  // for the terminated service worker, which besides leaking memory can lead to
  // unexpected behavior when new service worker objects are created with the
  // same key for the service worker object map (which in Cobalt's case
  // happens when a new service worker object is constructed at the same
  // memory address).
  for (auto& context : web_context_registrations_) {
    context->message_loop()->task_runner()->PostBlockingTask(
        FROM_HERE, base::Bind(
                       [](web::Context* context, ServiceWorkerObject* worker) {
                         auto worker_obj = context->LookupServiceWorker(worker);
                         if (worker_obj) {
                           worker_obj->set_state(kServiceWorkerStateRedundant);
                           worker_obj->DispatchEvent(
                               new web::Event(base::Tokens::statechange()));
                         }
                         context->RemoveServiceWorker(worker);
                       },
                       context, base::Unretained(worker)));
  }

  // 1.5. Abort the script currently running in serviceWorker.
  if (worker->is_running()) {
    worker->Abort();
  }

  // 1.6. Set serviceWorker’s start status to null.
  worker->set_start_status(nullptr);
}

void ServiceWorkerContext::MaybeResolveReadyPromiseSubSteps(
    web::Context* client) {
  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  // Algorithm for Sub steps of ServiceWorkerContainer.ready():
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#navigator-service-worker-ready

  //    3.1. Let client by this's service worker client.
  //    3.2. Let storage key be the result of running obtain a storage
  //         key given client.
  url::Origin storage_key = client->environment_settings()->ObtainStorageKey();
  //    3.3. Let registration be the result of running Match Service
  //         Worker Registration given storage key and client’s
  //         creation URL.
  // TODO(b/234659851): Investigate whether this should use the creation URL
  // directly instead.
  const GURL& base_url = client->environment_settings()->creation_url();
  GURL client_url = base_url.Resolve("");
  scoped_refptr<ServiceWorkerRegistrationObject> registration =
      scope_to_registration_map_->MatchServiceWorkerRegistration(storage_key,
                                                                 client_url);
  //    3.3. If registration is not null, and registration’s active
  //         worker is not null, queue a task on readyPromise’s
  //         relevant settings object's responsible event loop, using
  //         the DOM manipulation task source, to resolve readyPromise
  //         with the result of getting the service worker
  //         registration object that represents registration in
  //         readyPromise’s relevant settings object.
  if (registration && registration->active_worker()) {
    client->message_loop()->task_runner()->PostTask(
        FROM_HERE,
        base::BindOnce(&ServiceWorkerContainer::MaybeResolveReadyPromise,
                       base::Unretained(client->GetWindowOrWorkerGlobalScope()
                                            ->navigator_base()
                                            ->service_worker()
                                            .get()),
                       registration));
  }
}

void ServiceWorkerContext::GetRegistrationSubSteps(
    const url::Origin& storage_key, const GURL& client_url,
    web::Context* client,
    std::unique_ptr<script::ValuePromiseWrappable::Reference>
        promise_reference) {
  TRACE_EVENT0("cobalt::worker",
               "ServiceWorkerContext::GetRegistrationSubSteps()");
  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  // Algorithm for Sub steps of ServiceWorkerContainer.getRegistration():
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#navigator-service-worker-getRegistration

  // 8.1. Let registration be the result of running Match Service Worker
  //      Registration algorithm with clientURL as its argument.
  scoped_refptr<ServiceWorkerRegistrationObject> registration =
      scope_to_registration_map_->MatchServiceWorkerRegistration(storage_key,
                                                                 client_url);
  // 8.2. If registration is null, resolve promise with undefined and abort
  //      these steps.
  // 8.3. Resolve promise with the result of getting the service worker
  //      registration object that represents registration in promise’s
  //      relevant settings object.
  client->message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(
          [](web::Context* client,
             std::unique_ptr<script::ValuePromiseWrappable::Reference> promise,
             scoped_refptr<ServiceWorkerRegistrationObject> registration) {
            TRACE_EVENT0(
                "cobalt::worker",
                "ServiceWorkerContext::GetRegistrationSubSteps() Resolve");
            promise->value().Resolve(
                client->GetServiceWorkerRegistration(registration));
          },
          client, std::move(promise_reference), registration));
}

void ServiceWorkerContext::GetRegistrationsSubSteps(
    const url::Origin& storage_key, web::Context* client,
    std::unique_ptr<script::ValuePromiseSequenceWrappable::Reference>
        promise_reference) {
  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  std::vector<scoped_refptr<ServiceWorkerRegistrationObject>>
      registration_objects =
          scope_to_registration_map_->GetRegistrations(storage_key);
  client->message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(
          [](web::Context* client,
             std::unique_ptr<script::ValuePromiseSequenceWrappable::Reference>
                 promise,
             std::vector<scoped_refptr<ServiceWorkerRegistrationObject>>
                 registration_objects) {
            TRACE_EVENT0(
                "cobalt::worker",
                "ServiceWorkerContext::GetRegistrationSubSteps() Resolve");
            script::Sequence<scoped_refptr<script::Wrappable>> registrations;
            for (auto registration_object : registration_objects) {
              registrations.push_back(scoped_refptr<script::Wrappable>(
                  client->GetServiceWorkerRegistration(registration_object)
                      .get()));
            }
            promise->value().Resolve(std::move(registrations));
          },
          client, std::move(promise_reference),
          std::move(registration_objects)));
}

void ServiceWorkerContext::SkipWaitingSubSteps(
    web::Context* worker_context, ServiceWorkerObject* service_worker,
    std::unique_ptr<script::ValuePromiseVoid::Reference> promise_reference) {
  TRACE_EVENT0("cobalt::worker", "ServiceWorkerContext::SkipWaitingSubSteps()");
  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  // Check if the client web context is still active. This may trigger if
  // skipWaiting() was called and service worker installation fails.
  if (!IsWebContextRegistered(worker_context)) {
    promise_reference.release();
    return;
  }

  // Algorithm for Sub steps of ServiceWorkerGlobalScope.skipWaiting():
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#dom-serviceworkerglobalscope-skipwaiting

  // 2.1. Set service worker's skip waiting flag.
  service_worker->set_skip_waiting();

  // 2.2. Invoke Try Activate with service worker's containing service worker
  // registration.
  TryActivate(service_worker->containing_service_worker_registration());

  // 2.3. Resolve promise with undefined.
  worker_context->message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(
          [](std::unique_ptr<script::ValuePromiseVoid::Reference> promise) {
            promise->value().Resolve();
          },
          std::move(promise_reference)));
}

void ServiceWorkerContext::WaitUntilSubSteps(
    ServiceWorkerRegistrationObject* registration) {
  TRACE_EVENT0("cobalt::worker", "ServiceWorkerContext::WaitUntilSubSteps()");
  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  // Sub steps for WaitUntil.
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#dom-extendableevent-waituntil
  // 5.2.2. If registration is unregistered, invoke Try Clear Registration
  //        with registration.
  if (scope_to_registration_map_->IsUnregistered(registration)) {
    TryClearRegistration(registration);
  }
  // 5.2.3. If registration is not null, invoke Try Activate with
  //        registration.
  if (registration) {
    TryActivate(registration);
  }
}

void ServiceWorkerContext::ClientsGetSubSteps(
    web::Context* worker_context,
    ServiceWorkerObject* associated_service_worker,
    std::unique_ptr<script::ValuePromiseWrappable::Reference> promise_reference,
    const std::string& id) {
  TRACE_EVENT0("cobalt::worker", "ServiceWorkerContext::ClientsGetSubSteps()");
  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  // Check if the client web context is still active. This may trigger if
  // Clients.get() was called and service worker installation fails.
  if (!IsWebContextRegistered(worker_context)) {
    promise_reference.release();
    return;
  }
  // Parallel sub steps (2) for algorithm for Clients.get(id):
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#clients-get
  // 2.1. For each service worker client client where the result of running
  //      obtain a storage key given client equals the associated service
  //      worker's containing service worker registration's storage key:
  const url::Origin& storage_key =
      associated_service_worker->containing_service_worker_registration()
          ->storage_key();
  for (auto& client : web_context_registrations_) {
    url::Origin client_storage_key =
        client->environment_settings()->ObtainStorageKey();
    if (client_storage_key.IsSameOriginWith(storage_key)) {
      // 2.1.1. If client’s id is not id, continue.
      if (client->environment_settings()->id() != id) continue;

      // 2.1.2. Wait for either client’s execution ready flag to be set or for
      //        client’s discarded flag to be set.
      // Web Contexts exist only in the web_context_registrations_ set when they
      // are both execution ready and not discarded.

      // 2.1.3. If client’s execution ready flag is set, then invoke Resolve Get
      //        Client Promise with client and promise, and abort these steps.
      ResolveGetClientPromise(client, worker_context,
                              std::move(promise_reference));
      return;
    }
  }
  // 2.2. Resolve promise with undefined.
  worker_context->message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(
          [](std::unique_ptr<script::ValuePromiseWrappable::Reference>
                 promise_reference) {
            TRACE_EVENT0("cobalt::worker",
                         "ServiceWorkerContext::ClientsGetSubSteps() Resolve");
            promise_reference->value().Resolve(scoped_refptr<Client>());
          },
          std::move(promise_reference)));
}

void ServiceWorkerContext::ClientsMatchAllSubSteps(
    web::Context* worker_context,
    ServiceWorkerObject* associated_service_worker,
    std::unique_ptr<script::ValuePromiseSequenceWrappable::Reference>
        promise_reference,
    bool include_uncontrolled, ClientType type) {
  TRACE_EVENT0("cobalt::worker",
               "ServiceWorkerContext::ClientsMatchAllSubSteps()");
  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  // Check if the worker web context is still active. This may trigger if
  // Clients.matchAll() was called and service worker installation fails.
  if (!IsWebContextRegistered(worker_context)) {
    promise_reference.release();
    return;
  }

  // Parallel sub steps (2) for algorithm for Clients.matchAll():
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#clients-matchall
  // 2.1. Let targetClients be a new list.
  std::list<web::Context*> target_clients;

  // 2.2. For each service worker client client where the result of running
  //      obtain a storage key given client equals the associated service
  //      worker's containing service worker registration's storage key:
  const url::Origin& storage_key =
      associated_service_worker->containing_service_worker_registration()
          ->storage_key();
  for (auto& client : web_context_registrations_) {
    url::Origin client_storage_key =
        client->environment_settings()->ObtainStorageKey();
    if (client_storage_key.IsSameOriginWith(storage_key)) {
      // 2.2.1. If client’s execution ready flag is unset or client’s discarded
      //        flag is set, continue.
      // Web Contexts exist only in the web_context_registrations_ set when they
      // are both execution ready and not discarded.

      // 2.2.2. If client is not a secure context, continue.
      // In production, Cobalt requires https, therefore all workers and their
      // owners are secure contexts.

      // 2.2.3. If options["includeUncontrolled"] is false, and if client’s
      //        active service worker is not the associated service worker,
      //        continue.
      if (!include_uncontrolled &&
          (client->active_service_worker() != associated_service_worker)) {
        continue;
      }

      // 2.2.4. Add client to targetClients.
      target_clients.push_back(client);
    }
  }

  // 2.3. Let matchedWindowData be a new list.
  std::unique_ptr<std::vector<WindowData>> matched_window_data(
      new std::vector<WindowData>);

  // 2.4. Let matchedClients be a new list.
  std::unique_ptr<std::vector<web::Context*>> matched_clients(
      new std::vector<web::Context*>);

  // 2.5. For each service worker client client in targetClients:
  for (auto* client : target_clients) {
    auto* global_scope = client->GetWindowOrWorkerGlobalScope();

    if ((type == kClientTypeWindow || type == kClientTypeAll) &&
        (global_scope->IsWindow())) {
      // 2.5.1. If options["type"] is "window" or "all", and client is not an
      //        environment settings object or is a window client, then:

      // 2.5.1.1. Let windowData be [ "client" -> client, "ancestorOriginsList"
      //          -> a new list ].
      WindowData window_data(client->environment_settings());

      // 2.5.1.2. Let browsingContext be null.

      // 2.5.1.3. Let isClientEnumerable be true.
      // For Cobalt, isClientEnumerable is always true because the clauses that
      // would set it to false in 2.5.1.6. do not apply to Cobalt.

      // 2.5.1.4. If client is an environment settings object, set
      //          browsingContext to client’s global object's browsing context.
      // 2.5.1.5. Else, set browsingContext to client’s target browsing context.
      web::Context* browsing_context = client;

      // 2.5.1.6. Queue a task task to run the following substeps on
      //          browsingContext’s event loop using the user interaction task
      //          source:
      // Note: The task below does not currently perform any actual
      // functionality. It is included however to help future implementation for
      // fetching values for WindowClient properties, with similar logic
      // existing in ResolveGetClientPromise.
      browsing_context->message_loop()->task_runner()->PostBlockingTask(
          FROM_HERE, base::Bind(
                         [](WindowData* window_data) {
                           // 2.5.1.6.1. If browsingContext has been discarded,
                           //            then set isClientEnumerable to false
                           //            and abort these steps.
                           // 2.5.1.6.2. If client is a window client and
                           //            client’s responsible document is not
                           //            browsingContext’s active document, then
                           //            set isClientEnumerable to false and
                           //            abort these steps.
                           // In Cobalt, the document of a window browsing
                           // context doesn't change: When a new document is
                           // created, a new browsing context is created with
                           // it.

                           // 2.5.1.6.3. Set windowData["frameType"] to the
                           //            result of running Get Frame Type with
                           //            browsingContext.
                           // Cobalt does not support nested or auxiliary
                           // browsing contexts.
                           // 2.5.1.6.4. Set windowData["visibilityState"] to
                           //            browsingContext’s active document's
                           //            visibilityState attribute value.
                           // 2.5.1.6.5. Set windowData["focusState"] to the
                           //            result of running the has focus steps
                           //            with browsingContext’s active document
                           //            as the argument.

                           // 2.5.1.6.6. If client is a window client, then set
                           //            windowData["ancestorOriginsList"] to
                           //            browsingContext’s active document's
                           //            relevant global object's Location
                           //            object’s ancestor origins list's
                           //            associated list.
                           // Cobalt does not implement
                           // Location.ancestorOrigins.
                         },
                         &window_data));

      // 2.5.1.7. Wait for task to have executed.
      // The task above is posted as a blocking task.

      // 2.5.1.8. If isClientEnumerable is true, then:

      // 2.5.1.8.1. Add windowData to matchedWindowData.
      matched_window_data->emplace_back(window_data);

      // 2.5.2. Else if options["type"] is "worker" or "all" and client is a
      //        dedicated worker client, or options["type"] is "sharedworker" or
      //        "all" and client is a shared worker client, then:
    } else if (((type == kClientTypeWorker || type == kClientTypeAll) &&
                global_scope->IsDedicatedWorker())) {
      // Note: Cobalt does not support shared workers.
      // 2.5.2.1. Add client to matchedClients.
      matched_clients->emplace_back(client);
    }
  }

  // 2.6. Queue a task to run the following steps on promise’s relevant
  // settings object's responsible event loop using the DOM manipulation
  // task source:
  worker_context->message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(
          [](std::unique_ptr<script::ValuePromiseSequenceWrappable::Reference>
                 promise_reference,
             std::unique_ptr<std::vector<WindowData>> matched_window_data,
             std::unique_ptr<std::vector<web::Context*>> matched_clients) {
            TRACE_EVENT0("cobalt::worker",
                         "ServiceWorkerContext::ClientsMatchAllSubSteps() "
                         "Resolve Promise");
            // 2.6.1. Let clientObjects be a new list.
            script::Sequence<scoped_refptr<script::Wrappable>> client_objects;

            // 2.6.2. For each windowData in matchedWindowData:
            for (auto& window_data : *matched_window_data) {
              // 2.6.2.1. Let WindowClient be the result of running
              //          Create Window Client algorithm with
              //          windowData["client"],
              //          windowData["frameType"],
              //          windowData["visibilityState"],
              //          windowData["focusState"], and
              //          windowData["ancestorOriginsList"] as the
              //          arguments.
              // TODO(b/235838698): Implement WindowClient methods.
              scoped_refptr<Client> window_client =
                  WindowClient::Create(window_data);

              // 2.6.2.2. Append WindowClient to clientObjects.
              client_objects.push_back(window_client);
            }

            // 2.6.3. For each client in matchedClients:
            for (auto& client : *matched_clients) {
              // 2.6.3.1. Let clientObject be the result of running
              //          Create Client algorithm with client as the
              //          argument.
              scoped_refptr<Client> client_object =
                  Client::Create(client->environment_settings());

              // 2.6.3.2. Append clientObject to clientObjects.
              client_objects.push_back(client_object);
            }
            // 2.6.4. Sort clientObjects such that:
            //        . WindowClient objects whose browsing context has been
            //          focused are placed first, sorted in the most recently
            //          focused order.
            //        . WindowClient objects whose browsing context has never
            //          been focused are placed next, sorted in their service
            //          worker client's creation order.
            //        . Client objects whose associated service worker client is
            //          a worker client are placed next, sorted in their service
            //          worker client's creation order.
            // TODO(b/235876598): Implement sorting of clientObjects.

            // 2.6.5. Resolve promise with a new frozen array of clientObjects
            //        in promise’s relevant Realm.
            promise_reference->value().Resolve(client_objects);
          },
          std::move(promise_reference), std::move(matched_window_data),
          std::move(matched_clients)));
}

void ServiceWorkerContext::ClaimSubSteps(
    web::Context* worker_context,
    ServiceWorkerObject* associated_service_worker,
    std::unique_ptr<script::ValuePromiseVoid::Reference> promise_reference) {
  TRACE_EVENT0("cobalt::worker", "ServiceWorkerContext::ClaimSubSteps()");
  DCHECK_EQ(message_loop(), base::MessageLoop::current());

  // Check if the client web context is still active. This may trigger if
  // Clients.claim() was called and service worker installation fails.
  if (!IsWebContextRegistered(worker_context)) {
    promise_reference.release();
    return;
  }

  // Parallel sub steps (3) for algorithm for Clients.claim():
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#dom-clients-claim
  std::list<web::Context*> target_clients;

  // 3.1. For each service worker client client where the result of running
  //      obtain a storage key given client equals the service worker's
  //      containing service worker registration's storage key:
  const url::Origin& storage_key =
      associated_service_worker->containing_service_worker_registration()
          ->storage_key();
  for (auto& client : web_context_registrations_) {
    // Don't claim to be our own service worker.
    if (client == worker_context) continue;
    url::Origin client_storage_key =
        client->environment_settings()->ObtainStorageKey();
    if (client_storage_key.IsSameOriginWith(storage_key)) {
      // 3.1.1. If client’s execution ready flag is unset or client’s discarded
      //        flag is set, continue.
      // Web Contexts exist only in the web_context_registrations_ set when they
      // are both execution ready and not discarded.

      // 3.1.2. If client is not a secure context, continue.
      // In production, Cobalt requires https, therefore all clients are secure
      // contexts.

      // 3.1.3. Let storage key be the result of running obtain a storage key
      //        given client.
      // 3.1.4. Let registration be the result of running Match Service Worker
      //        Registration given storage key and client’s creation URL.
      // TODO(b/234659851): Investigate whether this should use the creation
      // URL directly instead.
      const GURL& base_url = client->environment_settings()->creation_url();
      GURL client_url = base_url.Resolve("");
      scoped_refptr<ServiceWorkerRegistrationObject> registration =
          scope_to_registration_map_->MatchServiceWorkerRegistration(
              client_storage_key, client_url);

      // 3.1.5. If registration is not the service worker's containing service
      //        worker registration, continue.
      if (registration !=
          associated_service_worker->containing_service_worker_registration()) {
        continue;
      }

      // 3.1.6. If client’s active service worker is not the service worker,
      //        then:
      if (client->active_service_worker() != associated_service_worker) {
        // 3.1.6.1. Invoke Handle Service Worker Client Unload with client as
        //          the argument.
        HandleServiceWorkerClientUnload(client);

        // 3.1.6.2. Set client’s active service worker to service worker.
        client->set_active_service_worker(associated_service_worker);

        // 3.1.6.3. Invoke Notify Controller Change algorithm with client as the
        //          argument.
        NotifyControllerChange(client);
      }
    }
  }
  // 3.2. Resolve promise with undefined.
  worker_context->message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(
          [](std::unique_ptr<script::ValuePromiseVoid::Reference> promise) {
            promise->value().Resolve();
          },
          std::move(promise_reference)));
}

void ServiceWorkerContext::ServiceWorkerPostMessageSubSteps(
    ServiceWorkerObject* service_worker, web::Context* incumbent_client,
    std::unique_ptr<script::StructuredClone> structured_clone) {
  // Parallel sub steps (6) for algorithm for ServiceWorker.postMessage():
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#service-worker-postmessage-options
  // 3. Let incumbentGlobal be incumbentSettings’s global object.
  // Note: The 'incumbent' is the sender of the message.
  // 6.1 If the result of running the Run Service Worker algorithm with
  //     serviceWorker is failure, then return.
  auto* run_result = RunServiceWorker(service_worker);
  if (!run_result) return;
  if (!structured_clone || structured_clone->failed()) return;

  // 6.2 Queue a task on the DOM manipulation task source to run the following
  //     steps:
  incumbent_client->message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(
          [](ServiceWorkerObject* service_worker,
             web::Context* incumbent_client,
             std::unique_ptr<script::StructuredClone> structured_clone) {
            web::EventTarget* event_target =
                service_worker->worker_global_scope();
            if (!event_target) return;

            web::WindowOrWorkerGlobalScope* incumbent_global =
                incumbent_client->GetWindowOrWorkerGlobalScope();
            DCHECK_EQ(incumbent_client->environment_settings(),
                      incumbent_global->environment_settings());
            base::TypeId incumbent_type = incumbent_global->GetWrappableType();
            ServiceWorkerObject* incumbent_worker =
                incumbent_global->IsServiceWorker()
                    ? incumbent_global->AsServiceWorker()
                          ->service_worker_object()
                    : nullptr;
            base::MessageLoop* message_loop =
                event_target->environment_settings()->context()->message_loop();
            if (!message_loop) {
              return;
            }
            message_loop->task_runner()->PostTask(
                FROM_HERE,
                base::BindOnce(
                    [](const base::TypeId& incumbent_type,
                       ServiceWorkerObject* incumbent_worker,
                       web::Context* incumbent_client,
                       web::EventTarget* event_target,
                       std::unique_ptr<script::StructuredClone>
                           structured_clone) {
                      ExtendableMessageEventInit init_dict;
                      if (incumbent_type ==
                          base::GetTypeId<ServiceWorkerGlobalScope>()) {
                        // 6.2.1. Let source be determined by switching on the
                        //        type of incumbentGlobal:
                        //        . ServiceWorkerGlobalScope
                        //          The result of getting the service worker
                        //          object that represents incumbentGlobal’s
                        //          service worker in the relevant settings
                        //          object of serviceWorker’s global object.
                        init_dict.set_source(ExtendableMessageEvent::SourceType(
                            event_target->environment_settings()
                                ->context()
                                ->GetServiceWorker(incumbent_worker)));
                      } else if (incumbent_type ==
                                 base::GetTypeId<dom::Window>()) {
                        //        . Window
                        //          a new WindowClient object that represents
                        //          incumbentGlobal’s relevant settings object.
                        init_dict.set_source(ExtendableMessageEvent::SourceType(
                            WindowClient::Create(WindowData(
                                incumbent_client->environment_settings()))));
                      } else {
                        //        . Otherwise
                        //          a new Client object that represents
                        //          incumbentGlobal’s associated worker
                        init_dict.set_source(
                            ExtendableMessageEvent::SourceType(Client::Create(
                                incumbent_client->environment_settings())));
                      }

                      event_target->DispatchEvent(
                          new worker::ExtendableMessageEvent(
                              event_target->environment_settings(),
                              base::Tokens::message(), init_dict,
                              std::move(structured_clone)));
                    },
                    incumbent_type, base::Unretained(incumbent_worker),
                    // Note: These should probably be weak pointers for when
                    // the message sender disappears before the recipient
                    // processes the event, but since base::WeakPtr
                    // dereferencing isn't thread-safe, that can't actually be
                    // used here.
                    base::Unretained(incumbent_client),
                    base::Unretained(event_target),
                    std::move(structured_clone)));
          },
          base::Unretained(service_worker), base::Unretained(incumbent_client),
          std::move(structured_clone)));
}

void ServiceWorkerContext::RegisterWebContext(web::Context* context) {
  DCHECK_NE(nullptr, context);
  web_context_registrations_cleared_.Reset();
  if (base::MessageLoop::current() != message_loop()) {
    DCHECK(message_loop());
    message_loop()->task_runner()->PostTask(
        FROM_HERE, base::BindOnce(&ServiceWorkerContext::RegisterWebContext,
                                  base::Unretained(this), context));
    return;
  }
  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  DCHECK_EQ(0, web_context_registrations_.count(context));
  web_context_registrations_.insert(context);
}

void ServiceWorkerContext::SetActiveWorker(web::EnvironmentSettings* client) {
  if (!client) return;
  if (base::MessageLoop::current() != message_loop()) {
    DCHECK(message_loop());
    message_loop()->task_runner()->PostTask(
        FROM_HERE, base::Bind(&ServiceWorkerContext::SetActiveWorker,
                              base::Unretained(this), client));
    return;
  }
  DCHECK(scope_to_registration_map_);
  scoped_refptr<ServiceWorkerRegistrationObject> client_registration =
      scope_to_registration_map_->MatchServiceWorkerRegistration(
          client->ObtainStorageKey(), client->creation_url());
  if (client_registration.get() && client_registration->active_worker()) {
    client->context()->set_active_service_worker(
        client_registration->active_worker());
  } else {
    client->context()->set_active_service_worker(nullptr);
  }
}

void ServiceWorkerContext::UnregisterWebContext(web::Context* context) {
  DCHECK_NE(nullptr, context);
  if (base::MessageLoop::current() != message_loop()) {
    // Block to ensure that the context is unregistered before it is destroyed.
    DCHECK(message_loop());
    message_loop()->task_runner()->PostBlockingTask(
        FROM_HERE, base::Bind(&ServiceWorkerContext::UnregisterWebContext,
                              base::Unretained(this), context));
    return;
  }
  DCHECK_EQ(message_loop(), base::MessageLoop::current());
  DCHECK_EQ(1, web_context_registrations_.count(context));
  web_context_registrations_.erase(context);
  HandleServiceWorkerClientUnload(context);
  PrepareForClientShutdown(context);
  if (web_context_registrations_.empty()) {
    web_context_registrations_cleared_.Signal();
  }
}

void ServiceWorkerContext::PrepareForClientShutdown(web::Context* client) {
  DCHECK(client);
  if (!client) return;
  DCHECK(base::MessageLoop::current() == message_loop());
  // Note: This could be rewritten to use the decomposition declaration
  // 'const auto& [scope, queue]' after switching to C++17.
  jobs_->PrepareForClientShutdown(client);
}

}  // namespace worker
}  // namespace cobalt
