blob: 03ed4950794ae751ddbe353522326363a0016157 [file] [log] [blame]
/*
* 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);