/* * 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" #include "DOMWindow.h" #include "ExceptionCode.h" #include "Geolocation.h" #include "GeolocationService.h" #include "JSCustomPositionCallback.h" #include "JSCustomPositionErrorCallback.h" #include "JSDOMWindow.h" #include "PositionOptions.h" #include <runtime/InternalFunction.h> using namespace JSC; using namespace std; namespace WebCore { static PassRefPtr<PositionCallback> createPositionCallback(ExecState* exec, JSDOMGlobalObject* globalObject, JSValue value) { // The spec specifies 'FunctionOnly' for this object. if (!value.inherits(&InternalFunction::info)) { setDOMException(exec, TYPE_MISMATCH_ERR); return 0; } JSObject* object = asObject(value); return JSCustomPositionCallback::create(object, globalObject); } static PassRefPtr<PositionErrorCallback> 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. if (!value.inherits(&InternalFunction::info)) { setDOMException(exec, TYPE_MISMATCH_ERR); return 0; } JSObject* object = asObject(value); return JSCustomPositionErrorCallback::create(object, globalObject); } static PassRefPtr<PositionOptions> createPositionOptions(ExecState* exec, JSValue value) { // Create default options. RefPtr<PositionOptions> 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, const ArgList& args) { // Arguments: PositionCallback, (optional)PositionErrorCallback, (optional)PositionOptions RefPtr<PositionCallback> positionCallback = createPositionCallback(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), args.at(0)); if (exec->hadException()) return jsUndefined(); ASSERT(positionCallback); RefPtr<PositionErrorCallback> positionErrorCallback = createPositionErrorCallback(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), args.at(1)); if (exec->hadException()) return jsUndefined(); RefPtr<PositionOptions> positionOptions = createPositionOptions(exec, args.at(2)); if (exec->hadException()) return jsUndefined(); ASSERT(positionOptions); m_impl->getCurrentPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.release()); return jsUndefined(); } JSValue JSGeolocation::watchPosition(ExecState* exec, const ArgList& args) { // Arguments: PositionCallback, (optional)PositionErrorCallback, (optional)PositionOptions RefPtr<PositionCallback> positionCallback = createPositionCallback(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), args.at(0)); if (exec->hadException()) return jsUndefined(); ASSERT(positionCallback); RefPtr<PositionErrorCallback> positionErrorCallback = createPositionErrorCallback(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), args.at(1)); if (exec->hadException()) return jsUndefined(); RefPtr<PositionOptions> positionOptions = createPositionOptions(exec, args.at(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