dom/system/mac/CoreLocationLocationProvider.mm

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "nsCOMPtr.h"
     8 #include "nsGeoPosition.h"
     9 #include "nsIConsoleService.h"
    10 #include "nsServiceManagerUtils.h"
    11 #include "nsIDOMGeoPositionError.h"
    12 #include "CoreLocationLocationProvider.h"
    13 #include "nsCocoaFeatures.h"
    14 #include "prtime.h"
    16 #include <CoreLocation/CLError.h>
    17 #include <CoreLocation/CLLocation.h>
    18 #include <CoreLocation/CLLocationManager.h>
    19 #include <CoreLocation/CLLocationManagerDelegate.h>
    21 #include <objc/objc.h>
    22 #include <objc/objc-runtime.h>
    24 #include "nsObjCExceptions.h"
    26 using namespace mozilla;
    28 static const CLLocationAccuracy kHIGH_ACCURACY = kCLLocationAccuracyBest;
    29 static const CLLocationAccuracy kDEFAULT_ACCURACY = kCLLocationAccuracyNearestTenMeters;
    31 @interface LocationDelegate : NSObject <CLLocationManagerDelegate>
    32 {
    33   CoreLocationLocationProvider* mProvider;
    34 }
    36 - (id)init:(CoreLocationLocationProvider*)aProvider;
    37 - (void)locationManager:(CLLocationManager*)aManager
    38   didFailWithError:(NSError *)aError;
    40 /* XXX (ggp) didUpdateToLocation is supposedly deprecated in favor of
    41  * locationManager:didUpdateLocations, which is undocumented and didn't seem to
    42  * work for me. This should be changed in the future, though.
    43  */
    44 - (void)locationManager:(CLLocationManager*)aManager
    45   didUpdateToLocation:(CLLocation *)aNewLocation
    46   fromLocation:(CLLocation *)aOldLocation;
    47 @end
    49 @implementation LocationDelegate
    50 - (id) init:(CoreLocationLocationProvider*) aProvider
    51 {
    52   if (self = [super init]) {
    53     mProvider = aProvider;
    54   }
    56   return self;
    57 }
    59 - (void)locationManager:(CLLocationManager*)aManager
    60   didFailWithError:(NSError *)aError
    61 {
    62   nsCOMPtr<nsIConsoleService> console =
    63     do_GetService(NS_CONSOLESERVICE_CONTRACTID);
    65   NS_ENSURE_TRUE_VOID(console);
    67   NSString* message =
    68     [@"Failed to acquire position: " stringByAppendingString: [aError localizedDescription]];
    70   console->LogStringMessage(NS_ConvertUTF8toUTF16([message UTF8String]).get());
    72   uint16_t err = nsIDOMGeoPositionError::POSITION_UNAVAILABLE;
    73   if ([aError code] == kCLErrorDenied) {
    74     err = nsIDOMGeoPositionError::PERMISSION_DENIED;
    75   }
    77   mProvider->NotifyError(err);
    78 }
    80 - (void)locationManager:(CLLocationManager*)aManager
    81   didUpdateToLocation:(CLLocation *)aNewLocation
    82   fromLocation:(CLLocation *)aOldLocation
    83 {
    84   nsCOMPtr<nsIDOMGeoPosition> geoPosition =
    85     new nsGeoPosition(aNewLocation.coordinate.latitude,
    86                       aNewLocation.coordinate.longitude,
    87                       aNewLocation.altitude,
    88                       aNewLocation.horizontalAccuracy,
    89                       aNewLocation.verticalAccuracy,
    90                       aNewLocation.course,
    91                       aNewLocation.speed,
    92                       PR_Now());
    94   mProvider->Update(geoPosition);
    95 }
    96 @end
    98 class CoreLocationObjects {
    99 public:
   100   NS_METHOD Init(CoreLocationLocationProvider* aProvider) {
   101     mLocationManager = [[CLLocationManager alloc] init];
   102     NS_ENSURE_TRUE(mLocationManager, NS_ERROR_NOT_AVAILABLE);
   104     mLocationDelegate = [[LocationDelegate alloc] init:aProvider];
   105     NS_ENSURE_TRUE(mLocationDelegate, NS_ERROR_NOT_AVAILABLE);
   107     mLocationManager.desiredAccuracy = kDEFAULT_ACCURACY;
   108     mLocationManager.delegate = mLocationDelegate;
   110     return NS_OK;
   111   }
   113   ~CoreLocationObjects() {
   114     if (mLocationManager) {
   115       [mLocationManager release];
   116     }
   118     if (mLocationDelegate) {
   119       [mLocationDelegate release];
   120     }
   121   }
   123   LocationDelegate* mLocationDelegate;
   124   CLLocationManager* mLocationManager;
   125 };
   127 NS_IMPL_ISUPPORTS(CoreLocationLocationProvider, nsIGeolocationProvider)
   129 CoreLocationLocationProvider::CoreLocationLocationProvider()
   130   : mCLObjects(nullptr)
   131 {
   132 }
   134 NS_IMETHODIMP
   135 CoreLocationLocationProvider::Startup()
   136 {
   137   if (!mCLObjects) {
   138     nsAutoPtr<CoreLocationObjects> clObjs(new CoreLocationObjects());
   140     nsresult rv = clObjs->Init(this);
   141     NS_ENSURE_SUCCESS(rv, rv);
   143     mCLObjects = clObjs.forget();
   144   }
   146   [mCLObjects->mLocationManager startUpdatingLocation];
   147   return NS_OK;
   148 }
   150 NS_IMETHODIMP
   151 CoreLocationLocationProvider::Watch(nsIGeolocationUpdate* aCallback)
   152 {
   153   if (mCallback) {
   154     return NS_OK;
   155   }
   157   mCallback = aCallback;
   158   return NS_OK;
   159 }
   161 NS_IMETHODIMP
   162 CoreLocationLocationProvider::Shutdown()
   163 {
   164   NS_ENSURE_STATE(mCLObjects);
   166   [mCLObjects->mLocationManager stopUpdatingLocation];
   168   delete mCLObjects;
   169   mCLObjects = nullptr;
   170   return NS_OK;
   171 }
   173 NS_IMETHODIMP
   174 CoreLocationLocationProvider::SetHighAccuracy(bool aEnable)
   175 {
   176   NS_ENSURE_STATE(mCLObjects);
   178   mCLObjects->mLocationManager.desiredAccuracy =
   179     (aEnable ? kHIGH_ACCURACY : kDEFAULT_ACCURACY);
   181   return NS_OK;
   182 }
   184 void
   185 CoreLocationLocationProvider::Update(nsIDOMGeoPosition* aSomewhere)
   186 {
   187   if (aSomewhere && mCallback) {
   188     mCallback->Update(aSomewhere);
   189   }
   190 }
   192 void
   193 CoreLocationLocationProvider::NotifyError(uint16_t aErrorCode)
   194 {
   195   mCallback->NotifyError(aErrorCode);
   196 }

mercurial