diff -r 000000000000 -r 4f2f89ce4247 WebCore/bindings/js/JSGeolocationCustom.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebCore/bindings/js/JSGeolocationCustom.cpp Fri Sep 17 09:02:29 2010 +0300 @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "JSGeolocation.h" + +#if ENABLE(GEOLOCATION) + +#include "DOMWindow.h" +#include "ExceptionCode.h" +#include "Geolocation.h" +#include "JSCustomPositionCallback.h" +#include "JSCustomPositionErrorCallback.h" +#include "JSDOMWindow.h" +#include "PositionOptions.h" +#include + +#if !ENABLE(CLIENT_BASED_GEOLOCATION) +#include "GeolocationService.h" +#endif + +using namespace JSC; +using namespace std; + +namespace WebCore { + +static PassRefPtr createPositionCallback(ExecState* exec, JSDOMGlobalObject* globalObject, JSValue value) +{ + // The spec specifies 'FunctionOnly' for this object. + // FIXME: This check disallows callable objects created via JSC API. It's not clear what exactly the specification intends to allow. + if (!value.inherits(&JSFunction::info)) { + setDOMException(exec, TYPE_MISMATCH_ERR); + return 0; + } + + JSObject* object = asObject(value); + return JSCustomPositionCallback::create(object, globalObject); +} + +static PassRefPtr createPositionErrorCallback(ExecState* exec, JSDOMGlobalObject* globalObject, JSValue value) +{ + // Argument is optional (hence undefined is allowed), and null is allowed. + if (value.isUndefinedOrNull()) + return 0; + + // The spec specifies 'FunctionOnly' for this object. + // FIXME: This check disallows callable objects created via JSC API. It's not clear what exactly the specification intends to allow. + if (!value.inherits(&JSFunction::info)) { + setDOMException(exec, TYPE_MISMATCH_ERR); + return 0; + } + + JSObject* object = asObject(value); + return JSCustomPositionErrorCallback::create(object, globalObject); +} + +static PassRefPtr createPositionOptions(ExecState* exec, JSValue value) +{ + // Create default options. + RefPtr options = PositionOptions::create(); + + // Argument is optional (hence undefined is allowed), and null is allowed. + if (value.isUndefinedOrNull()) { + // Use default options. + return options.release(); + } + + // Given the above test, this will always yield an object. + JSObject* object = value.toObject(exec); + + // For all three properties, we apply the following ... + // - If the getter or the property's valueOf method throws an exception, we + // quit so as not to risk overwriting the exception. + // - If the value is absent or undefined, we don't override the default. + JSValue enableHighAccuracyValue = object->get(exec, Identifier(exec, "enableHighAccuracy")); + if (exec->hadException()) + return 0; + if (!enableHighAccuracyValue.isUndefined()) { + options->setEnableHighAccuracy(enableHighAccuracyValue.toBoolean(exec)); + if (exec->hadException()) + return 0; + } + + JSValue timeoutValue = object->get(exec, Identifier(exec, "timeout")); + if (exec->hadException()) + return 0; + if (!timeoutValue.isUndefined()) { + double timeoutNumber = timeoutValue.toNumber(exec); + if (exec->hadException()) + return 0; + // If the value is positive infinity, there's nothing to do. + if (!(isinf(timeoutNumber) && (timeoutNumber > 0))) { + // Wrap to int32 and force non-negative to match behavior of window.setTimeout. + options->setTimeout(max(0, timeoutValue.toInt32(exec))); + if (exec->hadException()) + return 0; + } + } + + JSValue maximumAgeValue = object->get(exec, Identifier(exec, "maximumAge")); + if (exec->hadException()) + return 0; + if (!maximumAgeValue.isUndefined()) { + double maximumAgeNumber = maximumAgeValue.toNumber(exec); + if (exec->hadException()) + return 0; + if (isinf(maximumAgeNumber) && (maximumAgeNumber > 0)) { + // If the value is positive infinity, clear maximumAge. + options->clearMaximumAge(); + } else { + // Wrap to int32 and force non-negative to match behavior of window.setTimeout. + options->setMaximumAge(max(0, maximumAgeValue.toInt32(exec))); + if (exec->hadException()) + return 0; + } + } + + return options.release(); +} + +JSValue JSGeolocation::getCurrentPosition(ExecState* exec) +{ + // Arguments: PositionCallback, (optional)PositionErrorCallback, (optional)PositionOptions + + RefPtr positionCallback = createPositionCallback(exec, static_cast(exec->lexicalGlobalObject()), exec->argument(0)); + if (exec->hadException()) + return jsUndefined(); + ASSERT(positionCallback); + + RefPtr positionErrorCallback = createPositionErrorCallback(exec, static_cast(exec->lexicalGlobalObject()), exec->argument(1)); + if (exec->hadException()) + return jsUndefined(); + + RefPtr positionOptions = createPositionOptions(exec, exec->argument(2)); + if (exec->hadException()) + return jsUndefined(); + ASSERT(positionOptions); + + m_impl->getCurrentPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.release()); + return jsUndefined(); +} + +JSValue JSGeolocation::watchPosition(ExecState* exec) +{ + // Arguments: PositionCallback, (optional)PositionErrorCallback, (optional)PositionOptions + + RefPtr positionCallback = createPositionCallback(exec, static_cast(exec->lexicalGlobalObject()), exec->argument(0)); + if (exec->hadException()) + return jsUndefined(); + ASSERT(positionCallback); + + RefPtr positionErrorCallback = createPositionErrorCallback(exec, static_cast(exec->lexicalGlobalObject()), exec->argument(1)); + if (exec->hadException()) + return jsUndefined(); + + RefPtr positionOptions = createPositionOptions(exec, exec->argument(2)); + if (exec->hadException()) + return jsUndefined(); + ASSERT(positionOptions); + + int watchID = m_impl->watchPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.release()); + return jsNumber(exec, watchID); +} + +} // namespace WebCore + +#endif // ENABLE(GEOLOCATION)