Skip to content

Instantly share code, notes, and snippets.

@jdm
Created October 7, 2013 04:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdm/6862469 to your computer and use it in GitHub Desktop.
Save jdm/6862469 to your computer and use it in GitHub Desktop.
# HG changeset patch
# Parent 9366ee0396451492b3097fbb499b20fc5c63b82b
# User Josh Matthews <josh@joshmatthews.net>
diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -2724,16 +2724,17 @@ ContentParent::RecvAddGeolocationListene
}
}
#endif
// To ensure no geolocation updates are skipped, we always force the
// creation of a new listener.
RecvRemoveGeolocationListener();
mGeolocationWatchID = AddGeolocationListener(this, aHighAccuracy);
+ mGeoUseHighAccuracy = aHighAccuracy;
return true;
}
bool
ContentParent::RecvRemoveGeolocationListener()
{
if (mGeolocationWatchID != -1) {
nsCOMPtr<nsIDOMGeoGeolocation> geo = do_GetService("@mozilla.org/geolocation;1");
@@ -2746,19 +2747,20 @@ ContentParent::RecvRemoveGeolocationList
return true;
}
bool
ContentParent::RecvSetGeolocationHigherAccuracy(const bool& aEnable)
{
// This should never be called without a listener already present,
// so this check allows us to forgo securing privileges.
- if (mGeolocationWatchID != -1) {
+ if (mGeolocationWatchID != -1 && aEnable != mGeoUseHighAccuracy) {
RecvRemoveGeolocationListener();
mGeolocationWatchID = AddGeolocationListener(this, aEnable);
+ mGeoUseHighAccuracy = aEnable;
}
return true;
}
NS_IMETHODIMP
ContentParent::HandleEvent(nsIDOMGeoPosition* postion)
{
unused << SendGeolocationUpdate(GeoPosition(postion));
diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -448,16 +448,17 @@ private:
// release these objects in ShutDownProcess. See the comment there for more
// details.
GeckoChildProcessHost* mSubprocess;
base::ChildPrivileges mOSPrivileges;
uint64_t mChildID;
int32_t mGeolocationWatchID;
+ bool mGeoUseHighAccuracy;
// This is a reporter holding the reports from the child's last
// "child-memory-reporter-update" notification. To update this, one can
// broadcast the topic "child-memory-reporter-request" using the
// nsIObserverService.
//
// Note that this assumes there is at most one child process at a time!
nsCOMPtr<nsIMemoryReporter> mChildReporter;
diff --git a/dom/src/geolocation/nsGeolocation.cpp b/dom/src/geolocation/nsGeolocation.cpp
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -72,16 +72,17 @@ class nsGeolocationRequest
const GeoPositionCallback& aCallback,
const GeoPositionErrorCallback& aErrorCallback,
PositionOptions* aOptions,
bool aWatchPositionRequest = false,
int32_t aWatchId = 0);
void Shutdown();
void SendLocation(nsIDOMGeoPosition* location);
+ bool WantsHighAccuracy() {return !mShutdown && mOptions && mOptions->enableHighAccuracy;}
bool WantsHighAccuracy() {return mOptions && mOptions->mEnableHighAccuracy;}
void SetTimeoutTimer();
nsIPrincipal* GetPrincipal();
~nsGeolocationRequest();
virtual bool Recv__delete__(const bool& allow) MOZ_OVERRIDE;
virtual void IPDLRelease() MOZ_OVERRIDE { Release(); }
@@ -434,17 +435,17 @@ nsGeolocationRequest::Cancel()
return NS_OK;
}
NS_IMETHODIMP
nsGeolocationRequest::Allow()
{
// Kick off the geo device, if it isn't already running
nsRefPtr<nsGeolocationService> gs = nsGeolocationService::GetGeolocationService();
- nsresult rv = gs->StartDevice(GetPrincipal());
+ nsresult rv = gs->StartDevice(GetPrincipal(), WantsHighAccuracy());
if (NS_FAILED(rv)) {
// Location provider error
NotifyError(nsIDOMGeoPositionError::POSITION_UNAVAILABLE);
return NS_OK;
}
nsCOMPtr<nsIDOMGeoPosition> lastPosition = gs->GetCachedPosition();
@@ -461,17 +462,17 @@ nsGeolocationRequest::Allow()
// b) the cached position time is some reasonable value to return to the user (<30s)
uint32_t maximumAge = 30 * PR_MSEC_PER_SEC;
if (mOptions) {
if (mOptions->mMaximumAge >= 0) {
maximumAge = mOptions->mMaximumAge;
}
}
- gs->SetHigherAccuracy(mOptions && mOptions->mEnableHighAccuracy);
+ gs->SetHigherAccuracy(WantsHighAccuracy());
bool canUseCache = lastPosition && maximumAge > 0 &&
(PRTime(PR_Now() / PR_USEC_PER_MSEC) - maximumAge <=
PRTime(cachedPositionTime));
if (canUseCache) {
// okay, we can return a cached position
// getCurrentPosition requests serviced by the cache
@@ -847,31 +848,31 @@ nsGeolocationService::SetCachedPosition(
nsIDOMGeoPosition*
nsGeolocationService::GetCachedPosition()
{
return mLastPosition;
}
nsresult
-nsGeolocationService::StartDevice(nsIPrincipal *aPrincipal)
+nsGeolocationService::StartDevice(nsIPrincipal *aPrincipal, bool aEnableHighAccuracy)
{
if (!sGeoEnabled || sGeoInitPending) {
return NS_ERROR_NOT_AVAILABLE;
}
// we do not want to keep the geolocation devices online
// indefinitely. Close them down after a reasonable period of
// inactivivity
SetDisconnectTimer();
if (XRE_GetProcessType() == GeckoProcessType_Content) {
ContentChild* cpc = ContentChild::GetSingleton();
cpc->SendAddGeolocationListener(IPC::Principal(aPrincipal),
- HighAccuracyRequested());
+ aEnableHighAccuracy || HighAccuracyRequested());
return NS_OK;
}
// Start them up!
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (!obs) {
return NS_ERROR_FAILURE;
}
diff --git a/dom/src/geolocation/nsGeolocation.h b/dom/src/geolocation/nsGeolocation.h
--- a/dom/src/geolocation/nsGeolocation.h
+++ b/dom/src/geolocation/nsGeolocation.h
@@ -72,17 +72,17 @@ public:
// Management of the Geolocation objects
void AddLocator(mozilla::dom::Geolocation* locator);
void RemoveLocator(mozilla::dom::Geolocation* locator);
void SetCachedPosition(nsIDOMGeoPosition* aPosition);
nsIDOMGeoPosition* GetCachedPosition();
// Find and startup a geolocation device (gps, nmea, etc.)
- nsresult StartDevice(nsIPrincipal* aPrincipal);
+ nsresult StartDevice(nsIPrincipal* aPrincipal, bool aEnableHighAccuracy);
// Stop the started geolocation device (gps, nmea, etc.)
void StopDevice();
// create, or reinitalize the callback timer
void SetDisconnectTimer();
// request higher accuracy, if possible
diff --git a/dom/tests/unit/test_high_accuracy_timeout.js b/dom/tests/unit/test_high_accuracy_timeout.js
new file mode 100644
--- /dev/null
+++ b/dom/tests/unit/test_high_accuracy_timeout.js
@@ -0,0 +1,93 @@
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+const providerCID = Components.ID("{14aa4b81-e266-45cb-88f8-89595dece114}");
+const providerContract = "@mozilla.org/geolocation/provider;1";
+
+const categoryName = "geolocation-provider";
+
+var provider = {
+ QueryInterface: function eventsink_qi(iid) {
+ if (iid.equals(Components.interfaces.nsISupports) ||
+ iid.equals(Components.interfaces.nsIFactory) ||
+ iid.equals(Components.interfaces.nsIGeolocationProvider))
+ return this;
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ },
+ createInstance: function eventsink_ci(outer, iid) {
+ if (outer)
+ throw Components.results.NS_ERROR_NO_AGGREGATION;
+ return this.QueryInterface(iid);
+ },
+ lockFactory: function eventsink_lockf(lock) {
+ throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+ },
+ startup: function() {
+ do_print("startup");
+ },
+ watch: function(callback, isPrivate) {
+ do_print("watch");
+ /*do_execute_soon(function() {
+ callback.update({coords: {latitude: 42, longitude: 42}, timestamp: 0});
+ });*/
+ },
+ shutdown: function() {
+ do_print("shutdown");
+ do_execute_soon(do_test_finished);
+ },
+ setHighAccuracy: function(enable) {
+ do_print("high: " + enable);
+ if (enable) {
+ this._seenHigh = true;
+ } else {
+ this._seenNotHigh = true;
+ }
+ },
+ _seenHigh: false,
+ _seenNotHigh: false
+};
+
+let runningInParent = true;
+try {
+ runningInParent = Components.classes["@mozilla.org/xre/runtime;1"].
+ getService(Components.interfaces.nsIXULRuntime).processType
+ == Components.interfaces.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
+}
+catch (e) { }
+
+var geolocation;
+function run_test()
+{
+ do_test_pending();
+
+ if (runningInParent) {
+ Components.manager.nsIComponentRegistrar.registerFactory(providerCID,
+ "Unit test geo provider", providerContract, provider);
+ var catMan = Components.classes["@mozilla.org/categorymanager;1"]
+ .getService(Components.interfaces.nsICategoryManager);
+ catMan.nsICategoryManager.addCategoryEntry(categoryName, "unit test",
+ providerContract, false, true);
+
+ var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
+ prefs.setBoolPref("geo.testing.ignore_ipc_principal", true);
+ prefs.setBoolPref("geo.wifi.scan", false);
+ }
+
+ do_print("hi");
+ geolocation = Cc["@mozilla.org/geolocation;1"].createInstance(Ci.nsISupports);
+ geolocation.getCurrentPosition(function() { do_check_true(false); },
+ function() {
+ do_print("timed out");
+ if (!runningInParent) {
+ do_test_finished();
+ }
+ //do_test_finished();
+ /*geolocation.getCurrentPosition(function() {
+ if (runningInParent) {
+ do_check_true(provider._seenNotHigh);
+ do_check_true(provider._seenHigh);
+ }
+ do_test_finished();
+ }, null, {enableHighAccuracy: false, maxAge: 0});*/
+ }, {enableHighAccuracy: true, timeout: 1});
+}
\ No newline at end of file
diff --git a/dom/tests/unit/test_high_accuracy_timeout_wrap.js b/dom/tests/unit/test_high_accuracy_timeout_wrap.js
new file mode 100644
--- /dev/null
+++ b/dom/tests/unit/test_high_accuracy_timeout_wrap.js
@@ -0,0 +1,67 @@
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+const providerCID = Components.ID("{14aa4b81-e266-45cb-88f8-89595dece114}");
+const providerContract = "@mozilla.org/geolocation/provider;1";
+
+const categoryName = "geolocation-provider";
+
+var provider = {
+ QueryInterface: function eventsink_qi(iid) {
+ if (iid.equals(Components.interfaces.nsISupports) ||
+ iid.equals(Components.interfaces.nsIFactory) ||
+ iid.equals(Components.interfaces.nsIGeolocationProvider))
+ return this;
+ throw Components.results.NS_ERROR_NO_INTERFACE;
+ },
+ createInstance: function eventsink_ci(outer, iid) {
+ if (outer)
+ throw Components.results.NS_ERROR_NO_AGGREGATION;
+ return this.QueryInterface(iid);
+ },
+ lockFactory: function eventsink_lockf(lock) {
+ throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+ },
+ startup: function() {
+ do_print("startup");
+ },
+ watch: function(callback, isPrivate) {
+ do_print("watch");
+ /*do_execute_soon(function() {
+ callback.update({coords: {latitude: 42, longitude: 42}, timestamp: 0});
+ });*/
+ },
+ shutdown: function() {
+ do_print("shutdown");
+ do_execute_soon(do_test_finished);
+ },
+ setHighAccuracy: function(enable) {
+ do_print("high: " + enable);
+ if (enable) {
+ this._seenHigh = true;
+ } else {
+ this._seenNotHigh = true;
+ }
+ },
+ _seenHigh: false,
+ _seenNotHigh: false
+};
+
+
+function run_test()
+{
+ Components.manager.nsIComponentRegistrar.registerFactory(providerCID,
+ "Unit test geo provider", providerContract, provider);
+ var catMan = Components.classes["@mozilla.org/categorymanager;1"]
+ .getService(Components.interfaces.nsICategoryManager);
+ catMan.nsICategoryManager.addCategoryEntry(categoryName, "unit test",
+ providerContract, false, true);
+
+ var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
+ prefs.setBoolPref("geo.testing.ignore_ipc_principal", true);
+ prefs.setBoolPref("geo.wifi.scan", false);
+ run_test_in_child("test_high_accuracy_timeout.js", function() {
+ //do_check_true(provider._seenNotHigh);
+ //do_check_true(provider._seenHigh);
+ //do_test_finished();
+ });
+}
diff --git a/dom/tests/unit/xpcshell.ini b/dom/tests/unit/xpcshell.ini
--- a/dom/tests/unit/xpcshell.ini
+++ b/dom/tests/unit/xpcshell.ini
@@ -5,8 +5,10 @@ tail =
[test_bug319968.js]
[test_bug465752.js]
[test_geolocation_provider.js]
# Bug 684962: test hangs consistently on Android
skip-if = os == "android"
[test_geolocation_timeout.js]
[test_geolocation_timeout_wrap.js]
skip-if = os == "mac" || os == "android"
+[test_high_accuracy_timeout.js]
+[test_high_accuracy_timeout_wrap.js]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment