diff options
Diffstat (limited to 'src/core/location_provider_qt.cpp')
-rw-r--r-- | src/core/location_provider_qt.cpp | 127 |
1 files changed, 65 insertions, 62 deletions
diff --git a/src/core/location_provider_qt.cpp b/src/core/location_provider_qt.cpp index b5d0f21f2..dc0d80aa7 100644 --- a/src/core/location_provider_qt.cpp +++ b/src/core/location_provider_qt.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWebEngine module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "location_provider_qt.h" @@ -48,12 +12,18 @@ #include <QtCore/QThread> #include <QtPositioning/QGeoPositionInfoSource> -#include "base/bind.h" +#if QT_CONFIG(permissions) +#include <QtCore/qpermissions.h> +#endif + +#include "base/functional/bind.h" #include "base/memory/weak_ptr.h" #include "content/public/browser/browser_thread.h" #include "services/device/geolocation/geolocation_provider.h" #include "services/device/geolocation/geolocation_provider_impl.h" +#include "services/device/public/mojom/geoposition.mojom.h" + namespace QtWebEngineCore { using content::BrowserThread; @@ -73,11 +43,12 @@ private Q_SLOTS: void error(QGeoPositionInfoSource::Error positioningError); private: + void startImpl(bool highAccuracy); LocationProviderQt *m_locationProvider; QGeoPositionInfoSource *m_positionInfoSource; base::WeakPtrFactory<LocationProviderQt> m_locationProviderFactory; - void postToLocationProvider(const base::Closure &task); + void postToLocationProvider(base::OnceClosure task); friend class LocationProviderQt; }; @@ -102,6 +73,38 @@ static bool isHighAccuracySource(const QGeoPositionInfoSource *source) void QtPositioningHelper::start(bool highAccuracy) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + + // New Qt permissions API from 6.5.0 +#if QT_CONFIG(permissions) + QLocationPermission locationPermission; + locationPermission.setAvailability(QLocationPermission::WhenInUse); + + QLocationPermission::Accuracy accuracy = highAccuracy ? QLocationPermission::Precise + : QLocationPermission::Approximate; + locationPermission.setAccuracy(accuracy); + + switch (qApp->checkPermission(locationPermission)) { + case Qt::PermissionStatus::Undetermined: + qApp->requestPermission(locationPermission, this, + [this, &highAccuracy](const QPermission &permission) { + if (permission.status() == Qt::PermissionStatus::Granted) + this->startImpl(highAccuracy); + }); + + return; + case Qt::PermissionStatus::Denied: + qWarning("Failed to initialize location provider: The user does not have the right " + "permissions or has denied the permission request."); + return; + case Qt::PermissionStatus::Granted: + break; // Proceed + } +#endif + startImpl(highAccuracy); +} + +void QtPositioningHelper::startImpl(bool highAccuracy){ + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!m_positionInfoSource) m_positionInfoSource = QGeoPositionInfoSource::createDefaultSource(this); if (!m_positionInfoSource) { @@ -160,64 +163,64 @@ void QtPositioningHelper::updatePosition(const QGeoPositionInfo &pos) if (!pos.isValid()) return; Q_ASSERT(m_positionInfoSource->error() == QGeoPositionInfoSource::NoError); - device::mojom::Geoposition newPos; - newPos.error_code = device::mojom::Geoposition::ErrorCode::NONE; - newPos.error_message.clear(); + auto newPos = device::mojom::Geoposition::New(); - newPos.timestamp = toTime(pos.timestamp()); - newPos.latitude = pos.coordinate().latitude(); - newPos.longitude = pos.coordinate().longitude(); + newPos->timestamp = toTime(pos.timestamp()); + newPos->latitude = pos.coordinate().latitude(); + newPos->longitude = pos.coordinate().longitude(); const double altitude = pos.coordinate().altitude(); if (!qIsNaN(altitude)) - newPos.altitude = altitude; + newPos->altitude = altitude; // Chromium's geoposition needs a valid (as in >=0.) accuracy field. // try and get an accuracy estimate from QGeoPositionInfo. // If we don't have any accuracy info, 100m seems a pesimistic enough default. if (!pos.hasAttribute(QGeoPositionInfo::VerticalAccuracy) && !pos.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) - newPos.accuracy = 100; + newPos->accuracy = 100; else { const double vAccuracy = pos.hasAttribute(QGeoPositionInfo::VerticalAccuracy) ? pos.attribute(QGeoPositionInfo::VerticalAccuracy) : 0; const double hAccuracy = pos.hasAttribute(QGeoPositionInfo::HorizontalAccuracy) ? pos.attribute(QGeoPositionInfo::HorizontalAccuracy) : 0; - newPos.accuracy = sqrt(vAccuracy * vAccuracy + hAccuracy * hAccuracy); + newPos->accuracy = sqrt(vAccuracy * vAccuracy + hAccuracy * hAccuracy); } // And now the "nice to have" fields (-1 means invalid). - newPos.speed = pos.hasAttribute(QGeoPositionInfo::GroundSpeed) ? pos.attribute(QGeoPositionInfo::GroundSpeed) : -1; - newPos.heading = pos.hasAttribute(QGeoPositionInfo::Direction) ? pos.attribute(QGeoPositionInfo::Direction) : -1; + newPos->speed = pos.hasAttribute(QGeoPositionInfo::GroundSpeed) ? pos.attribute(QGeoPositionInfo::GroundSpeed) : -1; + newPos->heading = pos.hasAttribute(QGeoPositionInfo::Direction) ? pos.attribute(QGeoPositionInfo::Direction) : -1; + auto newResult = device::mojom::GeopositionResult::NewPosition(std::move(newPos)); if (m_locationProvider) - postToLocationProvider(base::Bind(&LocationProviderQt::updatePosition, m_locationProviderFactory.GetWeakPtr(), newPos)); + postToLocationProvider(base::BindOnce(&LocationProviderQt::updatePosition, m_locationProviderFactory.GetWeakPtr(), std::move(newResult))); } void QtPositioningHelper::error(QGeoPositionInfoSource::Error positioningError) { Q_ASSERT(positioningError != QGeoPositionInfoSource::NoError); - device::mojom::Geoposition newPos; + auto newError = device::mojom::GeopositionError::New(); switch (positioningError) { case QGeoPositionInfoSource::AccessError: - newPos.error_code = device::mojom::Geoposition::ErrorCode::PERMISSION_DENIED; + newError->error_code = device::mojom::GeopositionErrorCode::kPermissionDenied; break; case QGeoPositionInfoSource::UpdateTimeoutError: // content::Geoposition::ERROR_CODE_TIMEOUT is not handled properly in the renderer process, and the timeout // argument used in JS never comes all the way to the browser process. // Let's just treat it like any other error where the position is unavailable. - newPos.error_code = device::mojom::Geoposition::ErrorCode::POSITION_UNAVAILABLE; + newError->error_code = device::mojom::GeopositionErrorCode::kPositionUnavailable; break; case QGeoPositionInfoSource::ClosedError: case QGeoPositionInfoSource::UnknownSourceError: // position unavailable is as good as it gets in Geoposition default: - newPos.error_code = device::mojom::Geoposition::ErrorCode::POSITION_UNAVAILABLE; + newError->error_code = device::mojom::GeopositionErrorCode::kPositionUnavailable; break; } + auto newResult = device::mojom::GeopositionResult::NewError(std::move(newError)); if (m_locationProvider) - postToLocationProvider(base::Bind(&LocationProviderQt::updatePosition, m_locationProviderFactory.GetWeakPtr(), newPos)); + postToLocationProvider(base::BindOnce(&LocationProviderQt::updatePosition, m_locationProviderFactory.GetWeakPtr(), std::move(newResult))); } -inline void QtPositioningHelper::postToLocationProvider(const base::Closure &task) +inline void QtPositioningHelper::postToLocationProvider(base::OnceClosure task) { - static_cast<device::GeolocationProviderImpl*>(device::GeolocationProvider::GetInstance())->task_runner()->PostTask(FROM_HERE, task); + static_cast<device::GeolocationProviderImpl*>(device::GeolocationProvider::GetInstance())->task_runner()->PostTask(FROM_HERE, std::move(task)); } LocationProviderQt::LocationProviderQt() @@ -262,10 +265,10 @@ void LocationProviderQt::SetUpdateCallback(const LocationProviderUpdateCallback& m_callback = callback; } -void LocationProviderQt::updatePosition(const device::mojom::Geoposition &position) +void LocationProviderQt::updatePosition(device::mojom::GeopositionResultPtr position) { - m_lastKnownPosition = position; - m_callback.Run(this, position); + m_lastKnownPosition = std::move(position); + m_callback.Run(this, m_lastKnownPosition.Clone()); } } // namespace QtWebEngineCore |