chromium/services/device/geolocation/geolocation_provider_impl.cc

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "services/device/geolocation/geolocation_provider_impl.h"

#include <iterator>
#include <memory>
#include <utility>

#include "base/check.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/memory/singleton.h"
#include "base/notreached.h"
#include "base/ranges/algorithm.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/default_tick_clock.h"
#include "build/build_config.h"
#include "components/device_event_log/device_event_log.h"
#include "net/base/network_change_notifier.h"
#include "services/device/geolocation/location_provider_manager.h"
#include "services/device/geolocation/position_cache_impl.h"
#include "services/device/public/cpp/device_features.h"
#include "services/device/public/cpp/geolocation/geoposition.h"
#include "services/device/public/cpp/geolocation/location_system_permission_status.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"

#if BUILDFLAG(IS_ANDROID)
#include "base/android/jni_android.h"
#include "services/device/geolocation/geolocation_jni_headers/LocationProviderFactory_jni.h"
#endif

namespace device {

namespace {
base::LazyInstance<CustomLocationProviderCallback>::Leaky
    g_custom_location_provider_callback =;
base::LazyInstance<std::unique_ptr<network::PendingSharedURLLoaderFactory>>::
    Leaky g_pending_url_loader_factory =;
base::LazyInstance<std::string>::Leaky g_api_key =;
GeolocationSystemPermissionManager* g_geolocation_system_permission_manager =;
}  // namespace

// static
GeolocationProvider* GeolocationProvider::instance_for_testing_ =;

// static
GeolocationProvider* GeolocationProvider::GetInstance() {}

// static
void GeolocationProvider::SetInstanceForTesting(
    GeolocationProvider* instance_for_testing) {}

// static
void GeolocationProviderImpl::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 GeolocationProviderImpl::SetGeolocationSystemPermissionManagerForTesting(
    GeolocationSystemPermissionManager* instance_for_testing) {}

base::CallbackListSubscription
GeolocationProviderImpl::AddLocationUpdateCallback(
    const LocationUpdateCallback& callback,
    bool enable_high_accuracy) {}

bool GeolocationProviderImpl::HighAccuracyLocationInUse() {}

void GeolocationProviderImpl::OverrideLocationForTesting(
    mojom::GeopositionResultPtr result) {}

void GeolocationProviderImpl::OnLocationUpdate(
    const LocationProvider* provider,
    mojom::GeopositionResultPtr result) {}

// static
GeolocationProviderImpl* GeolocationProviderImpl::GetInstance() {}

void GeolocationProviderImpl::BindGeolocationControlReceiver(
    mojo::PendingReceiver<mojom::GeolocationControl> receiver) {}

void GeolocationProviderImpl::BindGeolocationInternalsReceiver(
    mojo::PendingReceiver<mojom::GeolocationInternals> receiver) {}

void GeolocationProviderImpl::UserDidOptIntoLocationServices() {}

GeolocationProviderImpl::GeolocationProviderImpl()
    :{}

GeolocationProviderImpl::~GeolocationProviderImpl() {}

void GeolocationProviderImpl::SetLocationProviderManagerForTesting(
    std::unique_ptr<LocationProvider> location_provider_manager) {}

bool GeolocationProviderImpl::OnGeolocationThread() const {}

void GeolocationProviderImpl::OnClientsChanged() {}

void GeolocationProviderImpl::OnInternalsUpdated() {}

void GeolocationProviderImpl::OnNetworkLocationRequested(
    std::vector<mojom::AccessPointDataPtr> request) {}

void GeolocationProviderImpl::OnNetworkLocationReceived(
    mojom::NetworkLocationResponsePtr response) {}

void GeolocationProviderImpl::OnInternalsObserverDisconnected(
    mojo::RemoteSetElementId element_id) {}

void GeolocationProviderImpl::StopProviders() {}

void GeolocationProviderImpl::StartProviders(bool enable_high_accuracy,
                                             bool enable_diagnostics) {}

void GeolocationProviderImpl::InformProvidersPermissionGranted() {}

void GeolocationProviderImpl::NotifyClients(
    mojom::GeopositionResultPtr result) {}

void GeolocationProviderImpl::NotifyInternalsUpdated(
    mojom::GeolocationDiagnosticsPtr diagnostics) {}

void GeolocationProviderImpl::NotifyNetworkLocationRequested(
    std::vector<mojom::AccessPointDataPtr> request) {}

void GeolocationProviderImpl::NotifyNetworkLocationReceived(
    mojom::NetworkLocationResponsePtr response) {}

void GeolocationProviderImpl::Init() {}

void GeolocationProviderImpl::CleanUp() {}

void GeolocationProviderImpl::AddInternalsObserver(
    mojo::PendingRemote<mojom::GeolocationInternalsObserver> observer,
    AddInternalsObserverCallback callback) {}

void GeolocationProviderImpl::SimulateInternalsUpdatedForTesting() {}

mojom::GeolocationDiagnosticsPtr
GeolocationProviderImpl::EnableAndGetDiagnosticsOnGeolocationThread() {}

void GeolocationProviderImpl::DisableDiagnosticsOnGeolocationThread() {}

#if BUILDFLAG(OS_LEVEL_GEOLOCATION_PERMISSION_SUPPORTED)
void GeolocationProviderImpl::OnSystemPermissionUpdated(
    LocationSystemPermissionStatus new_status) {
  CHECK(main_task_runner_->BelongsToCurrentThread());
  if (new_status == LocationSystemPermissionStatus::kAllowed) {
    GEOLOCATION_LOG(DEBUG) << "New system permission state is kAllowed";
    if (!high_accuracy_callbacks_.empty() || !low_accuracy_callbacks_.empty()) {
      DoStartProvidersOnGeolocationThread();
    }
  } else if (new_status == LocationSystemPermissionStatus::kDenied) {
    GEOLOCATION_LOG(DEBUG) << "New system permission state is kDenied";
    NotifyClientsSystemPermissionDenied();
  } else {
    // System permission state reset to kUndetermined: Treat as if permission
    // was denied. This state transition is unusual in normal operation. It
    // likely indicates manual intervention for testing purposes. Since this
    // simulates a lack of permission, handle it as 'kDenied' for consistent
    // logic.
    GEOLOCATION_LOG(DEBUG) << "New system permission state is kUndetermined";
    NotifyClientsSystemPermissionDenied();
  }

  system_permission_status_ = new_status;
}

void GeolocationProviderImpl::NotifyClientsSystemPermissionDenied() {
  CHECK(main_task_runner_->BelongsToCurrentThread());
  auto error_result =
      mojom::GeopositionResult::NewError(mojom::GeopositionError::New(
          mojom::GeopositionErrorCode::kPermissionDenied,
          kSystemPermissionDeniedErrorMessage, ""));
  NotifyClients(std::move(error_result));
}
#endif

void GeolocationProviderImpl::DoStartProvidersOnGeolocationThread() {}

}  // namespace device