Rename ENABLE_ENCRYPTED_MEDIA_V2 to ENABLE_LEGACY_ENCRYPTED_MEDIA
[WebKit.git] / Source / WebCore / bindings / js / JSDictionary.cpp
1 /*
2  * Copyright (C) 2011, 2016 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  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "JSDictionary.h"
28
29 #include "ArrayValue.h"
30 #include "DOMWindow.h"
31 #include "Dictionary.h"
32 #include "JSCSSFontFaceRule.h"
33 #include "JSDOMError.h"
34 #include "JSDOMWindow.h"
35 #include "JSEventTarget.h"
36 #include "JSMessagePortCustom.h"
37 #include "JSNode.h"
38 #include "JSStorage.h"
39 #include "JSTrackCustom.h"
40 #include "JSVoidCallback.h"
41 #include "SerializedScriptValue.h"
42 #include <runtime/JSTypedArrays.h>
43 #include <wtf/HashSet.h>
44 #include <wtf/MathExtras.h>
45 #include <wtf/text/AtomicString.h>
46
47 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
48 #include "JSMediaKeyError.h"
49 #endif
50
51 #if ENABLE(FETCH_API)
52 #include "JSFetchHeaders.h"
53 #endif
54
55 #if ENABLE(MEDIA_STREAM)
56 #include "JSMediaStream.h"
57 #include "JSMediaStreamTrack.h"
58 #include "JSOverconstrainedError.h"
59 #endif
60
61 #if ENABLE(WEB_RTC)
62 #include "JSRTCRtpReceiver.h"
63 #include "JSRTCRtpTransceiver.h"
64 #endif
65
66
67 #if ENABLE(GAMEPAD)
68 #include "JSGamepad.h"
69 #endif
70
71 #if ENABLE(IOS_TOUCH_EVENTS) || ENABLE(TOUCH_EVENTS)
72 #include "JSTouch.h"
73 #include "JSTouchList.h"
74 #endif
75
76 using namespace JSC;
77
78 namespace WebCore {
79
80 JSDictionary::GetPropertyResult JSDictionary::tryGetProperty(const char* propertyName, JSValue& finalResult) const
81 {
82     VM& vm = m_exec->vm();
83     auto scope = DECLARE_THROW_SCOPE(vm);
84     ASSERT(isValid());
85     Identifier identifier = Identifier::fromString(m_exec, propertyName);
86     bool propertyFound = m_initializerObject.get()->getPropertySlot(m_exec, identifier, [&] (bool propertyFound, PropertySlot& slot) -> bool {
87         if (!propertyFound)
88             return false;
89         finalResult = slot.getValue(m_exec, identifier);
90         return true;
91     });
92     RETURN_IF_EXCEPTION(scope, ExceptionThrown);
93     return propertyFound ? PropertyFound : NoPropertyFound;
94 }
95
96 void JSDictionary::convertValue(ExecState* exec, JSValue value, bool& result)
97 {
98     result = value.toBoolean(exec);
99 }
100
101 void JSDictionary::convertValue(ExecState* exec, JSValue value, int& result)
102 {
103     result = value.toInt32(exec);
104 }
105
106 void JSDictionary::convertValue(ExecState* exec, JSValue value, long int& result)
107 {
108     result = value.toInt32(exec);
109 }
110
111 void JSDictionary::convertValue(ExecState* exec, JSValue value, unsigned& result)
112 {
113     result = value.toUInt32(exec);
114 }
115
116 void JSDictionary::convertValue(ExecState* exec, JSValue value, unsigned short& result)
117 {
118     result = static_cast<unsigned short>(value.toUInt32(exec));
119 }
120
121 void JSDictionary::convertValue(ExecState* exec, JSValue value, unsigned long& result)
122 {
123     result = static_cast<unsigned long>(value.toUInt32(exec));
124 }
125
126 void JSDictionary::convertValue(ExecState* exec, JSValue value, unsigned long long& result)
127 {
128     double d = value.toNumber(exec);
129     doubleToInteger(d, result);
130 }
131
132 void JSDictionary::convertValue(ExecState* exec, JSValue value, long long& result)
133 {
134     double d = value.toNumber(exec);
135     result = llrint(d);
136 }
137
138 void JSDictionary::convertValue(ExecState* exec, JSValue value, double& result)
139 {
140     result = value.toNumber(exec);
141 }
142
143 void JSDictionary::convertValue(JSC::ExecState* exec, JSC::JSValue value, Dictionary& result)
144 {
145     result = Dictionary(exec, value);
146 }
147
148 void JSDictionary::convertValue(ExecState* exec, JSValue value, String& result)
149 {
150     result = value.toString(exec)->value(exec);
151 }
152
153 void JSDictionary::convertValue(ExecState* exec, JSValue value, Vector<String>& result)
154 {
155     ASSERT(exec);
156     VM& vm = exec->vm();
157     auto scope = DECLARE_THROW_SCOPE(vm);
158
159     if (value.isUndefinedOrNull())
160         return;
161
162     unsigned length = 0;
163     JSObject* object = toJSSequence(*exec, value, length);
164     RETURN_IF_EXCEPTION(scope, void());
165
166     for (unsigned i = 0 ; i < length; ++i) {
167         JSValue itemValue = object->get(exec, i);
168         RETURN_IF_EXCEPTION(scope, void());
169         result.append(itemValue.toString(exec)->value(exec));
170     }
171 }
172
173 void JSDictionary::convertValue(ExecState* exec, JSValue value, Deprecated::ScriptValue& result)
174 {
175     result = Deprecated::ScriptValue(exec->vm(), value);
176 }
177
178 void JSDictionary::convertValue(ExecState* exec, JSValue value, RefPtr<SerializedScriptValue>& result)
179 {
180     result = SerializedScriptValue::create(exec, value, 0, 0);
181 }
182
183 void JSDictionary::convertValue(ExecState* state, JSValue value, RefPtr<DOMWindow>& result)
184 {
185     VM& vm = state->vm();
186     auto scope = DECLARE_THROW_SCOPE(vm);
187
188     auto* window = JSDOMWindow::toWrapped(value);
189     if (UNLIKELY(!window) && !value.isUndefinedOrNull()) {
190         throwVMTypeError(state, scope, "Dictionary member is not of type Window");
191         return;
192     }
193     result = window;
194 }
195
196 void JSDictionary::convertValue(ExecState*, JSValue value, RefPtr<EventTarget>& result)
197 {
198     result = JSEventTarget::toWrapped(value);
199 }
200
201 void JSDictionary::convertValue(ExecState*, JSValue value, RefPtr<Node>& result)
202 {
203     result = JSNode::toWrapped(value);
204 }
205
206 void JSDictionary::convertValue(ExecState*, JSValue value, RefPtr<Storage>& result)
207 {
208     result = JSStorage::toWrapped(value);
209 }
210
211 void JSDictionary::convertValue(ExecState* exec, JSValue value, MessagePortArray& result)
212 {
213     ArrayBufferArray arrayBuffers;
214     fillMessagePortArray(*exec, value, result, arrayBuffers);
215 }
216
217 #if ENABLE(VIDEO_TRACK)
218 void JSDictionary::convertValue(ExecState*, JSValue value, RefPtr<TrackBase>& result)
219 {
220     result = toTrack(value);
221 }
222 #endif
223
224 void JSDictionary::convertValue(ExecState* exec, JSValue value, HashSet<AtomicString>& result)
225 {
226     ASSERT(exec);
227     VM& vm = exec->vm();
228     auto scope = DECLARE_THROW_SCOPE(vm);
229
230     result.clear();
231
232     if (value.isUndefinedOrNull())
233         return;
234
235     unsigned length = 0;
236     JSObject* object = toJSSequence(*exec, value, length);
237     RETURN_IF_EXCEPTION(scope, void());
238
239     for (unsigned i = 0 ; i < length; ++i) {
240         JSValue itemValue = object->get(exec, i);
241         RETURN_IF_EXCEPTION(scope, void());
242         result.add(itemValue.toString(exec)->value(exec));
243     }
244 }
245
246 void JSDictionary::convertValue(ExecState* exec, JSValue value, ArrayValue& result)
247 {
248     if (value.isUndefinedOrNull())
249         return;
250
251     result = ArrayValue(exec, value);
252 }
253
254 void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<Uint8Array>& result)
255 {
256     result = toUint8Array(value);
257 }
258
259 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
260 void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<MediaKeyError>& result)
261 {
262     result = JSMediaKeyError::toWrapped(value);
263 }
264 #endif
265
266 #if ENABLE(FETCH_API)
267 void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<FetchHeaders>& result)
268 {
269     result = JSFetchHeaders::toWrapped(value);
270 }
271 #endif
272
273 #if ENABLE(MEDIA_STREAM)
274 void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<MediaStream>& result)
275 {
276     result = JSMediaStream::toWrapped(value);
277 }
278
279 void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<MediaStreamTrack>& result)
280 {
281     result = JSMediaStreamTrack::toWrapped(value);
282 }
283
284 void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<OverconstrainedError>& result)
285 {
286     result = JSOverconstrainedError::toWrapped(value);
287 }
288 #endif
289
290 #if ENABLE(WEB_RTC)
291 void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<RTCRtpReceiver>& result)
292 {
293     result = JSRTCRtpReceiver::toWrapped(value);
294 }
295
296 void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<RTCRtpTransceiver>& result)
297 {
298     result = JSRTCRtpTransceiver::toWrapped(value);
299 }
300
301 void JSDictionary::convertValue(ExecState* exec, JSValue value, Vector<RefPtr<MediaStream>>& result)
302 {
303     ASSERT(exec);
304     VM& vm = exec->vm();
305     auto scope = DECLARE_THROW_SCOPE(vm);
306
307     if (value.isUndefinedOrNull())
308         return;
309
310     unsigned length = 0;
311     JSObject* object = toJSSequence(*exec, value, length);
312     RETURN_IF_EXCEPTION(scope, void());
313
314     for (unsigned i = 0 ; i < length; ++i) {
315         JSValue itemValue = object->get(exec, i);
316         RETURN_IF_EXCEPTION(scope, void());
317
318         auto stream = JSMediaStream::toWrapped(itemValue);
319         if (!stream) {
320             setDOMException(exec, TypeError);
321             return;
322         }
323         result.append(stream);
324     }
325 }
326 #endif
327
328 #if ENABLE(FONT_LOAD_EVENTS)
329 void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<CSSFontFaceRule>& result)
330 {
331     result = JSCSSFontFaceRule::toWrapped(value);
332 }
333
334 void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<DOMError>& result)
335 {
336     result = JSDOMError::toWrapped(value);
337 }
338
339 void JSDictionary::convertValue(JSC::ExecState* exec, JSC::JSValue value, RefPtr<VoidCallback>& result)
340 {
341     if (!value.isFunction())
342         return;
343
344     result = JSVoidCallback::create(asObject(value), jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()));
345 }
346 #endif
347
348 #if ENABLE(GAMEPAD)
349 void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<Gamepad>& result)
350 {
351     result = JSGamepad::toWrapped(value);
352 }
353 #endif
354
355 #if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
356 void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<TouchList>& result)
357 {
358     result = JSTouchList::toWrapped(value);
359 }
360 #endif
361
362 #if ENABLE(IOS_TOUCH_EVENTS)
363 void JSDictionary::convertValue(JSC::ExecState* exec, JSC::JSValue value, RefPtr<TouchList>& result)
364 {
365     VM& vm = exec->vm();
366     auto scope = DECLARE_THROW_SCOPE(vm);
367
368     JSObject* object = value.getObject();
369     if (!object) {
370         result = nullptr;
371         return;
372     }
373
374     // Allow both TouchList and sequence<Touch> as input.
375     const ClassInfo* classInfo = object->classInfo();
376     if (classInfo == JSTouchList::info()) {
377         result = JSTouchList::toWrapped(value);
378         return;
379     }
380
381     auto touches = toRefNativeArray<Touch, JSTouch>(*exec, value);
382     RETURN_IF_EXCEPTION(scope, void());
383     result = TouchList::create(WTFMove(touches));
384 }
385 #endif
386
387 void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, JSC::JSFunction*& result)
388 {
389     result = jsDynamicCast<JSC::JSFunction*>(value);
390 }
391
392 bool JSDictionary::getWithUndefinedOrNullCheck(const char* propertyName, String& result) const
393 {
394     ASSERT(isValid());
395     JSValue value;
396     if (tryGetProperty(propertyName, value) != PropertyFound || value.isUndefinedOrNull())
397         return false;
398
399     result = value.toWTFString(m_exec);
400     return true;
401 }
402
403 } // namespace WebCore