| /* |
| * Copyright 2013 Research In Motion Limited. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* global Windows, WinJS */ |
| |
| var PositionError = require('./PositionError'); |
| var callbacks = {}; |
| var locs = {}; |
| |
| // constants |
| var FALLBACK_EPSILON = 0.001; |
| |
| function ensureAndCreateLocator() { |
| var deferral; |
| |
| var loc = new Windows.Devices.Geolocation.Geolocator(); |
| |
| if (typeof Windows.Devices.Geolocation.Geolocator.requestAccessAsync === 'function') { |
| deferral = Windows.Devices.Geolocation.Geolocator.requestAccessAsync().then(function (result) { |
| if (result === Windows.Devices.Geolocation.GeolocationAccessStatus.allowed) { |
| return loc; |
| } |
| |
| return WinJS.Promise.wrapError({ |
| code: PositionError.PERMISSION_DENIED, |
| message: 'Geolocation access has not been allowed by user.' |
| }); |
| }); |
| } else { |
| deferral = WinJS.Promise.wrap(loc); |
| } |
| |
| return deferral; |
| } |
| |
| function createErrorCode(loc) { |
| switch (loc.locationStatus) { |
| case Windows.Devices.Geolocation.PositionStatus.initializing: |
| // This status indicates that a location device is still initializing |
| case Windows.Devices.Geolocation.PositionStatus.noData: |
| // No location data is currently available |
| case Windows.Devices.Geolocation.PositionStatus.notInitialized: |
| // This status indicates that the app has not yet requested |
| // location data by calling GetGeolocationAsync() or |
| // registering an event handler for the positionChanged event. |
| case Windows.Devices.Geolocation.PositionStatus.notAvailable: |
| // Location is not available on this version of Windows |
| return PositionError.POSITION_UNAVAILABLE; |
| |
| case Windows.Devices.Geolocation.PositionStatus.disabled: |
| // The app doesn't have permission to access location, |
| // either because location has been turned off. |
| return PositionError.PERMISSION_DENIED; |
| |
| default: |
| break; |
| } |
| } |
| function createResult(pos) { |
| var res = { |
| accuracy: pos.coordinate.accuracy, |
| heading: pos.coordinate.heading, |
| velocity: pos.coordinate.speed, |
| altitudeAccuracy: pos.coordinate.altitudeAccuracy, |
| timestamp: pos.coordinate.timestamp |
| }; |
| |
| if (pos.coordinate.point) { |
| res.latitude = pos.coordinate.point.position.latitude; |
| res.longitude = pos.coordinate.point.position.longitude; |
| res.altitude = pos.coordinate.point.position.altitude; |
| } else { // compatibility with old windows8.0 api |
| res.latitude = pos.coordinate.latitude; |
| res.longitude = pos.coordinate.longitude; |
| res.altitude = pos.coordinate.altitude; |
| } |
| |
| return res; |
| } |
| |
| module.exports = { |
| getLocation: function (success, fail, args, env) { |
| ensureAndCreateLocator().done(function (loc) { |
| if (loc) { |
| var highAccuracy = args[0], |
| maxAge = args[1]; |
| |
| loc.desiredAccuracy = highAccuracy ? |
| Windows.Devices.Geolocation.PositionAccuracy.high : |
| Windows.Devices.Geolocation.PositionAccuracy.default; |
| |
| loc.reportInterval = maxAge ? maxAge : 0; |
| |
| loc.getGeopositionAsync().then( |
| function (pos) { |
| success(createResult(pos)); |
| }, |
| function (err) { |
| fail({ |
| code: createErrorCode(loc), |
| message: err.message |
| }); |
| } |
| ); |
| } |
| else { |
| fail({ |
| code: PositionError.POSITION_UNAVAILABLE, |
| message: "You do not have the required location services present on your system." |
| }); |
| } |
| }, fail); |
| }, |
| |
| addWatch: function (success, fail, args, env) { |
| ensureAndCreateLocator().done(function (loc) { |
| var clientId = args[0]; |
| var highAccuracy = args[1]; |
| |
| var onPositionChanged = function (e) { |
| success(createResult(e.position), { keepCallback: true }); |
| }; |
| |
| var onStatusChanged = function (e) { |
| switch (e.status) { |
| case Windows.Devices.Geolocation.PositionStatus.noData: |
| case Windows.Devices.Geolocation.PositionStatus.notAvailable: |
| fail({ |
| code: PositionError.POSITION_UNAVAILABLE, |
| message: "Data from location services is currently unavailable or you do not have the required location services present on your system." |
| }); |
| break; |
| |
| case Windows.Devices.Geolocation.PositionStatus.disabled: |
| fail({ |
| code: PositionError.PERMISSION_DENIED, |
| message: "Your location is currently turned off." |
| }); |
| break; |
| |
| // case Windows.Devices.Geolocation.PositionStatus.initializing: |
| // case Windows.Devices.Geolocation.PositionStatus.ready: |
| default: |
| break; |
| } |
| }; |
| |
| loc.desiredAccuracy = highAccuracy ? |
| Windows.Devices.Geolocation.PositionAccuracy.high : |
| Windows.Devices.Geolocation.PositionAccuracy.default; |
| |
| if (cordova.platformId == 'windows') { |
| // 'positionchanged' event fails with error below if movementThreshold is not set |
| // JavaScript runtime error: Operation aborted |
| // You must set the MovementThreshold property or the ReportInterval property before adding event handlers. |
| // WinRT information: You must set the MovementThreshold property or the ReportInterval property before adding event handlers |
| if (Number.EPSILON) { |
| loc.movementThreshold = Number.EPSILON; |
| } else { |
| loc.movementThreshold = FALLBACK_EPSILON; |
| } |
| } |
| |
| loc.addEventListener("positionchanged", onPositionChanged); |
| loc.addEventListener("statuschanged", onStatusChanged); |
| |
| callbacks[clientId] = { pos: onPositionChanged, status: onStatusChanged }; |
| locs[clientId] = loc; |
| }, fail); |
| }, |
| |
| clearWatch: function (success, fail, args, env) { |
| var clientId = args[0]; |
| var callback = callbacks[clientId]; |
| var loc = locs[clientId]; |
| |
| if (callback && loc) { |
| loc.removeEventListener("positionchanged", callback.pos); |
| loc.removeEventListener("statuschanged", callback.status); |
| |
| delete callbacks[clientId]; |
| delete locs[clientId]; |
| } |
| |
| success(); |
| } |
| }; |
| |
| require("cordova/exec/proxy").add("Geolocation", module.exports); |