Home | History | Annotate | Download | only in js
      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 
     34 using namespace JSC;
     35 
     36 namespace WebCore {
     37 
     38 static 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 
     76 static 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 
    114 static JSObject* createAccelerationObject(const DeviceMotionData::Acceleration* acceleration, ExecState* exec)
    115 {
    116     JSObject* object = constructEmptyObject(exec);
    117     object->putDirect(exec->globalData(), Identifier(exec, "x"), acceleration->canProvideX() ? jsNumber(acceleration->x()) : jsNull());
    118     object->putDirect(exec->globalData(), Identifier(exec, "y"), acceleration->canProvideY() ? jsNumber(acceleration->y()) : jsNull());
    119     object->putDirect(exec->globalData(), Identifier(exec, "z"), acceleration->canProvideZ() ? jsNumber(acceleration->z()) : jsNull());
    120     return object;
    121 }
    122 
    123 static JSObject* createRotationRateObject(const DeviceMotionData::RotationRate* rotationRate, ExecState* exec)
    124 {
    125     JSObject* object = constructEmptyObject(exec);
    126     object->putDirect(exec->globalData(), Identifier(exec, "alpha"), rotationRate->canProvideAlpha() ? jsNumber(rotationRate->alpha()) : jsNull());
    127     object->putDirect(exec->globalData(), Identifier(exec, "beta"),  rotationRate->canProvideBeta()  ? jsNumber(rotationRate->beta())  : jsNull());
    128     object->putDirect(exec->globalData(), Identifier(exec, "gamma"), rotationRate->canProvideGamma() ? jsNumber(rotationRate->gamma()) : jsNull());
    129     return object;
    130 }
    131 
    132 JSValue 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 
    140 JSValue 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 
    148 JSValue 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 
    156 JSValue 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 
    164 JSValue 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