// Copyright 2019 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 "third_party/blink/renderer/modules/wake_lock/wake_lock_test_utils.h"

#include <utility>

#include "base/check.h"
#include "base/macros.h"
#include "base/notreached.h"
#include "base/run_loop.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_wake_lock_sentinel.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/modules/wake_lock/wake_lock_type.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"

namespace blink {

using mojom::blink::PermissionDescriptorPtr;
using mojom::blink::PermissionStatus;

namespace {

void RunWithStack(base::RunLoop* run_loop) {
  HeapPointersOnStackScope scan_stack(ThreadState::Current());
  run_loop->Run();
}

// Helper class for WaitForPromise{Fulfillment,Rejection}(). It provides a
// function that invokes |callback| when a ScriptPromise is resolved.
class ClosureRunnerFunction final : public ScriptFunction {
 public:
  static v8::Local<v8::Function> CreateFunction(
      ScriptState* script_state,
      base::RepeatingClosure callback) {
    auto* function = MakeGarbageCollected<ClosureRunnerFunction>(
        script_state, std::move(callback));
    return function->BindToV8Function();
  }

  ClosureRunnerFunction(ScriptState* script_state,
                        base::RepeatingClosure callback)
      : ScriptFunction(script_state), callback_(std::move(callback)) {}

 private:
  ScriptValue Call(ScriptValue) override {
    if (callback_)
      std::move(callback_).Run();
    return ScriptValue();
  }

  base::RepeatingClosure callback_;
};

WakeLockType ToBlinkWakeLockType(device::mojom::blink::WakeLockType type) {
  switch (type) {
    case device::mojom::blink::WakeLockType::kPreventDisplaySleep:
      return WakeLockType::kScreen;
    case device::mojom::blink::WakeLockType::kPreventAppSuspension:
      return WakeLockType::kSystem;
    default:
      NOTREACHED();
      return WakeLockType::kMaxValue;
  }
}

}  // namespace

// MockWakeLock

MockWakeLock::MockWakeLock() = default;
MockWakeLock::~MockWakeLock() = default;

void MockWakeLock::Bind(
    mojo::PendingReceiver<device::mojom::blink::WakeLock> receiver) {
  DCHECK(!receiver_.is_bound());
  receiver_.Bind(std::move(receiver));
  receiver_.set_disconnect_handler(
      WTF::Bind(&MockWakeLock::OnConnectionError, WTF::Unretained(this)));
}

void MockWakeLock::Unbind() {
  OnConnectionError();
}

void MockWakeLock::WaitForRequest() {
  DCHECK(!request_wake_lock_callback_);
  base::RunLoop run_loop;
  request_wake_lock_callback_ = run_loop.QuitClosure();
  RunWithStack(&run_loop);
}

void MockWakeLock::WaitForCancelation() {
  DCHECK(!cancel_wake_lock_callback_);
  if (!receiver_.is_bound()) {
    // If OnConnectionError() has been called, bail out early to avoid waiting
    // forever.
    DCHECK(!is_acquired_);
    return;
  }
  base::RunLoop run_loop;
  cancel_wake_lock_callback_ = run_loop.QuitClosure();
  RunWithStack(&run_loop);
}

void MockWakeLock::OnConnectionError() {
  receiver_.reset();
  CancelWakeLock();
}

void MockWakeLock::RequestWakeLock() {
  is_acquired_ = true;
  if (request_wake_lock_callback_)
    std::move(request_wake_lock_callback_).Run();
}

void MockWakeLock::CancelWakeLock() {
  is_acquired_ = false;
  if (cancel_wake_lock_callback_)
    std::move(cancel_wake_lock_callback_).Run();
}

void MockWakeLock::AddClient(
    mojo::PendingReceiver<device::mojom::blink::WakeLock>) {}
void MockWakeLock::ChangeType(device::mojom::blink::WakeLockType,
                              ChangeTypeCallback) {}
void MockWakeLock::HasWakeLockForTests(HasWakeLockForTestsCallback) {}

// MockWakeLockService

MockWakeLockService::MockWakeLockService() = default;
MockWakeLockService::~MockWakeLockService() = default;

void MockWakeLockService::BindRequest(mojo::ScopedMessagePipeHandle handle) {
  receivers_.Add(this, mojo::PendingReceiver<mojom::blink::WakeLockService>(
                           std::move(handle)));
}

MockWakeLock& MockWakeLockService::get_wake_lock(WakeLockType type) {
  size_t pos = static_cast<size_t>(type);
  return mock_wake_lock_[pos];
}

void MockWakeLockService::GetWakeLock(
    device::mojom::blink::WakeLockType type,
    device::mojom::blink::WakeLockReason reason,
    const String& description,
    mojo::PendingReceiver<device::mojom::blink::WakeLock> receiver) {
  size_t pos = static_cast<size_t>(ToBlinkWakeLockType(type));
  mock_wake_lock_[pos].Bind(std::move(receiver));
}

// MockPermissionService

MockPermissionService::MockPermissionService() = default;
MockPermissionService::~MockPermissionService() = default;

void MockPermissionService::BindRequest(mojo::ScopedMessagePipeHandle handle) {
  DCHECK(!receiver_.is_bound());
  receiver_.Bind(mojo::PendingReceiver<mojom::blink::PermissionService>(
      std::move(handle)));
  receiver_.set_disconnect_handler(WTF::Bind(
      &MockPermissionService::OnConnectionError, WTF::Unretained(this)));
}

void MockPermissionService::SetPermissionResponse(WakeLockType type,
                                                  PermissionStatus status) {
  DCHECK(status == PermissionStatus::GRANTED ||
         status == PermissionStatus::DENIED);
  permission_responses_[static_cast<size_t>(type)] = status;
}

void MockPermissionService::OnConnectionError() {
  ignore_result(receiver_.Unbind());
}

bool MockPermissionService::GetWakeLockTypeFromDescriptor(
    const PermissionDescriptorPtr& descriptor,
    WakeLockType* output) {
  if (descriptor->name == mojom::blink::PermissionName::SCREEN_WAKE_LOCK) {
    *output = WakeLockType::kScreen;
    return true;
  }
  if (descriptor->name == mojom::blink::PermissionName::SYSTEM_WAKE_LOCK) {
    *output = WakeLockType::kSystem;
    return true;
  }
  return false;
}

void MockPermissionService::WaitForPermissionRequest(WakeLockType type) {
  size_t pos = static_cast<size_t>(type);
  DCHECK(!request_permission_callbacks_[pos]);
  base::RunLoop run_loop;
  request_permission_callbacks_[pos] = run_loop.QuitClosure();
  RunWithStack(&run_loop);
}

void MockPermissionService::HasPermission(PermissionDescriptorPtr permission,
                                          HasPermissionCallback callback) {
  WakeLockType type;
  if (!GetWakeLockTypeFromDescriptor(permission, &type)) {
    std::move(callback).Run(PermissionStatus::DENIED);
    return;
  }
  size_t pos = static_cast<size_t>(type);
  DCHECK(permission_responses_[pos].has_value());
  std::move(callback).Run(
      permission_responses_[pos].value_or(PermissionStatus::DENIED));
}

void MockPermissionService::RequestPermission(
    PermissionDescriptorPtr permission,
    bool user_gesture,
    RequestPermissionCallback callback) {
  WakeLockType type;
  if (!GetWakeLockTypeFromDescriptor(permission, &type)) {
    std::move(callback).Run(PermissionStatus::DENIED);
    return;
  }

  size_t pos = static_cast<size_t>(type);
  DCHECK(permission_responses_[pos].has_value());
  if (request_permission_callbacks_[pos])
    std::move(request_permission_callbacks_[pos]).Run();
  std::move(callback).Run(
      permission_responses_[pos].value_or(PermissionStatus::DENIED));
}

void MockPermissionService::RequestPermissions(
    Vector<PermissionDescriptorPtr> permissions,
    bool user_gesture,
    mojom::blink::PermissionService::RequestPermissionsCallback) {
  NOTREACHED();
}

void MockPermissionService::RevokePermission(PermissionDescriptorPtr permission,
                                             RevokePermissionCallback) {
  NOTREACHED();
}

void MockPermissionService::AddPermissionObserver(
    PermissionDescriptorPtr permission,
    PermissionStatus last_known_status,
    mojo::PendingRemote<mojom::blink::PermissionObserver>) {
  NOTREACHED();
}

// WakeLockTestingContext

WakeLockTestingContext::WakeLockTestingContext(
    MockWakeLockService* mock_wake_lock_service) {
  DomWindow()->GetBrowserInterfaceBroker().SetBinderForTesting(
      mojom::blink::WakeLockService::Name_,
      WTF::BindRepeating(&MockWakeLockService::BindRequest,
                         WTF::Unretained(mock_wake_lock_service)));
  DomWindow()->GetBrowserInterfaceBroker().SetBinderForTesting(
      mojom::blink::PermissionService::Name_,
      WTF::BindRepeating(&MockPermissionService::BindRequest,
                         WTF::Unretained(&permission_service_)));
}

WakeLockTestingContext::~WakeLockTestingContext() {
  // Remove the testing binder to avoid crashes between tests caused by
  // our mocks rebinding an already-bound Binding.
  // See https://crbug.com/1010116 for more information.
  DomWindow()->GetBrowserInterfaceBroker().SetBinderForTesting(
      mojom::blink::WakeLockService::Name_, {});
  DomWindow()->GetBrowserInterfaceBroker().SetBinderForTesting(
      mojom::blink::PermissionService::Name_, {});
}

LocalDOMWindow* WakeLockTestingContext::DomWindow() {
  return Frame()->DomWindow();
}

LocalFrame* WakeLockTestingContext::Frame() {
  return &testing_scope_.GetFrame();
}

ScriptState* WakeLockTestingContext::GetScriptState() {
  return testing_scope_.GetScriptState();
}

MockPermissionService& WakeLockTestingContext::GetPermissionService() {
  return permission_service_;
}

ScriptPromise WakeLockTestingContext::WaitForPromiseFulfillment(
    ScriptPromise promise) {
  base::RunLoop run_loop;
  ScriptPromise return_promise =
      promise.Then(ClosureRunnerFunction::CreateFunction(
          GetScriptState(), run_loop.QuitClosure()));
  // Execute pending microtasks, otherwise it can take a few seconds for the
  // promise to resolve.
  v8::MicrotasksScope::PerformCheckpoint(GetScriptState()->GetIsolate());
  RunWithStack(&run_loop);
  return return_promise;
}

// Synchronously waits for |promise| to be rejected.
void WakeLockTestingContext::WaitForPromiseRejection(ScriptPromise promise) {
  base::RunLoop run_loop;
  promise.Then(v8::Local<v8::Function>(),
               ClosureRunnerFunction::CreateFunction(GetScriptState(),
                                                     run_loop.QuitClosure()));
  // Execute pending microtasks, otherwise it can take a few seconds for the
  // promise to resolve.
  v8::MicrotasksScope::PerformCheckpoint(GetScriptState()->GetIsolate());
  RunWithStack(&run_loop);
}

// ScriptPromiseUtils

// static
v8::Promise::PromiseState ScriptPromiseUtils::GetPromiseState(
    const ScriptPromise& promise) {
  return promise.V8Promise()->State();
}

// static
DOMException* ScriptPromiseUtils::GetPromiseResolutionAsDOMException(
    const ScriptPromise& promise) {
  return V8DOMException::ToImplWithTypeCheck(promise.GetIsolate(),
                                             promise.V8Promise()->Result());
}

// static
WakeLockSentinel* ScriptPromiseUtils::GetPromiseResolutionAsWakeLockSentinel(
    const ScriptPromise& promise) {
  return V8WakeLockSentinel::ToImplWithTypeCheck(promise.GetIsolate(),
                                                 promise.V8Promise()->Result());
}

}  // namespace blink
