JSDeviceMotionEventCustom.cpp revision cad810f21b803229eb11403f9209855525a25d57
1/*
2 * Copyright (C) 2010 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 *  * Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 *  * 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "JSDeviceMotionEvent.h"
28
29#if ENABLE(DEVICE_ORIENTATION)
30
31#include "DeviceMotionData.h"
32#include "DeviceMotionEvent.h"
33
34using namespace JSC;
35
36namespace WebCore {
37
38static PassRefPtr<DeviceMotionData::Acceleration> readAccelerationArgument(JSValue value, ExecState* exec)
39{
40    if (value.isUndefinedOrNull())
41        return 0;
42
43    // Given the above test, this will always yield an object.
44    JSObject* object = value.toObject(exec);
45
46    JSValue xValue = object->get(exec, Identifier(exec, "x"));
47    if (exec->hadException())
48        return 0;
49    bool canProvideX = !xValue.isUndefinedOrNull();
50    double x = xValue.toNumber(exec);
51    if (exec->hadException())
52        return 0;
53
54    JSValue yValue = object->get(exec, Identifier(exec, "y"));
55    if (exec->hadException())
56        return 0;
57    bool canProvideY = !yValue.isUndefinedOrNull();
58    double y = yValue.toNumber(exec);
59    if (exec->hadException())
60        return 0;
61
62    JSValue zValue = object->get(exec, Identifier(exec, "z"));
63    if (exec->hadException())
64        return 0;
65    bool canProvideZ = !zValue.isUndefinedOrNull();
66    double z = zValue.toNumber(exec);
67    if (exec->hadException())
68        return 0;
69
70    if (!canProvideX && !canProvideY && !canProvideZ)
71        return 0;
72
73    return DeviceMotionData::Acceleration::create(canProvideX, x, canProvideY, y, canProvideZ, z);
74}
75
76static PassRefPtr<DeviceMotionData::RotationRate> readRotationRateArgument(JSValue value, ExecState* exec)
77{
78    if (value.isUndefinedOrNull())
79        return 0;
80
81    // Given the above test, this will always yield an object.
82    JSObject* object = value.toObject(exec);
83
84    JSValue alphaValue = object->get(exec, Identifier(exec, "alpha"));
85    if (exec->hadException())
86        return 0;
87    bool canProvideAlpha = !alphaValue.isUndefinedOrNull();
88    double alpha = alphaValue.toNumber(exec);
89    if (exec->hadException())
90        return 0;
91
92    JSValue betaValue = object->get(exec, Identifier(exec, "beta"));
93    if (exec->hadException())
94        return 0;
95    bool canProvideBeta = !betaValue.isUndefinedOrNull();
96    double beta = betaValue.toNumber(exec);
97    if (exec->hadException())
98        return 0;
99
100    JSValue gammaValue = object->get(exec, Identifier(exec, "gamma"));
101    if (exec->hadException())
102        return 0;
103    bool canProvideGamma = !gammaValue.isUndefinedOrNull();
104    double gamma = gammaValue.toNumber(exec);
105    if (exec->hadException())
106        return 0;
107
108    if (!canProvideAlpha && !canProvideBeta && !canProvideGamma)
109        return 0;
110
111    return DeviceMotionData::RotationRate::create(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma);
112}
113
114static JSObject* createAccelerationObject(const DeviceMotionData::Acceleration* acceleration, ExecState* exec)
115{
116    JSObject* object = constructEmptyObject(exec);
117    object->putDirect(Identifier(exec, "x"), acceleration->canProvideX() ? jsNumber(acceleration->x()) : jsNull());
118    object->putDirect(Identifier(exec, "y"), acceleration->canProvideY() ? jsNumber(acceleration->y()) : jsNull());
119    object->putDirect(Identifier(exec, "z"), acceleration->canProvideZ() ? jsNumber(acceleration->z()) : jsNull());
120    return object;
121}
122
123static JSObject* createRotationRateObject(const DeviceMotionData::RotationRate* rotationRate, ExecState* exec)
124{
125    JSObject* object = constructEmptyObject(exec);
126    object->putDirect(Identifier(exec, "alpha"), rotationRate->canProvideAlpha() ? jsNumber(rotationRate->alpha()) : jsNull());
127    object->putDirect(Identifier(exec, "beta"),  rotationRate->canProvideBeta()  ? jsNumber(rotationRate->beta())  : jsNull());
128    object->putDirect(Identifier(exec, "gamma"), rotationRate->canProvideGamma() ? jsNumber(rotationRate->gamma()) : jsNull());
129    return object;
130}
131
132JSValue JSDeviceMotionEvent::acceleration(ExecState* exec) const
133{
134    DeviceMotionEvent* imp = static_cast<DeviceMotionEvent*>(impl());
135    if (!imp->deviceMotionData()->acceleration())
136        return jsNull();
137    return createAccelerationObject(imp->deviceMotionData()->acceleration(), exec);
138}
139
140JSValue JSDeviceMotionEvent::accelerationIncludingGravity(ExecState* exec) const
141{
142    DeviceMotionEvent* imp = static_cast<DeviceMotionEvent*>(impl());
143    if (!imp->deviceMotionData()->accelerationIncludingGravity())
144        return jsNull();
145    return createAccelerationObject(imp->deviceMotionData()->accelerationIncludingGravity(), exec);
146}
147
148JSValue JSDeviceMotionEvent::rotationRate(ExecState* exec) const
149{
150    DeviceMotionEvent* imp = static_cast<DeviceMotionEvent*>(impl());
151    if (!imp->deviceMotionData()->rotationRate())
152        return jsNull();
153    return createRotationRateObject(imp->deviceMotionData()->rotationRate(), exec);
154}
155
156JSValue JSDeviceMotionEvent::interval(ExecState*) const
157{
158    DeviceMotionEvent* imp = static_cast<DeviceMotionEvent*>(impl());
159    if (!imp->deviceMotionData()->canProvideInterval())
160        return jsNull();
161    return jsNumber(imp->deviceMotionData()->interval());
162}
163
164JSValue JSDeviceMotionEvent::initDeviceMotionEvent(ExecState* exec)
165{
166    const String& type = ustringToString(exec->argument(0).toString(exec));
167    bool bubbles = exec->argument(1).toBoolean(exec);
168    bool cancelable = exec->argument(2).toBoolean(exec);
169
170    // If any of the parameters are null or undefined, mark them as not provided.
171    // Otherwise, use the standard JavaScript conversion.
172    RefPtr<DeviceMotionData::Acceleration> acceleration = readAccelerationArgument(exec->argument(3), exec);
173    if (exec->hadException())
174        return jsUndefined();
175
176    RefPtr<DeviceMotionData::Acceleration> accelerationIncludingGravity = readAccelerationArgument(exec->argument(4), exec);
177    if (exec->hadException())
178        return jsUndefined();
179
180    RefPtr<DeviceMotionData::RotationRate> rotationRate = readRotationRateArgument(exec->argument(5), exec);
181    if (exec->hadException())
182        return jsUndefined();
183
184    bool intervalProvided = !exec->argument(6).isUndefinedOrNull();
185    double interval = exec->argument(6).toNumber(exec);
186    RefPtr<DeviceMotionData> deviceMotionData = DeviceMotionData::create(acceleration, accelerationIncludingGravity, rotationRate, intervalProvided, interval);
187    DeviceMotionEvent* imp = static_cast<DeviceMotionEvent*>(impl());
188    imp->initDeviceMotionEvent(type, bubbles, cancelable, deviceMotionData.get());
189    return jsUndefined();
190}
191
192} // namespace WebCore
193
194#endif // ENABLE(DEVICE_ORIENTATION)
195