1 /*
2  * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  *    notice, this list of conditions and the following disclaimer in the
10  *    documentation and/or other materials provided with the distribution.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
27 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_GLOBAL_SCOPE_H_
28 #define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_GLOBAL_SCOPE_H_
29 
30 #include <memory>
31 #include "services/network/public/mojom/fetch_api.mojom-blink-forward.h"
32 #include "services/network/public/mojom/ip_address_space.mojom-blink-forward.h"
33 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
34 #include "third_party/blink/public/common/loader/worker_main_script_load_parameters.h"
35 #include "third_party/blink/public/common/tokens/tokens.h"
36 #include "third_party/blink/public/mojom/script/script_type.mojom-blink-forward.h"
37 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
38 #include "third_party/blink/renderer/core/core_export.h"
39 #include "third_party/blink/renderer/core/dom/frame_request_callback_collection.h"
40 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
41 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
42 #include "third_party/blink/renderer/core/script/script.h"
43 #include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
44 #include "third_party/blink/renderer/core/workers/worker_classic_script_loader.h"
45 #include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
46 #include "third_party/blink/renderer/core/workers/worker_settings.h"
47 #include "third_party/blink/renderer/platform/heap/handle.h"
48 #include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
49 #include "third_party/blink/renderer/platform/wtf/casting.h"
50 
51 namespace blink {
52 
53 struct BlinkTransferableMessage;
54 class ConsoleMessage;
55 class FetchClientSettingsObjectSnapshot;
56 class FontFaceSet;
57 class FontMatchingMetrics;
58 class InstalledScriptsManager;
59 class OffscreenFontSelector;
60 class WorkerResourceTimingNotifier;
61 class TrustedTypePolicyFactory;
62 class V8VoidFunction;
63 class WorkerLocation;
64 class WorkerNavigator;
65 class WorkerThread;
66 
67 class CORE_EXPORT WorkerGlobalScope
68     : public WorkerOrWorkletGlobalScope,
69       public ActiveScriptWrappable<WorkerGlobalScope>,
70       public Supplementable<WorkerGlobalScope> {
71   DEFINE_WRAPPERTYPEINFO();
72 
73  public:
74   ~WorkerGlobalScope() override;
75 
76   // Returns null if caching is not supported.
CreateWorkerScriptCachedMetadataHandler(const KURL & script_url,std::unique_ptr<Vector<uint8_t>> meta_data)77   virtual SingleCachedMetadataHandler* CreateWorkerScriptCachedMetadataHandler(
78       const KURL& script_url,
79       std::unique_ptr<Vector<uint8_t>> meta_data) {
80     return nullptr;
81   }
82 
83   // WorkerOrWorkletGlobalScope
IsClosing()84   bool IsClosing() const final { return closing_; }
85   void Dispose() override;
GetThread()86   WorkerThread* GetThread() const final { return thread_; }
87   const base::UnguessableToken& GetDevToolsToken() const override;
88 
89   void ExceptionUnhandled(int exception_id);
90 
91   // WorkerGlobalScope
self()92   WorkerGlobalScope* self() { return this; }
93   WorkerLocation* location() const;
94   WorkerNavigator* navigator() const override;
95   void close();
isSecureContextForBindings()96   bool isSecureContextForBindings() const {
97     return ExecutionContext::IsSecureContext();
98   }
99 
100   String origin() const;
101 
102   DEFINE_ATTRIBUTE_EVENT_LISTENER(error, kError)
103   DEFINE_ATTRIBUTE_EVENT_LISTENER(languagechange, kLanguagechange)
104   DEFINE_ATTRIBUTE_EVENT_LISTENER(rejectionhandled, kRejectionhandled)
105   DEFINE_ATTRIBUTE_EVENT_LISTENER(timezonechange, kTimezonechange)
106   DEFINE_ATTRIBUTE_EVENT_LISTENER(unhandledrejection, kUnhandledrejection)
107 
108   // This doesn't take an ExceptionState argument, but actually can throw
109   // exceptions directly to V8 (crbug/1114610).
110   virtual void importScripts(const Vector<String>& urls);
111 
112   // ExecutionContext
113   const KURL& Url() const final;
114   KURL CompleteURL(const String&) const final;
IsWorkerGlobalScope()115   bool IsWorkerGlobalScope() const final { return true; }
116   bool IsContextThread() const final;
117   const KURL& BaseURL() const final;
UserAgent()118   String UserAgent() const final { return user_agent_; }
GetUserAgentMetadata()119   const UserAgentMetadata& GetUserAgentMetadata() const { return ua_metadata_; }
GetHttpsState()120   HttpsState GetHttpsState() const override { return https_state_; }
121   scheduler::WorkerScheduler* GetScheduler() final;
122   ukm::UkmRecorder* UkmRecorder() final;
ToScriptWrappable()123   ScriptWrappable* ToScriptWrappable() final { return this; }
124 
125   void AddConsoleMessageImpl(ConsoleMessage*, bool discard_duplicates) final;
126   BrowserInterfaceBrokerProxy& GetBrowserInterfaceBroker() final;
127 
GetFontSelector()128   OffscreenFontSelector* GetFontSelector() { return font_selector_; }
129 
130   CoreProbeSink* GetProbeSink() final;
131 
132   // EventTarget
133   ExecutionContext* GetExecutionContext() const final;
IsWindowOrWorkerGlobalScope()134   bool IsWindowOrWorkerGlobalScope() const final { return true; }
135 
136   // Initializes this global scope. This must be called after worker script
137   // fetch, and before initiali script evaluation.
138   //
139   // This corresponds to following specs:
140   // - For dedicated/shared workers, step 12.3-12.6 (a custom perform the fetch
141   //   hook) in https://html.spec.whatwg.org/C/#run-a-worker
142   // - For service workers, step 4.5-4.11 in
143   //   https://w3c.github.io/ServiceWorker/#run-service-worker-algorithm
144   virtual void Initialize(
145       const KURL& response_url,
146       network::mojom::ReferrerPolicy response_referrer_policy,
147       network::mojom::IPAddressSpace response_address_space,
148       const Vector<CSPHeaderAndType>& response_csp_headers,
149       const Vector<String>* response_origin_trial_tokens,
150       int64_t appcache_id) = 0;
151 
152   // These methods should be called in the scope of a pausable
153   // task runner. ie. They should not be called when the context
154   // is paused.
155   void EvaluateClassicScript(const KURL& script_url,
156                              String source_code,
157                              std::unique_ptr<Vector<uint8_t>> cached_meta_data,
158                              const v8_inspector::V8StackTraceId& stack_id);
159 
160   // Should be called (in all successful cases) when the worker top-level
161   // script fetch is finished.
162   // At this time, WorkerGlobalScope::Initialize() should be already called.
163   // Spec: https://html.spec.whatwg.org/C/#run-a-worker Step 12 is completed,
164   // and it's ready to proceed to Step 23.
165   void WorkerScriptFetchFinished(Script&,
166                                  base::Optional<v8_inspector::V8StackTraceId>);
167 
168   // Fetches and evaluates the top-level classic script.
169   virtual void FetchAndRunClassicScript(
170       const KURL& script_url,
171       std::unique_ptr<WorkerMainScriptLoadParameters>
172           worker_main_script_load_params_for_modules,
173       const FetchClientSettingsObjectSnapshot& outside_settings_object,
174       WorkerResourceTimingNotifier& outside_resource_timing_notifier,
175       const v8_inspector::V8StackTraceId& stack_id) = 0;
176 
177   // Fetches and evaluates the top-level module script.
178   virtual void FetchAndRunModuleScript(
179       const KURL& module_url_record,
180       std::unique_ptr<WorkerMainScriptLoadParameters>
181           worker_main_script_load_params_for_modules,
182       const FetchClientSettingsObjectSnapshot& outside_settings_object,
183       WorkerResourceTimingNotifier& outside_resource_timing_notifier,
184       network::mojom::CredentialsMode,
185       RejectCoepUnsafeNone reject_coep_unsafe_none) = 0;
186 
187   void ReceiveMessage(BlinkTransferableMessage);
TimeOrigin()188   base::TimeTicks TimeOrigin() const { return time_origin_; }
GetWorkerSettings()189   WorkerSettings* GetWorkerSettings() const { return worker_settings_.get(); }
190 
191   void Trace(Visitor*) const override;
192 
GetInstalledScriptsManager()193   virtual InstalledScriptsManager* GetInstalledScriptsManager() {
194     return nullptr;
195   }
196 
197   // TODO(fserb): This can be removed once we WorkerGlobalScope implements
198   // FontFaceSource on the IDL.
199   FontFaceSet* fonts();
200 
201   // https://html.spec.whatwg.org/C/#windoworworkerglobalscope-mixin
202   void queueMicrotask(V8VoidFunction*);
203 
204   TrustedTypePolicyFactory* GetTrustedTypes() const override;
trustedTypes()205   TrustedTypePolicyFactory* trustedTypes() const { return GetTrustedTypes(); }
206 
207   // TODO(https://crbug.com/835717): Remove this function after dedicated
208   // workers support off-the-main-thread script fetch by default.
IsOffMainThreadScriptFetchDisabled()209   virtual bool IsOffMainThreadScriptFetchDisabled() { return false; }
210 
211   // Takes the ownership of the parameters used to load the worker main module
212   // script in renderer process.
213   std::unique_ptr<WorkerMainScriptLoadParameters>
214   TakeWorkerMainScriptLoadingParametersForModules();
215 
UkmSourceID()216   ukm::SourceId UkmSourceID() const override { return ukm_source_id_; }
217 
218   // Returns the token uniquely identifying this worker. The token type will
219   // match the actual worker type.
220   virtual WorkerToken GetWorkerToken() const = 0;
221 
222   // Tracks and reports metrics of attempted font match attempts (both
223   // successful and not successful) by the worker.
224   FontMatchingMetrics* GetFontMatchingMetrics();
225 
226  protected:
227   WorkerGlobalScope(std::unique_ptr<GlobalScopeCreationParams>,
228                     WorkerThread*,
229                     base::TimeTicks time_origin,
230                     ukm::SourceId);
231 
232   // ExecutionContext
233   void ExceptionThrown(ErrorEvent*) override;
234   void RemoveURLFromMemoryCache(const KURL&) final;
235 
236   virtual bool FetchClassicImportedScript(
237       const KURL& script_url,
238       KURL* out_response_url,
239       String* out_source_code,
240       std::unique_ptr<Vector<uint8_t>>* out_cached_meta_data);
241 
242   // Notifies that the top-level worker script is ready to evaluate.
243   // Worker top-level script is evaluated after it is fetched and
244   // ReadyToRunWorkerScript() is called.
245   void ReadyToRunWorkerScript();
246 
247   void InitializeURL(const KURL& url);
248 
GetScriptType()249   mojom::blink::ScriptType GetScriptType() const { return script_type_; }
250 
251   // Sets the parameters for the worker main module script loaded by the browser
252   // process.
253   void SetWorkerMainScriptLoadingParametersForModules(
254       std::unique_ptr<WorkerMainScriptLoadParameters>
255           worker_main_script_load_params_for_modules);
256 
257  private:
258   void SetWorkerSettings(std::unique_ptr<WorkerSettings>);
259 
260   // https://html.spec.whatwg.org/C/#run-a-worker Step 24.
261   void RunWorkerScript();
262 
263   // Used for importScripts().
264   void ImportScriptsInternal(const Vector<String>& urls);
265   // ExecutionContext
266   void AddInspectorIssue(mojom::blink::InspectorIssueInfoPtr) final;
ErrorEventTarget()267   EventTarget* ErrorEventTarget() final { return this; }
268 
269   KURL url_;
270   const mojom::blink::ScriptType script_type_;
271   const String user_agent_;
272   const UserAgentMetadata ua_metadata_;
273   std::unique_ptr<WorkerSettings> worker_settings_;
274 
275   mutable Member<WorkerLocation> location_;
276   mutable Member<WorkerNavigator> navigator_;
277   mutable Member<TrustedTypePolicyFactory> trusted_types_;
278 
279   WorkerThread* thread_;
280 
281   bool closing_ = false;
282 
283   const base::TimeTicks time_origin_;
284 
285   HeapHashMap<int, Member<ErrorEvent>> pending_error_events_;
286   int last_pending_error_event_id_ = 0;
287 
288   Member<OffscreenFontSelector> font_selector_;
289 
290   // Tracks and reports UKM metrics of the number of attempted font family match
291   // attempts (both successful and not successful) by the worker.
292   std::unique_ptr<FontMatchingMetrics> font_matching_metrics_;
293 
294   blink::BrowserInterfaceBrokerProxy browser_interface_broker_proxy_;
295 
296   // State transition about worker top-level script evaluation.
297   enum class ScriptEvalState {
298     // Initial state: ReadyToRunWorkerScript() was not yet called.
299     // Worker top-level script fetch might or might not be completed, and even
300     // when the fetch completes in this state, script evaluation will be
301     // deferred to when ReadyToRunWorkerScript() is called later.
302     kPauseAfterFetch,
303     // ReadyToRunWorkerScript() was already called.
304     kReadyToEvaluate,
305     // The worker top-level script was evaluated.
306     kEvaluated,
307   };
308   ScriptEvalState script_eval_state_;
309 
310   Member<Script> worker_script_;
311   base::Optional<v8_inspector::V8StackTraceId> stack_id_;
312 
313   HttpsState https_state_;
314 
315   std::unique_ptr<ukm::UkmRecorder> ukm_recorder_;
316 
317   // |worker_main_script_load_params_for_modules_| is used to load a root module
318   // script for dedicated workers (when PlzDedicatedWorker is enabled) and
319   // shared workers.
320   std::unique_ptr<WorkerMainScriptLoadParameters>
321       worker_main_script_load_params_for_modules_;
322 
323   const ukm::SourceId ukm_source_id_;
324 };
325 
326 template <>
327 struct DowncastTraits<WorkerGlobalScope> {
328   static bool AllowFrom(const ExecutionContext& context) {
329     return context.IsWorkerGlobalScope();
330   }
331 };
332 
333 }  // namespace blink
334 
335 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_GLOBAL_SCOPE_H_
336