// 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 <utility>

#include "base/bind.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/permission_manager.h"
#include "content/public/browser/permission_type.h"

namespace content {

namespace {

PermissionType PermissionNameToPermissionType(PermissionName name) {
  switch(name) {
    case PermissionName::GEOLOCATION:
      return PermissionType::GEOLOCATION;
    case PermissionName::NOTIFICATIONS:
      return PermissionType::NOTIFICATIONS;
    case PermissionName::PUSH_NOTIFICATIONS:
      return PermissionType::PUSH_MESSAGING;
    case PermissionName::MIDI:
      return PermissionType::MIDI;
    case PermissionName::MIDI_SYSEX:
      return PermissionType::MIDI_SYSEX;
    case PermissionName::PROTECTED_MEDIA_IDENTIFIER:
      return PermissionType::PROTECTED_MEDIA_IDENTIFIER;
    case PermissionName::DURABLE_STORAGE:
      return PermissionType::DURABLE_STORAGE;
    case PermissionName::AUDIO_CAPTURE:
      return PermissionType::AUDIO_CAPTURE;
    case PermissionName::VIDEO_CAPTURE:
      return PermissionType::VIDEO_CAPTURE;
  }

  NOTREACHED();
  return PermissionType::NUM;
}

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

} // anonymous namespace

PermissionServiceImpl::PendingRequest::PendingRequest(
    const PermissionsStatusCallback& callback,
    int request_count)
    : callback(callback),
      request_count(request_count) {
}

PermissionServiceImpl::PendingRequest::~PendingRequest() {
  if (callback.is_null())
    return;

  mojo::Array<PermissionStatus> result =
      mojo::Array<PermissionStatus>::New(request_count);
  for (int i = 0; i < request_count; ++i)
    result[i] = PermissionStatus::DENIED;
  callback.Run(std::move(result));
}

PermissionServiceImpl::PendingSubscription::PendingSubscription(
    PermissionType permission,
    const GURL& origin,
    const PermissionStatusCallback& callback)
    : id(-1),
      permission(permission),
      origin(origin),
      callback(callback) {
}

PermissionServiceImpl::PendingSubscription::~PendingSubscription() {
  if (!callback.is_null())
    callback.Run(PermissionStatus::ASK);
}

PermissionServiceImpl::PermissionServiceImpl(
    PermissionServiceContext* context,
    mojo::InterfaceRequest<PermissionService> request)
    : context_(context),
      binding_(this, std::move(request)),
      weak_factory_(this) {
  binding_.set_connection_error_handler(
      base::Bind(&PermissionServiceImpl::OnConnectionError,
                 base::Unretained(this)));
}

PermissionServiceImpl::~PermissionServiceImpl() {
  DCHECK(pending_requests_.IsEmpty());
}

void PermissionServiceImpl::OnConnectionError() {
  context_->ServiceHadConnectionError(this);
  // After that call, |this| will be deleted.
}

void PermissionServiceImpl::RequestPermission(
    PermissionName permission,
    const mojo::String& origin,
    bool user_gesture,
    const PermissionStatusCallback& 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.
  BrowserContext* browser_context = context_->GetBrowserContext();
  DCHECK(browser_context);
  if (!context_->render_frame_host() ||
      !browser_context->GetPermissionManager()) {
    callback.Run(GetPermissionStatusFromName(permission, GURL(origin.get())));
    return;
  }

  int pending_request_id = pending_requests_.Add(new PendingRequest(
      base::Bind(&PermissionRequestResponseCallbackWrapper, callback), 1));
  int id = browser_context->GetPermissionManager()->RequestPermission(
      PermissionNameToPermissionType(permission),
      context_->render_frame_host(),
      GURL(origin.get()),
      user_gesture, // TODO(mlamouri): should be removed (crbug.com/423770)
      base::Bind(&PermissionServiceImpl::OnRequestPermissionResponse,
                 weak_factory_.GetWeakPtr(),
                 pending_request_id));

  // Check if the request still exists. It might have been removed by the
  // callback if it was run synchronously.
  PendingRequest* pending_request = pending_requests_.Lookup(
      pending_request_id);
  if (!pending_request)
      return;
  pending_request->id = id;
}

void PermissionServiceImpl::OnRequestPermissionResponse(
    int pending_request_id,
    PermissionStatus status) {
  OnRequestPermissionsResponse(pending_request_id,
      std::vector<PermissionStatus>(1, status));
}

void PermissionServiceImpl::RequestPermissions(
    mojo::Array<PermissionName> permissions,
    const mojo::String& origin,
    bool user_gesture,
    const PermissionsStatusCallback& callback) {
  if (permissions.is_null()) {
    callback.Run(mojo::Array<PermissionStatus>());
    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.
  BrowserContext* browser_context = context_->GetBrowserContext();
  DCHECK(browser_context);
  if (!context_->render_frame_host() ||
      !browser_context->GetPermissionManager()) {
    mojo::Array<PermissionStatus> result(permissions.size());
    for (size_t i = 0; i < permissions.size(); ++i) {
      result[i] =
          GetPermissionStatusFromName(permissions[i], GURL(origin.get()));
    }
    callback.Run(std::move(result));
    return;
  }

  std::vector<PermissionType> types(permissions.size());
  for (size_t i = 0; i < types.size(); ++i)
    types[i] = PermissionNameToPermissionType(permissions[i]);

  int pending_request_id = pending_requests_.Add(
      new PendingRequest(callback, permissions.size()));
  int id = browser_context->GetPermissionManager()->RequestPermissions(
      types,
      context_->render_frame_host(),
      GURL(origin.get()),
      user_gesture, // TODO(mlamouri): should be removed (crbug.com/423770)
      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* pending_request = pending_requests_.Lookup(
      pending_request_id);
  if (!pending_request)
      return;
  pending_request->id = id;
}

void PermissionServiceImpl::OnRequestPermissionsResponse(
    int pending_request_id,
    const std::vector<PermissionStatus>& result) {
  PendingRequest* request = pending_requests_.Lookup(pending_request_id);
  PermissionsStatusCallback callback(request->callback);
  request->callback.reset();
  pending_requests_.Remove(pending_request_id);
  callback.Run(mojo::Array<PermissionStatus>::From(result));
}

void PermissionServiceImpl::CancelPendingOperations() {
  DCHECK(context_->GetBrowserContext());

  PermissionManager* permission_manager =
      context_->GetBrowserContext()->GetPermissionManager();
  if (!permission_manager)
    return;

  // Cancel pending requests.
  for (RequestsMap::Iterator<PendingRequest> it(&pending_requests_);
       !it.IsAtEnd(); it.Advance()) {
    permission_manager->CancelPermissionRequest(
        it.GetCurrentValue()->id);
  }
  pending_requests_.Clear();

  // Cancel pending subscriptions.
  for (SubscriptionsMap::Iterator<PendingSubscription>
          it(&pending_subscriptions_); !it.IsAtEnd(); it.Advance()) {
    it.GetCurrentValue()->callback.Run(GetPermissionStatusFromType(
        it.GetCurrentValue()->permission, it.GetCurrentValue()->origin));
    it.GetCurrentValue()->callback.reset();
    permission_manager->UnsubscribePermissionStatusChange(
        it.GetCurrentValue()->id);
  }
  pending_subscriptions_.Clear();
}

void PermissionServiceImpl::HasPermission(
    PermissionName permission,
    const mojo::String& origin,
    const PermissionStatusCallback& callback) {
  callback.Run(GetPermissionStatusFromName(permission, GURL(origin.get())));
}

void PermissionServiceImpl::RevokePermission(
    PermissionName permission,
    const mojo::String& origin,
    const PermissionStatusCallback& callback) {
  GURL origin_url(origin.get());
  PermissionType permission_type = PermissionNameToPermissionType(permission);
  PermissionStatus status = GetPermissionStatusFromType(permission_type,
                                                        origin_url);

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

  ResetPermissionStatus(permission_type, origin_url);

  callback.Run(GetPermissionStatusFromType(permission_type, origin_url));
}

void PermissionServiceImpl::GetNextPermissionChange(
    PermissionName permission,
    const mojo::String& mojo_origin,
    PermissionStatus last_known_status,
    const PermissionStatusCallback& callback) {
  GURL origin(mojo_origin.get());
  PermissionStatus current_status =
      GetPermissionStatusFromName(permission, origin);
  if (current_status != last_known_status) {
    callback.Run(current_status);
    return;
  }

  BrowserContext* browser_context = context_->GetBrowserContext();
  DCHECK(browser_context);
  if (!browser_context->GetPermissionManager()) {
    callback.Run(current_status);
    return;
  }

  PermissionType permission_type = PermissionNameToPermissionType(permission);

  // We need to pass the id of PendingSubscription in pending_subscriptions_
  // to the callback but SubscribePermissionStatusChange() will also return an
  // id which is different.
  PendingSubscription* subscription =
      new PendingSubscription(permission_type, origin, callback);
  int pending_subscription_id = pending_subscriptions_.Add(subscription);

  GURL embedding_origin = context_->GetEmbeddingOrigin();
  subscription->id =
      browser_context->GetPermissionManager()->SubscribePermissionStatusChange(
          permission_type,
          origin,
          // If the embedding_origin is empty, we,ll use the |origin| instead.
          embedding_origin.is_empty() ? origin : embedding_origin,
          base::Bind(&PermissionServiceImpl::OnPermissionStatusChanged,
                     weak_factory_.GetWeakPtr(),
                     pending_subscription_id));
}

PermissionStatus PermissionServiceImpl::GetPermissionStatusFromName(
    PermissionName permission, const GURL& origin) {
  return GetPermissionStatusFromType(PermissionNameToPermissionType(permission),
                                     origin);
}

PermissionStatus PermissionServiceImpl::GetPermissionStatusFromType(
    PermissionType type, const GURL& origin) {
  BrowserContext* browser_context = context_->GetBrowserContext();
  DCHECK(browser_context);
  if (!browser_context->GetPermissionManager())
    return PermissionStatus::DENIED;

  // If the embedding_origin is empty we'll use |origin| instead.
  GURL embedding_origin = context_->GetEmbeddingOrigin();
  return browser_context->GetPermissionManager()->GetPermissionStatus(
      type, origin, embedding_origin.is_empty() ? origin : embedding_origin);
}

void PermissionServiceImpl::ResetPermissionStatus(PermissionType type,
                                                  const GURL& origin) {
  BrowserContext* browser_context = context_->GetBrowserContext();
  DCHECK(browser_context);
  if (!browser_context->GetPermissionManager())
    return;

  // If the embedding_origin is empty we'll use |origin| instead.
  GURL embedding_origin = context_->GetEmbeddingOrigin();
  browser_context->GetPermissionManager()->ResetPermission(
      type, origin, embedding_origin.is_empty() ? origin : embedding_origin);
}

void PermissionServiceImpl::OnPermissionStatusChanged(
    int pending_subscription_id,
    PermissionStatus status) {
  PendingSubscription* subscription =
      pending_subscriptions_.Lookup(pending_subscription_id);

  BrowserContext* browser_context = context_->GetBrowserContext();
  DCHECK(browser_context);
  if (browser_context->GetPermissionManager()) {
    browser_context->GetPermissionManager()->UnsubscribePermissionStatusChange(
        subscription->id);
  }

  PermissionStatusCallback callback = subscription->callback;

  subscription->callback.reset();
  pending_subscriptions_.Remove(pending_subscription_id);

  callback.Run(status);
}

}  // namespace content
