diff options
Diffstat (limited to 'StoneIsland/plugins/cordova-plugin-geolocation/src')
7 files changed, 899 insertions, 0 deletions
diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/src/firefoxos/GeolocationProxy.js b/StoneIsland/plugins/cordova-plugin-geolocation/src/firefoxos/GeolocationProxy.js new file mode 100644 index 00000000..e4b40529 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-geolocation/src/firefoxos/GeolocationProxy.js @@ -0,0 +1,67 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * +*/ + +// latest geolocation spec can be found here: http://www.w3.org/TR/geolocation-API/ + +var idsMap = {}; + +module.exports = { + getLocation: function(success, error, args) { + var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); + function successCallback(position) { + // Cordova is creating Position object using just coords + success(position.coords); + } + geo.getCurrentPosition(successCallback, error, { + enableHighAccuracy: args[0], + maximumAge: args[1] + }); + }, + + addWatch: function(success, error, args) { + var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); + var id = args[0]; + function successCallback(position) { + success(position.coords); + } + var nativeId = geo.watchPosition(successCallback, error, { + enableHighAccuracy: args[1] + }); + + idsMap[id] = nativeId; + }, + + clearWatch: function(success, error, args) { + var geo = cordova.require('cordova/modulemapper').getOriginalSymbol(window, 'navigator.geolocation'); + var id = args[0]; + + if(id in idsMap) { + geo.clearWatch(idsMap[id]); + delete idsMap[id]; + } + + if(success) { + success(); + } + } +}; + +require("cordova/exec/proxy").add("Geolocation", module.exports); diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/src/ios/CDVLocation.h b/StoneIsland/plugins/cordova-plugin-geolocation/src/ios/CDVLocation.h new file mode 100644 index 00000000..cce2738f --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-geolocation/src/ios/CDVLocation.h @@ -0,0 +1,70 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. + */ + +#import <UIKit/UIKit.h> +#import <CoreLocation/CoreLocation.h> +#import <Cordova/CDVPlugin.h> + +enum CDVLocationStatus { + PERMISSIONDENIED = 1, + POSITIONUNAVAILABLE, + TIMEOUT +}; +typedef NSUInteger CDVLocationStatus; + +// simple object to keep track of location information +@interface CDVLocationData : NSObject { + CDVLocationStatus locationStatus; + NSMutableArray* locationCallbacks; + NSMutableDictionary* watchCallbacks; + CLLocation* locationInfo; +} + +@property (nonatomic, assign) CDVLocationStatus locationStatus; +@property (nonatomic, strong) CLLocation* locationInfo; +@property (nonatomic, strong) NSMutableArray* locationCallbacks; +@property (nonatomic, strong) NSMutableDictionary* watchCallbacks; + +@end + +@interface CDVLocation : CDVPlugin <CLLocationManagerDelegate>{ + @private BOOL __locationStarted; + @private BOOL __highAccuracyEnabled; + CDVLocationData* locationData; +} + +@property (nonatomic, strong) CLLocationManager* locationManager; +@property (nonatomic, strong) CDVLocationData* locationData; + +- (void)getLocation:(CDVInvokedUrlCommand*)command; +- (void)addWatch:(CDVInvokedUrlCommand*)command; +- (void)clearWatch:(CDVInvokedUrlCommand*)command; +- (void)returnLocationInfo:(NSString*)callbackId andKeepCallback:(BOOL)keepCallback; +- (void)returnLocationError:(NSUInteger)errorCode withMessage:(NSString*)message; +- (void)startLocation:(BOOL)enableHighAccuracy; + +- (void)locationManager:(CLLocationManager*)manager + didUpdateToLocation:(CLLocation*)newLocation + fromLocation:(CLLocation*)oldLocation; + +- (void)locationManager:(CLLocationManager*)manager + didFailWithError:(NSError*)error; + +- (BOOL)isLocationServicesEnabled; +@end diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/src/ios/CDVLocation.m b/StoneIsland/plugins/cordova-plugin-geolocation/src/ios/CDVLocation.m new file mode 100644 index 00000000..8b543c8e --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-geolocation/src/ios/CDVLocation.m @@ -0,0 +1,366 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. + */ + +#import "CDVLocation.h" + +#pragma mark Constants + +#define kPGLocationErrorDomain @"kPGLocationErrorDomain" +#define kPGLocationDesiredAccuracyKey @"desiredAccuracy" +#define kPGLocationForcePromptKey @"forcePrompt" +#define kPGLocationDistanceFilterKey @"distanceFilter" +#define kPGLocationFrequencyKey @"frequency" + +#pragma mark - +#pragma mark Categories + +@implementation CDVLocationData + +@synthesize locationStatus, locationInfo, locationCallbacks, watchCallbacks; +- (CDVLocationData*)init +{ + self = (CDVLocationData*)[super init]; + if (self) { + self.locationInfo = nil; + self.locationCallbacks = nil; + self.watchCallbacks = nil; + } + return self; +} + +@end + +#pragma mark - +#pragma mark CDVLocation + +@implementation CDVLocation + +@synthesize locationManager, locationData; + +- (void)pluginInitialize +{ + self.locationManager = [[CLLocationManager alloc] init]; + self.locationManager.delegate = self; // Tells the location manager to send updates to this object + __locationStarted = NO; + __highAccuracyEnabled = NO; + self.locationData = nil; +} + +- (BOOL)isAuthorized +{ + BOOL authorizationStatusClassPropertyAvailable = [CLLocationManager respondsToSelector:@selector(authorizationStatus)]; // iOS 4.2+ + + if (authorizationStatusClassPropertyAvailable) { + NSUInteger authStatus = [CLLocationManager authorizationStatus]; +#ifdef __IPHONE_8_0 + if ([self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) { //iOS 8.0+ + return (authStatus == kCLAuthorizationStatusAuthorizedWhenInUse) || (authStatus == kCLAuthorizationStatusAuthorizedAlways) || (authStatus == kCLAuthorizationStatusNotDetermined); + } +#endif + return (authStatus == kCLAuthorizationStatusAuthorized) || (authStatus == kCLAuthorizationStatusNotDetermined); + } + + // by default, assume YES (for iOS < 4.2) + return YES; +} + +- (BOOL)isLocationServicesEnabled +{ + BOOL locationServicesEnabledInstancePropertyAvailable = [self.locationManager respondsToSelector:@selector(locationServicesEnabled)]; // iOS 3.x + BOOL locationServicesEnabledClassPropertyAvailable = [CLLocationManager respondsToSelector:@selector(locationServicesEnabled)]; // iOS 4.x + + if (locationServicesEnabledClassPropertyAvailable) { // iOS 4.x + return [CLLocationManager locationServicesEnabled]; + } else if (locationServicesEnabledInstancePropertyAvailable) { // iOS 2.x, iOS 3.x + return [(id)self.locationManager locationServicesEnabled]; + } else { + return NO; + } +} + +- (void)startLocation:(BOOL)enableHighAccuracy +{ + if (![self isLocationServicesEnabled]) { + [self returnLocationError:PERMISSIONDENIED withMessage:@"Location services are not enabled."]; + return; + } + if (![self isAuthorized]) { + NSString* message = nil; + BOOL authStatusAvailable = [CLLocationManager respondsToSelector:@selector(authorizationStatus)]; // iOS 4.2+ + if (authStatusAvailable) { + NSUInteger code = [CLLocationManager authorizationStatus]; + if (code == kCLAuthorizationStatusNotDetermined) { + // could return POSITION_UNAVAILABLE but need to coordinate with other platforms + message = @"User undecided on application's use of location services."; + } else if (code == kCLAuthorizationStatusRestricted) { + message = @"Application's use of location services is restricted."; + } + } + // PERMISSIONDENIED is only PositionError that makes sense when authorization denied + [self returnLocationError:PERMISSIONDENIED withMessage:message]; + + return; + } + +#ifdef __IPHONE_8_0 + NSUInteger code = [CLLocationManager authorizationStatus]; + if (code == kCLAuthorizationStatusNotDetermined && ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)] || [self.locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)])) { //iOS8+ + __highAccuracyEnabled = enableHighAccuracy; + if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationAlwaysUsageDescription"]){ + [self.locationManager requestAlwaysAuthorization]; + } else if([[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"]) { + [self.locationManager requestWhenInUseAuthorization]; + } else { + NSLog(@"[Warning] No NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription key is defined in the Info.plist file."); + } + return; + } +#endif + + // Tell the location manager to start notifying us of location updates. We + // first stop, and then start the updating to ensure we get at least one + // update, even if our location did not change. + [self.locationManager stopUpdatingLocation]; + [self.locationManager startUpdatingLocation]; + __locationStarted = YES; + if (enableHighAccuracy) { + __highAccuracyEnabled = YES; + // Set distance filter to 5 for a high accuracy. Setting it to "kCLDistanceFilterNone" could provide a + // higher accuracy, but it's also just spamming the callback with useless reports which drain the battery. + self.locationManager.distanceFilter = 5; + // Set desired accuracy to Best. + self.locationManager.desiredAccuracy = kCLLocationAccuracyBest; + } else { + __highAccuracyEnabled = NO; + // TODO: Set distance filter to 10 meters? and desired accuracy to nearest ten meters? arbitrary. + self.locationManager.distanceFilter = 10; + self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters; + } +} + +- (void)_stopLocation +{ + if (__locationStarted) { + if (![self isLocationServicesEnabled]) { + return; + } + + [self.locationManager stopUpdatingLocation]; + __locationStarted = NO; + __highAccuracyEnabled = NO; + } +} + +- (void)locationManager:(CLLocationManager*)manager + didUpdateToLocation:(CLLocation*)newLocation + fromLocation:(CLLocation*)oldLocation +{ + CDVLocationData* cData = self.locationData; + + cData.locationInfo = newLocation; + if (self.locationData.locationCallbacks.count > 0) { + for (NSString* callbackId in self.locationData.locationCallbacks) { + [self returnLocationInfo:callbackId andKeepCallback:NO]; + } + + [self.locationData.locationCallbacks removeAllObjects]; + } + if (self.locationData.watchCallbacks.count > 0) { + for (NSString* timerId in self.locationData.watchCallbacks) { + [self returnLocationInfo:[self.locationData.watchCallbacks objectForKey:timerId] andKeepCallback:YES]; + } + } else { + // No callbacks waiting on us anymore, turn off listening. + [self _stopLocation]; + } +} + +- (void)getLocation:(CDVInvokedUrlCommand*)command +{ + NSString* callbackId = command.callbackId; + BOOL enableHighAccuracy = [[command argumentAtIndex:0] boolValue]; + + if ([self isLocationServicesEnabled] == NO) { + NSMutableDictionary* posError = [NSMutableDictionary dictionaryWithCapacity:2]; + [posError setObject:[NSNumber numberWithInt:PERMISSIONDENIED] forKey:@"code"]; + [posError setObject:@"Location services are disabled." forKey:@"message"]; + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:posError]; + [self.commandDelegate sendPluginResult:result callbackId:callbackId]; + } else { + if (!self.locationData) { + self.locationData = [[CDVLocationData alloc] init]; + } + CDVLocationData* lData = self.locationData; + if (!lData.locationCallbacks) { + lData.locationCallbacks = [NSMutableArray arrayWithCapacity:1]; + } + + if (!__locationStarted || (__highAccuracyEnabled != enableHighAccuracy)) { + // add the callbackId into the array so we can call back when get data + if (callbackId != nil) { + [lData.locationCallbacks addObject:callbackId]; + } + // Tell the location manager to start notifying us of heading updates + [self startLocation:enableHighAccuracy]; + } else { + [self returnLocationInfo:callbackId andKeepCallback:NO]; + } + } +} + +- (void)addWatch:(CDVInvokedUrlCommand*)command +{ + NSString* callbackId = command.callbackId; + NSString* timerId = [command argumentAtIndex:0]; + BOOL enableHighAccuracy = [[command argumentAtIndex:1] boolValue]; + + if (!self.locationData) { + self.locationData = [[CDVLocationData alloc] init]; + } + CDVLocationData* lData = self.locationData; + + if (!lData.watchCallbacks) { + lData.watchCallbacks = [NSMutableDictionary dictionaryWithCapacity:1]; + } + + // add the callbackId into the dictionary so we can call back whenever get data + [lData.watchCallbacks setObject:callbackId forKey:timerId]; + + if ([self isLocationServicesEnabled] == NO) { + NSMutableDictionary* posError = [NSMutableDictionary dictionaryWithCapacity:2]; + [posError setObject:[NSNumber numberWithInt:PERMISSIONDENIED] forKey:@"code"]; + [posError setObject:@"Location services are disabled." forKey:@"message"]; + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:posError]; + [self.commandDelegate sendPluginResult:result callbackId:callbackId]; + } else { + if (!__locationStarted || (__highAccuracyEnabled != enableHighAccuracy)) { + // Tell the location manager to start notifying us of location updates + [self startLocation:enableHighAccuracy]; + } + } +} + +- (void)clearWatch:(CDVInvokedUrlCommand*)command +{ + NSString* timerId = [command argumentAtIndex:0]; + + if (self.locationData && self.locationData.watchCallbacks && [self.locationData.watchCallbacks objectForKey:timerId]) { + [self.locationData.watchCallbacks removeObjectForKey:timerId]; + if([self.locationData.watchCallbacks count] == 0) { + [self _stopLocation]; + } + } +} + +- (void)stopLocation:(CDVInvokedUrlCommand*)command +{ + [self _stopLocation]; +} + +- (void)returnLocationInfo:(NSString*)callbackId andKeepCallback:(BOOL)keepCallback +{ + CDVPluginResult* result = nil; + CDVLocationData* lData = self.locationData; + + if (lData && !lData.locationInfo) { + // return error + result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:POSITIONUNAVAILABLE]; + } else if (lData && lData.locationInfo) { + CLLocation* lInfo = lData.locationInfo; + NSMutableDictionary* returnInfo = [NSMutableDictionary dictionaryWithCapacity:8]; + NSNumber* timestamp = [NSNumber numberWithDouble:([lInfo.timestamp timeIntervalSince1970] * 1000)]; + [returnInfo setObject:timestamp forKey:@"timestamp"]; + [returnInfo setObject:[NSNumber numberWithDouble:lInfo.speed] forKey:@"velocity"]; + [returnInfo setObject:[NSNumber numberWithDouble:lInfo.verticalAccuracy] forKey:@"altitudeAccuracy"]; + [returnInfo setObject:[NSNumber numberWithDouble:lInfo.horizontalAccuracy] forKey:@"accuracy"]; + [returnInfo setObject:[NSNumber numberWithDouble:lInfo.course] forKey:@"heading"]; + [returnInfo setObject:[NSNumber numberWithDouble:lInfo.altitude] forKey:@"altitude"]; + [returnInfo setObject:[NSNumber numberWithDouble:lInfo.coordinate.latitude] forKey:@"latitude"]; + [returnInfo setObject:[NSNumber numberWithDouble:lInfo.coordinate.longitude] forKey:@"longitude"]; + + result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:returnInfo]; + [result setKeepCallbackAsBool:keepCallback]; + } + if (result) { + [self.commandDelegate sendPluginResult:result callbackId:callbackId]; + } +} + +- (void)returnLocationError:(NSUInteger)errorCode withMessage:(NSString*)message +{ + NSMutableDictionary* posError = [NSMutableDictionary dictionaryWithCapacity:2]; + + [posError setObject:[NSNumber numberWithUnsignedInteger:errorCode] forKey:@"code"]; + [posError setObject:message ? message:@"" forKey:@"message"]; + CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:posError]; + + for (NSString* callbackId in self.locationData.locationCallbacks) { + [self.commandDelegate sendPluginResult:result callbackId:callbackId]; + } + + [self.locationData.locationCallbacks removeAllObjects]; + + for (NSString* callbackId in self.locationData.watchCallbacks) { + [self.commandDelegate sendPluginResult:result callbackId:callbackId]; + } +} + +- (void)locationManager:(CLLocationManager*)manager didFailWithError:(NSError*)error +{ + NSLog(@"locationManager::didFailWithError %@", [error localizedFailureReason]); + + CDVLocationData* lData = self.locationData; + if (lData && __locationStarted) { + // TODO: probably have to once over the various error codes and return one of: + // PositionError.PERMISSION_DENIED = 1; + // PositionError.POSITION_UNAVAILABLE = 2; + // PositionError.TIMEOUT = 3; + NSUInteger positionError = POSITIONUNAVAILABLE; + if (error.code == kCLErrorDenied) { + positionError = PERMISSIONDENIED; + } + [self returnLocationError:positionError withMessage:[error localizedDescription]]; + } + + if (error.code != kCLErrorLocationUnknown) { + [self.locationManager stopUpdatingLocation]; + __locationStarted = NO; + } +} + +//iOS8+ +-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status +{ + if(!__locationStarted){ + [self startLocation:__highAccuracyEnabled]; + } +} + +- (void)dealloc +{ + self.locationManager.delegate = nil; +} + +- (void)onReset +{ + [self _stopLocation]; + [self.locationManager stopUpdatingHeading]; +} + +@end diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/src/ubuntu/geolocation.cpp b/StoneIsland/plugins/cordova-plugin-geolocation/src/ubuntu/geolocation.cpp new file mode 100644 index 00000000..c820cfef --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-geolocation/src/ubuntu/geolocation.cpp @@ -0,0 +1,119 @@ +/* + * + * Copyright 2013 Canonical Ltd. + * + * 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. + * +*/ + +#include <QUuid> + +#include "geolocation.h" + +Geolocation::Geolocation(Cordova *cordova): CPlugin(cordova), + _geoPositionInfoSource(QGeoPositionInfoSource::createDefaultSource(this)) { + if (_geoPositionInfoSource.data() != 0) { + QObject::connect(_geoPositionInfoSource.data(), SIGNAL(positionUpdated(QGeoPositionInfo)), this, SLOT(positionUpdated(QGeoPositionInfo))); + QObject::connect(_geoPositionInfoSource.data(), SIGNAL(updateTimeout()), this, SLOT(updateTimeout())); + } +} + +void Geolocation::addWatch(int scId, int ecId, const QString &id, bool enableHighAccuracy) { + Q_UNUSED(enableHighAccuracy); + + assert(_id2sc.find(id) == _id2sc.end()); + + if (!_geoPositionInfoSource.data()) { + QVariantMap err; + err.insert("code", POSITION_UNAVAILABLE); + err.insert("message", "unavailable"); + + this->cb(ecId, err); + return; + } + + _id2sc[id] = scId; + _id2ec[id] = ecId; +} + +void Geolocation::clearWatch(int scId, int ecId, const QString &id) { + _id2sc.remove(id); + _id2ec.remove(id); +} + +void Geolocation::getLocation(int scId, int ecId, bool enableHighAccuracy, qint64 maximumAge) { + Q_UNUSED(maximumAge); + Q_UNUSED(enableHighAccuracy); + + if (!_geoPositionInfoSource.data()) { + QVariantMap err; + err.insert("code", POSITION_UNAVAILABLE); + err.insert("message", "unavailable"); + + this->cb(ecId, err); + return; + } + + _geoPositionInfoSource->requestUpdate(); + + QString id = QString("_INTERNAL_") + QUuid::createUuid().toString(); + + _id2sc[id] = scId; + _id2ec[id] = ecId; + _singleUpdate.insert(id); +} + +void Geolocation::positionUpdated(const QGeoPositionInfo &update) { + QGeoCoordinate coordinate = update.coordinate(); + + QVariantMap p; + + p.insert("latitude", coordinate.latitude()); + p.insert("longitude", coordinate.longitude()); + p.insert("altitude", coordinate.altitude()); + + if (update.hasAttribute(QGeoPositionInfo::VerticalAccuracy)) + p.insert("accuracy", update.attribute(QGeoPositionInfo::VerticalAccuracy)); + if (update.hasAttribute(QGeoPositionInfo::Direction)) + p.insert("heading", update.attribute(QGeoPositionInfo::Direction)); + if (update.hasAttribute(QGeoPositionInfo::GroundSpeed)) + p.insert("velocity", update.attribute(QGeoPositionInfo::GroundSpeed)); + if (update.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) + p.insert("altitudeAccuracy", update.attribute(QGeoPositionInfo::HorizontalAccuracy)); + p.insert("timestamp", update.timestamp().toMSecsSinceEpoch()); + + for (const QString &id: _id2sc.keys()) { + int scId = _id2sc[id]; + this->cb(scId, p); + if (_singleUpdate.contains(id)) { + _singleUpdate.remove(id); + _id2sc.remove(id); + _id2ec.remove(id); + } + } +} + +void Geolocation::updateTimeout() { + QVariantMap err; + err.insert("code", TIMEOUT); + err.insert("message", "timeout"); + + for (int ecId: _id2ec) { + this->cb(ecId, err); + } + + _id2ec.clear(); + _id2sc.clear(); + _singleUpdate.clear(); +} diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/src/ubuntu/geolocation.h b/StoneIsland/plugins/cordova-plugin-geolocation/src/ubuntu/geolocation.h new file mode 100644 index 00000000..7345bec9 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-geolocation/src/ubuntu/geolocation.h @@ -0,0 +1,69 @@ +/* + * + * Copyright 2013 Canonical Ltd. + * + * 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. + * +*/ + +#ifndef GEOLOCATION_H_SVO2013 +#define GEOLOCATION_H_SVO2013 + +#include <QGeoPositionInfoSource> +#include <QGeoPositionInfo> +#include <QtCore> +#include <cassert> + +#include <cplugin.h> + +class Geolocation: public CPlugin { + Q_OBJECT +public: + explicit Geolocation(Cordova *cordova); + + virtual const QString fullName() override { + return Geolocation::fullID(); + } + + virtual const QString shortName() override { + return "Geolocation"; + } + + static const QString fullID() { + return "Geolocation"; + } + +public slots: + void getLocation(int scId, int ecId, bool enableHighAccuracy, qint64 maximumAge); + void addWatch(int scId, int ecId, const QString &id, bool enableHighAccuracy); + void clearWatch(int scId, int ecId, const QString &id); + +protected slots: + void positionUpdated(const QGeoPositionInfo &update); + void updateTimeout(); + +private: + QMap<QString, int> _id2sc; + QMap<QString, int> _id2ec; + QSet<QString> _singleUpdate; + QSharedPointer<QGeoPositionInfoSource> _geoPositionInfoSource; + + enum PositionError { + PERMISSION_DENIED = 1, + POSITION_UNAVAILABLE = 2, + TIMEOUT = 3 + }; +}; + +#endif diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/src/windows/GeolocationProxy.js b/StoneIsland/plugins/cordova-plugin-geolocation/src/windows/GeolocationProxy.js new file mode 100644 index 00000000..9cab6a4d --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-geolocation/src/windows/GeolocationProxy.js @@ -0,0 +1,174 @@ +/* + * 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. + */ + +var PositionError = require('./PositionError'), + ids = {}, + loc; + +function ensureLocator() { + if (loc == null) + loc = new Windows.Devices.Geolocation.Geolocator(); + + return loc; +} + +function createErrorCode() { + 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) { + ensureLocator(); + if (loc != null) + { + 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(), + message: err.message + }); + } + ); + } + else + { + fail({ + code: PositionError.POSITION_UNAVAILABLE, + message: "You do not have the required location services present on your system." + }); + } + }, + + addWatch: function (success, fail, args, env) { + ensureLocator(); + var clientId = args[0], + highAccuracy = args[1], + + onPositionChanged = function (e) { + success(createResult(e.position), {keepCallback: true}); + }, + + 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' && WinJS.Utilities.isPhone) { + // on Windows Phone 8.1 '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 + loc.movementThreshold = loc.movementThreshold || 1; // 1 meter + } + + loc.addEventListener("positionchanged", onPositionChanged); + loc.addEventListener("statuschanged", onStatusChanged); + + ids[clientId] = { pos: onPositionChanged, status: onStatusChanged }; + }, + + clearWatch: function (success, fail, args, env) { + var clientId = args[0], + callbacks = ids[clientId]; + + if (callbacks) { + loc.removeEventListener("positionchanged", callbacks.pos); + loc.removeEventListener("statuschanged", callbacks.status); + + delete ids[clientId]; + } + + success && success(); + } +}; + +require("cordova/exec/proxy").add("Geolocation", module.exports);
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-geolocation/src/wp/GeoLocation.cs b/StoneIsland/plugins/cordova-plugin-geolocation/src/wp/GeoLocation.cs new file mode 100644 index 00000000..42af72de --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-geolocation/src/wp/GeoLocation.cs @@ -0,0 +1,34 @@ +/* + 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. +*/ + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Threading; +using System.Device.Location; + +namespace WPCordovaClassLib.Cordova.Commands +{ + /// <summary> + /// This is a command stub, the browser provides the correct implementation. We use this to trigger the static analyzer that we require this permission + /// </summary> + public class Geolocation + { + /* Unreachable code, by design -jm */ + private void triggerGeoInclusion() + { + new GeoCoordinateWatcher(); + } + } +} |
