Web Replay: capture and replay mouse events
[WebKit-https.git] / Source / WebCore / replay / SerializationMethods.cpp
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 "PlatformMouseEvent.h"
35 #include "ReplayInputTypes.h"
36 #include "SecurityOrigin.h"
37 #include "URL.h"
38
39 using WebCore::IntPoint;
40 using WebCore::MouseButton;
41 using WebCore::PlatformEvent;
42 using WebCore::PlatformMouseEvent;
43 using WebCore::SecurityOrigin;
44 using WebCore::URL;
45 using WebCore::inputTypes;
46
47 #define IMPORT_FROM_WEBCORE_NAMESPACE(name) \
48 using WebCore::name; \
49
50 WEB_REPLAY_INPUT_NAMES_FOR_EACH(IMPORT_FROM_WEBCORE_NAMESPACE)
51 #undef IMPORT_FROM_WEBCORE_NAMESPACE
52
53 #define ENCODE_SCALAR_TYPE_WITH_KEY(_encodedValue, _type, _key, _value) \
54     _encodedValue.put<_type>(ASCIILiteral(#_key), _value)
55
56 #define DECODE_SCALAR_TYPE_WITH_KEY(_encodedValue, _type, _key) \
57     _type _key; \
58     if (!_encodedValue.get<_type>(ASCIILiteral(#_key), _key)) \
59         return false
60
61 namespace JSC {
62
63 EncodedValue EncodingTraits<NondeterministicInputBase>::encodeValue(const NondeterministicInputBase& input)
64 {
65     EncodedValue encodedValue = EncodedValue::createObject();
66     const AtomicString& type = input.type();
67     encodedValue.put<String>(ASCIILiteral("type"), type.string());
68
69 #define ENCODE_IF_TYPE_TAG_MATCHES(name) \
70     if (type == inputTypes().name) { \
71         InputTraits<name>::encode(encodedValue, static_cast<const name&>(input)); \
72         return encodedValue; \
73     } \
74
75     JS_REPLAY_INPUT_NAMES_FOR_EACH(ENCODE_IF_TYPE_TAG_MATCHES)
76     WEB_REPLAY_INPUT_NAMES_FOR_EACH(ENCODE_IF_TYPE_TAG_MATCHES)
77 #undef ENCODE_IF_TYPE_TAG_MATCHES
78
79     // The macro won't work here because of the class template argument.
80     if (type == inputTypes().MemoizedDOMResult) {
81         InputTraits<MemoizedDOMResultBase>::encode(encodedValue, static_cast<const MemoizedDOMResultBase&>(input));
82         return encodedValue;
83     }
84
85     ASSERT_NOT_REACHED();
86     return EncodedValue();
87 }
88
89 bool EncodingTraits<NondeterministicInputBase>::decodeValue(EncodedValue& encodedValue, std::unique_ptr<NondeterministicInputBase>& input)
90 {
91     String type;
92     if (!encodedValue.get<String>(ASCIILiteral("type"), type))
93         return false;
94
95 #define DECODE_IF_TYPE_TAG_MATCHES(name) \
96     if (type == inputTypes().name) { \
97         std::unique_ptr<name> decodedInput; \
98         if (!InputTraits<name>::decode(encodedValue, decodedInput)) \
99             return false; \
100         \
101         input = std::move(decodedInput); \
102         return true; \
103     } \
104
105     JS_REPLAY_INPUT_NAMES_FOR_EACH(DECODE_IF_TYPE_TAG_MATCHES)
106     WEB_REPLAY_INPUT_NAMES_FOR_EACH(DECODE_IF_TYPE_TAG_MATCHES)
107 #undef DECODE_IF_TYPE_TAG_MATCHES
108
109     if (type == inputTypes().MemoizedDOMResult) {
110         std::unique_ptr<MemoizedDOMResultBase> decodedInput;
111         if (!InputTraits<MemoizedDOMResultBase>::decode(encodedValue, decodedInput))
112             return false;
113
114         input = std::move(decodedInput);
115         return true;
116     }
117
118     return false;
119 }
120
121 EncodedValue EncodingTraits<PlatformMouseEvent>::encodeValue(const PlatformMouseEvent& input)
122 {
123     EncodedValue encodedValue = EncodedValue::createObject();
124
125     ENCODE_SCALAR_TYPE_WITH_KEY(encodedValue, int, positionX, input.position().x());
126     ENCODE_SCALAR_TYPE_WITH_KEY(encodedValue, int, positionY, input.position().y());
127     ENCODE_SCALAR_TYPE_WITH_KEY(encodedValue, int, globalPositionX, input.globalPosition().x());
128     ENCODE_SCALAR_TYPE_WITH_KEY(encodedValue, int, globalPositionY, input.globalPosition().y());
129     ENCODE_SCALAR_TYPE_WITH_KEY(encodedValue, MouseButton, button, input.button());
130     ENCODE_SCALAR_TYPE_WITH_KEY(encodedValue, PlatformEvent::Type, type, input.type());
131     ENCODE_SCALAR_TYPE_WITH_KEY(encodedValue, int, clickCount, input.clickCount());
132     ENCODE_SCALAR_TYPE_WITH_KEY(encodedValue, bool, shiftKey, input.shiftKey());
133     ENCODE_SCALAR_TYPE_WITH_KEY(encodedValue, bool, ctrlKey, input.ctrlKey());
134     ENCODE_SCALAR_TYPE_WITH_KEY(encodedValue, bool, altKey, input.altKey());
135     ENCODE_SCALAR_TYPE_WITH_KEY(encodedValue, bool, metaKey, input.metaKey());
136     ENCODE_SCALAR_TYPE_WITH_KEY(encodedValue, int, timestamp, input.timestamp());
137
138     return encodedValue;
139 }
140
141 bool EncodingTraits<PlatformMouseEvent>::decodeValue(EncodedValue& encodedValue, std::unique_ptr<PlatformMouseEvent>& input)
142 {
143     DECODE_SCALAR_TYPE_WITH_KEY(encodedValue, int, positionX);
144     DECODE_SCALAR_TYPE_WITH_KEY(encodedValue, int, positionY);
145     DECODE_SCALAR_TYPE_WITH_KEY(encodedValue, int, globalPositionX);
146     DECODE_SCALAR_TYPE_WITH_KEY(encodedValue, int, globalPositionY);
147     DECODE_SCALAR_TYPE_WITH_KEY(encodedValue, MouseButton, button);
148     DECODE_SCALAR_TYPE_WITH_KEY(encodedValue, PlatformEvent::Type, type);
149     DECODE_SCALAR_TYPE_WITH_KEY(encodedValue, int, clickCount);
150     DECODE_SCALAR_TYPE_WITH_KEY(encodedValue, bool, shiftKey);
151     DECODE_SCALAR_TYPE_WITH_KEY(encodedValue, bool, ctrlKey);
152     DECODE_SCALAR_TYPE_WITH_KEY(encodedValue, bool, altKey);
153     DECODE_SCALAR_TYPE_WITH_KEY(encodedValue, bool, metaKey);
154     DECODE_SCALAR_TYPE_WITH_KEY(encodedValue, int, timestamp);
155
156     input = std::make_unique<PlatformMouseEvent>(IntPoint(positionX, positionY),
157         IntPoint(globalPositionX, globalPositionY),
158         button, type, clickCount,
159         shiftKey, ctrlKey, altKey, metaKey, timestamp);
160     return true;
161 }
162
163 EncodedValue EncodingTraits<SecurityOrigin>::encodeValue(RefPtr<SecurityOrigin> input)
164 {
165     return EncodedValue::createString(input->toString());
166 }
167
168 bool EncodingTraits<SecurityOrigin>::decodeValue(EncodedValue& encodedValue, RefPtr<SecurityOrigin>& input)
169 {
170     input = SecurityOrigin::createFromString(encodedValue.convertTo<String>());
171     return true;
172 }
173
174 EncodedValue EncodingTraits<URL>::encodeValue(const URL& input)
175 {
176     return EncodedValue::createString(input.string());
177 }
178
179 bool EncodingTraits<URL>::decodeValue(EncodedValue& encodedValue, URL& input)
180 {
181     input = URL(WebCore::ParsedURLString, encodedValue.convertTo<String>());
182     return true;
183 }
184
185 } // namespace JSC
186
187 #endif // ENABLE(WEB_REPLAY)