From c11d4eaa2b0f122febb0409228647e7d8ea3edb0 Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Sat, 22 Mar 2014 00:42:55 -0700 Subject: [PATCH] Bug 977725 - MLS Geolocation seeding GONK GPS Provider. r=kanru --- b2g/app/b2g.js | 3 +- browser/app/profile/firefox.js | 5 ++ dom/src/geolocation/nsGeolocation.cpp | 4 +- dom/system/NetworkGeolocationProvider.js | 19 ++--- .../gonk/GonkGPSGeolocationProvider.cpp | 81 ++++++++++++++++++- dom/system/gonk/GonkGPSGeolocationProvider.h | 17 +++- 6 files changed, 114 insertions(+), 15 deletions(-) diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index 52ed0fe9511..de929f839d6 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -187,7 +187,8 @@ pref("privacy.item.syncAccount", true); // base url for the wifi geolocation network provider pref("geo.provider.use_mls", false); -pref("geo.wifi.uri", "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%"); +pref("geo.cell.scan", true); +pref("geo.wifi.uri", "https://location.services.mozilla.com/v1/geolocate?key=%MOZ_MOZILLA_API_KEY%"); // enable geo pref("geo.enabled", true); diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index cccbb364127..3c3ba6244b4 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1369,6 +1369,11 @@ pref("dom.debug.propagate_gesture_events_through_content", false); // The request URL of the GeoLocation backend. pref("geo.wifi.uri", "https://www.googleapis.com/geolocation/v1/geolocate?key=%GOOGLE_API_KEY%"); +#ifdef RELEASE_BUILD +pref("geo.wifi.logging.enabled", false); +#else +pref("geo.wifi.logging.enabled", true); +#endif // Necko IPC security checks only needed for app isolation for cookies/cache/etc: // currently irrelevant for desktop e10s diff --git a/dom/src/geolocation/nsGeolocation.cpp b/dom/src/geolocation/nsGeolocation.cpp index a2e87a6f2ae..6a1a3ee6b6c 100644 --- a/dom/src/geolocation/nsGeolocation.cpp +++ b/dom/src/geolocation/nsGeolocation.cpp @@ -684,7 +684,7 @@ nsresult nsGeolocationService::Init() #endif #ifdef MOZ_WIDGET_GONK - mProvider = do_GetService(GONK_GPS_GEOLOCATION_PROVIDER_CONTRACTID); + mProvider = do_CreateInstance(GONK_GPS_GEOLOCATION_PROVIDER_CONTRACTID); #endif #ifdef MOZ_WIDGET_COCOA @@ -694,7 +694,7 @@ nsresult nsGeolocationService::Init() #endif if (Preferences::GetBool("geo.provider.use_mls", false)) { - mProvider = do_GetService("@mozilla.org/geolocation/mls-provider;1"); + mProvider = do_CreateInstance("@mozilla.org/geolocation/mls-provider;1"); } // Override platform-specific providers with the default (network) diff --git a/dom/system/NetworkGeolocationProvider.js b/dom/system/NetworkGeolocationProvider.js index f0dac5064e9..dcc5f5038d3 100755 --- a/dom/system/NetworkGeolocationProvider.js +++ b/dom/system/NetworkGeolocationProvider.js @@ -87,6 +87,8 @@ WifiGeoPositionProvider.prototype = { QueryInterface: XPCOMUtils.generateQI([Ci.nsIGeolocationProvider, Ci.nsIWifiListener, Ci.nsITimerCallback]), + listener: null, + startup: function() { if (this.started) return; @@ -104,6 +106,7 @@ WifiGeoPositionProvider.prototype = { }, watch: function(c) { + this.listener = c; }, shutdown: function() { @@ -121,6 +124,7 @@ WifiGeoPositionProvider.prototype = { this.wifiService.stopWatching(this); this.wifiService = null; } + this.listener = null; this.started = false; }, @@ -186,17 +190,18 @@ WifiGeoPositionProvider.prototype = { notify: function (timeoutTimer) { let url = Services.urlFormatter.formatURLPref("geo.wifi.uri"); + let listener = this.listener; LOG("Sending request: " + url + "\n"); let xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"] .createInstance(Ci.nsIXMLHttpRequest); - getGeoService().locationUpdatePending(); + listener.locationUpdatePending(); try { xhr.open("POST", url, true); } catch (e) { - getGeoService().notifyError(POSITION_UNAVAILABLE); + listener.notifyError(POSITION_UNAVAILABLE); return; } xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8"); @@ -204,13 +209,13 @@ WifiGeoPositionProvider.prototype = { xhr.mozBackgroundRequest = true; xhr.channel.loadFlags = Ci.nsIChannel.LOAD_ANONYMOUS; xhr.onerror = function() { - getGeoService().notifyError(POSITION_UNAVAILABLE); + listener.notifyError(POSITION_UNAVAILABLE); }; xhr.onload = function() { LOG("gls returned status: " + xhr.status + " --> " + JSON.stringify(xhr.response)); if ((xhr.channel instanceof Ci.nsIHttpChannel && xhr.status != 200) || !xhr.response || !xhr.response.location) { - getGeoService().notifyError(POSITION_UNAVAILABLE); + listener.notifyError(POSITION_UNAVAILABLE); return; } @@ -218,7 +223,7 @@ WifiGeoPositionProvider.prototype = { xhr.response.location.lng, xhr.response.accuracy); - getGeoService().update(newLocation); + listener.update(newLocation); }; if (gCellScanningEnabled) { @@ -239,8 +244,4 @@ WifiGeoPositionProvider.prototype = { }, }; -function getGeoService() { - return Cc["@mozilla.org/geolocation/service;1"].getService(Ci.nsIGeolocationUpdate); -} - this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WifiGeoPositionProvider]); diff --git a/dom/system/gonk/GonkGPSGeolocationProvider.cpp b/dom/system/gonk/GonkGPSGeolocationProvider.cpp index 42fa6d4bd08..ecb598298b9 100644 --- a/dom/system/gonk/GonkGPSGeolocationProvider.cpp +++ b/dom/system/gonk/GonkGPSGeolocationProvider.cpp @@ -26,6 +26,7 @@ #include "nsServiceManagerUtils.h" #include "nsThreadUtils.h" #include "nsContentUtils.h" +#include "prtime.h" #ifdef MOZ_B2G_RIL #include "nsIDOMIccInfo.h" @@ -98,6 +99,7 @@ GonkGPSGeolocationProvider::LocationCallback(GpsLocation* location) NS_IMETHOD Run() { nsRefPtr provider = GonkGPSGeolocationProvider::GetSingleton(); + provider->mLastGPSDerivedLocationTime = PR_Now(); nsCOMPtr callback = provider->mLocationCallback; if (callback) { callback->Update(mPosition); @@ -285,8 +287,8 @@ GonkGPSGeolocationProvider::GonkGPSGeolocationProvider() : mStarted(false) , mSupportsScheduling(false) #ifdef MOZ_B2G_RIL - , mSupportsMSB(false) - , mSupportsMSA(false) + , mSupportsMSB(false) + , mSupportsMSA(false) #endif , mSupportsSingleShot(false) , mSupportsTimeInjection(false) @@ -523,8 +525,29 @@ GonkGPSGeolocationProvider::SetReferenceLocation() } } } + #endif // MOZ_B2G_RIL +void +GonkGPSGeolocationProvider::InjectLocation(double latitude, + double longitude, + float accuracy) +{ +#ifdef DEBUG_GPS + printf_stderr("*** injecting location\n"); + printf_stderr("*** lat: %f\n", latitude); + printf_stderr("*** lon: %f\n", longitude); + printf_stderr("*** accuracy: %f\n", accuracy); +#endif + + MOZ_ASSERT(NS_IsMainThread()); + if (!mGpsInterface) { + return; + } + + mGpsInterface->inject_location(latitude, longitude, accuracy); +} + void GonkGPSGeolocationProvider::Init() { @@ -626,6 +649,49 @@ GonkGPSGeolocationProvider::SetupAGPS() } #endif // MOZ_B2G_RIL + +NS_IMPL_ISUPPORTS1(GonkGPSGeolocationProvider::NetworkLocationUpdate, + nsIGeolocationUpdate) + +NS_IMETHODIMP +GonkGPSGeolocationProvider::NetworkLocationUpdate::Update(nsIDOMGeoPosition *position) +{ + nsRefPtr provider = + GonkGPSGeolocationProvider::GetSingleton(); + + nsCOMPtr coords; + position->GetCoords(getter_AddRefs(coords)); + if (!coords) { + return NS_ERROR_FAILURE; + } + + // if we haven't seen anything from the GPS device for 1s, + // use this network derived location. + int64_t diff = PR_Now() - provider->mLastGPSDerivedLocationTime; + if (provider->mLocationCallback && diff > kDefaultPeriod) { + provider->mLocationCallback->Update(position); + } + + double lat, lon, acc; + coords->GetLatitude(&lat); + coords->GetLongitude(&lon); + coords->GetAccuracy(&acc); + provider->InjectLocation(lat, lon, acc); + return NS_OK; +} + +NS_IMETHODIMP +GonkGPSGeolocationProvider::NetworkLocationUpdate::LocationUpdatePending() +{ + return NS_OK; +} + +NS_IMETHODIMP +GonkGPSGeolocationProvider::NetworkLocationUpdate::NotifyError(uint16_t error) +{ + return NS_OK; +} + NS_IMETHODIMP GonkGPSGeolocationProvider::Startup() { @@ -643,6 +709,16 @@ GonkGPSGeolocationProvider::Startup() mInitThread->Dispatch(NS_NewRunnableMethod(this, &GonkGPSGeolocationProvider::Init), NS_DISPATCH_NORMAL); + mNetworkLocationProvider = do_CreateInstance("@mozilla.org/geolocation/mls-provider;1"); + if (mNetworkLocationProvider) { + nsresult rv = mNetworkLocationProvider->Startup(); + if (NS_SUCCEEDED(rv)) { + nsRefPtr update = new NetworkLocationUpdate(); + mNetworkLocationProvider->Watch(update); + } + } + + mLastGPSDerivedLocationTime = 0; mStarted = true; return NS_OK; } @@ -665,6 +741,7 @@ GonkGPSGeolocationProvider::Shutdown() return NS_OK; } mStarted = false; + mNetworkLocationProvider = nullptr; #ifdef MOZ_B2G_RIL if (mRadioInterface) { diff --git a/dom/system/gonk/GonkGPSGeolocationProvider.h b/dom/system/gonk/GonkGPSGeolocationProvider.h index cc59d8a064e..d0364d95015 100644 --- a/dom/system/gonk/GonkGPSGeolocationProvider.h +++ b/dom/system/gonk/GonkGPSGeolocationProvider.h @@ -55,7 +55,7 @@ private: GonkGPSGeolocationProvider(); GonkGPSGeolocationProvider(const GonkGPSGeolocationProvider &); GonkGPSGeolocationProvider & operator = (const GonkGPSGeolocationProvider &); - ~GonkGPSGeolocationProvider(); + virtual ~GonkGPSGeolocationProvider(); static void LocationCallback(GpsLocation* location); static void StatusCallback(GpsStatus* status); @@ -81,6 +81,7 @@ private: void Init(); void StartGPS(); void ShutdownGPS(); + void InjectLocation(double latitude, double longitude, float accuracy); #ifdef MOZ_B2G_RIL void SetupAGPS(); int32_t GetDataConnectionState(); @@ -113,7 +114,21 @@ private: nsCOMPtr mRadioInterface; #endif nsCOMPtr mLocationCallback; + PRTime mLastGPSDerivedLocationTime; nsCOMPtr mInitThread; + nsCOMPtr mNetworkLocationProvider; + + class NetworkLocationUpdate : public nsIGeolocationUpdate + { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIGEOLOCATIONUPDATE + + NetworkLocationUpdate() {} + + private: + virtual ~NetworkLocationUpdate() {} + }; }; #endif /* GonkGPSGeolocationProvider_h */