WebCore/bindings/js/JSGeolocationCustom.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2008 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  * 1. Redistributions of source code must retain the above copyright
       
     8  *    notice, this list of conditions and the following disclaimer.
       
     9  * 2. 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 APPLE INC. ``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 APPLE INC. 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 "JSGeolocation.h"
       
    28 
       
    29 #if ENABLE(GEOLOCATION)
       
    30 
       
    31 #include "DOMWindow.h"
       
    32 #include "ExceptionCode.h"
       
    33 #include "Geolocation.h"
       
    34 #include "JSCustomPositionCallback.h"
       
    35 #include "JSCustomPositionErrorCallback.h"
       
    36 #include "JSDOMWindow.h"
       
    37 #include "PositionOptions.h"
       
    38 #include <runtime/JSFunction.h>
       
    39 
       
    40 #if !ENABLE(CLIENT_BASED_GEOLOCATION)
       
    41 #include "GeolocationService.h"
       
    42 #endif
       
    43 
       
    44 using namespace JSC;
       
    45 using namespace std;
       
    46 
       
    47 namespace WebCore {
       
    48 
       
    49 static PassRefPtr<PositionCallback> createPositionCallback(ExecState* exec, JSDOMGlobalObject* globalObject, JSValue value)
       
    50 {
       
    51     // The spec specifies 'FunctionOnly' for this object.
       
    52     // FIXME: This check disallows callable objects created via JSC API. It's not clear what exactly the specification intends to allow.
       
    53     if (!value.inherits(&JSFunction::info)) {
       
    54         setDOMException(exec, TYPE_MISMATCH_ERR);
       
    55         return 0;
       
    56     }
       
    57 
       
    58     JSObject* object = asObject(value);
       
    59     return JSCustomPositionCallback::create(object, globalObject);
       
    60 }
       
    61 
       
    62 static PassRefPtr<PositionErrorCallback> createPositionErrorCallback(ExecState* exec, JSDOMGlobalObject* globalObject, JSValue value)
       
    63 {
       
    64     // Argument is optional (hence undefined is allowed), and null is allowed.
       
    65     if (value.isUndefinedOrNull())
       
    66         return 0;
       
    67 
       
    68     // The spec specifies 'FunctionOnly' for this object.
       
    69     // FIXME: This check disallows callable objects created via JSC API. It's not clear what exactly the specification intends to allow.
       
    70     if (!value.inherits(&JSFunction::info)) {
       
    71         setDOMException(exec, TYPE_MISMATCH_ERR);
       
    72         return 0;
       
    73     }
       
    74 
       
    75     JSObject* object = asObject(value);
       
    76     return JSCustomPositionErrorCallback::create(object, globalObject);
       
    77 }
       
    78 
       
    79 static PassRefPtr<PositionOptions> createPositionOptions(ExecState* exec, JSValue value)
       
    80 {
       
    81     // Create default options.
       
    82     RefPtr<PositionOptions> options = PositionOptions::create();
       
    83 
       
    84     // Argument is optional (hence undefined is allowed), and null is allowed.
       
    85     if (value.isUndefinedOrNull()) {
       
    86         // Use default options.
       
    87         return options.release();
       
    88     }
       
    89 
       
    90     // Given the above test, this will always yield an object.
       
    91     JSObject* object = value.toObject(exec);
       
    92 
       
    93     // For all three properties, we apply the following ...
       
    94     // - If the getter or the property's valueOf method throws an exception, we
       
    95     //   quit so as not to risk overwriting the exception.
       
    96     // - If the value is absent or undefined, we don't override the default.
       
    97     JSValue enableHighAccuracyValue = object->get(exec, Identifier(exec, "enableHighAccuracy"));
       
    98     if (exec->hadException())
       
    99         return 0;
       
   100     if (!enableHighAccuracyValue.isUndefined()) {
       
   101         options->setEnableHighAccuracy(enableHighAccuracyValue.toBoolean(exec));
       
   102         if (exec->hadException())
       
   103             return 0;
       
   104     }
       
   105 
       
   106     JSValue timeoutValue = object->get(exec, Identifier(exec, "timeout"));
       
   107     if (exec->hadException())
       
   108         return 0;
       
   109     if (!timeoutValue.isUndefined()) {
       
   110         double timeoutNumber = timeoutValue.toNumber(exec);
       
   111         if (exec->hadException())
       
   112             return 0;
       
   113         // If the value is positive infinity, there's nothing to do.
       
   114         if (!(isinf(timeoutNumber) && (timeoutNumber > 0))) {
       
   115             // Wrap to int32 and force non-negative to match behavior of window.setTimeout.
       
   116             options->setTimeout(max(0, timeoutValue.toInt32(exec)));
       
   117             if (exec->hadException())
       
   118                 return 0;
       
   119         }
       
   120     }
       
   121 
       
   122     JSValue maximumAgeValue = object->get(exec, Identifier(exec, "maximumAge"));
       
   123     if (exec->hadException())
       
   124         return 0;
       
   125     if (!maximumAgeValue.isUndefined()) {
       
   126         double maximumAgeNumber = maximumAgeValue.toNumber(exec);
       
   127         if (exec->hadException())
       
   128             return 0;
       
   129         if (isinf(maximumAgeNumber) && (maximumAgeNumber > 0)) {
       
   130             // If the value is positive infinity, clear maximumAge.
       
   131             options->clearMaximumAge();
       
   132         } else {
       
   133             // Wrap to int32 and force non-negative to match behavior of window.setTimeout.
       
   134             options->setMaximumAge(max(0, maximumAgeValue.toInt32(exec)));
       
   135             if (exec->hadException())
       
   136                 return 0;
       
   137         }
       
   138     }
       
   139 
       
   140     return options.release();
       
   141 }
       
   142 
       
   143 JSValue JSGeolocation::getCurrentPosition(ExecState* exec)
       
   144 {
       
   145     // Arguments: PositionCallback, (optional)PositionErrorCallback, (optional)PositionOptions
       
   146 
       
   147     RefPtr<PositionCallback> positionCallback = createPositionCallback(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->argument(0));
       
   148     if (exec->hadException())
       
   149         return jsUndefined();
       
   150     ASSERT(positionCallback);
       
   151 
       
   152     RefPtr<PositionErrorCallback> positionErrorCallback = createPositionErrorCallback(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->argument(1));
       
   153     if (exec->hadException())
       
   154         return jsUndefined();
       
   155 
       
   156     RefPtr<PositionOptions> positionOptions = createPositionOptions(exec, exec->argument(2));
       
   157     if (exec->hadException())
       
   158         return jsUndefined();
       
   159     ASSERT(positionOptions);
       
   160 
       
   161     m_impl->getCurrentPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.release());
       
   162     return jsUndefined();
       
   163 }
       
   164 
       
   165 JSValue JSGeolocation::watchPosition(ExecState* exec)
       
   166 {
       
   167     // Arguments: PositionCallback, (optional)PositionErrorCallback, (optional)PositionOptions
       
   168 
       
   169     RefPtr<PositionCallback> positionCallback = createPositionCallback(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->argument(0));
       
   170     if (exec->hadException())
       
   171         return jsUndefined();
       
   172     ASSERT(positionCallback);
       
   173 
       
   174     RefPtr<PositionErrorCallback> positionErrorCallback = createPositionErrorCallback(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->argument(1));
       
   175     if (exec->hadException())
       
   176         return jsUndefined();
       
   177 
       
   178     RefPtr<PositionOptions> positionOptions = createPositionOptions(exec, exec->argument(2));
       
   179     if (exec->hadException())
       
   180         return jsUndefined();
       
   181     ASSERT(positionOptions);
       
   182 
       
   183     int watchID = m_impl->watchPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.release());
       
   184     return jsNumber(exec, watchID);
       
   185 }
       
   186 
       
   187 } // namespace WebCore
       
   188 
       
   189 #endif // ENABLE(GEOLOCATION)