/src/serenity/Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #include <AK/Vector.h> |
8 | | #include <LibWeb/Bindings/Intrinsics.h> |
9 | | #include <LibWeb/Bindings/WorkerGlobalScopePrototype.h> |
10 | | #include <LibWeb/CSS/FontFaceSet.h> |
11 | | #include <LibWeb/HTML/EventHandler.h> |
12 | | #include <LibWeb/HTML/EventNames.h> |
13 | | #include <LibWeb/HTML/MessageEvent.h> |
14 | | #include <LibWeb/HTML/MessagePort.h> |
15 | | #include <LibWeb/HTML/Scripting/ClassicScript.h> |
16 | | #include <LibWeb/HTML/StructuredSerialize.h> |
17 | | #include <LibWeb/HTML/WorkerGlobalScope.h> |
18 | | #include <LibWeb/HTML/WorkerLocation.h> |
19 | | #include <LibWeb/HTML/WorkerNavigator.h> |
20 | | #include <LibWeb/Page/Page.h> |
21 | | |
22 | | namespace Web::HTML { |
23 | | |
24 | | JS_DEFINE_ALLOCATOR(WorkerGlobalScope); |
25 | | |
26 | | WorkerGlobalScope::WorkerGlobalScope(JS::Realm& realm, JS::NonnullGCPtr<Web::Page> page) |
27 | 0 | : DOM::EventTarget(realm) |
28 | 0 | , m_page(page) |
29 | 0 | { |
30 | 0 | } |
31 | | |
32 | 0 | WorkerGlobalScope::~WorkerGlobalScope() = default; |
33 | | |
34 | | void WorkerGlobalScope::initialize_web_interfaces_impl() |
35 | 0 | { |
36 | 0 | auto& realm = this->realm(); |
37 | 0 | Base::initialize(realm); |
38 | |
|
39 | 0 | WindowOrWorkerGlobalScopeMixin::initialize(realm); |
40 | |
|
41 | 0 | m_navigator = WorkerNavigator::create(*this); |
42 | 0 | } |
43 | | |
44 | | void WorkerGlobalScope::visit_edges(Cell::Visitor& visitor) |
45 | 0 | { |
46 | 0 | Base::visit_edges(visitor); |
47 | 0 | WindowOrWorkerGlobalScopeMixin::visit_edges(visitor); |
48 | |
|
49 | 0 | visitor.visit(m_location); |
50 | 0 | visitor.visit(m_navigator); |
51 | 0 | visitor.visit(m_internal_port); |
52 | 0 | visitor.visit(m_page); |
53 | 0 | visitor.visit(m_fonts); |
54 | 0 | } |
55 | | |
56 | | void WorkerGlobalScope::finalize() |
57 | 0 | { |
58 | 0 | Base::finalize(); |
59 | 0 | WindowOrWorkerGlobalScopeMixin::finalize(); |
60 | 0 | } |
61 | | |
62 | | void WorkerGlobalScope::set_internal_port(JS::NonnullGCPtr<MessagePort> port) |
63 | 0 | { |
64 | 0 | m_internal_port = port; |
65 | 0 | m_internal_port->set_worker_event_target(*this); |
66 | 0 | } |
67 | | |
68 | | // https://html.spec.whatwg.org/multipage/workers.html#close-a-worker |
69 | | void WorkerGlobalScope::close_a_worker() |
70 | 0 | { |
71 | | // 1. Discard any tasks that have been added to workerGlobal's relevant agent's event loop's task queues. |
72 | 0 | relevant_settings_object(*this).responsible_event_loop().task_queue().remove_tasks_matching([](HTML::Task const& task) { |
73 | | // NOTE: We don't discard tasks with the PostedMessage source, as the spec expects PostMessage() to act as if it is invoked immediately |
74 | 0 | return task.source() != HTML::Task::Source::PostedMessage; |
75 | 0 | }); |
76 | | |
77 | | // 2. Set workerGlobal's closing flag to true. (This prevents any further tasks from being queued.) |
78 | 0 | m_closing = true; |
79 | 0 | } |
80 | | |
81 | | // https://html.spec.whatwg.org/multipage/workers.html#importing-scripts-and-libraries |
82 | | WebIDL::ExceptionOr<void> WorkerGlobalScope::import_scripts(Vector<String> const& urls, PerformTheFetchHook perform_fetch) |
83 | 0 | { |
84 | | // The algorithm may optionally be customized by supplying custom perform the fetch hooks, |
85 | | // which if provided will be used when invoking fetch a classic worker-imported script. |
86 | | // NOTE: Service Workers is an example of a specification that runs this algorithm with its own options for the perform the fetch hook. |
87 | | |
88 | | // FIXME: 1. If worker global scope's type is "module", throw a TypeError exception. |
89 | | |
90 | | // 2. Let settings object be the current settings object. |
91 | 0 | auto& settings_object = HTML::current_settings_object(); |
92 | | |
93 | | // 3. If urls is empty, return. |
94 | 0 | if (urls.is_empty()) |
95 | 0 | return {}; |
96 | | |
97 | | // 4. Let urlRecords be « ». |
98 | 0 | Vector<URL::URL> url_records; |
99 | 0 | url_records.ensure_capacity(urls.size()); |
100 | | |
101 | | // 5. For each url of urls: |
102 | 0 | for (auto const& url : urls) { |
103 | | // 1. Let urlRecord be the result of encoding-parsing a URL given url, relative to settings object. |
104 | 0 | auto url_record = settings_object.parse_url(url); |
105 | | |
106 | | // 2. If urlRecord is failure, then throw a "SyntaxError" DOMException. |
107 | 0 | if (!url_record.is_valid()) |
108 | 0 | return WebIDL::SyntaxError::create(realm(), "Invalid URL"_string); |
109 | | |
110 | | // 3. Append urlRecord to urlRecords. |
111 | 0 | url_records.unchecked_append(url_record); |
112 | 0 | } |
113 | | |
114 | | // 6. For each urlRecord of urlRecords: |
115 | 0 | for (auto const& url_record : url_records) { |
116 | | // 1. Fetch a classic worker-imported script given urlRecord and settings object, passing along performFetch if provided. |
117 | | // If this succeeds, let script be the result. Otherwise, rethrow the exception. |
118 | 0 | auto classic_script = TRY(HTML::fetch_a_classic_worker_imported_script(url_record, settings_object, perform_fetch)); |
119 | | |
120 | | // 2. Run the classic script script, with the rethrow errors argument set to true. |
121 | | // NOTE: script will run until it either returns, fails to parse, fails to catch an exception, |
122 | | // or gets prematurely aborted by the terminate a worker algorithm defined above. |
123 | | // If an exception was thrown or if the script was prematurely aborted, then abort all these steps, |
124 | | // letting the exception or aborting continue to be processed by the calling script. |
125 | 0 | TRY(classic_script->run(ClassicScript::RethrowErrors::Yes)); |
126 | 0 | } |
127 | | |
128 | 0 | return {}; |
129 | 0 | } |
130 | | |
131 | | // https://html.spec.whatwg.org/multipage/workers.html#dom-workerglobalscope-location |
132 | | JS::NonnullGCPtr<WorkerLocation> WorkerGlobalScope::location() const |
133 | 0 | { |
134 | | // The location attribute must return the WorkerLocation object whose associated WorkerGlobalScope object is the WorkerGlobalScope object. |
135 | 0 | return *m_location; |
136 | 0 | } |
137 | | |
138 | | // https://html.spec.whatwg.org/multipage/workers.html#dom-worker-navigator |
139 | | JS::NonnullGCPtr<WorkerNavigator> WorkerGlobalScope::navigator() const |
140 | 0 | { |
141 | | // The navigator attribute of the WorkerGlobalScope interface must return an instance of the WorkerNavigator interface, |
142 | | // which represents the identity and state of the user agent (the client). |
143 | 0 | return *m_navigator; |
144 | 0 | } |
145 | | |
146 | | #undef __ENUMERATE |
147 | | #define __ENUMERATE(attribute_name, event_name) \ |
148 | | void WorkerGlobalScope::set_##attribute_name(WebIDL::CallbackType* value) \ |
149 | 0 | { \ |
150 | 0 | set_event_handler_attribute(event_name, move(value)); \ |
151 | 0 | } \ Unexecuted instantiation: Web::HTML::WorkerGlobalScope::set_onerror(Web::WebIDL::CallbackType*) Unexecuted instantiation: Web::HTML::WorkerGlobalScope::set_onlanguagechange(Web::WebIDL::CallbackType*) Unexecuted instantiation: Web::HTML::WorkerGlobalScope::set_ononline(Web::WebIDL::CallbackType*) Unexecuted instantiation: Web::HTML::WorkerGlobalScope::set_onoffline(Web::WebIDL::CallbackType*) Unexecuted instantiation: Web::HTML::WorkerGlobalScope::set_onrejectionhandled(Web::WebIDL::CallbackType*) Unexecuted instantiation: Web::HTML::WorkerGlobalScope::set_onunhandledrejection(Web::WebIDL::CallbackType*) |
152 | | WebIDL::CallbackType* WorkerGlobalScope::attribute_name() \ |
153 | 0 | { \ |
154 | 0 | return event_handler_attribute(event_name); \ |
155 | 0 | } Unexecuted instantiation: Web::HTML::WorkerGlobalScope::onerror() Unexecuted instantiation: Web::HTML::WorkerGlobalScope::onlanguagechange() Unexecuted instantiation: Web::HTML::WorkerGlobalScope::ononline() Unexecuted instantiation: Web::HTML::WorkerGlobalScope::onoffline() Unexecuted instantiation: Web::HTML::WorkerGlobalScope::onrejectionhandled() Unexecuted instantiation: Web::HTML::WorkerGlobalScope::onunhandledrejection() |
156 | | ENUMERATE_WORKER_GLOBAL_SCOPE_EVENT_HANDLERS(__ENUMERATE) |
157 | | #undef __ENUMERATE |
158 | | |
159 | | JS::NonnullGCPtr<CSS::FontFaceSet> WorkerGlobalScope::fonts() |
160 | 0 | { |
161 | 0 | if (!m_fonts) |
162 | 0 | m_fonts = CSS::FontFaceSet::create(realm()); |
163 | 0 | return *m_fonts; |
164 | 0 | } |
165 | | |
166 | | } |