2013-07-01 06:43:17 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsGeoPosition.h"
|
|
|
|
#include "nsIConsoleService.h"
|
|
|
|
#include "nsServiceManagerUtils.h"
|
|
|
|
#include "nsIDOMGeoPositionError.h"
|
|
|
|
#include "CoreLocationLocationProvider.h"
|
2013-10-24 19:10:10 -07:00
|
|
|
#include "nsCocoaFeatures.h"
|
2013-07-03 08:56:26 -07:00
|
|
|
#include "prtime.h"
|
2013-07-01 06:43:17 -07:00
|
|
|
|
2013-07-10 10:07:50 -07:00
|
|
|
#include <CoreLocation/CLError.h>
|
|
|
|
#include <CoreLocation/CLLocation.h>
|
|
|
|
#include <CoreLocation/CLLocationManager.h>
|
|
|
|
#include <CoreLocation/CLLocationManagerDelegate.h>
|
2013-07-01 06:43:17 -07:00
|
|
|
|
2013-10-20 17:53:09 -07:00
|
|
|
#include <objc/objc.h>
|
|
|
|
#include <objc/objc-runtime.h>
|
|
|
|
|
|
|
|
#include "nsObjCExceptions.h"
|
|
|
|
#import <CoreWLAN/CoreWLAN.h>
|
|
|
|
|
2013-07-01 06:43:17 -07:00
|
|
|
using namespace mozilla;
|
|
|
|
|
|
|
|
static const CLLocationAccuracy kHIGH_ACCURACY = kCLLocationAccuracyBest;
|
|
|
|
static const CLLocationAccuracy kDEFAULT_ACCURACY = kCLLocationAccuracyNearestTenMeters;
|
|
|
|
|
|
|
|
@interface LocationDelegate : NSObject <CLLocationManagerDelegate>
|
|
|
|
{
|
|
|
|
CoreLocationLocationProvider* mProvider;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id)init:(CoreLocationLocationProvider*)aProvider;
|
|
|
|
- (void)locationManager:(CLLocationManager*)aManager
|
|
|
|
didFailWithError:(NSError *)aError;
|
|
|
|
|
|
|
|
/* XXX (ggp) didUpdateToLocation is supposedly deprecated in favor of
|
|
|
|
* locationManager:didUpdateLocations, which is undocumented and didn't seem to
|
|
|
|
* work for me. This should be changed in the future, though.
|
|
|
|
*/
|
|
|
|
- (void)locationManager:(CLLocationManager*)aManager
|
|
|
|
didUpdateToLocation:(CLLocation *)aNewLocation
|
|
|
|
fromLocation:(CLLocation *)aOldLocation;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation LocationDelegate
|
|
|
|
- (id) init:(CoreLocationLocationProvider*) aProvider
|
|
|
|
{
|
|
|
|
if (self = [super init]) {
|
|
|
|
mProvider = aProvider;
|
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)locationManager:(CLLocationManager*)aManager
|
|
|
|
didFailWithError:(NSError *)aError
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIConsoleService> console =
|
|
|
|
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
|
|
|
|
|
|
|
NS_ENSURE_TRUE_VOID(console);
|
|
|
|
|
|
|
|
NSString* message =
|
|
|
|
[@"Failed to acquire position: " stringByAppendingString: [aError localizedDescription]];
|
|
|
|
|
|
|
|
console->LogStringMessage(NS_ConvertUTF8toUTF16([message UTF8String]).get());
|
|
|
|
|
|
|
|
uint16_t err = nsIDOMGeoPositionError::POSITION_UNAVAILABLE;
|
|
|
|
if ([aError code] == kCLErrorDenied) {
|
|
|
|
err = nsIDOMGeoPositionError::PERMISSION_DENIED;
|
|
|
|
}
|
|
|
|
|
|
|
|
mProvider->NotifyError(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)locationManager:(CLLocationManager*)aManager
|
|
|
|
didUpdateToLocation:(CLLocation *)aNewLocation
|
|
|
|
fromLocation:(CLLocation *)aOldLocation
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMGeoPosition> geoPosition =
|
|
|
|
new nsGeoPosition(aNewLocation.coordinate.latitude,
|
|
|
|
aNewLocation.coordinate.longitude,
|
|
|
|
aNewLocation.altitude,
|
|
|
|
aNewLocation.horizontalAccuracy,
|
|
|
|
aNewLocation.verticalAccuracy,
|
|
|
|
aNewLocation.course,
|
|
|
|
aNewLocation.speed,
|
|
|
|
PR_Now());
|
|
|
|
|
|
|
|
mProvider->Update(geoPosition);
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
class CoreLocationObjects {
|
|
|
|
public:
|
|
|
|
NS_METHOD Init(CoreLocationLocationProvider* aProvider) {
|
|
|
|
mLocationManager = [[CLLocationManager alloc] init];
|
|
|
|
NS_ENSURE_TRUE(mLocationManager, NS_ERROR_NOT_AVAILABLE);
|
|
|
|
|
|
|
|
mLocationDelegate = [[LocationDelegate alloc] init:aProvider];
|
|
|
|
NS_ENSURE_TRUE(mLocationDelegate, NS_ERROR_NOT_AVAILABLE);
|
|
|
|
|
|
|
|
mLocationManager.desiredAccuracy = kDEFAULT_ACCURACY;
|
|
|
|
mLocationManager.delegate = mLocationDelegate;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
~CoreLocationObjects() {
|
|
|
|
if (mLocationManager) {
|
|
|
|
[mLocationManager release];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mLocationDelegate) {
|
|
|
|
[mLocationDelegate release];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LocationDelegate* mLocationDelegate;
|
|
|
|
CLLocationManager* mLocationManager;
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS1(CoreLocationLocationProvider, nsIGeolocationProvider)
|
|
|
|
|
|
|
|
CoreLocationLocationProvider::CoreLocationLocationProvider()
|
|
|
|
: mCLObjects(nullptr)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-10-20 17:53:09 -07:00
|
|
|
bool
|
|
|
|
CoreLocationLocationProvider::IsCoreLocationAvailable()
|
|
|
|
{
|
2013-10-24 19:10:10 -07:00
|
|
|
#if !defined(MAC_OS_X_VERSION_10_9) || \
|
|
|
|
MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_9
|
|
|
|
if (nsCocoaFeatures::OnMavericksOrLater()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-10-20 17:53:09 -07:00
|
|
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
|
|
|
|
|
|
@try {
|
|
|
|
NSBundle * bundle = [[[NSBundle alloc] initWithPath:@"/System/Library/Frameworks/CoreWLAN.framework"] autorelease];
|
|
|
|
if (!bundle) {
|
|
|
|
[pool release];
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Class CWI_class = [bundle classNamed:@"CWInterface"];
|
|
|
|
if (!CWI_class) {
|
|
|
|
[pool release];
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ([[[CWI_class interface] interfaceState] intValue] == kCWInterfaceStateRunning) {
|
|
|
|
[pool release];
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@catch(NSException *e) {
|
|
|
|
}
|
|
|
|
[pool release];
|
2013-10-24 19:10:10 -07:00
|
|
|
#endif
|
2013-10-20 17:53:09 -07:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-07-01 06:43:17 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
CoreLocationLocationProvider::Startup()
|
|
|
|
{
|
|
|
|
if (!mCLObjects) {
|
|
|
|
nsAutoPtr<CoreLocationObjects> clObjs(new CoreLocationObjects());
|
|
|
|
|
|
|
|
nsresult rv = clObjs->Init(this);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
mCLObjects = clObjs.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
[mCLObjects->mLocationManager startUpdatingLocation];
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
CoreLocationLocationProvider::Watch(nsIGeolocationUpdate* aCallback)
|
|
|
|
{
|
|
|
|
if (mCallback) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
mCallback = aCallback;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
CoreLocationLocationProvider::Shutdown()
|
|
|
|
{
|
|
|
|
NS_ENSURE_STATE(mCLObjects);
|
|
|
|
|
|
|
|
[mCLObjects->mLocationManager stopUpdatingLocation];
|
|
|
|
|
|
|
|
delete mCLObjects;
|
|
|
|
mCLObjects = nullptr;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
CoreLocationLocationProvider::SetHighAccuracy(bool aEnable)
|
|
|
|
{
|
|
|
|
NS_ENSURE_STATE(mCLObjects);
|
|
|
|
|
|
|
|
mCLObjects->mLocationManager.desiredAccuracy =
|
|
|
|
(aEnable ? kHIGH_ACCURACY : kDEFAULT_ACCURACY);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2014-01-08 13:04:21 -08:00
|
|
|
void
|
2013-07-01 06:43:17 -07:00
|
|
|
CoreLocationLocationProvider::Update(nsIDOMGeoPosition* aSomewhere)
|
|
|
|
{
|
|
|
|
if (aSomewhere && mCallback) {
|
|
|
|
mCallback->Update(aSomewhere);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-08 13:04:21 -08:00
|
|
|
void
|
2013-07-01 06:43:17 -07:00
|
|
|
CoreLocationLocationProvider::NotifyError(uint16_t aErrorCode)
|
|
|
|
{
|
|
|
|
mCallback->NotifyError(aErrorCode);
|
|
|
|
}
|