blob: 49749b506128ca4fa0a6f1ac513b786ce6bff4f2 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "core/dom/Modulator.h"
#include "bindings/core/v8/V8BindingForCore.h"
#include "core/dom/Document.h"
#include "core/dom/DocumentModulatorImpl.h"
#include "core/dom/WorkerModulatorImpl.h"
#include "core/dom/WorkletModulatorImpl.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/workers/WorkletGlobalScope.h"
#include "platform/bindings/ScriptState.h"
#include "platform/bindings/V8PerContextData.h"
namespace blink {
namespace {
const char kPerContextDataKey[] = "Modulator";
} // namespace
Modulator* Modulator::From(ScriptState* script_state) {
if (!script_state)
return nullptr;
V8PerContextData* per_context_data = script_state->PerContextData();
if (!per_context_data)
return nullptr;
Modulator* modulator =
static_cast<Modulator*>(per_context_data->GetData(kPerContextDataKey));
if (modulator)
return modulator;
ExecutionContext* execution_context = ExecutionContext::From(script_state);
if (execution_context->IsDocument()) {
Document* document = ToDocument(execution_context);
modulator =
DocumentModulatorImpl::Create(script_state, document->Fetcher());
Modulator::SetModulator(script_state, modulator);
// See comment in LocalDOMWindow::modulator_ for this workaround.
LocalDOMWindow* window = document->ExecutingWindow();
window->SetModulator(modulator);
} else if (execution_context->IsWorkletGlobalScope()) {
modulator = WorkletModulatorImpl::Create(script_state);
Modulator::SetModulator(script_state, modulator);
// See comment in WorkerOrWorkletGlobalScope::modulator_ for this
// workaround.
ToWorkerOrWorkletGlobalScope(execution_context)->SetModulator(modulator);
} else if (execution_context->IsWorkerGlobalScope()) {
modulator = WorkerModulatorImpl::Create(script_state);
Modulator::SetModulator(script_state, modulator);
// See comment in WorkerOrWorkletGlobalScope::modulator_ for this
// workaround.
ToWorkerOrWorkletGlobalScope(execution_context)->SetModulator(modulator);
} else {
NOTREACHED();
}
return modulator;
}
Modulator::~Modulator() {}
void Modulator::SetModulator(ScriptState* script_state, Modulator* modulator) {
DCHECK(script_state);
V8PerContextData* per_context_data = script_state->PerContextData();
DCHECK(per_context_data);
per_context_data->AddData(kPerContextDataKey, modulator);
}
void Modulator::ClearModulator(ScriptState* script_state) {
DCHECK(script_state);
V8PerContextData* per_context_data = script_state->PerContextData();
DCHECK(per_context_data);
per_context_data->ClearData(kPerContextDataKey);
}
KURL Modulator::ResolveModuleSpecifier(const String& module_request,
const KURL& base_url,
String* failure_reason) {
// https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier
// Step 1. "Apply the URL parser to specifier. If the result is not failure,
// return the result." [spec text]
KURL url(NullURL(), module_request);
if (url.IsValid())
return url;
// Step 2. "If specifier does not start with the character U+002F SOLIDUS (/),
// the two-character sequence U+002E FULL STOP, U+002F SOLIDUS (./), or the
// three-character sequence U+002E FULL STOP, U+002E FULL STOP, U+002F SOLIDUS
// (../), return failure and abort these steps." [spec text]
if (!module_request.StartsWith("/") && !module_request.StartsWith("./") &&
!module_request.StartsWith("../")) {
if (failure_reason) {
*failure_reason =
"Relative references must start with either \"/\", \"./\", or "
"\"../\".";
}
return KURL();
}
// Step 3. "Return the result of applying the URL parser to specifier with
// script's base URL as the base URL." [spec text]
DCHECK(base_url.IsValid());
KURL absolute_url(base_url, module_request);
if (absolute_url.IsValid())
return absolute_url;
if (failure_reason) {
*failure_reason = "Invalid relative url or base scheme isn't hierarchical.";
}
return KURL();
}
} // namespace blink