1/*
2 * Copyright (C) 2012 University of Washington. All rights reserved.
3 * Copyright (C) 2014 Apple Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1.  Redistributions of source code must retain the above copyright
10 *     notice, this list of conditions and the following disclaimer.
11 * 2.  Redistributions in binary form must reproduce the above copyright
12 *     notice, this list of conditions and the following disclaimer in the
13 *     documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "config.h"
29#include "SerializationMethods.h"
30
31#if ENABLE(WEB_REPLAY)
32
33#include "AllReplayInputs.h"
34#include "Document.h"
35#include "Frame.h"
36#include "FrameTree.h"
37#include "MainFrame.h"
38#include "Page.h"
39#include "PlatformKeyboardEvent.h"
40#include "PlatformMouseEvent.h"
41#include "PlatformWheelEvent.h"
42#include "PluginData.h"
43#include "ReplayInputTypes.h"
44#include "SecurityOrigin.h"
45#include "URL.h"
46#include <wtf/text/Base64.h>
47
48using WebCore::IntPoint;
49using WebCore::MimeClassInfo;
50using WebCore::MouseButton;
51using WebCore::PlatformEvent;
52using WebCore::PlatformKeyboardEvent;
53using WebCore::PlatformMouseEvent;
54using WebCore::PlatformWheelEvent;
55using WebCore::PlatformWheelEventGranularity;
56using WebCore::PluginData;
57using WebCore::PluginInfo;
58using WebCore::SecurityOrigin;
59using WebCore::URL;
60using WebCore::inputTypes;
61
62#if PLATFORM(COCOA)
63using WebCore::KeypressCommand;
64using WebCore::PlatformWheelEventPhase;
65#endif
66
67#define IMPORT_FROM_WEBCORE_NAMESPACE(name) \
68using WebCore::name; \
69
70WEB_REPLAY_INPUT_NAMES_FOR_EACH(IMPORT_FROM_WEBCORE_NAMESPACE)
71#undef IMPORT_FROM_WEBCORE_NAMESPACE
72
73namespace WebCore {
74
75unsigned long frameIndexFromDocument(const Document* document)
76{
77    ASSERT(document);
78    ASSERT(document->frame());
79    return frameIndexFromFrame(document->frame());
80}
81
82unsigned long frameIndexFromFrame(const Frame* targetFrame)
83{
84    ASSERT(targetFrame);
85
86    unsigned long currentIndex = 0;
87    const Frame* mainFrame = &targetFrame->tree().top();
88    for (const Frame* frame = mainFrame; frame; ++currentIndex, frame = frame->tree().traverseNext(mainFrame)) {
89        if (frame == targetFrame)
90            return currentIndex;
91    }
92
93    ASSERT_NOT_REACHED();
94    return 0;
95}
96
97Document* documentFromFrameIndex(Page* page, unsigned long frameIndex)
98{
99    Frame* frame = frameFromFrameIndex(page, frameIndex);
100    return frame ? frame->document() : nullptr;
101}
102
103Frame* frameFromFrameIndex(Page* page, unsigned long frameIndex)
104{
105    ASSERT(page);
106    ASSERT(frameIndex >= 0);
107
108    MainFrame* mainFrame = &page->mainFrame();
109    Frame* frame = mainFrame;
110    unsigned long currentIndex = 0;
111    for (; currentIndex < frameIndex && frame; ++currentIndex, frame = frame->tree().traverseNext(mainFrame)) { }
112
113    return frame;
114}
115
116} // namespace WebCore
117
118#define ENCODE_TYPE_WITH_KEY(_encodedValue, _type, _key, _value) \
119    _encodedValue.put<_type>(ASCIILiteral(#_key), _value)
120
121#define ENCODE_OPTIONAL_TYPE_WITH_KEY(_encodedValue, _type, _key, _value, condition) \
122    if (condition) \
123        ENCODE_TYPE_WITH_KEY(_encodedValue, _type, _key, _value)
124
125#define DECODE_TYPE_WITH_KEY_TO_LVALUE(_encodedValue, _type, _key, _lvalue) \
126    if (!_encodedValue.get<_type>(ASCIILiteral(#_key), _lvalue)) \
127        return false
128
129#define DECODE_TYPE_WITH_KEY(_encodedValue, _type, _key) \
130    EncodingTraits<_type>::DecodedType _key; \
131    DECODE_TYPE_WITH_KEY_TO_LVALUE(_encodedValue, _type, _key, _key)
132
133#define DECODE_OPTIONAL_TYPE_WITH_KEY_TO_LVALUE(_encodedValue, _type, _key, _lvalue) \
134    bool _key ## WasDecoded = _encodedValue.get<_type>(ASCIILiteral(#_key), _lvalue)
135
136#define DECODE_OPTIONAL_TYPE_WITH_KEY(_encodedValue, _type, _key) \
137    EncodingTraits<_type>::DecodedType _key; \
138    DECODE_OPTIONAL_TYPE_WITH_KEY_TO_LVALUE(_encodedValue, _type, _key, _key)
139
140namespace JSC {
141
142template<>
143EncodedValue EncodingTraits<MimeClassInfo>::encodeValue(const MimeClassInfo& input)
144{
145    EncodedValue encodedData = EncodedValue::createObject();
146
147    ENCODE_TYPE_WITH_KEY(encodedData, String, type, input.type);
148    ENCODE_TYPE_WITH_KEY(encodedData, String, desc, input.desc);
149    ENCODE_TYPE_WITH_KEY(encodedData, Vector<String>, extensions, input.extensions);
150
151    return encodedData;
152}
153
154template<>
155bool EncodingTraits<MimeClassInfo>::decodeValue(EncodedValue& encodedData, MimeClassInfo& input)
156{
157    MimeClassInfo info;
158
159    DECODE_TYPE_WITH_KEY_TO_LVALUE(encodedData, String, type, info.type);
160    DECODE_TYPE_WITH_KEY_TO_LVALUE(encodedData, String, desc, info.desc);
161    DECODE_TYPE_WITH_KEY_TO_LVALUE(encodedData, Vector<String>, extensions, info.extensions);
162
163    input = info;
164    return true;
165}
166
167EncodedValue EncodingTraits<NondeterministicInputBase>::encodeValue(const NondeterministicInputBase& input)
168{
169    EncodedValue encodedValue = EncodedValue::createObject();
170    const AtomicString& type = input.type();
171
172    ENCODE_TYPE_WITH_KEY(encodedValue, String, type, type.string());
173
174#define ENCODE_IF_TYPE_TAG_MATCHES(name) \
175    if (type == inputTypes().name) { \
176        InputTraits<name>::encode(encodedValue, static_cast<const name&>(input)); \
177        return encodedValue; \
178    } \
179
180    JS_REPLAY_INPUT_NAMES_FOR_EACH(ENCODE_IF_TYPE_TAG_MATCHES)
181    WEB_REPLAY_INPUT_NAMES_FOR_EACH(ENCODE_IF_TYPE_TAG_MATCHES)
182#undef ENCODE_IF_TYPE_TAG_MATCHES
183
184    // The macro won't work here because of the class template argument.
185    if (type == inputTypes().MemoizedDOMResult) {
186        InputTraits<MemoizedDOMResultBase>::encode(encodedValue, static_cast<const MemoizedDOMResultBase&>(input));
187        return encodedValue;
188    }
189
190    ASSERT_NOT_REACHED();
191    return EncodedValue();
192}
193
194bool EncodingTraits<NondeterministicInputBase>::decodeValue(EncodedValue& encodedValue, std::unique_ptr<NondeterministicInputBase>& input)
195{
196    DECODE_TYPE_WITH_KEY(encodedValue, String, type);
197
198#define DECODE_IF_TYPE_TAG_MATCHES(name) \
199    if (type == inputTypes().name) { \
200        std::unique_ptr<name> decodedInput; \
201        if (!InputTraits<name>::decode(encodedValue, decodedInput)) \
202            return false; \
203        \
204        input = WTF::move(decodedInput); \
205        return true; \
206    } \
207
208    JS_REPLAY_INPUT_NAMES_FOR_EACH(DECODE_IF_TYPE_TAG_MATCHES)
209    WEB_REPLAY_INPUT_NAMES_FOR_EACH(DECODE_IF_TYPE_TAG_MATCHES)
210#undef DECODE_IF_TYPE_TAG_MATCHES
211
212    if (type == inputTypes().MemoizedDOMResult) {
213        std::unique_ptr<MemoizedDOMResultBase> decodedInput;
214        if (!InputTraits<MemoizedDOMResultBase>::decode(encodedValue, decodedInput))
215            return false;
216
217        input = WTF::move(decodedInput);
218        return true;
219    }
220
221    return false;
222}
223
224#if USE(APPKIT)
225EncodedValue EncodingTraits<KeypressCommand>::encodeValue(const KeypressCommand& command)
226{
227    EncodedValue encodedValue = EncodedValue::createObject();
228
229    ENCODE_TYPE_WITH_KEY(encodedValue, String, commandName, command.commandName);
230    ENCODE_OPTIONAL_TYPE_WITH_KEY(encodedValue, String, text, command.text, !command.text.isEmpty());
231
232    return encodedValue;
233}
234
235bool EncodingTraits<KeypressCommand>::decodeValue(EncodedValue& encodedValue, KeypressCommand& decodedValue)
236{
237    DECODE_TYPE_WITH_KEY(encodedValue, String, commandName);
238    DECODE_OPTIONAL_TYPE_WITH_KEY(encodedValue, String, text);
239
240    decodedValue = textWasDecoded ? KeypressCommand(commandName, text) : KeypressCommand(commandName);
241    return true;
242}
243
244class PlatformKeyboardEventAppKit : public WebCore::PlatformKeyboardEvent {
245public:
246    PlatformKeyboardEventAppKit(const PlatformKeyboardEvent& event, bool handledByInputMethod, Vector<KeypressCommand>& commands)
247        : PlatformKeyboardEvent(event)
248    {
249        m_handledByInputMethod = handledByInputMethod;
250        m_commands = commands;
251    }
252};
253#endif // USE(APPKIT)
254
255EncodedValue EncodingTraits<PlatformKeyboardEvent>::encodeValue(const PlatformKeyboardEvent& input)
256{
257    EncodedValue encodedValue = EncodedValue::createObject();
258
259    ENCODE_TYPE_WITH_KEY(encodedValue, double, timestamp, input.timestamp());
260    ENCODE_TYPE_WITH_KEY(encodedValue, PlatformEvent::Type, type, input.type());
261    ENCODE_TYPE_WITH_KEY(encodedValue, PlatformEvent::Modifiers, modifiers, static_cast<PlatformEvent::Modifiers>(input.modifiers()));
262    ENCODE_TYPE_WITH_KEY(encodedValue, String, text, input.text());
263    ENCODE_TYPE_WITH_KEY(encodedValue, String, unmodifiedText, input.unmodifiedText());
264    ENCODE_TYPE_WITH_KEY(encodedValue, String, keyIdentifier, input.keyIdentifier());
265    ENCODE_TYPE_WITH_KEY(encodedValue, int, windowsVirtualKeyCode, input.windowsVirtualKeyCode());
266    ENCODE_TYPE_WITH_KEY(encodedValue, int, nativeVirtualKeyCode, input.nativeVirtualKeyCode());
267    ENCODE_TYPE_WITH_KEY(encodedValue, int, macCharCode, input.macCharCode());
268    ENCODE_TYPE_WITH_KEY(encodedValue, bool, autoRepeat, input.isAutoRepeat());
269    ENCODE_TYPE_WITH_KEY(encodedValue, bool, keypad, input.isKeypad());
270    ENCODE_TYPE_WITH_KEY(encodedValue, bool, systemKey, input.isSystemKey());
271#if USE(APPKIT)
272    ENCODE_TYPE_WITH_KEY(encodedValue, bool, handledByInputMethod, input.handledByInputMethod());
273    ENCODE_TYPE_WITH_KEY(encodedValue, Vector<KeypressCommand>, commands, input.commands());
274#endif
275    return encodedValue;
276}
277
278bool EncodingTraits<PlatformKeyboardEvent>::decodeValue(EncodedValue& encodedValue, std::unique_ptr<PlatformKeyboardEvent>& input)
279{
280    DECODE_TYPE_WITH_KEY(encodedValue, double, timestamp);
281    DECODE_TYPE_WITH_KEY(encodedValue, PlatformEvent::Type, type);
282    DECODE_TYPE_WITH_KEY(encodedValue, PlatformEvent::Modifiers, modifiers);
283    DECODE_TYPE_WITH_KEY(encodedValue, String, text);
284    DECODE_TYPE_WITH_KEY(encodedValue, String, unmodifiedText);
285    DECODE_TYPE_WITH_KEY(encodedValue, String, keyIdentifier);
286    DECODE_TYPE_WITH_KEY(encodedValue, int, windowsVirtualKeyCode);
287    DECODE_TYPE_WITH_KEY(encodedValue, int, nativeVirtualKeyCode);
288    DECODE_TYPE_WITH_KEY(encodedValue, int, macCharCode);
289    DECODE_TYPE_WITH_KEY(encodedValue, bool, autoRepeat);
290    DECODE_TYPE_WITH_KEY(encodedValue, bool, keypad);
291    DECODE_TYPE_WITH_KEY(encodedValue, bool, systemKey);
292#if USE(APPKIT)
293    DECODE_TYPE_WITH_KEY(encodedValue, bool, handledByInputMethod);
294    DECODE_TYPE_WITH_KEY(encodedValue, Vector<KeypressCommand>, commands);
295#endif
296
297    PlatformKeyboardEvent platformEvent = PlatformKeyboardEvent(type, text, unmodifiedText, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, macCharCode, autoRepeat, keypad, systemKey, modifiers, timestamp);
298#if USE(APPKIT)
299    input = std::make_unique<PlatformKeyboardEventAppKit>(platformEvent, handledByInputMethod, commands);
300#else
301    input = std::make_unique<PlatformKeyboardEvent>(platformEvent);
302#endif
303    return true;
304}
305
306EncodedValue EncodingTraits<PlatformMouseEvent>::encodeValue(const PlatformMouseEvent& input)
307{
308    EncodedValue encodedValue = EncodedValue::createObject();
309
310    ENCODE_TYPE_WITH_KEY(encodedValue, int, positionX, input.position().x());
311    ENCODE_TYPE_WITH_KEY(encodedValue, int, positionY, input.position().y());
312    ENCODE_TYPE_WITH_KEY(encodedValue, int, globalPositionX, input.globalPosition().x());
313    ENCODE_TYPE_WITH_KEY(encodedValue, int, globalPositionY, input.globalPosition().y());
314    ENCODE_TYPE_WITH_KEY(encodedValue, MouseButton, button, input.button());
315    ENCODE_TYPE_WITH_KEY(encodedValue, PlatformEvent::Type, type, input.type());
316    ENCODE_TYPE_WITH_KEY(encodedValue, int, clickCount, input.clickCount());
317    ENCODE_TYPE_WITH_KEY(encodedValue, bool, shiftKey, input.shiftKey());
318    ENCODE_TYPE_WITH_KEY(encodedValue, bool, ctrlKey, input.ctrlKey());
319    ENCODE_TYPE_WITH_KEY(encodedValue, bool, altKey, input.altKey());
320    ENCODE_TYPE_WITH_KEY(encodedValue, bool, metaKey, input.metaKey());
321    ENCODE_TYPE_WITH_KEY(encodedValue, int, timestamp, input.timestamp());
322
323    return encodedValue;
324}
325
326bool EncodingTraits<PlatformMouseEvent>::decodeValue(EncodedValue& encodedValue, std::unique_ptr<PlatformMouseEvent>& input)
327{
328    DECODE_TYPE_WITH_KEY(encodedValue, int, positionX);
329    DECODE_TYPE_WITH_KEY(encodedValue, int, positionY);
330    DECODE_TYPE_WITH_KEY(encodedValue, int, globalPositionX);
331    DECODE_TYPE_WITH_KEY(encodedValue, int, globalPositionY);
332    DECODE_TYPE_WITH_KEY(encodedValue, MouseButton, button);
333    DECODE_TYPE_WITH_KEY(encodedValue, PlatformEvent::Type, type);
334    DECODE_TYPE_WITH_KEY(encodedValue, int, clickCount);
335    DECODE_TYPE_WITH_KEY(encodedValue, bool, shiftKey);
336    DECODE_TYPE_WITH_KEY(encodedValue, bool, ctrlKey);
337    DECODE_TYPE_WITH_KEY(encodedValue, bool, altKey);
338    DECODE_TYPE_WITH_KEY(encodedValue, bool, metaKey);
339    DECODE_TYPE_WITH_KEY(encodedValue, int, timestamp);
340
341    input = std::make_unique<PlatformMouseEvent>(IntPoint(positionX, positionY),
342        IntPoint(globalPositionX, globalPositionY),
343        button, type, clickCount,
344        shiftKey, ctrlKey, altKey, metaKey, timestamp);
345    return true;
346}
347
348#if PLATFORM(COCOA)
349struct PlatformWheelEventCocoaArguments {
350    bool directionInvertedFromDevice;
351    bool hasPreciseScrollingDeltas;
352    PlatformWheelEventPhase phase;
353    PlatformWheelEventPhase momentumPhase;
354    int scrollCount;
355    float unacceleratedScrollingDeltaX;
356    float unacceleratedScrollingDeltaY;
357};
358
359class PlatformWheelEventCocoa : public PlatformWheelEvent {
360public:
361    PlatformWheelEventCocoa(PlatformWheelEvent& event, PlatformWheelEventCocoaArguments& arguments)
362        : PlatformWheelEvent(event)
363    {
364        m_directionInvertedFromDevice = arguments.directionInvertedFromDevice;
365        m_hasPreciseScrollingDeltas = arguments.hasPreciseScrollingDeltas;
366        m_phase = arguments.phase;
367        m_momentumPhase = arguments.momentumPhase;
368        m_scrollCount = arguments.scrollCount;
369        m_unacceleratedScrollingDeltaX = arguments.unacceleratedScrollingDeltaX;
370        m_unacceleratedScrollingDeltaY = arguments.unacceleratedScrollingDeltaY;
371    }
372};
373#endif // PLATFORM(COCOA)
374
375EncodedValue EncodingTraits<PlatformWheelEvent>::encodeValue(const PlatformWheelEvent& input)
376{
377    EncodedValue encodedData = EncodedValue::createObject();
378
379    ENCODE_TYPE_WITH_KEY(encodedData, int, positionX, input.position().x());
380    ENCODE_TYPE_WITH_KEY(encodedData, int, positionY, input.position().y());
381    ENCODE_TYPE_WITH_KEY(encodedData, int, globalPositionX, input.globalPosition().x());
382    ENCODE_TYPE_WITH_KEY(encodedData, int, globalPositionY, input.globalPosition().y());
383    ENCODE_TYPE_WITH_KEY(encodedData, bool, shiftKey, input.shiftKey());
384    ENCODE_TYPE_WITH_KEY(encodedData, bool, ctrlKey, input.ctrlKey());
385    ENCODE_TYPE_WITH_KEY(encodedData, bool, altKey, input.altKey());
386    ENCODE_TYPE_WITH_KEY(encodedData, bool, metaKey, input.metaKey());
387    ENCODE_TYPE_WITH_KEY(encodedData, float, deltaX, input.deltaX());
388    ENCODE_TYPE_WITH_KEY(encodedData, float, deltaY, input.deltaY());
389    ENCODE_TYPE_WITH_KEY(encodedData, float, wheelTicksX, input.wheelTicksX());
390    ENCODE_TYPE_WITH_KEY(encodedData, float, wheelTicksY, input.wheelTicksY());
391    ENCODE_TYPE_WITH_KEY(encodedData, PlatformWheelEventGranularity, granularity, static_cast<PlatformWheelEventGranularity>(input.granularity()));
392
393#if PLATFORM(COCOA)
394    ENCODE_TYPE_WITH_KEY(encodedData, bool, directionInvertedFromDevice, input.directionInvertedFromDevice());
395    ENCODE_TYPE_WITH_KEY(encodedData, bool, hasPreciseScrollingDeltas, input.hasPreciseScrollingDeltas());
396    ENCODE_TYPE_WITH_KEY(encodedData, PlatformWheelEventPhase, phase, static_cast<PlatformWheelEventPhase>(input.phase()));
397    ENCODE_TYPE_WITH_KEY(encodedData, PlatformWheelEventPhase, momentumPhase, static_cast<PlatformWheelEventPhase>(input.momentumPhase()));
398    ENCODE_TYPE_WITH_KEY(encodedData, int, scrollCount, input.scrollCount());
399    ENCODE_TYPE_WITH_KEY(encodedData, float, unacceleratedScrollingDeltaX, input.unacceleratedScrollingDeltaX());
400    ENCODE_TYPE_WITH_KEY(encodedData, float, unacceleratedScrollingDeltaY, input.unacceleratedScrollingDeltaY());
401#endif
402
403    return encodedData;
404}
405
406bool EncodingTraits<PlatformWheelEvent>::decodeValue(EncodedValue& encodedData, std::unique_ptr<PlatformWheelEvent>& input)
407{
408    DECODE_TYPE_WITH_KEY(encodedData, int, positionX);
409    DECODE_TYPE_WITH_KEY(encodedData, int, positionY);
410    DECODE_TYPE_WITH_KEY(encodedData, int, globalPositionX);
411    DECODE_TYPE_WITH_KEY(encodedData, int, globalPositionY);
412    DECODE_TYPE_WITH_KEY(encodedData, bool, shiftKey);
413    DECODE_TYPE_WITH_KEY(encodedData, bool, ctrlKey);
414    DECODE_TYPE_WITH_KEY(encodedData, bool, altKey);
415    DECODE_TYPE_WITH_KEY(encodedData, bool, metaKey);
416    DECODE_TYPE_WITH_KEY(encodedData, float, deltaX);
417    DECODE_TYPE_WITH_KEY(encodedData, float, deltaY);
418    DECODE_TYPE_WITH_KEY(encodedData, float, wheelTicksX);
419    DECODE_TYPE_WITH_KEY(encodedData, float, wheelTicksY);
420    DECODE_TYPE_WITH_KEY(encodedData, PlatformWheelEventGranularity, granularity);
421
422#if PLATFORM(COCOA)
423    PlatformWheelEventCocoaArguments arguments;
424    DECODE_TYPE_WITH_KEY_TO_LVALUE(encodedData, bool, directionInvertedFromDevice, arguments.directionInvertedFromDevice);
425    DECODE_TYPE_WITH_KEY_TO_LVALUE(encodedData, bool, hasPreciseScrollingDeltas, arguments.hasPreciseScrollingDeltas);
426    DECODE_TYPE_WITH_KEY_TO_LVALUE(encodedData, PlatformWheelEventPhase, phase, arguments.phase);
427    DECODE_TYPE_WITH_KEY_TO_LVALUE(encodedData, PlatformWheelEventPhase, momentumPhase, arguments.momentumPhase);
428    DECODE_TYPE_WITH_KEY_TO_LVALUE(encodedData, int, scrollCount, arguments.scrollCount);
429    DECODE_TYPE_WITH_KEY_TO_LVALUE(encodedData, float, unacceleratedScrollingDeltaX, arguments.unacceleratedScrollingDeltaX);
430    DECODE_TYPE_WITH_KEY_TO_LVALUE(encodedData, float, unacceleratedScrollingDeltaY, arguments.unacceleratedScrollingDeltaY);
431#endif
432
433    PlatformWheelEvent event(IntPoint(positionX, positionY), IntPoint(globalPositionX, globalPositionY),
434        deltaX, deltaY, wheelTicksX, wheelTicksY, granularity, shiftKey, ctrlKey, altKey, metaKey);
435
436#if PLATFORM(COCOA)
437    input = std::make_unique<PlatformWheelEventCocoa>(event, arguments);
438#else
439    input = std::make_unique<PlatformWheelEvent>(event);
440#endif
441    return true;
442}
443
444EncodedValue EncodingTraits<PluginData>::encodeValue(RefPtr<PluginData> input)
445{
446    EncodedValue encodedData = EncodedValue::createObject();
447
448    ENCODE_TYPE_WITH_KEY(encodedData, Vector<PluginInfo>, plugins, input->plugins());
449    ENCODE_TYPE_WITH_KEY(encodedData, Vector<MimeClassInfo>, mimes, input->mimes());
450    ENCODE_TYPE_WITH_KEY(encodedData, Vector<size_t>, mimePluginIndices, input->mimePluginIndices());
451
452    return encodedData;
453}
454
455class DeserializedPluginData : public PluginData {
456public:
457    DeserializedPluginData(Vector<PluginInfo> plugins, Vector<MimeClassInfo> mimes, Vector<size_t> indices)
458        : PluginData(plugins, mimes, indices)
459    {
460    }
461};
462
463bool EncodingTraits<PluginData>::decodeValue(EncodedValue& encodedData, RefPtr<PluginData>& input)
464{
465    DECODE_TYPE_WITH_KEY(encodedData, Vector<PluginInfo>, plugins);
466    DECODE_TYPE_WITH_KEY(encodedData, Vector<MimeClassInfo>, mimes);
467    DECODE_TYPE_WITH_KEY(encodedData, Vector<size_t>, mimePluginIndices);
468
469    input = adoptRef(new DeserializedPluginData(plugins, mimes, mimePluginIndices));
470
471    return true;
472}
473
474template<>
475EncodedValue EncodingTraits<PluginInfo>::encodeValue(const PluginInfo& input)
476{
477    EncodedValue encodedData = EncodedValue::createObject();
478
479    ENCODE_TYPE_WITH_KEY(encodedData, String, name, input.name);
480    ENCODE_TYPE_WITH_KEY(encodedData, String, file, input.file);
481    ENCODE_TYPE_WITH_KEY(encodedData, String, desc, input.desc);
482    ENCODE_TYPE_WITH_KEY(encodedData, Vector<MimeClassInfo>, mimes, input.mimes);
483    ENCODE_TYPE_WITH_KEY(encodedData, bool, isApplicationPlugin, input.isApplicationPlugin);
484
485    return encodedData;
486}
487
488template<>
489bool EncodingTraits<PluginInfo>::decodeValue(EncodedValue& encodedData, PluginInfo& input)
490{
491    PluginInfo info;
492
493    DECODE_TYPE_WITH_KEY_TO_LVALUE(encodedData, String, name, info.name);
494    DECODE_TYPE_WITH_KEY_TO_LVALUE(encodedData, String, file, info.file);
495    DECODE_TYPE_WITH_KEY_TO_LVALUE(encodedData, String, desc, info.desc);
496    DECODE_TYPE_WITH_KEY_TO_LVALUE(encodedData, Vector<MimeClassInfo>, mimes, info.mimes);
497    DECODE_TYPE_WITH_KEY_TO_LVALUE(encodedData, bool, isApplicationPlugin, info.isApplicationPlugin);
498
499    input = info;
500    return true;
501}
502
503EncodedValue EncodingTraits<SecurityOrigin>::encodeValue(RefPtr<SecurityOrigin> input)
504{
505    return EncodedValue::createString(input->toString());
506}
507
508bool EncodingTraits<SecurityOrigin>::decodeValue(EncodedValue& encodedValue, RefPtr<SecurityOrigin>& input)
509{
510    input = SecurityOrigin::createFromString(encodedValue.convertTo<String>());
511    return true;
512}
513
514EncodedValue EncodingTraits<URL>::encodeValue(const URL& input)
515{
516    return EncodedValue::createString(input.string());
517}
518
519bool EncodingTraits<URL>::decodeValue(EncodedValue& encodedValue, URL& input)
520{
521    input = URL(WebCore::ParsedURLString, encodedValue.convertTo<String>());
522    return true;
523}
524
525} // namespace JSC
526
527#endif // ENABLE(WEB_REPLAY)
528