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

#include "content/browser/geolocation/geolocation_service_impl.h"

#include "base/bind_helpers.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/permissions/permission_controller_impl.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_type.h"
#include "content/public/common/content_features.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/test/mock_permission_manager.h"
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_service_manager_context.h"
#include "content/test/test_render_frame_host.h"
#include "services/device/public/cpp/test/scoped_geolocation_overrider.h"
#include "services/device/public/mojom/constants.mojom.h"
#include "services/device/public/mojom/geolocation.mojom.h"
#include "services/device/public/mojom/geolocation_context.mojom.h"
#include "services/device/public/mojom/geoposition.mojom.h"
#include "services/service_manager/public/cpp/bind_source_info.h"
#include "services/service_manager/public/cpp/connector.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom.h"

using base::test::ScopedFeatureList;
using blink::mojom::PermissionStatus;
using device::mojom::GeolocationPtr;
using device::mojom::GeopositionPtr;
using blink::mojom::GeolocationService;
using blink::mojom::GeolocationServicePtr;

typedef base::Callback<void(PermissionStatus)> PermissionCallback;

namespace content {
namespace {

double kMockLatitude = 1.0;
double kMockLongitude = 10.0;
GURL kMainUrl = GURL("https://www.google.com/maps");
GURL kEmbeddedUrl = GURL("https://embeddables.com/someframe");

class TestPermissionManager : public MockPermissionManager {
 public:
  TestPermissionManager()
      : request_id_(PermissionController::kNoPendingOperation) {}
  ~TestPermissionManager() override = default;

  int RequestPermission(PermissionType permissions,
                        RenderFrameHost* render_frame_host,
                        const GURL& requesting_origin,
                        bool user_gesture,
                        const PermissionCallback& callback) override {
    EXPECT_EQ(permissions, PermissionType::GEOLOCATION);
    EXPECT_TRUE(user_gesture);
    request_callback_.Run(callback);
    return request_id_;
  }

  void SetRequestId(int request_id) { request_id_ = request_id; }

  void SetRequestCallback(
      const base::Callback<void(const PermissionCallback&)>& request_callback) {
    request_callback_ = request_callback;
  }

 private:
  int request_id_;

  base::Callback<void(const PermissionCallback&)> request_callback_;
};

class GeolocationServiceTest : public RenderViewHostImplTestHarness {
 protected:
  GeolocationServiceTest() {}

  ~GeolocationServiceTest() override {}

  void SetUp() override {
    RenderViewHostImplTestHarness::SetUp();
    NavigateAndCommit(kMainUrl);
    browser_context_.reset(new content::TestBrowserContext());
    browser_context_->SetPermissionControllerDelegate(
        std::make_unique<TestPermissionManager>());
    permission_controller_.reset(
        new PermissionControllerImpl(browser_context_.get()));

    service_manager_context_ = std::make_unique<TestServiceManagerContext>();
    geolocation_overrider_ =
        std::make_unique<device::ScopedGeolocationOverrider>(kMockLatitude,
                                                             kMockLongitude);
    service_manager::Connector* connector =
        ServiceManagerConnection::GetForProcess()->GetConnector();
    connector->BindInterface(device::mojom::kServiceName,
                             mojo::MakeRequest(&context_ptr_));
  }

  void TearDown() override {
    context_ptr_.reset();
    geolocation_overrider_.reset();
    service_manager_context_.reset();
    browser_context_.reset();
    RenderViewHostImplTestHarness::TearDown();
  }

  void CreateEmbeddedFrameAndGeolocationService(bool allow_via_feature_policy) {
    if (allow_via_feature_policy) {
      RenderFrameHostTester::For(main_rfh())
          ->SimulateFeaturePolicyHeader(
              blink::mojom::FeaturePolicyFeature::kGeolocation,
              std::vector<url::Origin>{url::Origin::Create(kEmbeddedUrl)});
    }
    RenderFrameHost* embedded_rfh =
        RenderFrameHostTester::For(main_rfh())->AppendChild("");
    RenderFrameHostTester::For(embedded_rfh)->InitializeRenderFrameIfNeeded();
    auto navigation_simulator = NavigationSimulator::CreateRendererInitiated(
        kEmbeddedUrl, embedded_rfh);
    navigation_simulator->Commit();
    embedded_rfh = navigation_simulator->GetFinalRenderFrameHost();

    service_.reset(new GeolocationServiceImpl(
        context_ptr_.get(), permission_controller_.get(), embedded_rfh));
    service_->Bind(mojo::MakeRequest(&service_ptr_));
  }

  GeolocationServicePtr* service_ptr() { return &service_ptr_; }

  GeolocationService* service() { return &*service_ptr_; }

  TestPermissionManager* permission_manager() {
    return static_cast<TestPermissionManager*>(
        browser_context_->GetPermissionControllerDelegate());
  }

 private:
  std::unique_ptr<TestServiceManagerContext> service_manager_context_;
  std::unique_ptr<device::ScopedGeolocationOverrider> geolocation_overrider_;

  // The |permission_manager_| needs to come before the |service_| since
  // GeolocationService calls PermissionManager in its destructor.
  std::unique_ptr<TestBrowserContext> browser_context_;
  std::unique_ptr<PermissionControllerImpl> permission_controller_;
  std::unique_ptr<GeolocationServiceImpl> service_;
  GeolocationServicePtr service_ptr_;
  device::mojom::GeolocationContextPtr context_ptr_;

  DISALLOW_COPY_AND_ASSIGN(GeolocationServiceTest);
};

}  // namespace

TEST_F(GeolocationServiceTest, PermissionGrantedPolicyViolation) {
  // The embedded frame is not whitelisted.
  ScopedFeatureList feature_list;
  feature_list.InitFromCommandLine(
      features::kUseFeaturePolicyForPermissions.name, std::string());
  CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/false);

  permission_manager()->SetRequestCallback(
      base::Bind([](const PermissionCallback& callback) {
        ADD_FAILURE() << "Permissions checked unexpectedly.";
      }));
  GeolocationPtr geolocation;
  service()->CreateGeolocation(mojo::MakeRequest(&geolocation), true);

  base::RunLoop loop;
  geolocation.set_connection_error_handler(loop.QuitClosure());

  geolocation->QueryNextPosition(base::BindOnce([](GeopositionPtr geoposition) {
    ADD_FAILURE() << "Position updated unexpectedly";
  }));
  loop.Run();
}

TEST_F(GeolocationServiceTest, PermissionGrantedNoPolicyViolation) {
  // Whitelist the embedded frame.
  ScopedFeatureList feature_list;
  feature_list.InitFromCommandLine(
      features::kUseFeaturePolicyForPermissions.name, std::string());
  CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);

  permission_manager()->SetRequestCallback(
      base::Bind([](const PermissionCallback& callback) {
        callback.Run(PermissionStatus::GRANTED);
      }));
  GeolocationPtr geolocation;
  service()->CreateGeolocation(mojo::MakeRequest(&geolocation), true);

  base::RunLoop loop;
  geolocation.set_connection_error_handler(base::BindOnce(
      [] { ADD_FAILURE() << "Connection error handler called unexpectedly"; }));

  geolocation->QueryNextPosition(base::BindOnce(
      [](base::Closure callback, GeopositionPtr geoposition) {
        EXPECT_DOUBLE_EQ(kMockLatitude, geoposition->latitude);
        EXPECT_DOUBLE_EQ(kMockLongitude, geoposition->longitude);
        std::move(callback).Run();
      },
      loop.QuitClosure()));
  loop.Run();
}

TEST_F(GeolocationServiceTest, PermissionGrantedSync) {
  CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
  permission_manager()->SetRequestCallback(
      base::Bind([](const PermissionCallback& callback) {
        callback.Run(PermissionStatus::GRANTED);
      }));
  GeolocationPtr geolocation;
  service()->CreateGeolocation(mojo::MakeRequest(&geolocation), true);

  base::RunLoop loop;
  geolocation.set_connection_error_handler(base::BindOnce(
      [] { ADD_FAILURE() << "Connection error handler called unexpectedly"; }));

  geolocation->QueryNextPosition(base::BindOnce(
      [](base::Closure callback, GeopositionPtr geoposition) {
        EXPECT_DOUBLE_EQ(kMockLatitude, geoposition->latitude);
        EXPECT_DOUBLE_EQ(kMockLongitude, geoposition->longitude);
        std::move(callback).Run();
      },
      loop.QuitClosure()));
  loop.Run();
}

TEST_F(GeolocationServiceTest, PermissionDeniedSync) {
  CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
  permission_manager()->SetRequestCallback(
      base::Bind([](const PermissionCallback& callback) {
        callback.Run(PermissionStatus::DENIED);
      }));
  GeolocationPtr geolocation;
  service()->CreateGeolocation(mojo::MakeRequest(&geolocation), true);

  base::RunLoop loop;
  geolocation.set_connection_error_handler(loop.QuitClosure());

  geolocation->QueryNextPosition(base::BindOnce([](GeopositionPtr geoposition) {
    ADD_FAILURE() << "Position updated unexpectedly";
  }));
  loop.Run();
}

TEST_F(GeolocationServiceTest, PermissionGrantedAsync) {
  CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
  permission_manager()->SetRequestId(42);
  permission_manager()->SetRequestCallback(
      base::Bind([](const PermissionCallback& permission_callback) {
        base::ThreadTaskRunnerHandle::Get()->PostTask(
            FROM_HERE, base::BindOnce(
                           [](const PermissionCallback& callback) {
                             callback.Run(PermissionStatus::GRANTED);
                           },
                           permission_callback));
      }));
  GeolocationPtr geolocation;
  service()->CreateGeolocation(mojo::MakeRequest(&geolocation), true);

  base::RunLoop loop;
  geolocation.set_connection_error_handler(base::BindOnce(
      [] { ADD_FAILURE() << "Connection error handler called unexpectedly"; }));

  geolocation->QueryNextPosition(base::BindOnce(
      [](base::Closure callback, GeopositionPtr geoposition) {
        EXPECT_DOUBLE_EQ(kMockLatitude, geoposition->latitude);
        EXPECT_DOUBLE_EQ(kMockLongitude, geoposition->longitude);
        std::move(callback).Run();
      },
      loop.QuitClosure()));
  loop.Run();
}

TEST_F(GeolocationServiceTest, PermissionDeniedAsync) {
  CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
  permission_manager()->SetRequestId(42);
  permission_manager()->SetRequestCallback(
      base::Bind([](const PermissionCallback& permission_callback) {
        base::ThreadTaskRunnerHandle::Get()->PostTask(
            FROM_HERE, base::BindOnce(
                           [](const PermissionCallback& callback) {
                             callback.Run(PermissionStatus::DENIED);
                           },
                           permission_callback));
      }));
  GeolocationPtr geolocation;
  service()->CreateGeolocation(mojo::MakeRequest(&geolocation), true);

  base::RunLoop loop;
  geolocation.set_connection_error_handler(loop.QuitClosure());

  geolocation->QueryNextPosition(base::BindOnce([](GeopositionPtr geoposition) {
    ADD_FAILURE() << "Position updated unexpectedly";
  }));
  loop.Run();
}

TEST_F(GeolocationServiceTest, ServiceClosedBeforePermissionResponse) {
  CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
  permission_manager()->SetRequestId(42);
  GeolocationPtr geolocation;
  service()->CreateGeolocation(mojo::MakeRequest(&geolocation), true);
  // Don't immediately respond to the request.
  permission_manager()->SetRequestCallback(base::DoNothing());

  base::RunLoop loop;
  service_ptr()->reset();

  geolocation->QueryNextPosition(base::BindOnce([](GeopositionPtr geoposition) {
    ADD_FAILURE() << "Position updated unexpectedly";
  }));
  loop.RunUntilIdle();
}

}  // namespace content
