1/* 2 * Copyright 2009, The Android Open Source Project 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 "V8Geolocation.h" 28 29#if ENABLE(GEOLOCATION) 30 31#include "Frame.h" 32#include "Geolocation.h" 33#include "V8Binding.h" 34#include "V8CustomPositionCallback.h" 35#include "V8CustomPositionErrorCallback.h" 36#include "V8Utilities.h" 37 38using namespace std; 39using namespace WTF; 40 41namespace WebCore { 42 43static PassRefPtr<PositionOptions> createPositionOptions(v8::Local<v8::Value> value, bool& succeeded) 44{ 45 succeeded = true; 46 47 // Create default options. 48 RefPtr<PositionOptions> options = PositionOptions::create(); 49 50 // Argument is optional (hence undefined is allowed), and null is allowed. 51 if (isUndefinedOrNull(value)) { 52 // Use default options. 53 return options.release(); 54 } 55 56 // Given the above test, this will always yield an object. 57 v8::Local<v8::Object> object = value->ToObject(); 58 59 // For all three properties, we apply the following ... 60 // - If the getter or the property's valueOf method throws an exception, we 61 // quit so as not to risk overwriting the exception. 62 // - If the value is absent or undefined, we don't override the default. 63 v8::Local<v8::Value> enableHighAccuracyValue = object->Get(v8::String::New("enableHighAccuracy")); 64 if (enableHighAccuracyValue.IsEmpty()) { 65 succeeded = false; 66 return 0; 67 } 68 if (!enableHighAccuracyValue->IsUndefined()) { 69 v8::Local<v8::Boolean> enableHighAccuracyBoolean = enableHighAccuracyValue->ToBoolean(); 70 if (enableHighAccuracyBoolean.IsEmpty()) { 71 succeeded = false; 72 return 0; 73 } 74 options->setEnableHighAccuracy(enableHighAccuracyBoolean->Value()); 75 } 76 77 v8::Local<v8::Value> timeoutValue = object->Get(v8::String::New("timeout")); 78 if (timeoutValue.IsEmpty()) { 79 succeeded = false; 80 return 0; 81 } 82 if (!timeoutValue->IsUndefined()) { 83 v8::Local<v8::Number> timeoutNumber = timeoutValue->ToNumber(); 84 if (timeoutNumber.IsEmpty()) { 85 succeeded = false; 86 return 0; 87 } 88 double timeoutDouble = timeoutNumber->Value(); 89 // If the value is positive infinity, there's nothing to do. 90 if (!(isinf(timeoutDouble) && timeoutDouble > 0)) { 91 v8::Local<v8::Int32> timeoutInt32 = timeoutValue->ToInt32(); 92 if (timeoutInt32.IsEmpty()) { 93 succeeded = false; 94 return 0; 95 } 96 // Wrap to int32 and force non-negative to match behavior of window.setTimeout. 97 options->setTimeout(max(0, timeoutInt32->Value())); 98 } 99 } 100 101 v8::Local<v8::Value> maximumAgeValue = object->Get(v8::String::New("maximumAge")); 102 if (maximumAgeValue.IsEmpty()) { 103 succeeded = false; 104 return 0; 105 } 106 if (!maximumAgeValue->IsUndefined()) { 107 v8::Local<v8::Number> maximumAgeNumber = maximumAgeValue->ToNumber(); 108 if (maximumAgeNumber.IsEmpty()) { 109 succeeded = false; 110 return 0; 111 } 112 double maximumAgeDouble = maximumAgeNumber->Value(); 113 if (isinf(maximumAgeDouble) && maximumAgeDouble > 0) { 114 // If the value is positive infinity, clear maximumAge. 115 options->clearMaximumAge(); 116 } else { 117 v8::Local<v8::Int32> maximumAgeInt32 = maximumAgeValue->ToInt32(); 118 if (maximumAgeInt32.IsEmpty()) { 119 succeeded = false; 120 return 0; 121 } 122 // Wrap to int32 and force non-negative to match behavior of window.setTimeout. 123 options->setMaximumAge(max(0, maximumAgeInt32->Value())); 124 } 125 } 126 127 return options.release(); 128} 129 130v8::Handle<v8::Value> V8Geolocation::getCurrentPositionCallback(const v8::Arguments& args) 131{ 132 INC_STATS("DOM.Geolocation.getCurrentPosition()"); 133 134 bool succeeded = false; 135 136 RefPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<V8CustomPositionCallback>(args[0], succeeded); 137 if (!succeeded) 138 return v8::Undefined(); 139 ASSERT(positionCallback); 140 141 // Argument is optional (hence undefined is allowed), and null is allowed. 142 RefPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<V8CustomPositionErrorCallback>(args[1], succeeded, CallbackAllowUndefined | CallbackAllowNull); 143 if (!succeeded) 144 return v8::Undefined(); 145 146 RefPtr<PositionOptions> positionOptions = createPositionOptions(args[2], succeeded); 147 if (!succeeded) 148 return v8::Undefined(); 149 ASSERT(positionOptions); 150 151 Geolocation* geolocation = V8Geolocation::toNative(args.Holder()); 152 geolocation->getCurrentPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.release()); 153 return v8::Undefined(); 154} 155 156v8::Handle<v8::Value> V8Geolocation::watchPositionCallback(const v8::Arguments& args) 157{ 158 INC_STATS("DOM.Geolocation.watchPosition()"); 159 160 bool succeeded = false; 161 162 RefPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<V8CustomPositionCallback>(args[0], succeeded); 163 if (!succeeded) 164 return v8::Undefined(); 165 ASSERT(positionCallback); 166 167 // Argument is optional (hence undefined is allowed), and null is allowed. 168 RefPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<V8CustomPositionErrorCallback>(args[1], succeeded, CallbackAllowUndefined | CallbackAllowNull); 169 if (!succeeded) 170 return v8::Undefined(); 171 172 RefPtr<PositionOptions> positionOptions = createPositionOptions(args[2], succeeded); 173 if (!succeeded) 174 return v8::Undefined(); 175 ASSERT(positionOptions); 176 177 Geolocation* geolocation = V8Geolocation::toNative(args.Holder()); 178 int watchId = geolocation->watchPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.release()); 179 return v8::Number::New(watchId); 180} 181 182} // namespace WebCore 183 184#endif // ENABLE(GEOLOCATION) 185