1 /*
2 * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
4 * Copyright (C) 2013 Samsung Electronics. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include "third_party/blink/renderer/core/frame/window_or_worker_global_scope.h"
34
35 #include "base/containers/span.h"
36 #include "third_party/blink/renderer/bindings/core/v8/scheduled_action.h"
37 #include "third_party/blink/renderer/bindings/core/v8/v8_gc_for_context_dispose.h"
38 #include "third_party/blink/renderer/core/dom/events/event_target.h"
39 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
40 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
41 #include "third_party/blink/renderer/core/frame/dom_timer.h"
42 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
43 #include "third_party/blink/renderer/core/frame/page_dismissal_scope.h"
44 #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
45 #include "third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h"
46 #include "third_party/blink/renderer/core/trustedtypes/trusted_types_util.h"
47 #include "third_party/blink/renderer/core/workers/worker_global_scope.h"
48 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
49 #include "third_party/blink/renderer/platform/heap/heap.h"
50 #include "third_party/blink/renderer/platform/weborigin/reporting_disposition.h"
51 #include "third_party/blink/renderer/platform/wtf/text/base64.h"
52 #include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
53
54 namespace blink {
55
IsAllowed(ExecutionContext * execution_context,bool is_eval,const String & source)56 static bool IsAllowed(ExecutionContext* execution_context,
57 bool is_eval,
58 const String& source) {
59 if (auto* window = DynamicTo<LocalDOMWindow>(execution_context)) {
60 if (!window->GetFrame())
61 return false;
62 if (is_eval && !window->GetContentSecurityPolicy()->AllowEval(
63 ReportingDisposition::kReport,
64 ContentSecurityPolicy::kWillNotThrowException, source)) {
65 return false;
66 }
67 if (PageDismissalScope::IsActive()) {
68 UseCounter::Count(execution_context,
69 window->document()->ProcessingBeforeUnload()
70 ? WebFeature::kTimerInstallFromBeforeUnload
71 : WebFeature::kTimerInstallFromUnload);
72 }
73 return true;
74 }
75 if (execution_context->IsWorkerGlobalScope()) {
76 WorkerGlobalScope* worker_global_scope =
77 static_cast<WorkerGlobalScope*>(execution_context);
78 if (!worker_global_scope->ScriptController())
79 return false;
80 ContentSecurityPolicy* policy =
81 worker_global_scope->GetContentSecurityPolicy();
82 if (is_eval && policy &&
83 !policy->AllowEval(ReportingDisposition::kReport,
84 ContentSecurityPolicy::kWillNotThrowException,
85 source)) {
86 return false;
87 }
88 return true;
89 }
90 NOTREACHED();
91 return false;
92 }
93
btoa(EventTarget &,const String & string_to_encode,ExceptionState & exception_state)94 String WindowOrWorkerGlobalScope::btoa(EventTarget&,
95 const String& string_to_encode,
96 ExceptionState& exception_state) {
97 if (string_to_encode.IsNull())
98 return String();
99
100 if (!string_to_encode.ContainsOnlyLatin1OrEmpty()) {
101 exception_state.ThrowDOMException(
102 DOMExceptionCode::kInvalidCharacterError,
103 "The string to be encoded contains "
104 "characters outside of the Latin1 range.");
105 return String();
106 }
107
108 return Base64Encode(
109 base::as_bytes(base::make_span(string_to_encode.Latin1())));
110 }
111
atob(EventTarget &,const String & encoded_string,ExceptionState & exception_state)112 String WindowOrWorkerGlobalScope::atob(EventTarget&,
113 const String& encoded_string,
114 ExceptionState& exception_state) {
115 if (encoded_string.IsNull())
116 return String();
117
118 if (!encoded_string.ContainsOnlyLatin1OrEmpty()) {
119 exception_state.ThrowDOMException(
120 DOMExceptionCode::kInvalidCharacterError,
121 "The string to be decoded contains "
122 "characters outside of the Latin1 range.");
123 return String();
124 }
125 Vector<char> out;
126 if (!Base64Decode(encoded_string, out, IsHTMLSpace<UChar>,
127 kBase64ValidatePadding)) {
128 exception_state.ThrowDOMException(
129 DOMExceptionCode::kInvalidCharacterError,
130 "The string to be decoded is not correctly encoded.");
131 return String();
132 }
133
134 return String(out.data(), out.size());
135 }
136
setTimeout(ScriptState * script_state,EventTarget & event_target,V8Function * handler,int timeout,const HeapVector<ScriptValue> & arguments)137 int WindowOrWorkerGlobalScope::setTimeout(
138 ScriptState* script_state,
139 EventTarget& event_target,
140 V8Function* handler,
141 int timeout,
142 const HeapVector<ScriptValue>& arguments) {
143 ExecutionContext* execution_context = event_target.GetExecutionContext();
144 if (!IsAllowed(execution_context, false, g_empty_string))
145 return 0;
146 if (timeout >= 0 && execution_context->IsWindow()) {
147 // FIXME: Crude hack that attempts to pass idle time to V8. This should
148 // be done using the scheduler instead.
149 V8GCForContextDispose::Instance().NotifyIdle();
150 }
151 auto* action = MakeGarbageCollected<ScheduledAction>(
152 script_state, execution_context, handler, arguments);
153 return DOMTimer::Install(execution_context, action,
154 base::TimeDelta::FromMilliseconds(timeout), true);
155 }
156
setTimeout(ScriptState * script_state,EventTarget & event_target,const String & handler,int timeout,const HeapVector<ScriptValue> &)157 int WindowOrWorkerGlobalScope::setTimeout(ScriptState* script_state,
158 EventTarget& event_target,
159 const String& handler,
160 int timeout,
161 const HeapVector<ScriptValue>&) {
162 ExecutionContext* execution_context = event_target.GetExecutionContext();
163 if (!IsAllowed(execution_context, true, handler))
164 return 0;
165 // Don't allow setting timeouts to run empty functions. Was historically a
166 // performance issue.
167 if (handler.IsEmpty())
168 return 0;
169 if (timeout >= 0 && execution_context->IsWindow()) {
170 // FIXME: Crude hack that attempts to pass idle time to V8. This should
171 // be done using the scheduler instead.
172 V8GCForContextDispose::Instance().NotifyIdle();
173 }
174 auto* action = MakeGarbageCollected<ScheduledAction>(
175 script_state, execution_context, handler);
176 return DOMTimer::Install(execution_context, action,
177 base::TimeDelta::FromMilliseconds(timeout), true);
178 }
179
setInterval(ScriptState * script_state,EventTarget & event_target,V8Function * handler,int timeout,const HeapVector<ScriptValue> & arguments)180 int WindowOrWorkerGlobalScope::setInterval(
181 ScriptState* script_state,
182 EventTarget& event_target,
183 V8Function* handler,
184 int timeout,
185 const HeapVector<ScriptValue>& arguments) {
186 ExecutionContext* execution_context = event_target.GetExecutionContext();
187 if (!IsAllowed(execution_context, false, g_empty_string))
188 return 0;
189 auto* action = MakeGarbageCollected<ScheduledAction>(
190 script_state, execution_context, handler, arguments);
191 return DOMTimer::Install(execution_context, action,
192 base::TimeDelta::FromMilliseconds(timeout), false);
193 }
194
setInterval(ScriptState * script_state,EventTarget & event_target,const String & handler,int timeout,const HeapVector<ScriptValue> &)195 int WindowOrWorkerGlobalScope::setInterval(ScriptState* script_state,
196 EventTarget& event_target,
197 const String& handler,
198 int timeout,
199 const HeapVector<ScriptValue>&) {
200 ExecutionContext* execution_context = event_target.GetExecutionContext();
201 if (!IsAllowed(execution_context, true, handler))
202 return 0;
203 // Don't allow setting timeouts to run empty functions. Was historically a
204 // performance issue.
205 if (handler.IsEmpty())
206 return 0;
207 auto* action = MakeGarbageCollected<ScheduledAction>(
208 script_state, execution_context, handler);
209 return DOMTimer::Install(execution_context, action,
210 base::TimeDelta::FromMilliseconds(timeout), false);
211 }
212
clearTimeout(EventTarget & event_target,int timeout_id)213 void WindowOrWorkerGlobalScope::clearTimeout(EventTarget& event_target,
214 int timeout_id) {
215 if (ExecutionContext* context = event_target.GetExecutionContext())
216 DOMTimer::RemoveByID(context, timeout_id);
217 }
218
clearInterval(EventTarget & event_target,int timeout_id)219 void WindowOrWorkerGlobalScope::clearInterval(EventTarget& event_target,
220 int timeout_id) {
221 if (ExecutionContext* context = event_target.GetExecutionContext())
222 DOMTimer::RemoveByID(context, timeout_id);
223 }
224
createImageBitmap(ScriptState * script_state,EventTarget &,const ImageBitmapSourceUnion & bitmap_source,const ImageBitmapOptions * options,ExceptionState & exception_state)225 ScriptPromise WindowOrWorkerGlobalScope::createImageBitmap(
226 ScriptState* script_state,
227 EventTarget&,
228 const ImageBitmapSourceUnion& bitmap_source,
229 const ImageBitmapOptions* options,
230 ExceptionState& exception_state) {
231 return ImageBitmapFactories::CreateImageBitmap(script_state, bitmap_source,
232 options, exception_state);
233 }
234
createImageBitmap(ScriptState * script_state,EventTarget &,const ImageBitmapSourceUnion & bitmap_source,int sx,int sy,int sw,int sh,const ImageBitmapOptions * options,ExceptionState & exception_state)235 ScriptPromise WindowOrWorkerGlobalScope::createImageBitmap(
236 ScriptState* script_state,
237 EventTarget&,
238 const ImageBitmapSourceUnion& bitmap_source,
239 int sx,
240 int sy,
241 int sw,
242 int sh,
243 const ImageBitmapOptions* options,
244 ExceptionState& exception_state) {
245 return ImageBitmapFactories::CreateImageBitmap(
246 script_state, bitmap_source, sx, sy, sw, sh, options, exception_state);
247 }
248
crossOriginIsolated(const ExecutionContext & execution_context)249 bool WindowOrWorkerGlobalScope::crossOriginIsolated(
250 const ExecutionContext& execution_context) {
251 return execution_context.CrossOriginIsolatedCapability();
252 }
253
254 } // namespace blink
255