/*
 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
 * Copyright (C) 2009, 2011 Google Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "third_party/blink/renderer/core/workers/worker_global_scope.h"

#include "base/memory/scoped_refptr.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/metrics/public/cpp/mojo_ukm_recorder.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/browser_interface_broker.mojom-blink.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_void_function.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
#include "third_party/blink/renderer/core/css/font_face_set_worker.h"
#include "third_party/blink/renderer/core/css/offscreen_font_selector.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/events/error_event.h"
#include "third_party/blink/renderer/core/events/message_event.h"
#include "third_party/blink/renderer/core/execution_context/agent.h"
#include "third_party/blink/renderer/core/frame/dom_timer_coordinator.h"
#include "third_party/blink/renderer/core/frame/user_activation.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/inspector/console_message_storage.h"
#include "third_party/blink/renderer/core/inspector/inspector_issue_storage.h"
#include "third_party/blink/renderer/core/inspector/worker_inspector_controller.h"
#include "third_party/blink/renderer/core/inspector/worker_thread_debugger.h"
#include "third_party/blink/renderer/core/loader/threadable_loader.h"
#include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/script/classic_script.h"
#include "third_party/blink/renderer/core/trustedtypes/trusted_script_url.h"
#include "third_party/blink/renderer/core/trustedtypes/trusted_type_policy_factory.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
#include "third_party/blink/renderer/core/workers/installed_scripts_manager.h"
#include "third_party/blink/renderer/core/workers/worker_classic_script_loader.h"
#include "third_party/blink/renderer/core/workers/worker_location.h"
#include "third_party/blink/renderer/core/workers/worker_navigator.h"
#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/microtask.h"
#include "third_party/blink/renderer/platform/fonts/font_matching_metrics.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/instrumentation/instance_counters.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h"
#include "third_party/blink/renderer/platform/network/content_security_policy_parsers.h"
#include "third_party/blink/renderer/platform/scheduler/public/event_loop.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"

namespace blink {
namespace {

void RemoveURLFromMemoryCacheInternal(const KURL& url) {
  GetMemoryCache()->RemoveURLFromCache(url);
}

scoped_refptr<SecurityOrigin> CreateSecurityOrigin(
    GlobalScopeCreationParams* creation_params,
    ExecutionContext* execution_context) {
  // A worker environment settings object's origin must be set as follows:
  //
  // - DedicatedWorkers and SharedWorkers
  // https://html.spec.whatwg.org/C/#set-up-a-worker-environment-settings-object
  // Step 2: Let inherited origin be outside settings's origin.
  // Step 6: Let settings object be a new environment settings object whose
  // algorithms are defined as follows:
  // The origin -> Return a unique opaque origin if worker global scope's url's
  // scheme is "data", and inherited origin otherwise. [spec text]
  //
  // - ServiceWorkers
  // https://w3c.github.io/ServiceWorker/#run-service-worker-algorithm
  // Step 7.4: Let settingsObject be a new environment settings object whose
  // algorithms are defined as follows:
  // The origin -> Return its registering service worker client's origin.
  // [spec text]
  //
  // The algorithm in ServiceWorkers differ from DedicatedWorkers and
  // SharedWorkers when worker global scope's url's scheme is "data", but
  // "data" url script is not allowed for ServiceWorkers, so all workers' origin
  // can be calculated in the same way.
  // https://w3c.github.io/ServiceWorker/#start-register
  // Step 3: If scriptURL’s scheme is not one of "http" and "https", reject
  // promise with a TypeError and abort these steps. [spec text]
  DCHECK(!execution_context->IsServiceWorkerGlobalScope() ||
         !KURL(creation_params->script_url).ProtocolIsData());

  // TODO(https://crbug.com/1058305) Inherit |agent_cluster_id_| for dedicated
  // workers. DO NOT inherit for shared workers and service workers.
  //
  // Create a new SecurityOrigin via CreateFromUrlOrigin() so that worker's
  // origin can avoid inheriting unnecessary capabilities from the starter
  // origin, while the worker's origin inherits url:Origin's internal nonce.
  scoped_refptr<SecurityOrigin> security_origin;
  if (KURL(creation_params->script_url).ProtocolIsData()) {
    security_origin = SecurityOrigin::CreateUniqueOpaque();
  } else {
    security_origin = SecurityOrigin::CreateFromUrlOrigin(
        creation_params->starter_origin->ToUrlOrigin());
  }

  if (creation_params->starter_origin) {
    security_origin->TransferPrivilegesFrom(
        creation_params->starter_origin->CreatePrivilegeData());
  }
  return security_origin;
}

}  // namespace

FontFaceSet* WorkerGlobalScope::fonts() {
  return FontFaceSetWorker::From(*this);
}

WorkerGlobalScope::~WorkerGlobalScope() {
  if (font_matching_metrics_)
    font_matching_metrics_->PublishAllMetrics();
  DCHECK(!ScriptController());
  InstanceCounters::DecrementCounter(
      InstanceCounters::kWorkerGlobalScopeCounter);
}

NOINLINE const KURL& WorkerGlobalScope::Url() const {
  CHECK(url_.IsValid());
  return url_;
}

KURL WorkerGlobalScope::CompleteURL(const String& url) const {
  // Always return a null URL when passed a null string.
  // FIXME: Should we change the KURL constructor to have this behavior?
  if (url.IsNull())
    return KURL();
  // Always use UTF-8 in Workers.
  return KURL(BaseURL(), url);
}

const KURL& WorkerGlobalScope::BaseURL() const {
  return Url();
}

scheduler::WorkerScheduler* WorkerGlobalScope::GetScheduler() {
  DCHECK(IsContextThread());
  return GetThread()->GetScheduler();
}

void WorkerGlobalScope::Dispose() {
  DCHECK(IsContextThread());
  closing_ = true;
  WorkerOrWorkletGlobalScope::Dispose();
}

const base::UnguessableToken& WorkerGlobalScope::GetDevToolsToken() const {
  return GetThread()->GetDevToolsWorkerToken();
}

void WorkerGlobalScope::ExceptionUnhandled(int exception_id) {
  ErrorEvent* event = pending_error_events_.Take(exception_id);
  DCHECK(event);
  if (WorkerThreadDebugger* debugger =
          WorkerThreadDebugger::From(GetThread()->GetIsolate()))
    debugger->ExceptionThrown(thread_, event);
}

WorkerLocation* WorkerGlobalScope::location() const {
  if (!location_)
    location_ = MakeGarbageCollected<WorkerLocation>(Url());
  return location_.Get();
}

WorkerNavigator* WorkerGlobalScope::navigator() const {
  if (!navigator_)
    navigator_ = MakeGarbageCollected<WorkerNavigator>(GetExecutionContext());
  return navigator_.Get();
}

void WorkerGlobalScope::close() {
  // Let current script run to completion, but tell the worker micro task
  // runner to tear down the thread after this task.
  closing_ = true;
}

String WorkerGlobalScope::origin() const {
  return GetSecurityOrigin()->ToString();
}

void WorkerGlobalScope::importScripts(const Vector<String>& urls) {
  ImportScriptsInternal(urls);
}

namespace {

String NetworkErrorMessageAtImportScript(const char* const property_name,
                                         const char* const interface_name,
                                         const KURL& url) {
  return ExceptionMessages::FailedToExecute(
      property_name, interface_name,
      "The script at '" + url.ElidedString() + "' failed to load.");
}

}  // namespace

// Implementation of the "import scripts into worker global scope" algorithm:
// https://html.spec.whatwg.org/C/#import-scripts-into-worker-global-scope
void WorkerGlobalScope::ImportScriptsInternal(const Vector<String>& urls) {
  DCHECK(GetContentSecurityPolicy());
  DCHECK(GetExecutionContext());
  v8::Isolate* isolate = GetThread()->GetIsolate();

  // Previously, exceptions here were thrown via ExceptionState but now are
  // thrown via V8ThrowException. To keep the existing error messages,
  // ExceptionMessages::FailedToExecute() is called directly (crbug/1114610).
  const char* const property_name = "importScripts";
  const char* const interface_name = "WorkerGlobalScope";

  // Step 1: "If worker global scope's type is "module", throw a TypeError
  // exception."
  if (script_type_ == mojom::blink::ScriptType::kModule) {
    V8ThrowException::ThrowTypeError(
        isolate, ExceptionMessages::FailedToExecute(
                     property_name, interface_name,
                     "Module scripts don't support importScripts()."));
    return;
  }

  // Step 2: "Let settings object be the current settings object."
  // |this| roughly corresponds to the current settings object.

  // Step 3: "If urls is empty, return."
  if (urls.IsEmpty())
    return;

  // Step 4: "Parse each value in urls relative to settings object. If any fail,
  // throw a "SyntaxError" DOMException."
  Vector<KURL> completed_urls;
  for (const String& url_string : urls) {
    const KURL& url = CompleteURL(url_string);
    if (!url.IsValid()) {
      V8ThrowException::ThrowException(
          isolate, V8ThrowDOMException::CreateOrEmpty(
                       isolate, DOMExceptionCode::kSyntaxError,
                       ExceptionMessages::FailedToExecute(
                           property_name, interface_name,
                           "The URL '" + url_string + "' is invalid.")));
      return;
    }
    if (!GetContentSecurityPolicy()->AllowScriptFromSource(
            url, AtomicString(), IntegrityMetadataSet(), kNotParserInserted,
            url, RedirectStatus::kNoRedirect)) {
      V8ThrowException::ThrowException(
          isolate, V8ThrowDOMException::CreateOrEmpty(
                       isolate, DOMExceptionCode::kNetworkError,
                       NetworkErrorMessageAtImportScript(property_name,
                                                         interface_name, url)));
      return;
    }
    completed_urls.push_back(url);
  }

  // Step 5: "For each url in the resulting URL records, run these substeps:"
  for (const KURL& complete_url : completed_urls) {
    KURL response_url;
    String source_code;
    std::unique_ptr<Vector<uint8_t>> cached_meta_data;
    const String error_message = NetworkErrorMessageAtImportScript(
        property_name, interface_name, complete_url);

    // Step 5.1: "Fetch a classic worker-imported script given url and settings
    // object, passing along any custom perform the fetch steps provided. If
    // this succeeds, let script be the result. Otherwise, rethrow the
    // exception."
    if (!FetchClassicImportedScript(complete_url, &response_url, &source_code,
                                    &cached_meta_data)) {
      // TODO(vogelheim): In case of certain types of failure - e.g. 'nosniff'
      // block - this ought to be a DOMExceptionCode::kSecurityError, but that
      // information presently gets lost on the way.
      V8ThrowException::ThrowException(
          isolate,
          V8ThrowDOMException::CreateOrEmpty(
              isolate, DOMExceptionCode::kNetworkError, error_message));
      return;
    }

    // importScripts always uses "no-cors", so simply checking the origin is
    // enough.
    // TODO(yhirano): Remove this ad-hoc logic and use the response type.
    const SanitizeScriptErrors sanitize_script_errors =
        GetSecurityOrigin()->CanReadContent(response_url)
            ? SanitizeScriptErrors::kDoNotSanitize
            : SanitizeScriptErrors::kSanitize;

    const KURL script_url =
        ScriptSourceCode::UsePostRedirectURL() ? response_url : complete_url;

    // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-classic-worker-imported-script
    // Step 7: Let script be the result of creating a classic script given
    // source text, settings object, response's url, the default classic script
    // fetch options, and muted errors.
    // TODO(crbug.com/1082086): Fix the base URL.
    SingleCachedMetadataHandler* handler(
        CreateWorkerScriptCachedMetadataHandler(complete_url,
                                                std::move(cached_meta_data)));
    ClassicScript* script = MakeGarbageCollected<ClassicScript>(
        ScriptSourceCode(source_code, ScriptSourceLocationType::kUnknown,
                         handler, script_url),
        script_url /* base_url */, ScriptFetchOptions(),
        sanitize_script_errors);

    // Step 5.2: "Run the classic script script, with the rethrow errors
    // argument set to true."
    ReportingProxy().WillEvaluateImportedClassicScript(
        source_code.length(), handler ? handler->GetCodeCacheSize() : 0);
    v8::HandleScope scope(isolate);
    ScriptEvaluationResult result =
        script->RunScriptOnScriptStateAndReturnValue(
            ScriptController()->GetScriptState(),
            ExecuteScriptPolicy::kDoNotExecuteScriptWhenScriptsDisabled,
            V8ScriptRunner::RethrowErrorsOption::Rethrow(error_message));

    // Step 5.2: "If an exception was thrown or if the script was prematurely
    // aborted, then abort all these steps, letting the exception or aborting
    // continue to be processed by the calling script."
    if (result.GetResultType() != ScriptEvaluationResult::ResultType::kSuccess)
      return;
  }
}

// Implementation of the "fetch a classic worker-imported script" algorithm.
// https://html.spec.whatwg.org/C/#fetch-a-classic-worker-imported-script
bool WorkerGlobalScope::FetchClassicImportedScript(
    const KURL& script_url,
    KURL* out_response_url,
    String* out_source_code,
    std::unique_ptr<Vector<uint8_t>>* out_cached_meta_data) {
  ExecutionContext* execution_context = GetExecutionContext();
  WorkerClassicScriptLoader* classic_script_loader =
      MakeGarbageCollected<WorkerClassicScriptLoader>();
  EnsureFetcher();
  classic_script_loader->LoadSynchronously(
      *execution_context, Fetcher(), script_url,
      mojom::blink::RequestContextType::SCRIPT,
      network::mojom::RequestDestination::kScript);
  if (classic_script_loader->Failed())
    return false;
  *out_response_url = classic_script_loader->ResponseURL();
  *out_source_code = classic_script_loader->SourceText();
  *out_cached_meta_data = classic_script_loader->ReleaseCachedMetadata();
  probe::ScriptImported(execution_context, classic_script_loader->Identifier(),
                        classic_script_loader->SourceText());
  return true;
}

bool WorkerGlobalScope::IsContextThread() const {
  return GetThread()->IsCurrentThread();
}

void WorkerGlobalScope::AddConsoleMessageImpl(ConsoleMessage* console_message,
                                              bool discard_duplicates) {
  DCHECK(IsContextThread());
  ReportingProxy().ReportConsoleMessage(
      console_message->Source(), console_message->Level(),
      console_message->Message(), console_message->Location());
  GetThread()->GetConsoleMessageStorage()->AddConsoleMessage(
      this, console_message, discard_duplicates);
}

void WorkerGlobalScope::AddInspectorIssue(
    mojom::blink::InspectorIssueInfoPtr info) {
  GetThread()->GetInspectorIssueStorage()->AddInspectorIssue(this,
                                                             std::move(info));
}

CoreProbeSink* WorkerGlobalScope::GetProbeSink() {
  if (IsClosing())
    return nullptr;
  if (WorkerInspectorController* controller =
          GetThread()->GetWorkerInspectorController())
    return controller->GetProbeSink();
  return nullptr;
}

const BrowserInterfaceBrokerProxy&
WorkerGlobalScope::GetBrowserInterfaceBroker() const {
  return browser_interface_broker_proxy_;
}

ExecutionContext* WorkerGlobalScope::GetExecutionContext() const {
  return const_cast<WorkerGlobalScope*>(this);
}

void WorkerGlobalScope::EvaluateClassicScript(
    const KURL& script_url,
    String source_code,
    std::unique_ptr<Vector<uint8_t>> cached_meta_data,
    const v8_inspector::V8StackTraceId& stack_id) {
  DCHECK(!IsContextPaused());

  SingleCachedMetadataHandler* handler =
      CreateWorkerScriptCachedMetadataHandler(script_url,
                                              std::move(cached_meta_data));
  // Cross-origin workers are disallowed, so use
  // SanitizeScriptErrors::kDoNotSanitize.
  Script* worker_script = MakeGarbageCollected<ClassicScript>(
      ScriptSourceCode(source_code, handler, script_url), script_url,
      ScriptFetchOptions(), SanitizeScriptErrors::kDoNotSanitize);
  WorkerScriptFetchFinished(*worker_script, stack_id);
}

void WorkerGlobalScope::WorkerScriptFetchFinished(
    Script& worker_script,
    base::Optional<v8_inspector::V8StackTraceId> stack_id) {
  DCHECK(IsContextThread());

  DCHECK_NE(ScriptEvalState::kEvaluated, script_eval_state_);
  DCHECK(!worker_script_);
  worker_script_ = worker_script;
  stack_id_ = stack_id;

  // Proceed to RunWorkerScript() once WorkerScriptFetchFinished() is called and
  // |script_eval_state_| becomes kReadyToEvaluate.
  if (script_eval_state_ == ScriptEvalState::kReadyToEvaluate)
    RunWorkerScript();
}

void WorkerGlobalScope::ReadyToRunWorkerScript() {
  DCHECK(IsContextThread());

  DCHECK_EQ(ScriptEvalState::kPauseAfterFetch, script_eval_state_);
  script_eval_state_ = ScriptEvalState::kReadyToEvaluate;

  // Proceed to RunWorkerScript() once WorkerScriptFetchFinished() is called and
  // |script_eval_state_| becomes kReadyToEvaluate.
  if (worker_script_)
    RunWorkerScript();
}

// https://html.spec.whatwg.org/C/#run-a-worker
void WorkerGlobalScope::RunWorkerScript() {
  DCHECK(IsContextThread());
  DCHECK(!IsContextPaused());
  CHECK(GetExecutionContext()) << "crbug.com/1045818: attempted to evaluate "
                                  "script but no execution context";
  CHECK(!GetExecutionContext()->IsContextDestroyed())
      << "crbug.com/1045818: attempted to evaluate script but worker global "
         "scope was already destroyed";

  DCHECK(worker_script_);
  DCHECK_EQ(script_eval_state_, ScriptEvalState::kReadyToEvaluate);

  WorkerThreadDebugger* debugger =
      WorkerThreadDebugger::From(GetThread()->GetIsolate());
  if (debugger && stack_id_)
    debugger->ExternalAsyncTaskStarted(*stack_id_);

  switch (worker_script_->GetScriptType()) {
    case mojom::blink::ScriptType::kClassic: {
      auto sizes = worker_script_->GetClassicScriptSizes();
      ReportingProxy().WillEvaluateClassicScript(sizes.first, sizes.second);
      break;
    }
    case mojom::blink::ScriptType::kModule:
      ReportingProxy().WillEvaluateModuleScript();
      break;
  }

  // Step 24. If script is a classic script, then run the classic script script.
  // Otherwise, it is a module script; run the module script script. [spec text]
  bool is_success =
      std::move(worker_script_)->RunScriptOnWorkerOrWorklet(*this);

  ReportingProxy().DidEvaluateTopLevelScript(is_success);

  if (debugger && stack_id_)
    debugger->ExternalAsyncTaskFinished(*stack_id_);

  script_eval_state_ = ScriptEvalState::kEvaluated;
}

void WorkerGlobalScope::ReceiveMessage(BlinkTransferableMessage message) {
  DCHECK(!IsContextPaused());
  MessagePortArray* ports =
      MessagePort::EntanglePorts(*this, std::move(message.ports));
  WorkerThreadDebugger* debugger =
      WorkerThreadDebugger::From(GetThread()->GetIsolate());
  if (debugger)
    debugger->ExternalAsyncTaskStarted(message.sender_stack_trace_id);
  UserActivation* user_activation = nullptr;
  if (message.user_activation) {
    user_activation = MakeGarbageCollected<UserActivation>(
        message.user_activation->has_been_active,
        message.user_activation->was_active);
  }
  DispatchEvent(*MessageEvent::Create(ports, std::move(message.message),
                                      user_activation));
  if (debugger)
    debugger->ExternalAsyncTaskFinished(message.sender_stack_trace_id);
}

WorkerGlobalScope::WorkerGlobalScope(
    std::unique_ptr<GlobalScopeCreationParams> creation_params,
    WorkerThread* thread,
    base::TimeTicks time_origin)
    : WorkerOrWorkletGlobalScope(
          thread->GetIsolate(),
          CreateSecurityOrigin(creation_params.get(), GetExecutionContext()),
          MakeGarbageCollected<Agent>(
              thread->GetIsolate(),
              (creation_params->agent_cluster_id.is_empty()
                   ? base::UnguessableToken::Create()
                   : creation_params->agent_cluster_id)),
          creation_params->global_scope_name,
          creation_params->parent_devtools_token,
          creation_params->v8_cache_options,
          creation_params->worker_clients,
          std::move(creation_params->content_settings_client),
          std::move(creation_params->web_worker_fetch_context),
          thread->GetWorkerReportingProxy()),
      script_type_(creation_params->script_type),
      user_agent_(creation_params->user_agent),
      ua_metadata_(creation_params->ua_metadata),
      thread_(thread),
      agent_group_scheduler_compositor_task_runner_(std::move(
          creation_params->agent_group_scheduler_compositor_task_runner)),
      time_origin_(time_origin),
      font_selector_(MakeGarbageCollected<OffscreenFontSelector>(this)),
      script_eval_state_(ScriptEvalState::kPauseAfterFetch),
      ukm_source_id_(creation_params->ukm_source_id) {
  InstanceCounters::IncrementCounter(
      InstanceCounters::kWorkerGlobalScopeCounter);

  // https://html.spec.whatwg.org/C/#run-a-worker
  // 4. Set worker global scope's HTTPS state to response's HTTPS state. [spec
  // text]
  https_state_ = CalculateHttpsState(GetSecurityOrigin(),
                                     creation_params->starter_https_state);

  SetOutsideContentSecurityPolicies(
      std::move(creation_params->outside_content_security_policies));
  SetWorkerSettings(std::move(creation_params->worker_settings));

  // TODO(sammc): Require a valid |creation_params->browser_interface_broker|
  // once all worker types provide a valid
  // |creation_params->browser_interface_broker|.
  if (creation_params->browser_interface_broker.is_valid()) {
    browser_interface_broker_proxy_.Bind(
        ToCrossVariantMojoType(
            std::move(creation_params->browser_interface_broker)),
        GetTaskRunner(TaskType::kInternalDefault));
  }

  // A FeaturePolicy is created by FeaturePolicy::CreateFromParentPolicy, even
  // if the parent policy is null.
  DCHECK(creation_params->worker_feature_policy);
  GetSecurityContext().SetFeaturePolicy(
      std::move(creation_params->worker_feature_policy));
}

void WorkerGlobalScope::ExceptionThrown(ErrorEvent* event) {
  int next_id = ++last_pending_error_event_id_;
  pending_error_events_.Set(next_id, event);
  ReportingProxy().ReportException(event->MessageForConsole(),
                                   event->Location()->Clone(), next_id);
}

void WorkerGlobalScope::RemoveURLFromMemoryCache(const KURL& url) {
  // MemoryCache can be accessed only from the main thread.
  PostCrossThreadTask(
      *Thread::MainThread()->GetTaskRunner(), FROM_HERE,
      CrossThreadBindOnce(&RemoveURLFromMemoryCacheInternal, url));
}

NOINLINE void WorkerGlobalScope::InitializeURL(const KURL& url) {
  CHECK(url_.IsNull());
  DCHECK(url.IsValid());
  if (GetSecurityOrigin()->IsOpaque()) {
    DCHECK(SecurityOrigin::Create(url)->IsOpaque());
  } else if (GetSecurityOrigin()->IsLocal()) {
    // SecurityOrigin::CanRequest called from CanReadContent has a special logic
    // for local origins, and the logic doesn't work here, so we have this
    // DCHECK instead.
    auto origin = SecurityOrigin::Create(url);
    DCHECK(origin->IsOpaque() || origin->IsLocal());
  } else {
    DCHECK(GetSecurityOrigin()->CanReadContent(url));
  }
  url_ = url;
}

void WorkerGlobalScope::SetWorkerMainScriptLoadingParametersForModules(
    std::unique_ptr<WorkerMainScriptLoadParameters>
        worker_main_script_load_params_for_modules) {
  DCHECK(worker_main_script_load_params_for_modules);
  DCHECK(!worker_main_script_load_params_for_modules_);
  worker_main_script_load_params_for_modules_ =
      std::move(worker_main_script_load_params_for_modules);
}

void WorkerGlobalScope::queueMicrotask(V8VoidFunction* callback) {
  GetAgent()->event_loop()->EnqueueMicrotask(
      WTF::Bind(&V8VoidFunction::InvokeAndReportException,
                WrapPersistent(callback), nullptr));
}

void WorkerGlobalScope::SetWorkerSettings(
    std::unique_ptr<WorkerSettings> worker_settings) {
  worker_settings_ = std::move(worker_settings);
  worker_settings_->MakeGenericFontFamilySettingsAtomic();
  font_selector_->UpdateGenericFontFamilySettings(
      worker_settings_->GetGenericFontFamilySettings());
}

TrustedTypePolicyFactory* WorkerGlobalScope::GetTrustedTypes() const {
  if (!trusted_types_) {
    trusted_types_ =
        MakeGarbageCollected<TrustedTypePolicyFactory>(GetExecutionContext());
  }
  return trusted_types_.Get();
}

ukm::UkmRecorder* WorkerGlobalScope::UkmRecorder() {
  if (ukm_recorder_)
    return ukm_recorder_.get();

  mojo::PendingRemote<ukm::mojom::UkmRecorderInterface> recorder;
  GetBrowserInterfaceBroker().GetInterface(
      recorder.InitWithNewPipeAndPassReceiver());
  ukm_recorder_ = std::make_unique<ukm::MojoUkmRecorder>(std::move(recorder));

  return ukm_recorder_.get();
}

std::unique_ptr<WorkerMainScriptLoadParameters>
WorkerGlobalScope::TakeWorkerMainScriptLoadingParametersForModules() {
  return std::move(worker_main_script_load_params_for_modules_);
}

void WorkerGlobalScope::Trace(Visitor* visitor) const {
  visitor->Trace(location_);
  visitor->Trace(navigator_);
  visitor->Trace(pending_error_events_);
  visitor->Trace(font_selector_);
  visitor->Trace(trusted_types_);
  visitor->Trace(worker_script_);
  WorkerOrWorkletGlobalScope::Trace(visitor);
  Supplementable<WorkerGlobalScope>::Trace(visitor);
}

FontMatchingMetrics* WorkerGlobalScope::GetFontMatchingMetrics() {
  if (!font_matching_metrics_) {
    font_matching_metrics_ = std::make_unique<FontMatchingMetrics>(
        UkmRecorder(), UkmSourceID(),
        GetTaskRunner(TaskType::kInternalDefault));
  }
  return font_matching_metrics_.get();
}

}  // namespace blink
