/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */
/** * |MLSGeolocationUpdate| provides a fallback if Portal is not supported.
*/ class PortalLocationProvider::MLSGeolocationUpdate final
: public nsIGeolocationUpdate { public:
NS_DECL_ISUPPORTS
NS_DECL_NSIGEOLOCATIONUPDATE
PortalLocationProvider::~PortalLocationProvider() { if (mDBUSLocationProxy || mRefreshTimer || mMLSProvider) {
NS_WARNING( "PortalLocationProvider: Shutdown() had not been called before " "destructor.");
Shutdown();
}
}
void PortalLocationProvider::Update(nsIDOMGeoPosition* aPosition) { if (!mCallback) { return; // not initialized or already shut down
}
if (mMLSProvider) {
LOG_PORTAL( "Update from location portal received: Cancelling fallback MLS " "provider\n");
mMLSProvider->Shutdown(MLSFallback::ShutdownReason::ProviderResponded);
mMLSProvider = nullptr;
}
LOG_PORTAL("Send updated location to the callback %p", mCallback.get());
mCallback->Update(aPosition);
aPosition->GetCoords(getter_AddRefs(mLastGeoPositionCoords)); // Schedule sending repetitive updates because we don't get more until // position is changed from portal. That would lead to timeout on the // Firefox side.
SetRefreshTimer(5000);
}
void PortalLocationProvider::NotifyError(int aError) {
LOG_PORTAL("*****NotifyError %d\n", aError); if (!mCallback) { return; // not initialized or already shut down
}
if (!mMLSProvider) { /* With Portal failed, we restart MLS. It will be canceled once we * get another location from Portal. Start it immediately.
*/
mMLSProvider = MakeAndAddRef<MLSFallback>(0);
mMLSProvider->Startup(new MLSGeolocationUpdate(mCallback));
}
// Listen to signals which will be send to us with the location data
mDBUSSignalHandler =
g_signal_connect(mDBUSLocationProxy, "g-signal",
G_CALLBACK(location_updated_signal_cb), this);
// Call CreateSession of the location portal
GVariantBuilder builder;
if (!result) {
g_printerr("Error calling CreateSession method: %s\n", error->message); return NS_OK; // fallback to MLS
}
// Start to listen to the location changes
g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
// TODO Use wayland:handle as described in // https://flatpak.github.io/xdg-desktop-portal/#parent_window const gchar* parent_window = "";
gchar* portalSession;
g_variant_get_child(result, 0, "o", &portalSession);
mPortalSession.reset(portalSession);
if (mLastGeoPositionCoords) { // We cannot immediately call the Update there becase the window is not // yet ready for that.
LOG_PORTAL( "Update location in 1ms because we have the valid coords cached.");
SetRefreshTimer(1); return NS_OK;
}
/* The MLS fallback will kick in after 12 seconds if portal * doesn't provide location information within time. Once we * see the first message from portal, the fallback will be * disabled in |Update|.
*/
mMLSProvider = MakeAndAddRef<MLSFallback>(12000);
mMLSProvider->Startup(new MLSGeolocationUpdate(aCallback));
void PortalLocationProvider::SetRefreshTimer(int aDelay) {
LOG_PORTAL("SetRefreshTimer for %p to %d ms\n", this, aDelay); if (!mRefreshTimer) {
NS_NewTimerWithCallback(getter_AddRefs(mRefreshTimer), this, aDelay,
nsITimer::TYPE_ONE_SHOT);
} else {
mRefreshTimer->Cancel();
mRefreshTimer->InitWithCallback(this, aDelay, nsITimer::TYPE_ONE_SHOT);
}
}
NS_IMETHODIMP
PortalLocationProvider::Notify(nsITimer* timer) { // We need to reschedule the timer because we won't get any update // from portal until the location is changed. That would cause // watchPosition to fail with TIMEOUT error.
SetRefreshTimer(5000); if (mLastGeoPositionCoords) {
LOG_PORTAL("Update location callback with latest coords.");
mCallback->Update( new nsGeoPosition(mLastGeoPositionCoords, PR_Now() / PR_USEC_PER_MSEC));
} return NS_OK;
}
NS_IMETHODIMP
PortalLocationProvider::Shutdown() {
LOG_PORTAL("Shutdown location provider"); if (mRefreshTimer) {
mRefreshTimer->Cancel();
mRefreshTimer = nullptr;
}
mLastGeoPositionCoords = nullptr; if (mDBUSLocationProxy) {
g_signal_handler_disconnect(mDBUSLocationProxy, mDBUSSignalHandler);
LOG_PORTAL("calling Close method to the session interface...\n");
RefPtr<GDBusMessage> message = dont_AddRef(g_dbus_message_new_method_call(
kDesktopBusName, mPortalSession.get(), kSessionInterfaceName, "Close"));
mPortalSession = nullptr; if (message) {
GUniquePtr<GError> error;
GDBusConnection* connection =
g_dbus_proxy_get_connection(mDBUSLocationProxy);
g_dbus_connection_send_message(
connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, /*out_serial=*/nullptr, getter_Transfers(error)); if (error) {
g_printerr("Failed to close the session: %s\n", error->message);
}
}
mDBUSLocationProxy = nullptr;
} if (mMLSProvider) {
mMLSProvider->Shutdown(MLSFallback::ShutdownReason::ProviderShutdown);
mMLSProvider = nullptr;
} return NS_OK;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.