// Copyright 2014 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/permissions/permission_service_impl.h"

#include <stddef.h>

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

#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "build/build_config.h"
#include "content/browser/bad_message.h"
#include "content/browser/permissions/permission_controller_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/permission_type.h"
#include "content/public/browser/render_frame_host.h"

using blink::mojom::PermissionDescriptorPtr;
using blink::mojom::PermissionName;
using blink::mojom::PermissionObserverPtr;
using blink::mojom::PermissionStatus;

namespace content {

namespace {

bool PermissionDescriptorToPermissionType(
    const PermissionDescriptorPtr& descriptor,
    PermissionType* permission_type) {
  switch (descriptor->name) {
    case PermissionName::GEOLOCATION:
      *permission_type = PermissionType::GEOLOCATION;
      return true;
    case PermissionName::NOTIFICATIONS:
      *permission_type = PermissionType::NOTIFICATIONS;
      return true;
    case PermissionName::MIDI: {
      if (descriptor->extension && descriptor->extension->is_midi() &&
          descriptor->extension->get_midi()->sysex) {
        *permission_type = PermissionType::MIDI_SYSEX;
        return true;
      }
      *permission_type = PermissionType::MIDI;
      return true;
    }
    case PermissionName::PROTECTED_MEDIA_IDENTIFIER:
#if defined(ENABLE_PROTECTED_MEDIA_IDENTIFIER_PERMISSION)
      *permission_type = PermissionType::PROTECTED_MEDIA_IDENTIFIER;
      return true;
#else
      NOTIMPLEMENTED();
      return false;
#endif  // defined(ENABLE_PROTECTED_MEDIA_IDENTIFIER_PERMISSION)
    case PermissionName::DURABLE_STORAGE:
      *permission_type = PermissionType::DURABLE_STORAGE;
      return true;
    case PermissionName::AUDIO_CAPTURE:
      *permission_type = PermissionType::AUDIO_CAPTURE;
      return true;
    case PermissionName::VIDEO_CAPTURE:
      *permission_type = PermissionType::VIDEO_CAPTURE;
      return true;
    case PermissionName::BACKGROUND_SYNC:
      *permission_type = PermissionType::BACKGROUND_SYNC;
      return true;
    case PermissionName::SENSORS:
      *permission_type = PermissionType::SENSORS;
      return true;
    case PermissionName::ACCESSIBILITY_EVENTS:
      *permission_type = PermissionType::ACCESSIBILITY_EVENTS;
      return true;
    case PermissionName::CLIPBOARD_READ:
      *permission_type = PermissionType::CLIPBOARD_READ;
      return true;
    case PermissionName::CLIPBOARD_WRITE:
      *permission_type = PermissionType::CLIPBOARD_WRITE;
      return true;
    case PermissionName::PAYMENT_HANDLER:
      *permission_type = PermissionType::PAYMENT_HANDLER;
      return true;
    case PermissionName::BACKGROUND_FETCH:
      *permission_type = PermissionType::BACKGROUND_FETCH;
      return true;
  }

  NOTREACHED();
  return false;
}

// 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]);
}

}  // anonymous namespace

class PermissionServiceImpl::PendingRequest {
 public:
  PendingRequest(std::vector<PermissionType> types,
                 RequestPermissionsCallback callback)
      : callback_(std::move(callback)), request_size_(types.size()) {}

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

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

  int id() const { return id_; }
  void set_id(int id) { id_ = id; }

  void RunCallback(const std::vector<PermissionStatus>& results) {
    std::move(callback_).Run(results);
  }

 private:
  // Request ID received from the PermissionController.
  int id_;
  RequestPermissionsCallback callback_;
  size_t request_size_;
};

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

PermissionServiceImpl::~PermissionServiceImpl() {}

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) {
  // 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.
  BrowserContext* browser_context = context_->GetBrowserContext();
  if (!browser_context)
    return;

  if (!context_->render_frame_host()) {
    std::vector<PermissionStatus> result(permissions.size());
    for (size_t i = 0; i < permissions.size(); ++i)
      result[i] = GetPermissionStatus(permissions[i]);
    std::move(callback).Run(result);
    return;
  }

  std::vector<PermissionType> types(permissions.size());
  std::set<PermissionType> duplicates_check;
  for (size_t i = 0; i < types.size(); ++i) {
    if (!PermissionDescriptorToPermissionType(permissions[i], &types[i])) {
      ReceivedBadMessage();
      return;
    }
    // Each permission should appear at most once in the message.
    bool inserted = duplicates_check.insert(types[i]).second;
    if (!inserted) {
      ReceivedBadMessage();
      return;
    }
  }

  std::unique_ptr<PendingRequest> pending_request =
      std::make_unique<PendingRequest>(types, std::move(callback));

  int pending_request_id = pending_requests_.Add(std::move(pending_request));
  int id =
      PermissionControllerImpl::FromBrowserContext(browser_context)
          ->RequestPermissions(
              types, context_->render_frame_host(), origin_.GetURL(),
              user_gesture,
              base::Bind(&PermissionServiceImpl::OnRequestPermissionsResponse,
                         weak_factory_.GetWeakPtr(), pending_request_id));

  // Check if the request still exists. It may have been removed by the
  // the response callback.
  PendingRequest* in_progress_request =
      pending_requests_.Lookup(pending_request_id);
  if (!in_progress_request)
    return;
  in_progress_request->set_id(id);
}

void PermissionServiceImpl::OnRequestPermissionsResponse(
    int pending_request_id,
    const std::vector<PermissionStatus>& 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(GetPermissionStatus(permission));
}

void PermissionServiceImpl::RevokePermission(
    PermissionDescriptorPtr permission,
    PermissionStatusCallback callback) {
  PermissionType permission_type;
  if (!PermissionDescriptorToPermissionType(permission, &permission_type)) {
    ReceivedBadMessage();
    return;
  }
  PermissionStatus status = GetPermissionStatusFromType(permission_type);

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

  ResetPermissionStatus(permission_type);

  std::move(callback).Run(GetPermissionStatusFromType(permission_type));
}

void PermissionServiceImpl::AddPermissionObserver(
    PermissionDescriptorPtr permission,
    PermissionStatus last_known_status,
    PermissionObserverPtr observer) {
  PermissionStatus current_status = GetPermissionStatus(permission);
  if (current_status != last_known_status) {
    observer->OnPermissionStatusChange(current_status);
    last_known_status = current_status;
  }

  PermissionType type;
  if (!PermissionDescriptorToPermissionType(permission, &type)) {
    ReceivedBadMessage();
    return;
  }

  context_->CreateSubscription(type, origin_, std::move(observer));
}

PermissionStatus PermissionServiceImpl::GetPermissionStatus(
    const PermissionDescriptorPtr& permission) {
  PermissionType type;
  if (!PermissionDescriptorToPermissionType(permission, &type)) {
    ReceivedBadMessage();
    return PermissionStatus::DENIED;
  }
  return GetPermissionStatusFromType(type);
}

PermissionStatus PermissionServiceImpl::GetPermissionStatusFromType(
    PermissionType type) {
  BrowserContext* browser_context = context_->GetBrowserContext();
  if (!browser_context)
    return PermissionStatus::DENIED;

  GURL requesting_origin(origin_.GetURL());
  if (context_->render_frame_host()) {
    return BrowserContext::GetPermissionController(browser_context)
        ->GetPermissionStatusForFrame(type, context_->render_frame_host(),
                                      requesting_origin);
  }

  DCHECK(context_->GetEmbeddingOrigin().is_empty());
  return BrowserContext::GetPermissionController(browser_context)
      ->GetPermissionStatus(type, requesting_origin, requesting_origin);
}

void PermissionServiceImpl::ResetPermissionStatus(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.
  GURL embedding_origin = context_->GetEmbeddingOrigin();
  PermissionControllerImpl::FromBrowserContext(browser_context)
      ->ResetPermission(
          type, requesting_origin,
          embedding_origin.is_empty() ? requesting_origin : embedding_origin);
}

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

}  // namespace content
