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