Commit 7bb4923c authored by Daniel Vogelheim's avatar Daniel Vogelheim Committed by Commit Bot

[Trusted Types] Worker constructor URLs are TrustedScriptURLs

Make URLs used to construct workers TrustedScriptURLs.

Minor rework of how to get the execution context in the generated
bindings, because the old method assumed presence of an "impl" object,
which is only created at the end in case of constructors. So instead,
implement a method with which we can always obtain the execution
context from the v8::FunctionCallbackInfo.

Bug: 1059684e
Change-Id: I00e3e52cad5c3736105289a9fda1eeca15fd6f62
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2105339
Commit-Queue: Daniel Vogelheim <vogelheim@chromium.org>
Reviewed-by: default avatarYuki Shiino <yukishiino@chromium.org>
Reviewed-by: default avatarHiroki Nakagawa <nhiroki@chromium.org>
Reviewed-by: default avatarYifan Luo <lyf@chromium.org>
Cr-Commit-Position: refs/heads/master@{#755315}
parent c5745818
...@@ -8,13 +8,11 @@ ...@@ -8,13 +8,11 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_element.h" #include "third_party/blink/renderer/bindings/core/v8/v8_element.h"
#include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/range.h" #include "third_party/blink/renderer/core/dom/range.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/html/custom/ce_reactions_scope.h" #include "third_party/blink/renderer/core/html/custom/ce_reactions_scope.h"
#include "third_party/blink/renderer/core/html/custom/v0_custom_element_processing_stack.h" #include "third_party/blink/renderer/core/html/custom/v0_custom_element_processing_stack.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/core/xml/dom_parser.h" #include "third_party/blink/renderer/core/xml/dom_parser.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h" #include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
...@@ -225,20 +223,6 @@ Document* ToDocumentFromExecutionContext(ExecutionContext* execution_context) { ...@@ -225,20 +223,6 @@ Document* ToDocumentFromExecutionContext(ExecutionContext* execution_context) {
return execution_context->ExecutingWindow()->document(); return execution_context->ExecutingWindow()->document();
} }
ExecutionContext* ExecutionContextFromV8Wrappable(
const LocalDOMWindow* window) {
return window->GetExecutionContext();
}
ExecutionContext* ExecutionContextFromV8Wrappable(
const WorkerGlobalScope* scope) {
return scope->GetExecutionContext();
}
ExecutionContext* ExecutionContextFromV8Wrappable(const Node* node) {
return node->GetExecutionContext();
}
ExecutionContext* ExecutionContextFromV8Wrappable(const Range* range) { ExecutionContext* ExecutionContextFromV8Wrappable(const Range* range) {
return range->startContainer()->GetDocument().ToExecutionContext(); return range->startContainer()->GetDocument().ToExecutionContext();
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/bindings/core/v8/idl_types.h" #include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h" #include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "v8/include/v8.h" #include "v8/include/v8.h"
...@@ -21,12 +22,9 @@ namespace blink { ...@@ -21,12 +22,9 @@ namespace blink {
class Document; class Document;
class DOMParser; class DOMParser;
class ExecutionContext; class ExecutionContext;
class LocalDOMWindow;
class Node;
class Range; class Range;
class QualifiedName; class QualifiedName;
class ScriptState; class ScriptState;
class WorkerGlobalScope;
CORE_EXPORT void V8ConstructorAttributeGetter( CORE_EXPORT void V8ConstructorAttributeGetter(
v8::Local<v8::Name> property_name, v8::Local<v8::Name> property_name,
...@@ -142,17 +140,14 @@ CORE_EXPORT bool IsEsIterableObject(v8::Isolate* isolate, ...@@ -142,17 +140,14 @@ CORE_EXPORT bool IsEsIterableObject(v8::Isolate* isolate,
CORE_EXPORT Document* ToDocumentFromExecutionContext( CORE_EXPORT Document* ToDocumentFromExecutionContext(
ExecutionContext* execution_context); ExecutionContext* execution_context);
CORE_EXPORT ExecutionContext* ExecutionContextFromV8Wrappable( // This function is mostly used for EventTargets, and so this version is
const LocalDOMWindow* window); // inlined. The less commonly used overloads are defined in the .cc file.
CORE_EXPORT inline ExecutionContext* ExecutionContextFromV8Wrappable(
CORE_EXPORT ExecutionContext* ExecutionContextFromV8Wrappable( const EventTarget* event_target) {
const WorkerGlobalScope* scope); return event_target->GetExecutionContext();
}
CORE_EXPORT ExecutionContext* ExecutionContextFromV8Wrappable(const Node* node);
CORE_EXPORT ExecutionContext* ExecutionContextFromV8Wrappable( CORE_EXPORT ExecutionContext* ExecutionContextFromV8Wrappable(
const Range* range); const Range* range);
CORE_EXPORT ExecutionContext* ExecutionContextFromV8Wrappable( CORE_EXPORT ExecutionContext* ExecutionContextFromV8Wrappable(
const DOMParser* parser); const DOMParser* parser);
......
...@@ -497,13 +497,17 @@ def v8_set_return_value(interface_name, ...@@ -497,13 +497,17 @@ def v8_set_return_value(interface_name,
is_static=method.is_static) is_static=method.is_static)
def v8_value_to_local_cpp_variadic_value(argument, index): def v8_value_to_local_cpp_variadic_value(argument,
index,
for_constructor_callback=False):
assert argument.is_variadic assert argument.is_variadic
idl_type = v8_types.native_value_traits_type_name( idl_type = v8_types.native_value_traits_type_name(
argument.idl_type, argument.extended_attributes, True) argument.idl_type, argument.extended_attributes, True)
execution_context_if_needed = '' execution_context_if_needed = ''
if argument.idl_type.has_string_context: if argument.idl_type.has_string_context:
execution_context_if_needed = ', bindings::ExecutionContextFromV8Wrappable(impl)' execution_context_if_needed = ', bindings::ExecutionContextFromV8Wrappable(impl)'
if for_constructor_callback:
execution_context_if_needed = ', CurrentExecutionContext(info.GetIsolate())'
assign_expression = 'ToImplArguments<%s>(info, %s, exception_state%s)' % ( assign_expression = 'ToImplArguments<%s>(info, %s, exception_state%s)' % (
idl_type, index, execution_context_if_needed) idl_type, index, execution_context_if_needed)
return { return {
...@@ -519,15 +523,18 @@ def v8_value_to_local_cpp_value(interface_name, method, argument, index): ...@@ -519,15 +523,18 @@ def v8_value_to_local_cpp_value(interface_name, method, argument, index):
idl_type = argument.idl_type idl_type = argument.idl_type
name = NameStyleConverter(argument.name).to_snake_case() name = NameStyleConverter(argument.name).to_snake_case()
v8_value = 'info[{index}]'.format(index=index) v8_value = 'info[{index}]'.format(index=index)
for_constructor_callback = method.name == 'Constructor'
if argument.is_variadic: if argument.is_variadic:
return v8_value_to_local_cpp_variadic_value(argument, index) return v8_value_to_local_cpp_variadic_value(
argument, index, for_constructor_callback=for_constructor_callback)
return idl_type.v8_value_to_local_cpp_value( return idl_type.v8_value_to_local_cpp_value(
extended_attributes, extended_attributes,
v8_value, v8_value,
name, name,
declare_variable=False, declare_variable=False,
use_exception_state=method.returns_promise) use_exception_state=method.returns_promise,
for_constructor_callback=for_constructor_callback)
################################################################################ ################################################################################
......
...@@ -694,7 +694,7 @@ def native_value_traits_type_name(idl_type, ...@@ -694,7 +694,7 @@ def native_value_traits_type_name(idl_type,
def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value,
variable_name, isolate): variable_name, isolate, for_constructor_callback):
if idl_type.name == 'void': if idl_type.name == 'void':
return '' return ''
...@@ -726,8 +726,11 @@ def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, ...@@ -726,8 +726,11 @@ def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value,
arguments = v8_value arguments = v8_value
if idl_type.has_string_context: if idl_type.has_string_context:
cpp_expression_format = 'NativeValueTraits<IDL%s>::NativeValue(%s, %s, exception_state, bindings::ExecutionContextFromV8Wrappable(impl))' % ( execution_context = 'bindings::ExecutionContextFromV8Wrappable(impl)'
idl_type.name, isolate, v8_value) if for_constructor_callback:
execution_context = 'CurrentExecutionContext(info.GetIsolate())'
cpp_expression_format = 'NativeValueTraits<IDL%s>::NativeValue(%s, %s, exception_state, %s)' % (
idl_type.name, isolate, v8_value, execution_context)
elif base_idl_type in V8_VALUE_TO_CPP_VALUE: elif base_idl_type in V8_VALUE_TO_CPP_VALUE:
cpp_expression_format = V8_VALUE_TO_CPP_VALUE[base_idl_type] cpp_expression_format = V8_VALUE_TO_CPP_VALUE[base_idl_type]
elif idl_type.name == 'ArrayBuffer': elif idl_type.name == 'ArrayBuffer':
...@@ -788,15 +791,21 @@ def v8_value_to_local_cpp_value(idl_type, ...@@ -788,15 +791,21 @@ def v8_value_to_local_cpp_value(idl_type,
isolate='info.GetIsolate()', isolate='info.GetIsolate()',
bailout_return_value=None, bailout_return_value=None,
use_exception_state=False, use_exception_state=False,
code_generation_target=None): code_generation_target=None,
for_constructor_callback=False):
"""Returns an expression that converts a V8 value to a C++ value and stores it as a local value.""" """Returns an expression that converts a V8 value to a C++ value and stores it as a local value."""
this_cpp_type = idl_type.cpp_type_args( this_cpp_type = idl_type.cpp_type_args(
extended_attributes=extended_attributes, raw_type=True) extended_attributes=extended_attributes, raw_type=True)
idl_type = idl_type.preprocessed_type idl_type = idl_type.preprocessed_type
cpp_value = v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, cpp_value = v8_value_to_cpp_value(
variable_name, isolate) idl_type,
extended_attributes,
v8_value,
variable_name,
isolate,
for_constructor_callback=for_constructor_callback)
# Optional expression that returns a value to be assigned to the local variable. # Optional expression that returns a value to be assigned to the local variable.
assign_expression = None assign_expression = None
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
// TODO(foolip): Exposed=(Window,Worker), // TODO(foolip): Exposed=(Window,Worker),
RuntimeEnabled=SharedWorker RuntimeEnabled=SharedWorker
] interface SharedWorker : EventTarget { ] interface SharedWorker : EventTarget {
[CallWith=ExecutionContext, RaisesException] constructor(DOMString scriptURL, optional (DOMString or WorkerOptions) options = {}); [CallWith=ExecutionContext, RaisesException] constructor(ScriptURLString scriptURL, optional (DOMString or WorkerOptions) options = {});
readonly attribute MessagePort port; readonly attribute MessagePort port;
}; };
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
Exposed=(Window,DedicatedWorker), Exposed=(Window,DedicatedWorker),
ImplementedAs=DedicatedWorker ImplementedAs=DedicatedWorker
] interface Worker : EventTarget { ] interface Worker : EventTarget {
[CallWith=ExecutionContext, RaisesException] constructor(DOMString scriptURL, optional WorkerOptions options = {}); [CallWith=ExecutionContext, RaisesException] constructor(ScriptURLString scriptURL, optional WorkerOptions options = {});
void terminate(); void terminate();
[CallWith=ScriptState, RaisesException] void postMessage(any message, sequence<object> transfer); [CallWith=ScriptState, RaisesException] void postMessage(any message, sequence<object> transfer);
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
readonly attribute ServiceWorker? controller; readonly attribute ServiceWorker? controller;
[CallWith=ScriptState, RaisesException] readonly attribute Promise<ServiceWorkerRegistration> ready; [CallWith=ScriptState, RaisesException] readonly attribute Promise<ServiceWorkerRegistration> ready;
[CallWith=ScriptState, ImplementedAs=registerServiceWorker] Promise<ServiceWorkerRegistration> register(USVString url, optional RegistrationOptions options = {}); [CallWith=ScriptState, ImplementedAs=registerServiceWorker] Promise<ServiceWorkerRegistration> register(ScriptURLString url, optional RegistrationOptions options = {});
[CallWith=ScriptState] Promise<ServiceWorkerRegistration> getRegistration(optional USVString documentURL = ""); [CallWith=ScriptState] Promise<ServiceWorkerRegistration> getRegistration(optional USVString documentURL = "");
[CallWith=ScriptState] Promise<sequence<ServiceWorkerRegistration>> getRegistrations(); [CallWith=ScriptState] Promise<sequence<ServiceWorkerRegistration>> getRegistrations();
......
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
const test_url = "support/WorkerGlobalScope-importScripts.https.js"
const trusted_url = trustedTypes.createPolicy("anythinggoes", {
createScriptURL: x => x}).createScriptURL(test_url);
const default_url = "support/WorkerGlobalScope-importScripts.potato.js"
async function service_worker(url) {
if (!('serviceWorker' in navigator)) return Promise.resolve();
const scope = 'support/some/scope/for/this/test';
const reg = await navigator.serviceWorker.getRegistration(scope);
if (reg) await reg.unregister();
return await navigator.serviceWorker.register(url, {scope});
}
// Most tests below don't need promises, but the ones related to
// ServiceWorkers do. Since we can't mix promise and non-promise tests,
// we'll just run the non-promise tests in the main function and return
// an empty-resolved promise for those.
// Since an active default policy will affect all subsequent DOM operations,
// we're wrapping policy creation in a promise_test. Together, this will
// force proper serialization of all tests.
//
// Generally, we don't actually care what the workers here do, we'll merely
// check whether creation succeeds.
promise_test(t => {
new Worker(trusted_url);
return Promise.resolve();
}, "Create Worker via ScriptTestUrl");
promise_test(t => {
new SharedWorker(trusted_url);
return Promise.resolve();
}, "Create SharedWorker via ScriptTestUrl");
promise_test(t => {
return service_worker(trusted_url);
}, "Create ServiceWorker via ScriptTestUrl");
promise_test(t => {
assert_throws_js(TypeError, () => new Worker(test_url));
return Promise.resolve();
}, "Block Worker creation via string");
promise_test(t => {
assert_throws_js(TypeError, () => new SharedWorker(test_url));
return Promise.resolve();
}, "Block SharedWorker creation via string");
promise_test(t => {
return promise_rejects_js(t, TypeError, service_worker(test_url));
}, "Block ServiceWorker creation via String");
// Tests with default policy.
promise_test(t => {
trustedTypes.createPolicy("default", {
createScriptURL: s => s.replace("potato", "https") });
return Promise.resolve();
}, "Setup default policy.");
promise_test(t => {
new Worker(default_url);
return Promise.resolve();
}, "Create Worker via string with default policy.");
promise_test(t => {
new SharedWorker(default_url);
return Promise.resolve();
}, "Create SharedWorker via string with default policy.");
promise_test(t => {
return service_worker(default_url);
}, "Create ServiceWorker via string with default policy.");
</script>
</body>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment