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 "V8DeviceMotionEvent.h"
28
29#include "bindings/v8/V8Binding.h"
30#include "modules/device_orientation/DeviceMotionData.h"
31#include <v8.h>
32
33namespace WebCore {
34
35namespace {
36
37RefPtr<DeviceMotionData::Acceleration> readAccelerationArgument(v8::Local<v8::Value> value, v8::Isolate* isolate)
38{
39    if (isUndefinedOrNull(value))
40        return 0;
41
42    // Given the test above, this will always yield an object.
43    v8::Local<v8::Object> object = value->ToObject();
44
45    v8::Local<v8::Value> xValue = object->Get(v8AtomicString(isolate, "x"));
46    if (xValue.IsEmpty())
47        return 0;
48    bool canProvideX = !isUndefinedOrNull(xValue);
49    double x = xValue->NumberValue();
50
51    v8::Local<v8::Value> yValue = object->Get(v8AtomicString(isolate, "y"));
52    if (yValue.IsEmpty())
53        return 0;
54    bool canProvideY = !isUndefinedOrNull(yValue);
55    double y = yValue->NumberValue();
56
57    v8::Local<v8::Value> zValue = object->Get(v8AtomicString(isolate, "z"));
58    if (zValue.IsEmpty())
59        return 0;
60    bool canProvideZ = !isUndefinedOrNull(zValue);
61    double z = zValue->NumberValue();
62
63    if (!canProvideX && !canProvideY && !canProvideZ)
64        return 0;
65
66    return DeviceMotionData::Acceleration::create(canProvideX, x, canProvideY, y, canProvideZ, z);
67}
68
69RefPtr<DeviceMotionData::RotationRate> readRotationRateArgument(v8::Local<v8::Value> value, v8::Isolate* isolate)
70{
71    if (isUndefinedOrNull(value))
72        return 0;
73
74    // Given the test above, this will always yield an object.
75    v8::Local<v8::Object> object = value->ToObject();
76
77    v8::Local<v8::Value> alphaValue = object->Get(v8AtomicString(isolate, "alpha"));
78    if (alphaValue.IsEmpty())
79        return 0;
80    bool canProvideAlpha = !isUndefinedOrNull(alphaValue);
81    double alpha = alphaValue->NumberValue();
82
83    v8::Local<v8::Value> betaValue = object->Get(v8AtomicString(isolate, "beta"));
84    if (betaValue.IsEmpty())
85        return 0;
86    bool canProvideBeta = !isUndefinedOrNull(betaValue);
87    double beta = betaValue->NumberValue();
88
89    v8::Local<v8::Value> gammaValue = object->Get(v8AtomicString(isolate, "gamma"));
90    if (gammaValue.IsEmpty())
91        return 0;
92    bool canProvideGamma = !isUndefinedOrNull(gammaValue);
93    double gamma = gammaValue->NumberValue();
94
95    if (!canProvideAlpha && !canProvideBeta && !canProvideGamma)
96        return 0;
97
98    return DeviceMotionData::RotationRate::create(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma);
99}
100
101} // namespace
102
103void V8DeviceMotionEvent::initDeviceMotionEventMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
104{
105    DeviceMotionEvent* imp = V8DeviceMotionEvent::toNative(info.Holder());
106    v8::Isolate* isolate = info.GetIsolate();
107    V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, info[0]);
108    bool bubbles = info[1]->BooleanValue();
109    bool cancelable = info[2]->BooleanValue();
110    RefPtr<DeviceMotionData::Acceleration> acceleration = readAccelerationArgument(info[3], isolate);
111    RefPtr<DeviceMotionData::Acceleration> accelerationIncludingGravity = readAccelerationArgument(info[4], isolate);
112    RefPtr<DeviceMotionData::RotationRate> rotationRate = readRotationRateArgument(info[5], isolate);
113    bool intervalProvided = !isUndefinedOrNull(info[6]);
114    double interval = info[6]->NumberValue();
115    RefPtr<DeviceMotionData> deviceMotionData = DeviceMotionData::create(acceleration, accelerationIncludingGravity, rotationRate, intervalProvided, interval);
116    imp->initDeviceMotionEvent(type, bubbles, cancelable, deviceMotionData.get());
117}
118
119} // namespace WebCore
120