blob: 8d4f0dd36e1a8ccba65cb41626e9b4e9ab4a1676 [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/functional/bind.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chromeos/ash/components/dbus/shill/shill_clients.h"
#include "chromeos/ash/components/network/geolocation_handler.h"
#endif
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/network_change_notifier.h"
#include "services/device/device_service_test_base.h"
#include "services/device/geolocation/geolocation_provider_impl.h"
#include "services/device/geolocation/mock_wifi_data_provider.h"
#include "services/device/geolocation/network_location_request.h"
#include "services/device/geolocation/wifi_data_provider_handle.h"
#include "services/device/public/cpp/device_features.h"
#include "services/device/public/mojom/geolocation.mojom.h"
#include "services/device/public/mojom/geolocation_config.mojom.h"
#include "services/device/public/mojom/geolocation_context.mojom.h"
#include "services/device/public/mojom/geolocation_control.mojom.h"
namespace device {
namespace {
void CheckBoolReturnValue(base::OnceClosure quit_closure,
bool expect,
bool result) {
EXPECT_EQ(expect, result);
std::move(quit_closure).Run();
}
class GeolocationServiceUnitTest : public DeviceServiceTestBase {
public:
GeolocationServiceUnitTest() = default;
GeolocationServiceUnitTest(const GeolocationServiceUnitTest&) = delete;
GeolocationServiceUnitTest& operator=(const GeolocationServiceUnitTest&) =
delete;
~GeolocationServiceUnitTest() override = default;
protected:
void SetUp() override {
#if BUILDFLAG(IS_CHROMEOS_ASH)
ash::shill_clients::InitializeFakes();
ash::NetworkHandler::Initialize();
#endif
network_change_notifier_ = net::NetworkChangeNotifier::CreateMockIfNeeded();
// We need to initialize the above *before* the base fixture instantiates
// the device service.
DeviceServiceTestBase::SetUp();
wifi_data_provider_ = MockWifiDataProvider::CreateInstance();
WifiDataProviderHandle::SetFactoryForTesting(
MockWifiDataProvider::GetInstance);
device_service()->BindGeolocationControl(
geolocation_control_.BindNewPipeAndPassReceiver());
geolocation_control_->UserDidOptIntoLocationServices();
device_service()->BindGeolocationContext(
geolocation_context_.BindNewPipeAndPassReceiver());
geolocation_context_->BindGeolocation(
geolocation_.BindNewPipeAndPassReceiver(), GURL());
}
void TearDown() override {
WifiDataProviderHandle::ResetFactoryForTesting();
DeviceServiceTestBase::TearDown();
#if BUILDFLAG(IS_CHROMEOS_ASH)
ash::NetworkHandler::Shutdown();
ash::shill_clients::Shutdown();
#endif
// Let the GeolocationImpl destruct earlier than GeolocationProviderImpl to
// make sure the base::RepeatingCallbackList<> member in
// GeolocationProviderImpl is empty.
geolocation_.reset();
GeolocationProviderImpl::GetInstance()
->clear_user_did_opt_into_location_services_for_testing();
base::RunLoop().RunUntilIdle();
}
void BindGeolocationConfig() {
device_service()->BindGeolocationConfig(
geolocation_config_.BindNewPipeAndPassReceiver());
}
scoped_refptr<MockWifiDataProvider> wifi_data_provider_;
std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_;
mojo::Remote<mojom::GeolocationControl> geolocation_control_;
mojo::Remote<mojom::GeolocationContext> geolocation_context_;
mojo::Remote<mojom::Geolocation> geolocation_;
mojo::Remote<mojom::GeolocationConfig> geolocation_config_;
};
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_ANDROID)
// ChromeOS fails to perform network geolocation when zero wifi networks are
// detected in a scan: https://crbug.com/767300.
#else
TEST_F(GeolocationServiceUnitTest, UrlWithApiKey) {
// To align with user expectation we do not make Network Location Requests
// on macOS unless the browser has Location Permission from the OS.
#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_CHROMEOS)
fake_geolocation_manager_->SetSystemPermission(
LocationSystemPermissionStatus::kAllowed);
#endif
base::RunLoop loop;
test_url_loader_factory_.SetInterceptor(base::BindLambdaForTesting(
[&loop](const network::ResourceRequest& request) {
// Verify the full URL including a fake Google API key.
std::string expected_url =
"https://www.googleapis.com/geolocation/v1/geolocate?key=";
expected_url.append(kTestGeolocationApiKey);
if (request.url == expected_url)
loop.Quit();
}));
geolocation_->SetHighAccuracy(true);
loop.Run();
// Clearing interceptor callback to ensure it does not outlive this scope.
test_url_loader_factory_.SetInterceptor(base::NullCallback());
}
#endif
// TODO(https://crbug.com/912057): Flaky on Chrome OS / Fails often on *San.
// TODO(https://crbug.com/999409): Also flaky on other platforms.
TEST_F(GeolocationServiceUnitTest, DISABLED_GeolocationConfig) {
BindGeolocationConfig();
{
base::RunLoop run_loop;
geolocation_config_->IsHighAccuracyLocationBeingCaptured(
base::BindOnce(&CheckBoolReturnValue, run_loop.QuitClosure(), false));
run_loop.Run();
}
geolocation_->SetHighAccuracy(true);
{
base::RunLoop run_loop;
geolocation_config_->IsHighAccuracyLocationBeingCaptured(
base::BindOnce(&CheckBoolReturnValue, run_loop.QuitClosure(), true));
run_loop.Run();
}
}
} // namespace
} // namespace device