author | Butkovits Atila <abutkovits@mozilla.com> |
Sun, 15 May 2022 15:28:12 +0300 (2022-05-15) | |
changeset 617348 | 7f6113218f5598eafb379c8d0968fd3976c746f9 |
parent 617347 | 39b20dac431b40d84718ec2080563084506df19d |
child 617349 | 675ae070ca44f59c27b65147aff5df46aba63fbd |
push id | 162864 |
push user | abutkovits@mozilla.com |
push date | Sun, 15 May 2022 12:28:51 +0000 (2022-05-15) |
treeherder | autoland@7f6113218f55 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 1063572 |
milestone | 102.0a1 |
backs out | 39b20dac431b40d84718ec2080563084506df19d |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
dom/geolocation/Geolocation.cpp | file | annotate | diff | comparison | revisions | |
dom/system/linux/GeoclueLocationProvider.cpp | file | annotate | diff | comparison | revisions | |
dom/system/linux/GeoclueLocationProvider.h | file | annotate | diff | comparison | revisions | |
dom/system/linux/moz.build | file | annotate | diff | comparison | revisions | |
modules/libpref/init/StaticPrefList.yaml | file | annotate | diff | comparison | revisions | |
widget/gtk/GRefPtr.h | file | annotate | diff | comparison | revisions |
--- a/dom/geolocation/Geolocation.cpp +++ b/dom/geolocation/Geolocation.cpp @@ -40,17 +40,16 @@ class nsIPrincipal; #endif #ifdef MOZ_GPSD # include "GpsdLocationProvider.h" #endif #ifdef MOZ_ENABLE_DBUS # include "mozilla/WidgetUtilsGtk.h" -# include "GeoclueLocationProvider.h" # include "PortalLocationProvider.h" #endif #ifdef MOZ_WIDGET_COCOA # include "CoreLocationLocationProvider.h" #endif #ifdef XP_WIN @@ -490,34 +489,25 @@ nsresult nsGeolocationService::Init() { obs->AddObserver(this, "xpcom-shutdown", false); #ifdef MOZ_WIDGET_ANDROID mProvider = new AndroidLocationProvider(); #endif #ifdef MOZ_WIDGET_GTK +# ifdef MOZ_GPSD + if (Preferences::GetBool("geo.provider.use_gpsd", false)) { + mProvider = new GpsdLocationProvider(); + } +# endif # ifdef MOZ_ENABLE_DBUS if (!mProvider && widget::ShouldUsePortal(widget::PortalKind::Location)) { mProvider = new PortalLocationProvider(); } - // Geoclue includes GPS data so it has higher priority than raw GPSD - if (!mProvider && StaticPrefs::geo_provider_use_geoclue()) { - nsCOMPtr<nsIGeolocationProvider> gcProvider = new GeoclueLocationProvider(); - // The Startup() method will only succeed if Geoclue is available on D-Bus - if (NS_SUCCEEDED(gcProvider->Startup())) { - gcProvider->Shutdown(); - mProvider = std::move(gcProvider); - } - } -# ifdef MOZ_GPSD - if (!mProvider && Preferences::GetBool("geo.provider.use_gpsd", false)) { - mProvider = new GpsdLocationProvider(); - } -# endif # endif #endif #ifdef MOZ_WIDGET_COCOA if (Preferences::GetBool("geo.provider.use_corelocation", true)) { mProvider = new CoreLocationLocationProvider(); } #endif
deleted file mode 100644 --- a/dom/system/linux/GeoclueLocationProvider.cpp +++ /dev/null @@ -1,1017 +0,0 @@ -/* - * 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/. - * - * Author: Maciej S. Szmigiero <mail@maciej.szmigiero.name> - */ - -#include "GeoclueLocationProvider.h" - -#include <gio/gio.h> -#include <glib.h> -#include "mozilla/AlreadyAddRefed.h" -#include "mozilla/FloatingPoint.h" -#include "mozilla/GRefPtr.h" -#include "mozilla/GUniquePtr.h" -#include "mozilla/Logging.h" -#include "mozilla/ScopeExit.h" -#include "mozilla/StaticPrefs_geo.h" -#include "mozilla/UniquePtrExtensions.h" -#include "mozilla/WeakPtr.h" -#include "mozilla/XREAppData.h" -#include "mozilla/dom/GeolocationPosition.h" -#include "mozilla/dom/GeolocationPositionErrorBinding.h" -#include "nsAppRunner.h" -#include "nsCOMPtr.h" -#include "nsIDOMGeoPosition.h" -#include "nsINamed.h" -#include "nsITimer.h" -#include "nsStringFwd.h" -#include "prtime.h" - -namespace mozilla::dom { - -static mozilla::LazyLogModule gGCLocationLog("GeoclueLocation"); - -#define GCL_LOG(level, ...) \ - MOZ_LOG(gGCLocationLog, mozilla::LogLevel::level, (__VA_ARGS__)) - -static const char* const kGeoclueBusName = "org.freedesktop.GeoClue2"; -static const char* const kGCManagerPath = "/org/freedesktop/GeoClue2/Manager"; -static const char* const kGCManagerInterface = - "org.freedesktop.GeoClue2.Manager"; -static const char* const kGCClientInterface = "org.freedesktop.GeoClue2.Client"; -static const char* const kGCLocationInterface = - "org.freedesktop.GeoClue2.Location"; -static const char* const kDBPropertySetMethod = - "org.freedesktop.DBus.Properties.Set"; - -/* - * Minimum altitude reported as valid (in meters), - * https://en.wikipedia.org/wiki/List_of_places_on_land_with_elevations_below_sea_level - * says that lowest land in the world is at -430 m, so let's use -500 m here. - */ -static const double kGCMinAlt = -500; - -/* - * Matches "enum GClueAccuracyLevel" values, see: - * https://www.freedesktop.org/software/geoclue/docs/geoclue-gclue-enums.html#GClueAccuracyLevel - */ -enum class GCAccuracyLevel { - None = 0, - Country = 1, - City = 4, - Neighborhood = 5, - Street = 6, - Exact = 8, -}; - -/* - * Whether to reuse D-Bus proxies between uses of this provider. - * Usually a good thing, can be disabled for debug purposes. - */ -static const bool kGCReuseDBusProxy = true; - -class GCLocProviderPriv final : public nsIGeolocationProvider, - public SupportsWeakPtr { - public: - NS_DECL_ISUPPORTS - NS_DECL_NSIGEOLOCATIONPROVIDER - - GCLocProviderPriv(); - - void UpdateLastPosition(); - - private: - class LocationTimerCallback final : public nsITimerCallback, public nsINamed { - public: - NS_DECL_ISUPPORTS - NS_DECL_NSITIMERCALLBACK - - explicit LocationTimerCallback(GCLocProviderPriv* aParent) - : mParent(aParent) {} - - NS_IMETHOD GetName(nsACString& aName) override { - aName.AssignLiteral("GCLocProvider::LocationTimerCallback"); - return NS_OK; - } - - private: - ~LocationTimerCallback() = default; - WeakPtr<GCLocProviderPriv> mParent; - }; - - enum class Accuracy { Unset, Low, High }; - // States: - // Uninit: The default / initial state, with no client proxy yet. - // Initing: Takes care of establishing the client connection (GetClient / - // ConnectClient / SetDesktopID). - // SettingAccuracy: Does SetAccuracy operation, knows it should just go idle - // after finishing it. - // SettingAccuracyForStart: Does SetAccuracy operation, knows it then needs - // to do a Start operation after finishing it. - // Idle: Fully initialized, but not running state (quiescent). - // Starting: Starts the client by calling the Start D-Bus method. - // Started: Normal running state. - // Stopping: Stops the client by calling the Stop D-Bus method, knows it - // should just go idle after finishing it. - // StoppingForRestart: Stops the client by calling the Stop D-Bus method as - // a part of a Stop -> Start sequence (with possibly - // an accuracy update between these method calls). - // - // Valid state transitions are: - // (any state) -> Uninit: Transition when a D-Bus call failed or - // provided invalid data. - // - // Watch() startup path: - // Uninit -> Initing: Transition after getting the very first Watch() - // request - // or any such request while not having the client proxy. - // Initing -> SettingAccuracyForStart: Transition after getting a successful - // SetDesktopID response. - // SettingAccuracyForStart -> Starting: Transition after getting a - // successful - // SetAccuracy response. - // Idle -> Starting: Transition after getting a Watch() request while in - // fully - // initialized, but not running state. - // SettingAccuracy -> SettingAccuracyForStart: Transition after getting a - // Watch() - // request in the middle of - // setting accuracy during idle - // status. - // Stopping -> StoppingForRestart: Transition after getting a Watch() - // request - // in the middle of doing a Stop D-Bus call - // for idle status. - // StoppingForRestart -> Starting: Transition after getting a successful - // Stop response as a part of a Stop -> - // Start sequence while the previously set - // accuracy is still correct. - // StoppingForRestart -> SettingAccuracyForStart: Transition after getting - // a successful Stop response - // as a part of a Stop -> - // Start sequence but the set - // accuracy needs updating. - // Starting -> Started: Transition after getting a successful Start - // response. - // - // Shutdown() path: - // (any state) -> Uninit: Transition when not reusing the client proxy for - // any reason. - // Started -> Stopping: Transition from normal running state when reusing - // the client proxy. - // SettingAccuracyForStart -> SettingAccuracy: Transition when doing - // a shutdown in the middle of - // setting accuracy for a start - // when reusing the client - // proxy. - // SettingAccuracy -> Idle: Transition after getting a successful - // SetAccuracy - // response. - // StoppingForRestart -> Stopping: Transition when doing shutdown - // in the middle of a Stop -> Start sequence - // when reusing the client proxy. - // Stopping -> Idle: Transition after getting a successful Stop response. - // - // SetHighAccuracy() path: - // Started -> StoppingForRestart: Transition when accuracy needs updating - // on a running client. - // (the rest of the flow in StoppingForRestart state is the same as when - // being in this state in the Watch() startup path) - enum class ClientState { - Uninit, - Initing, - SettingAccuracy, - SettingAccuracyForStart, - Idle, - Starting, - Started, - Stopping, - StoppingForRestart - }; - - ~GCLocProviderPriv(); - - static bool AlwaysHighAccuracy(); - - void SetState(ClientState aNewState, const char* aNewStateStr); - - void Update(nsIDOMGeoPosition* aPosition); - MOZ_CAN_RUN_SCRIPT void NotifyError(int aError); - void DBusProxyError(const GError* aGError, bool aResetManager = false); - - static void GetClientResponse(GDBusProxy* aProxy, GAsyncResult* aResult, - gpointer aUserData); - void ConnectClient(const gchar* aClientPath); - static void ConnectClientResponse(GObject* aObject, GAsyncResult* aResult, - gpointer aUserData); - void SetDesktopID(); - static void SetDesktopIDResponse(GDBusProxy* aProxy, GAsyncResult* aResult, - gpointer aUserData); - void SetAccuracy(); - static void SetAccuracyResponse(GDBusProxy* aProxy, GAsyncResult* aResult, - gpointer aUserData); - void StartClient(); - static void StartClientResponse(GDBusProxy* aProxy, GAsyncResult* aResult, - gpointer aUserData); - void StopClient(bool aForRestart); - static void StopClientResponse(GDBusProxy* aProxy, GAsyncResult* aResult, - gpointer aUserData); - void StopClientNoWait(); - void MaybeRestartForAccuracy(); - - static void GCManagerOwnerNotify(GObject* aObject, GParamSpec* aPSpec, - gpointer aUserData); - - static void GCClientSignal(GDBusProxy* aProxy, gchar* aSenderName, - gchar* aSignalName, GVariant* aParameters, - gpointer aUserData); - void ConnectLocation(const gchar* aLocationPath); - static bool GetLocationProperty(GDBusProxy* aProxyLocation, - const gchar* aName, double* aOut); - static void ConnectLocationResponse(GObject* aObject, GAsyncResult* aResult, - gpointer aUserData); - - void SetLocationTimer(); - void StopLocationTimer(); - - bool InDBusCall(); - bool InDBusStoppingCall(); - bool InDBusStoppedCall(); - - void DeleteManager(); - void DoShutdown(bool aDeleteClient, bool aDeleteManager); - void DoShutdownClearCallback(bool aDestroying); - - void WatchStart(); - - Accuracy mAccuracyWanted = Accuracy::Unset; - Accuracy mAccuracySet = Accuracy::Unset; - RefPtr<GDBusProxy> mProxyManager; - RefPtr<GDBusProxy> mProxyClient; - RefPtr<GCancellable> mCancellable; - nsCOMPtr<nsIGeolocationUpdate> mCallback; - ClientState mClientState = ClientState::Uninit; - RefPtr<nsIDOMGeoPosition> mLastPosition; - RefPtr<nsITimer> mLocationTimer; -}; - -// -// GCLocProviderPriv -// - -#define GCLP_SETSTATE(this, state) this->SetState(ClientState::state, #state) - -GCLocProviderPriv::GCLocProviderPriv() { - if (AlwaysHighAccuracy()) { - mAccuracyWanted = Accuracy::High; - } else { - mAccuracyWanted = Accuracy::Low; - } -} - -GCLocProviderPriv::~GCLocProviderPriv() { DoShutdownClearCallback(true); } - -bool GCLocProviderPriv::AlwaysHighAccuracy() { - return StaticPrefs::geo_provider_geoclue_always_high_accuracy(); -} - -void GCLocProviderPriv::SetState(ClientState aNewState, - const char* aNewStateStr) { - if (mClientState == aNewState) { - return; - } - - GCL_LOG(Debug, "changing state to %s", aNewStateStr); - mClientState = aNewState; -} - -void GCLocProviderPriv::Update(nsIDOMGeoPosition* aPosition) { - if (!mCallback) { - return; - } - - mCallback->Update(aPosition); -} - -void GCLocProviderPriv::UpdateLastPosition() { - MOZ_DIAGNOSTIC_ASSERT(mLastPosition, "No last position to update"); - StopLocationTimer(); - Update(mLastPosition); -} - -void GCLocProviderPriv::NotifyError(int aError) { - if (!mCallback) { - return; - } - - nsCOMPtr<nsIGeolocationUpdate> callback(mCallback); - callback->NotifyError(aError); -} - -void GCLocProviderPriv::DBusProxyError(const GError* aGError, - bool aResetManager) { - // that G_DBUS_ERROR below is actually a function call, not a constant - GQuark gdbusDomain = G_DBUS_ERROR; - int error = GeolocationPositionError_Binding::POSITION_UNAVAILABLE; - if (aGError) { - if (g_error_matches(aGError, gdbusDomain, G_DBUS_ERROR_TIMEOUT) || - g_error_matches(aGError, gdbusDomain, G_DBUS_ERROR_TIMED_OUT)) { - error = GeolocationPositionError_Binding::TIMEOUT; - } else if (g_error_matches(aGError, gdbusDomain, - G_DBUS_ERROR_LIMITS_EXCEEDED) || - g_error_matches(aGError, gdbusDomain, - G_DBUS_ERROR_ACCESS_DENIED) || - g_error_matches(aGError, gdbusDomain, - G_DBUS_ERROR_AUTH_FAILED)) { - error = GeolocationPositionError_Binding::PERMISSION_DENIED; - } - } - - DoShutdown(true, aResetManager); - NotifyError(error); -} - -void GCLocProviderPriv::GetClientResponse(GDBusProxy* aProxy, - GAsyncResult* aResult, - gpointer aUserData) { - auto* self = static_cast<GCLocProviderPriv*>(aUserData); - GUniquePtr<GError> error; - - RefPtr<GVariant> variant = dont_AddRef( - g_dbus_proxy_call_finish(aProxy, aResult, getter_Transfers(error))); - if (!variant) { - // if cancelled |self| might no longer be there - if (!g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - GCL_LOG(Error, "Failed to get client: %s\n", error->message); - self->DBusProxyError(error.get(), true); - } - return; - } - - MOZ_DIAGNOSTIC_ASSERT(self->mClientState == ClientState::Initing, - "Client in a wrong state"); - - auto signalError = - MakeScopeExit([&] { self->DBusProxyError(nullptr, true); }); - - if (!g_variant_is_of_type(variant, G_VARIANT_TYPE_TUPLE)) { - GCL_LOG(Error, "Unexpected get client call return type: %s\n", - g_variant_get_type_string(variant)); - return; - } - - if (g_variant_n_children(variant) < 1) { - GCL_LOG(Error, - "Not enough params in get client call return: %" G_GSIZE_FORMAT - "\n", - g_variant_n_children(variant)); - return; - } - - variant = dont_AddRef(g_variant_get_child_value(variant, 0)); - if (!g_variant_is_of_type(variant, G_VARIANT_TYPE_OBJECT_PATH)) { - GCL_LOG(Error, "Unexpected get client call return type inside tuple: %s\n", - g_variant_get_type_string(variant)); - return; - } - - const gchar* clientPath = g_variant_get_string(variant, nullptr); - GCL_LOG(Debug, "Client path: %s\n", clientPath); - - signalError.release(); - self->ConnectClient(clientPath); -} - -void GCLocProviderPriv::ConnectClient(const gchar* aClientPath) { - MOZ_DIAGNOSTIC_ASSERT(mClientState == ClientState::Initing, - "Client in a wrong state"); - MOZ_ASSERT(mCancellable, "Watch() wasn't successfully called"); - g_dbus_proxy_new_for_bus( - G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, kGeoclueBusName, - aClientPath, kGCClientInterface, mCancellable, - reinterpret_cast<GAsyncReadyCallback>(ConnectClientResponse), this); -} - -void GCLocProviderPriv::ConnectClientResponse(GObject* aObject, - GAsyncResult* aResult, - gpointer aUserData) { - auto* self = static_cast<GCLocProviderPriv*>(aUserData); - GUniquePtr<GError> error; - - RefPtr<GDBusProxy> proxyClient = - dont_AddRef(g_dbus_proxy_new_finish(aResult, getter_Transfers(error))); - if (!proxyClient) { - // if cancelled |self| might no longer be there - if (!g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - GCL_LOG(Error, "Failed to connect to client: %s\n", error->message); - self->DBusProxyError(error.get()); - } - return; - } - self->mProxyClient = std::move(proxyClient); - - MOZ_DIAGNOSTIC_ASSERT(self->mClientState == ClientState::Initing, - "Client in a wrong state"); - - GCL_LOG(Info, "Client interface connected\n"); - - g_signal_connect(self->mProxyClient, "g-signal", G_CALLBACK(GCClientSignal), - self); - self->SetDesktopID(); -} - -void GCLocProviderPriv::SetDesktopID() { - MOZ_DIAGNOSTIC_ASSERT(mClientState == ClientState::Initing, - "Client in a wrong state"); - MOZ_DIAGNOSTIC_ASSERT(mProxyClient && mCancellable, - "Watch() wasn't successfully called"); - - nsAutoCString appName; - gAppData->GetDBusAppName(appName); - g_dbus_proxy_call(mProxyClient, kDBPropertySetMethod, - g_variant_new("(ssv)", kGCClientInterface, "DesktopId", - g_variant_new_string(appName.get())), - G_DBUS_CALL_FLAGS_NONE, -1, mCancellable, - reinterpret_cast<GAsyncReadyCallback>(SetDesktopIDResponse), - this); -} - -void GCLocProviderPriv::SetDesktopIDResponse(GDBusProxy* aProxy, - GAsyncResult* aResult, - gpointer aUserData) { - auto* self = static_cast<GCLocProviderPriv*>(aUserData); - GUniquePtr<GError> error; - - RefPtr<GVariant> variant = dont_AddRef( - g_dbus_proxy_call_finish(aProxy, aResult, getter_Transfers(error))); - if (!variant) { - // if cancelled |self| might no longer be there - if (!g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - GCL_LOG(Error, "Failed to set DesktopId: %s\n", error->message); - self->DBusProxyError(error.get()); - } - return; - } - - MOZ_DIAGNOSTIC_ASSERT(self->mClientState == ClientState::Initing, - "Client in a wrong state"); - - GCLP_SETSTATE(self, Idle); - self->SetAccuracy(); -} - -void GCLocProviderPriv::SetAccuracy() { - MOZ_DIAGNOSTIC_ASSERT(mClientState == ClientState::Idle, - "Client in a wrong state"); - MOZ_DIAGNOSTIC_ASSERT(mProxyClient && mCancellable, - "Watch() wasn't successfully called"); - MOZ_ASSERT(mAccuracyWanted != Accuracy::Unset, "Invalid accuracy"); - - guint32 accuracy; - if (mAccuracyWanted == Accuracy::High) { - accuracy = (guint32)GCAccuracyLevel::Exact; - } else { - accuracy = (guint32)GCAccuracyLevel::City; - } - - mAccuracySet = mAccuracyWanted; - GCLP_SETSTATE(this, SettingAccuracyForStart); - g_dbus_proxy_call( - mProxyClient, kDBPropertySetMethod, - g_variant_new("(ssv)", kGCClientInterface, "RequestedAccuracyLevel", - g_variant_new_uint32(accuracy)), - G_DBUS_CALL_FLAGS_NONE, -1, mCancellable, - reinterpret_cast<GAsyncReadyCallback>(SetAccuracyResponse), this); -} - -void GCLocProviderPriv::SetAccuracyResponse(GDBusProxy* aProxy, - GAsyncResult* aResult, - gpointer aUserData) { - auto* self = static_cast<GCLocProviderPriv*>(aUserData); - GUniquePtr<GError> error; - - RefPtr<GVariant> variant = dont_AddRef( - g_dbus_proxy_call_finish(aProxy, aResult, getter_Transfers(error))); - if (!variant) { - // if cancelled |self| might no longer be there - if (!g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - GCL_LOG(Error, "Failed to set requested accuracy level: %s\n", - error->message); - self->DBusProxyError(error.get()); - } - return; - } - - MOZ_DIAGNOSTIC_ASSERT( - self->mClientState == ClientState::SettingAccuracyForStart || - self->mClientState == ClientState::SettingAccuracy, - "Client in a wrong state"); - bool wantStart = self->mClientState == ClientState::SettingAccuracyForStart; - GCLP_SETSTATE(self, Idle); - - if (wantStart) { - self->StartClient(); - } -} - -void GCLocProviderPriv::StartClient() { - MOZ_DIAGNOSTIC_ASSERT(mClientState == ClientState::Idle, - "Client in a wrong state"); - MOZ_DIAGNOSTIC_ASSERT(mProxyClient && mCancellable, - "Watch() wasn't successfully called"); - GCLP_SETSTATE(this, Starting); - g_dbus_proxy_call( - mProxyClient, "Start", nullptr, G_DBUS_CALL_FLAGS_NONE, -1, mCancellable, - reinterpret_cast<GAsyncReadyCallback>(StartClientResponse), this); -} - -void GCLocProviderPriv::StartClientResponse(GDBusProxy* aProxy, - GAsyncResult* aResult, - gpointer aUserData) { - auto* self = static_cast<GCLocProviderPriv*>(aUserData); - GUniquePtr<GError> error; - - RefPtr<GVariant> variant = dont_AddRef( - g_dbus_proxy_call_finish(aProxy, aResult, getter_Transfers(error))); - if (!variant) { - // if cancelled |self| might no longer be there - if (!g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - GCL_LOG(Error, "Failed to start client: %s\n", error->message); - - /* - * A workaround for - * https://gitlab.freedesktop.org/geoclue/geoclue/-/issues/143 We need to - * get a new client instance once the agent finally connects to the - * Geoclue service, otherwise every Start request on the old client - * interface will be denied. We need to reconnect to the Manager interface - * to achieve this since otherwise GetClient call will simply return the - * old client instance. - */ - bool resetManager = g_error_matches(error.get(), G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED); - self->DBusProxyError(error.get(), resetManager); - } - return; - } - - MOZ_DIAGNOSTIC_ASSERT(self->mClientState == ClientState::Starting, - "Client in a wrong state"); - GCLP_SETSTATE(self, Started); - self->MaybeRestartForAccuracy(); -} - -void GCLocProviderPriv::StopClient(bool aForRestart) { - MOZ_DIAGNOSTIC_ASSERT(mClientState == ClientState::Started, - "Client in a wrong state"); - MOZ_DIAGNOSTIC_ASSERT(mProxyClient && mCancellable, - "Watch() wasn't successfully called"); - - if (aForRestart) { - GCLP_SETSTATE(this, StoppingForRestart); - } else { - GCLP_SETSTATE(this, Stopping); - } - - g_dbus_proxy_call( - mProxyClient, "Stop", nullptr, G_DBUS_CALL_FLAGS_NONE, -1, mCancellable, - reinterpret_cast<GAsyncReadyCallback>(StopClientResponse), this); -} - -void GCLocProviderPriv::StopClientResponse(GDBusProxy* aProxy, - GAsyncResult* aResult, - gpointer aUserData) { - auto* self = static_cast<GCLocProviderPriv*>(aUserData); - GUniquePtr<GError> error; - - RefPtr<GVariant> variant = dont_AddRef( - g_dbus_proxy_call_finish(aProxy, aResult, getter_Transfers(error))); - if (!variant) { - // if cancelled |self| might no longer be there - if (!g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - GCL_LOG(Error, "Failed to stop client: %s\n", error->message); - self->DBusProxyError(error.get()); - } - return; - } - - MOZ_DIAGNOSTIC_ASSERT(self->InDBusStoppingCall(), "Client in a wrong state"); - bool wantRestart = self->mClientState == ClientState::StoppingForRestart; - GCLP_SETSTATE(self, Idle); - - if (!wantRestart) { - return; - } - - if (self->mAccuracyWanted != self->mAccuracySet) { - self->SetAccuracy(); - } else { - self->StartClient(); - } -} - -void GCLocProviderPriv::StopClientNoWait() { - MOZ_DIAGNOSTIC_ASSERT(mProxyClient, "Watch() wasn't successfully called"); - g_dbus_proxy_call(mProxyClient, "Stop", nullptr, G_DBUS_CALL_FLAGS_NONE, -1, - nullptr, nullptr, nullptr); -} - -void GCLocProviderPriv::MaybeRestartForAccuracy() { - if (mAccuracyWanted == mAccuracySet) { - return; - } - - if (mClientState != ClientState::Started) { - return; - } - - // Setting a new accuracy requires restarting the client - StopClient(true); -} - -void GCLocProviderPriv::GCManagerOwnerNotify(GObject* aObject, - GParamSpec* aPSpec, - gpointer aUserData) { - auto* self = static_cast<GCLocProviderPriv*>(aUserData); - - GUniquePtr<gchar> managerOwner( - g_dbus_proxy_get_name_owner(self->mProxyManager)); - if (!managerOwner) { - GCL_LOG(Info, "The Manager interface has lost its owner\n"); - self->DBusProxyError(nullptr, true); - } -} - -void GCLocProviderPriv::GCClientSignal(GDBusProxy* aProxy, gchar* aSenderName, - gchar* aSignalName, - GVariant* aParameters, - gpointer aUserData) { - auto* self = static_cast<GCLocProviderPriv*>(aUserData); - - if (g_strcmp0(aSignalName, "LocationUpdated")) { - return; - } - - if (!g_variant_is_of_type(aParameters, G_VARIANT_TYPE_TUPLE)) { - GCL_LOG(Error, "Unexpected location updated signal params type: %s\n", - g_variant_get_type_string(aParameters)); - return; - } - - if (g_variant_n_children(aParameters) < 2) { - GCL_LOG(Error, - "Not enough params in location updated signal: %" G_GSIZE_FORMAT - "\n", - g_variant_n_children(aParameters)); - return; - } - - RefPtr<GVariant> variant = - dont_AddRef(g_variant_get_child_value(aParameters, 1)); - if (!g_variant_is_of_type(variant, G_VARIANT_TYPE_OBJECT_PATH)) { - GCL_LOG(Error, - "Unexpected location updated signal new location path type: %s\n", - g_variant_get_type_string(variant)); - return; - } - - const gchar* locationPath = g_variant_get_string(variant, nullptr); - GCL_LOG(Verbose, "New location path: %s\n", locationPath); - self->ConnectLocation(locationPath); -} - -void GCLocProviderPriv::ConnectLocation(const gchar* aLocationPath) { - MOZ_ASSERT(mCancellable, "Startup() wasn't successfully called"); - g_dbus_proxy_new_for_bus( - G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, kGeoclueBusName, - aLocationPath, kGCLocationInterface, mCancellable, - reinterpret_cast<GAsyncReadyCallback>(ConnectLocationResponse), this); -} - -bool GCLocProviderPriv::GetLocationProperty(GDBusProxy* aProxyLocation, - const gchar* aName, double* aOut) { - RefPtr<GVariant> property = - dont_AddRef(g_dbus_proxy_get_cached_property(aProxyLocation, aName)); - if (!g_variant_is_of_type(property, G_VARIANT_TYPE_DOUBLE)) { - GCL_LOG(Error, "Unexpected location property %s type: %s\n", aName, - g_variant_get_type_string(property)); - return false; - } - - *aOut = g_variant_get_double(property); - return true; -} - -void GCLocProviderPriv::ConnectLocationResponse(GObject* aObject, - GAsyncResult* aResult, - gpointer aUserData) { - auto* self = static_cast<GCLocProviderPriv*>(aUserData); - GUniquePtr<GError> error; - - RefPtr<GDBusProxy> proxyLocation = - dont_AddRef(g_dbus_proxy_new_finish(aResult, getter_Transfers(error))); - if (!proxyLocation) { - if (!g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) { - GCL_LOG(Warning, "Failed to connect to location: %s\n", error->message); - } - return; - } - - /* - * nsGeoPositionCoords will convert NaNs to null for optional properties of - * the JavaScript Coordinates object. - */ - double lat = UnspecifiedNaN<double>(); - double lon = UnspecifiedNaN<double>(); - double alt = UnspecifiedNaN<double>(); - double hError = UnspecifiedNaN<double>(); - const double vError = UnspecifiedNaN<double>(); - double heading = UnspecifiedNaN<double>(); - double speed = UnspecifiedNaN<double>(); - struct { - const gchar* name; - double* out; - } props[] = { - {"Latitude", &lat}, {"Longitude", &lon}, {"Altitude", &alt}, - {"Accuracy", &hError}, {"Heading", &heading}, {"Speed", &speed}, - }; - - for (auto& prop : props) { - if (!GetLocationProperty(proxyLocation, prop.name, prop.out)) { - return; - } - } - - if (alt < kGCMinAlt) { - alt = UnspecifiedNaN<double>(); - } - if (speed < 0) { - speed = UnspecifiedNaN<double>(); - } - if (heading < 0 || IsNaN(speed) || speed == 0) { - heading = UnspecifiedNaN<double>(); - } - - GCL_LOG(Info, "New location: %f %f +-%fm @ %gm; hdg %f spd %fm/s\n", lat, lon, - hError, alt, heading, speed); - - self->mLastPosition = - new nsGeoPosition(lat, lon, alt, hError, vError, heading, speed, - PR_Now() / PR_USEC_PER_MSEC); - self->UpdateLastPosition(); -} - -void GCLocProviderPriv::SetLocationTimer() { - MOZ_DIAGNOSTIC_ASSERT(mLastPosition, "no last position to report"); - - StopLocationTimer(); - - RefPtr<LocationTimerCallback> timerCallback = new LocationTimerCallback(this); - NS_NewTimerWithCallback(getter_AddRefs(mLocationTimer), timerCallback, 1000, - nsITimer::TYPE_ONE_SHOT); -} - -void GCLocProviderPriv::StopLocationTimer() { - if (!mLocationTimer) { - return; - } - - mLocationTimer->Cancel(); - mLocationTimer = nullptr; -} - -// Did we made some D-Bus call and are still waiting for its response? -bool GCLocProviderPriv::InDBusCall() { - return mClientState == ClientState::Initing || - mClientState == ClientState::SettingAccuracy || - mClientState == ClientState::SettingAccuracyForStart || - mClientState == ClientState::Starting || - mClientState == ClientState::Stopping || - mClientState == ClientState::StoppingForRestart; -} - -bool GCLocProviderPriv::InDBusStoppingCall() { - return mClientState == ClientState::Stopping || - mClientState == ClientState::StoppingForRestart; -} - -/* - * Did we made some D-Bus call while stopped and - * are still waiting for its response? - */ -bool GCLocProviderPriv::InDBusStoppedCall() { - return mClientState == ClientState::SettingAccuracy || - mClientState == ClientState::SettingAccuracyForStart; -} - -void GCLocProviderPriv::DeleteManager() { - if (!mProxyManager) { - return; - } - - g_signal_handlers_disconnect_matched(mProxyManager, G_SIGNAL_MATCH_DATA, 0, 0, - nullptr, nullptr, this); - mProxyManager = nullptr; -} - -void GCLocProviderPriv::DoShutdown(bool aDeleteClient, bool aDeleteManager) { - MOZ_DIAGNOSTIC_ASSERT( - !aDeleteManager || aDeleteClient, - "deleting manager proxy requires deleting client one, too"); - - // Invalidate the cached last position - StopLocationTimer(); - mLastPosition = nullptr; - - /* - * Do we need to delete the D-Bus proxy (or proxies)? - * Either because that's what our caller wanted, or because we are set to - * never reuse them, or because we are in a middle of some D-Bus call while - * having the service running (and so not being able to issue an immediate - * Stop call). - */ - if (aDeleteClient || !kGCReuseDBusProxy || - (InDBusCall() && !InDBusStoppingCall() && !InDBusStoppedCall())) { - if (mClientState == ClientState::Started) { - StopClientNoWait(); - GCLP_SETSTATE(this, Idle); - } - if (mProxyClient) { - g_signal_handlers_disconnect_matched(mProxyClient, G_SIGNAL_MATCH_DATA, 0, - 0, nullptr, nullptr, this); - } - if (mCancellable) { - g_cancellable_cancel(mCancellable); - mCancellable = nullptr; - } - mProxyClient = nullptr; - - if (aDeleteManager || !kGCReuseDBusProxy) { - DeleteManager(); - } - - GCLP_SETSTATE(this, Uninit); - } else if (mClientState == ClientState::Started) { - StopClient(false); - } else if (mClientState == ClientState::SettingAccuracyForStart) { - GCLP_SETSTATE(this, SettingAccuracy); - } else if (mClientState == ClientState::StoppingForRestart) { - GCLP_SETSTATE(this, Stopping); - } -} - -void GCLocProviderPriv::DoShutdownClearCallback(bool aDestroying) { - mCallback = nullptr; - DoShutdown(aDestroying, aDestroying); -} - -NS_IMPL_ISUPPORTS(GCLocProviderPriv, nsIGeolocationProvider) - -// nsIGeolocationProvider -// - -/* - * The Startup() method should only succeed if Geoclue is available on D-Bus - * so it can be used for determining whether to continue with this geolocation - * provider in Geolocation.cpp - */ -NS_IMETHODIMP -GCLocProviderPriv::Startup() { - if (mProxyManager) { - return NS_OK; - } - - MOZ_DIAGNOSTIC_ASSERT(mClientState == ClientState::Uninit, - "Client in a initialized state but no manager"); - - GUniquePtr<GError> error; - mProxyManager = dont_AddRef(g_dbus_proxy_new_for_bus_sync( - G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, kGeoclueBusName, - kGCManagerPath, kGCManagerInterface, nullptr, getter_Transfers(error))); - if (!mProxyManager) { - GCL_LOG(Info, "Cannot connect to the Manager interface: %s\n", - error->message); - return NS_ERROR_FAILURE; - } - - g_signal_connect(mProxyManager, "notify::g-name-owner", - G_CALLBACK(GCManagerOwnerNotify), this); - - GUniquePtr<gchar> managerOwner(g_dbus_proxy_get_name_owner(mProxyManager)); - if (!managerOwner) { - GCL_LOG(Info, "The Manager interface has no owner\n"); - DeleteManager(); - return NS_ERROR_FAILURE; - } - - GCL_LOG(Info, "Manager interface connected successfully\n"); - - return NS_OK; -} - -void GCLocProviderPriv::WatchStart() { - if (mClientState == ClientState::Idle) { - StartClient(); - } else if (mClientState == ClientState::Started) { - if (mLastPosition && !mLocationTimer) { - GCL_LOG(Verbose, - "Will report the existing location if new one doesn't come up\n"); - SetLocationTimer(); - } - } else if (mClientState == ClientState::SettingAccuracy) { - GCLP_SETSTATE(this, SettingAccuracyForStart); - } else if (mClientState == ClientState::Stopping) { - GCLP_SETSTATE(this, StoppingForRestart); - } -} - -NS_IMETHODIMP -GCLocProviderPriv::Watch(nsIGeolocationUpdate* aCallback) { - mCallback = aCallback; - - if (!mCancellable) { - mCancellable = dont_AddRef(g_cancellable_new()); - } - - if (mClientState != ClientState::Uninit) { - WatchStart(); - return NS_OK; - } - - if (!mProxyManager) { - return NS_ERROR_FAILURE; - } - - GCLP_SETSTATE(this, Initing); - g_dbus_proxy_call(mProxyManager, "GetClient", nullptr, G_DBUS_CALL_FLAGS_NONE, - -1, mCancellable, - reinterpret_cast<GAsyncReadyCallback>(GetClientResponse), - this); - - return NS_OK; -} - -NS_IMETHODIMP -GCLocProviderPriv::Shutdown() { - DoShutdownClearCallback(false); - return NS_OK; -} - -NS_IMETHODIMP -GCLocProviderPriv::SetHighAccuracy(bool aHigh) { - GCL_LOG(Verbose, "Want %s accuracy\n", aHigh ? "high" : "low"); - if (!aHigh && AlwaysHighAccuracy()) { - GCL_LOG(Verbose, "Forcing high accuracy due to pref\n"); - aHigh = true; - } - - mAccuracyWanted = aHigh ? Accuracy::High : Accuracy::Low; - MaybeRestartForAccuracy(); - - return NS_OK; -} - -NS_IMPL_ISUPPORTS(GCLocProviderPriv::LocationTimerCallback, nsITimerCallback, - nsINamed) - -NS_IMETHODIMP -GCLocProviderPriv::LocationTimerCallback::Notify(nsITimer* aTimer) { - if (mParent) { - RefPtr<GCLocProviderPriv> parent(mParent); - parent->UpdateLastPosition(); - } - - return NS_OK; -} - -GeoclueLocationProvider::GeoclueLocationProvider() { - mPriv = new GCLocProviderPriv; -} - -// nsISupports -// - -NS_IMPL_ISUPPORTS(GeoclueLocationProvider, nsIGeolocationProvider) - -// nsIGeolocationProvider -// - -NS_IMETHODIMP -GeoclueLocationProvider::Startup() { return mPriv->Startup(); } - -NS_IMETHODIMP -GeoclueLocationProvider::Watch(nsIGeolocationUpdate* aCallback) { - return mPriv->Watch(aCallback); -} - -NS_IMETHODIMP -GeoclueLocationProvider::Shutdown() { return mPriv->Shutdown(); } - -NS_IMETHODIMP -GeoclueLocationProvider::SetHighAccuracy(bool aHigh) { - return mPriv->SetHighAccuracy(aHigh); -} - -} // namespace mozilla::dom
deleted file mode 100644 --- a/dom/system/linux/GeoclueLocationProvider.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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/. - */ - -#ifndef GeoclueLocationProvider_h -#define GeoclueLocationProvider_h - -#include "mozilla/RefPtr.h" -#include "nsIGeolocationProvider.h" - -namespace mozilla::dom { - -class GCLocProviderPriv; - -class GeoclueLocationProvider final : public nsIGeolocationProvider { - public: - NS_DECL_ISUPPORTS - NS_DECL_NSIGEOLOCATIONPROVIDER - - GeoclueLocationProvider(); - - private: - ~GeoclueLocationProvider() = default; - - RefPtr<GCLocProviderPriv> mPriv; -}; - -} // namespace mozilla::dom - -#endif /* GeoclueLocationProvider_h */
--- a/dom/system/linux/moz.build +++ b/dom/system/linux/moz.build @@ -10,15 +10,14 @@ if CONFIG["MOZ_GPSD"]: CXXFLAGS += CONFIG["MOZ_GPSD_CFLAGS"] OS_LIBS += CONFIG["MOZ_GPSD_LIBS"] LOCAL_INCLUDES += ["/dom/geolocation"] if CONFIG["MOZ_ENABLE_DBUS"]: - SOURCES += ["GeoclueLocationProvider.cpp"] SOURCES += ["PortalLocationProvider.cpp"] LOCAL_INCLUDES += ["/dom/geolocation"] CXXFLAGS += CONFIG["MOZ_DBUS_GLIB_CFLAGS"] CXXFLAGS += CONFIG["MOZ_GTK3_CFLAGS"] FINAL_LIBRARY = "xul"
--- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -5068,33 +5068,16 @@ mirror: always # Time, in milliseconds, to wait for the location provider to spin up. - name: geo.timeout type: int32_t value: 6000 mirror: always -#ifdef MOZ_ENABLE_DBUS -# Whether to use Geoclue location provider (if available on the system). -- name: geo.provider.use_geoclue - type: bool - value: false - mirror: always - -# Whether to always provide high location accuracy, even if site -# doesn't actually request this level of accuracy. -# Almost no site correctly requests high accuracy so force it by default -# for compatibility with other geolocation providers. -- name: geo.provider.geoclue.always_high_accuracy - type: bool - value: true - mirror: always -#endif - #--------------------------------------------------------------------------- # Prefs starting with "gfx." #--------------------------------------------------------------------------- - name: gfx.allow-texture-direct-mapping type: bool value: true mirror: once
--- a/widget/gtk/GRefPtr.h +++ b/widget/gtk/GRefPtr.h @@ -4,17 +4,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef GRefPtr_h_ #define GRefPtr_h_ // Allows to use RefPtr<T> with various kinds of GObjects #include <gdk/gdk.h> -#include <gio/gio.h> #include <gtk/gtk.h> #include "mozilla/RefPtr.h" #ifdef MOZ_ENABLE_DBUS // TODO: Remove this (we should use GDBus instead, which is not deprecated). # include <dbus/dbus-glib.h> #endif @@ -37,17 +36,16 @@ GOBJECT_TRAITS(GMenuItem) GOBJECT_TRAITS(GSimpleAction) GOBJECT_TRAITS(GSimpleActionGroup) GOBJECT_TRAITS(GDBusProxy) GOBJECT_TRAITS(GAppInfo) GOBJECT_TRAITS(GAppLaunchContext) GOBJECT_TRAITS(GdkDragContext) GOBJECT_TRAITS(GDBusMessage) GOBJECT_TRAITS(GdkPixbuf) -GOBJECT_TRAITS(GCancellable) #ifdef MOZ_ENABLE_DBUS GOBJECT_TRAITS(DBusGProxy) #endif #undef GOBJECT_TRAITS template <>