#ifndef SERVICES_DEVICE_GEOLOCATION_GEOLOCATION_PROVIDER_IMPL_H_
#define SERVICES_DEVICE_GEOLOCATION_GEOLOCATION_PROVIDER_IMPL_H_
#include <memory>
#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "base/functional/callback_forward.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote_set.h"
#include "services/device/geolocation/geolocation_provider.h"
#include "services/device/public/cpp/geolocation/geolocation_system_permission_manager.h"
#include "services/device/public/cpp/geolocation/location_provider.h"
#include "services/device/public/cpp/geolocation/location_system_permission_status.h"
#include "services/device/public/mojom/geolocation_control.mojom.h"
#include "services/device/public/mojom/geolocation_internals.mojom.h"
#include "services/device/public/mojom/geoposition.mojom.h"
#if BUILDFLAG(OS_LEVEL_GEOLOCATION_PERMISSION_SUPPORTED)
#include "base/scoped_observation.h"
#endif
namespace base {
template <typename Type>
struct DefaultSingletonTraits;
class SingleThreadTaskRunner;
}
namespace network {
class SharedURLLoaderFactory;
}
namespace device {
using CustomLocationProviderCallback =
base::RepeatingCallback<std::unique_ptr<LocationProvider>()>;
class GeolocationProviderImpl
: public GeolocationProvider,
public mojom::GeolocationControl,
public mojom::GeolocationInternals,
public base::Thread
#if BUILDFLAG(OS_LEVEL_GEOLOCATION_PERMISSION_SUPPORTED)
,
public GeolocationSystemPermissionManager::PermissionObserver
#endif
{
public:
base::CallbackListSubscription AddLocationUpdateCallback(
const LocationUpdateCallback& callback,
bool enable_high_accuracy) override;
void OverrideLocationForTesting(mojom::GeopositionResultPtr result) override;
void OnLocationUpdate(const LocationProvider* provider,
mojom::GeopositionResultPtr result);
static GeolocationProviderImpl* GetInstance();
GeolocationProviderImpl(const GeolocationProviderImpl&) = delete;
GeolocationProviderImpl& operator=(const GeolocationProviderImpl&) = delete;
static void SetGeolocationConfiguration(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const std::string& api_key,
const CustomLocationProviderCallback& custom_location_provider_getter,
GeolocationSystemPermissionManager* geolocation_system_permission_manager,
bool use_gms_core_location_provider);
static void SetGeolocationSystemPermissionManagerForTesting(
GeolocationSystemPermissionManager* instance_for_testing);
void BindGeolocationControlReceiver(
mojo::PendingReceiver<mojom::GeolocationControl> receiver);
void BindGeolocationInternalsReceiver(
mojo::PendingReceiver<mojom::GeolocationInternals> receiver);
void UserDidOptIntoLocationServices() override;
bool user_did_opt_into_location_services_for_testing() {
return user_did_opt_into_location_services_;
}
void clear_user_did_opt_into_location_services_for_testing() {
user_did_opt_into_location_services_ = false;
}
bool is_running_precise_for_testing() const { return is_running_precise_; }
void SetLocationProviderManagerForTesting(
std::unique_ptr<LocationProvider> location_provider_manager);
void AddInternalsObserver(
mojo::PendingRemote<mojom::GeolocationInternalsObserver> observer,
AddInternalsObserverCallback callback) override;
void SimulateInternalsUpdatedForTesting();
#if BUILDFLAG(OS_LEVEL_GEOLOCATION_PERMISSION_SUPPORTED)
void OnSystemPermissionUpdated(
LocationSystemPermissionStatus new_status) override;
void OnPermissionManagerShuttingDown() override;
#endif
static constexpr char kSystemPermissionDeniedErrorMessage[] =
"User denied Geolocation";
static constexpr char kSystemPermissionDeniedErrorTechnical[] =
"User has not allowed access to system location";
private:
friend struct base::DefaultSingletonTraits<GeolocationProviderImpl>;
GeolocationProviderImpl();
~GeolocationProviderImpl() override;
bool OnGeolocationThread() const;
void OnClientsChanged();
void StopProviders();
void StartProviders(bool enable_high_accuracy, bool enable_diagnostics);
void InformProvidersPermissionGranted();
void NotifyClients(mojom::GeopositionResultPtr result);
void Init() override;
void CleanUp() override;
void NotifyInternalsUpdated(mojom::GeolocationDiagnosticsPtr diagnostics);
void NotifyNetworkLocationRequested(
std::vector<mojom::AccessPointDataPtr> request);
void NotifyNetworkLocationReceived(
mojom::NetworkLocationResponsePtr response);
void OnInternalsObserverDisconnected(mojo::RemoteSetElementId element_id);
void OnInternalsUpdated();
void OnNetworkLocationRequested(
std::vector<mojom::AccessPointDataPtr> request);
void OnNetworkLocationReceived(mojom::NetworkLocationResponsePtr response);
mojom::GeolocationDiagnosticsPtr EnableAndGetDiagnosticsOnGeolocationThread();
void DisableDiagnosticsOnGeolocationThread();
void DoStartProvidersOnGeolocationThread();
#if BUILDFLAG(OS_LEVEL_GEOLOCATION_PERMISSION_SUPPORTED)
void NotifyClientsSystemPermissionDenied();
#endif
base::RepeatingCallbackList<void(const mojom::GeopositionResult&)>
high_accuracy_callbacks_;
base::RepeatingCallbackList<void(const mojom::GeopositionResult&)>
low_accuracy_callbacks_;
bool user_did_opt_into_location_services_ = false;
mojom::GeopositionResultPtr result_;
mojom::GeopositionResultPtr high_accuracy_result_;
mojom::GeopositionResultPtr low_accuracy_result_;
bool ignore_location_updates_ = false;
const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
std::unique_ptr<LocationProvider> location_provider_manager_;
mojo::Receiver<mojom::GeolocationControl> control_receiver_{this};
mojo::ReceiverSet<mojom::GeolocationInternals> internals_receivers_;
mojo::RemoteSet<mojom::GeolocationInternalsObserver> internals_observers_;
bool diagnostics_enabled_ = false;
bool is_running_precise_ = false;
#if BUILDFLAG(OS_LEVEL_GEOLOCATION_PERMISSION_SUPPORTED)
LocationSystemPermissionStatus system_permission_status_ =
LocationSystemPermissionStatus::kNotDetermined;
base::ScopedObservation<
GeolocationSystemPermissionManager,
GeolocationSystemPermissionManager::PermissionObserver>
geolocation_permission_observation_{this};
#endif
};
}
#endif