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

#include "content/browser/permissions/permission_service_impl.h"

#include <stddef.h>

#include <algorithm>
#include <memory>
#include <set>
#include <utility>

#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "content/browser/bad_message.h"
#include "content/browser/permissions/embedded_permission_control_checker.h"
#include "content/browser/permissions/permission_controller_impl.h"
#include "content/browser/permissions/permission_util.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/permission_request_description.h"
#include "content/public/browser/permission_result.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/features_generated.h"
#include "third_party/blink/public/common/permissions/permission_utils.h"
#include "third_party/blink/public/mojom/permissions/permission.mojom-shared.h"
#include "url/origin.h"

using blink::mojom::EmbeddedPermissionControlClient;
using blink::mojom::EmbeddedPermissionControlResult;
using blink::mojom::EmbeddedPermissionRequestDescriptorPtr;
using blink::mojom::PermissionDescriptorPtr;
using blink::mojom::PermissionName;
using blink::mojom::PermissionStatus;

namespace content {

namespace {

// This function allows the usage of the the multiple request map with single
// requests.
void PermissionRequestResponseCallbackWrapper(
    base::OnceCallback<void(PermissionStatus)> callback,
    const std::vector<PermissionStatus>& vector) {
  DCHECK_EQ(vector.size(), 1ul);
  std::move(callback).Run(vector[0]);
}

// Helper converts given `PermissionStatus` to `EmbeddedPermissionControlResult`
EmbeddedPermissionControlResult
PermissionStatusToEmbeddedPermissionControlResult(PermissionStatus status) {
  switch (status) {
    case PermissionStatus::GRANTED:
      return EmbeddedPermissionControlResult::kGranted;
    case PermissionStatus::DENIED:
    case blink::mojom::PermissionStatus::UNSATISFIED_OPTIONS:
      return EmbeddedPermissionControlResult::kDenied;
    case PermissionStatus::ASK:
      return EmbeddedPermissionControlResult::kDismissed;
  }

  NOTREACHED();
}

// Helper wraps `RequestPageEmbeddedPermissionCallback` to
// `RequestPermissionsCallback`.
void EmbeddedPermissionRequestCallbackWrapper(
    base::OnceCallback<void(EmbeddedPermissionControlResult)> callback,
    const std::vector<PermissionStatus>& statuses) {
  DCHECK(std::ranges::all_of(
      statuses, [&](auto const& status) { return statuses[0] == status; }));
  std::move(callback).Run(
      PermissionStatusToEmbeddedPermissionControlResult(statuses[0]));
}

// Helper which returns true if there are any duplicate or invalid permissions.
bool HasDuplicatesOrInvalidPermissions(
    const std::vector<PermissionDescriptorPtr>& permissions) {
  std::vector<blink::PermissionType> types(permissions.size());
  std::set<blink::PermissionType> duplicates_check;
  for (size_t i = 0; i < types.size(); ++i) {
    auto type =
        blink::MaybePermissionDescriptorToPermissionType(permissions[i]);
    if (!type) {
      return true;
    }

    types[i] = *type;

    bool inserted = duplicates_check.insert(types[i]).second;
    if (!inserted) {
      return true;
    }
  }
  return false;
}

// Helper check if permission types are all supported by Page Embedded
// Permission.
bool CheckPageEmbeddedPermissionTypes(
    const std::vector<PermissionDescriptorPtr>& permissions) {
  for (const auto& permission_type : permissions) {
    auto type = blink::PermissionDescriptorToPermissionType(permission_type);
    if (type != blink::PermissionType::GEOLOCATION &&
        type != blink::PermissionType::AUDIO_CAPTURE &&
        type != blink::PermissionType::VIDEO_CAPTURE) {
      return false;
    }
  }
  return true;
}

}  // anonymous namespace

class PermissionServiceImpl::PendingRequest {
 public:
  PendingRequest(const std::vector<blink::mojom::PermissionDescriptorPtr>&
                     request_descriptors,
                 RequestPermissionsCallback callback)
      : callback_(std::move(callback)),
        request_size_(request_descriptors.size()) {}

  ~PendingRequest() {
    if (callback_.is_null())
      return;

    std::move(callback_).Run(
        std::vector<PermissionStatus>(request_size_, PermissionStatus::DENIED));
  }

  void RunCallback(const std::vector<PermissionResult>& results) {
    std::vector<PermissionStatus> permission_statuses;
    for (const auto& result : results) {
      permission_statuses.push_back(result.status);
    }
    std::move(callback_).Run(permission_statuses);
  }

 private:
  RequestPermissionsCallback callback_;
  size_t request_size_;
};

PermissionServiceImpl::PermissionServiceImpl(PermissionServiceContext* context,
                                             const url::Origin& origin)
    : context_(context), origin_(origin) {}

PermissionServiceImpl::~PermissionServiceImpl() {}

void PermissionServiceImpl::RegisterPageEmbeddedPermissionControl(
    std::vector<PermissionDescriptorPtr> permissions,
    blink::mojom::EmbeddedPermissionRequestDescriptorPtr descriptor,
    mojo::PendingRemote<EmbeddedPermissionControlClient> observer) {
  if (!base::FeatureList::IsEnabled(blink::features::kPermissionElement)) {
    bad_message::ReceivedBadMessage(
        context_->render_frame_host()->GetProcess(),
        bad_message::PSI_REGISTER_PERMISSION_ELEMENT_WITHOUT_FEATURE);
    return;
  }

  WebContents* web_contents =
      WebContents::FromRenderFrameHost(context_->render_frame_host());
  CHECK(web_contents);
  auto* checker = EmbeddedPermissionControlChecker::GetOrCreateForPage(
      web_contents->GetPrimaryPage());
  std::set<PermissionName> permission_names;
  for (const auto& permission : permissions) {
    // Ensure all requested permissions are device permissions and check for
    // duplicates.
    if (!PermissionUtil::IsDevicePermission(permission) ||
        !permission_names.insert(permission->name).second) {
      ReceivedBadMessage();
      return;
    }
  }

  auto source =
      descriptor->geolocation
          ? EmbeddedPermissionControlChecker::Source::kGeolocationElement
          : EmbeddedPermissionControlChecker::Source::kPermissionElement;
  checker->CheckPageEmbeddedPermission(
      source, std::move(permission_names), std::move(observer),
      base::BindOnce(
          &PermissionServiceImpl::OnPageEmbeddedPermissionControlRegistered,
          weak_factory_.GetWeakPtr(), std::move(permissions)));
}

void PermissionServiceImpl::OnPageEmbeddedPermissionControlRegistered(
    std::vector<PermissionDescriptorPtr> permissions,
    bool allow,
    const mojo::Remote<EmbeddedPermissionControlClient>& client) {
  if (!allow) {
    client->OnEmbeddedPermissionControlRegistered(
        /*allow=*/false,
        /*statuses=*/std::nullopt);
    return;
  }

  std::vector<PermissionStatus> statuses(permissions.size());
  std::ranges::transform(
      permissions, statuses.begin(), [&](const auto& permission) {
        return this->GetCombinedPermissionAndDeviceResult(permission).status;
      });
  client->OnEmbeddedPermissionControlRegistered(/*allow=*/true,
                                                std::move(statuses));
}

void PermissionServiceImpl::RequestPageEmbeddedPermission(
    std::vector<PermissionDescriptorPtr> permissions,
    EmbeddedPermissionRequestDescriptorPtr descriptor,
    RequestPageEmbeddedPermissionCallback callback) {
  if (!base::FeatureList::IsEnabled(blink::features::kPermissionElement)) {
    bad_message::ReceivedBadMessage(
        context_->render_frame_host()->GetProcess(),
        bad_message::PSI_REQUEST_EMBEDDED_PERMISSION_WITHOUT_FEATURE);
    std::move(callback).Run(EmbeddedPermissionControlResult::kNotSupported);
    return;
  }

  if (auto* browser_context = context_->GetBrowserContext()) {
    if (HasDuplicatesOrInvalidPermissions(permissions) ||
        !CheckPageEmbeddedPermissionTypes(permissions)) {
      ReceivedBadMessage();
      return;
    }

    RequestPermissionsInternal(
        browser_context,
        PermissionRequestDescription(std::move(permissions),
                                     std::move(descriptor)),
        base::BindOnce(&EmbeddedPermissionRequestCallbackWrapper,
                       std::move(callback)));
  }
}

void PermissionServiceImpl::RequestPermission(
    PermissionDescriptorPtr permission,
    bool user_gesture,
    PermissionStatusCallback callback) {
  std::vector<PermissionDescriptorPtr> permissions;
  permissions.push_back(std::move(permission));
  RequestPermissions(std::move(permissions), user_gesture,
                     base::BindOnce(&PermissionRequestResponseCallbackWrapper,
                                    std::move(callback)));
}

void PermissionServiceImpl::RequestPermissions(
    std::vector<PermissionDescriptorPtr> permissions,
    bool user_gesture,
    RequestPermissionsCallback callback) {
  BrowserContext* browser_context = context_->GetBrowserContext();
  if (!browser_context) {
    return;
  }

  // This condition is valid if the call is coming from a ChildThread instead
  // of a RenderFrame. Some consumers of the service run in Workers and some
  // in Frames. In the context of a Worker, it is not possible to show a
  // permission prompt because there is no tab. In the context of a Frame, we
  // can. Even if the call comes from a context where it is not possible to
  // show any UI, we want to still return something relevant so the current
  // permission status is returned for each permission.
  if (!context_->render_frame_host()) {
    std::vector<PermissionStatus> result(permissions.size());
    for (size_t i = 0; i < permissions.size(); ++i) {
      result[i] = GetPermissionResult(permissions[i]).status;
    }
    std::move(callback).Run(result);
    return;
  }

  if (HasDuplicatesOrInvalidPermissions(permissions)) {
    ReceivedBadMessage();
    return;
  }

  RequestPermissionsInternal(
      browser_context,
      PermissionRequestDescription(std::move(permissions), user_gesture),
      std::move(callback));
}

void PermissionServiceImpl::RequestPermissionsInternal(
    BrowserContext* browser_context,
    PermissionRequestDescription request_description,
    RequestPermissionsCallback callback) {
  const auto& permissions = request_description.permissions;
  std::unique_ptr<PendingRequest> pending_request =
      std::make_unique<PendingRequest>(request_description.permissions,
                                       std::move(callback));

  int pending_request_id = pending_requests_.Add(std::move(pending_request));

  if (!permissions.empty() &&
      PermissionUtil::IsDomainOverride(permissions[0])) {
    if (!PermissionUtil::ValidateDomainOverride(request_description.permissions,
                                                context_->render_frame_host(),
                                                permissions[0])) {
      ReceivedBadMessage();
      return;
    }
    const url::Origin& requesting_origin =
        PermissionUtil::ExtractDomainOverride(permissions[0]);
    request_description.requesting_origin = requesting_origin.GetURL();
    PermissionControllerImpl::FromBrowserContext(browser_context)
        ->RequestPermissions(
            context_->render_frame_host(), request_description,
            base::BindOnce(&PermissionServiceImpl::OnRequestPermissionsResponse,
                           weak_factory_.GetWeakPtr(), pending_request_id));
  } else {
    PermissionControllerImpl::FromBrowserContext(browser_context)
        ->RequestPermissionsFromCurrentDocument(
            context_->render_frame_host(), std::move(request_description),
            base::BindOnce(&PermissionServiceImpl::OnRequestPermissionsResponse,
                           weak_factory_.GetWeakPtr(), pending_request_id));
  }
}

void PermissionServiceImpl::OnRequestPermissionsResponse(
    int pending_request_id,
    const std::vector<PermissionResult>& results) {
  PendingRequest* request = pending_requests_.Lookup(pending_request_id);
  request->RunCallback(results);
  pending_requests_.Remove(pending_request_id);
}

void PermissionServiceImpl::HasPermission(PermissionDescriptorPtr permission,
                                          PermissionStatusCallback callback) {
  std::move(callback).Run(GetPermissionResult(permission).status);
}

void PermissionServiceImpl::RevokePermission(
    PermissionDescriptorPtr permission,
    PermissionStatusCallback callback) {
  auto permission_type =
      blink::MaybePermissionDescriptorToPermissionType(permission);
  if (!permission_type) {
    ReceivedBadMessage();
    return;
  }
  PermissionResult result = GetPermissionResultForCurrentContext(permission);

  // Resetting the permission should only be possible if the permission is
  // already granted.
  if (result.status != PermissionStatus::GRANTED) {
    std::move(callback).Run(result.status);
    return;
  }

  ResetPermissionStatus(*permission_type);

  std::move(callback).Run(
      GetPermissionResultForCurrentContext(permission).status);
}

void PermissionServiceImpl::AddPermissionObserver(
    PermissionDescriptorPtr permission,
    PermissionStatus last_known_status,
    mojo::PendingRemote<blink::mojom::PermissionObserver> observer) {
  auto type = blink::MaybePermissionDescriptorToPermissionType(permission);
  if (!type) {
    ReceivedBadMessage();
    return;
  }

  PermissionResult current_result = GetPermissionResult(permission);
  context_->CreateSubscription(
      permission, origin_, current_result, PermissionResult(last_known_status),
      /*should_include_device_status*/ false, std::move(observer));
}

void PermissionServiceImpl::AddCombinedPermissionObserver(
    PermissionDescriptorPtr permission,
    PermissionStatus last_known_status,
    mojo::PendingRemote<blink::mojom::PermissionObserver> observer) {
  auto type = blink::MaybePermissionDescriptorToPermissionType(permission);
  if (!type) {
    ReceivedBadMessage();
    return;
  }
  bool should_include_device_status =
      PermissionUtil::IsDevicePermission(permission);
  PermissionResult current_result =
      should_include_device_status
          ? GetCombinedPermissionAndDeviceResult(permission)
          : GetPermissionResultForCurrentContext(permission);
  context_->CreateSubscription(
      permission, origin_, current_result, PermissionResult(last_known_status),
      should_include_device_status, std::move(observer));
}

void PermissionServiceImpl::NotifyEventListener(
    blink::mojom::PermissionDescriptorPtr permission,
    const std::string& event_type,
    bool is_added) {
  auto type = blink::MaybePermissionDescriptorToPermissionType(permission);
  if (!type) {
    ReceivedBadMessage();
    return;
  }

  BrowserContext* browser_context = context_->GetBrowserContext();
  if (!browser_context) {
    return;
  }

  if (!context_->render_frame_host()) {
    return;
  }

  if (event_type == "change") {
    if (is_added) {
      context_->GetOnchangeEventListeners().insert(*type);
    } else {
      context_->GetOnchangeEventListeners().erase(*type);
    }
  }

  PermissionControllerImpl::FromBrowserContext(browser_context)
      ->NotifyEventListener();
}

PermissionResult PermissionServiceImpl::GetPermissionResult(
    const PermissionDescriptorPtr& permission) {
  auto type = blink::MaybePermissionDescriptorToPermissionType(permission);
  if (!type) {
    ReceivedBadMessage();
    return PermissionResult(PermissionStatus::DENIED);
  }
  if (PermissionUtil::IsDomainOverride(permission) &&
      context_->render_frame_host()) {
    BrowserContext* browser_context = context_->GetBrowserContext();

    std::vector<blink::mojom::PermissionDescriptorPtr>
        permisison_descriptor_ptr_array;
    permisison_descriptor_ptr_array.emplace_back(permission->Clone());
    if (browser_context && PermissionUtil::ValidateDomainOverride(
                               permisison_descriptor_ptr_array,
                               context_->render_frame_host(), permission)) {
      return PermissionControllerImpl::FromBrowserContext(browser_context)
          ->GetPermissionResultForEmbeddedRequester(
              permission, context_->render_frame_host(),
              PermissionUtil::ExtractDomainOverride(permission));
    }
  }

  return GetPermissionResultForCurrentContext(permission);
}

PermissionResult PermissionServiceImpl::GetPermissionResultForCurrentContext(
    const PermissionDescriptorPtr& permission) {
  BrowserContext* browser_context = context_->GetBrowserContext();
  if (!browser_context) {
    return PermissionResult(PermissionStatus::DENIED);
  }

  if (context_->render_frame_host()) {
    return browser_context->GetPermissionController()
        ->GetPermissionResultForCurrentDocument(permission,
                                                context_->render_frame_host());
  }

  if (context_->render_process_host()) {
    return browser_context->GetPermissionController()
        ->GetPermissionResultForWorker(
            permission, context_->render_process_host(), origin_);
  }

  DCHECK(!context_->GetEmbeddingOrigin().has_value());
  return browser_context->GetPermissionController()
      ->GetPermissionResultForOriginWithoutContext(permission, origin_);
}

PermissionResult PermissionServiceImpl::GetCombinedPermissionAndDeviceResult(
    const PermissionDescriptorPtr& permission) {
  BrowserContext* browser_context = context_->GetBrowserContext();
  if (!browser_context) {
    return PermissionResult(PermissionStatus::DENIED);
  }

  RenderFrameHost* render_frame_host = context_->render_frame_host();
  if (!render_frame_host) {
    return PermissionResult(PermissionStatus::DENIED);
  }

  auto type = blink::MaybePermissionDescriptorToPermissionType(permission);
  if (!type) {
    ReceivedBadMessage();
    return PermissionResult(PermissionStatus::DENIED);
  }

  return PermissionResult(
      PermissionControllerImpl::FromBrowserContext(browser_context)
          ->GetCombinedPermissionAndDeviceStatus(permission,
                                                 render_frame_host));
}

void PermissionServiceImpl::ResetPermissionStatus(blink::PermissionType type) {
  BrowserContext* browser_context = context_->GetBrowserContext();
  if (!browser_context) {
    return;
  }

  GURL requesting_origin(origin_.GetURL());
  // If the embedding_origin is empty we'll use |origin_| instead.
  PermissionControllerImpl::FromBrowserContext(browser_context)
      ->ResetPermission(
          type, requesting_origin,
          context_->GetEmbeddingOrigin().value_or(requesting_origin));
}

void PermissionServiceImpl::ReceivedBadMessage() {
  if (context_->render_frame_host()) {
    bad_message::ReceivedBadMessage(context_->render_frame_host()->GetProcess(),
                                    bad_message::PSI_BAD_PERMISSION_DESCRIPTOR);
  } else {
    bad_message::ReceivedBadMessage(context_->render_process_host(),
                                    bad_message::PSI_BAD_PERMISSION_DESCRIPTOR);
  }
}

}  // namespace content
