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