/*
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_EXCEPTION_STATE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_EXCEPTION_STATE_H_

#include "base/macros.h"
#include "base/notreached.h"
#include "third_party/blink/renderer/platform/bindings/exception_code.h"
#include "third_party/blink/renderer/platform/bindings/exception_context.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "v8/include/v8.h"

namespace blink {

// ExceptionState is a scope-like class and provides a way to throw an exception
// with an option to cancel it.  An exception message may be auto-generated.
class PLATFORM_EXPORT ExceptionState {
  STACK_ALLOCATED();

 public:
  // TODO(peria): Replace following enum aliases.
  using ContextType = ExceptionContext::Context;
  static constexpr ContextType kConstructionContext =
      ExceptionContext::Context::kConstructorOperationInvoke;
  static constexpr ContextType kExecutionContext =
      ExceptionContext::Context::kOperationInvoke;
  static constexpr ContextType kDeletionContext =
      ExceptionContext::Context::kNamedPropertyDelete;
  static constexpr ContextType kGetterContext =
      ExceptionContext::Context::kAttributeGet;
  static constexpr ContextType kSetterContext =
      ExceptionContext::Context::kAttributeSet;
  static constexpr ContextType kEnumerationContext =
      ExceptionContext::Context::kNamedPropertyEnumerate;
  static constexpr ContextType kQueryContext =
      ExceptionContext::Context::kNamedPropertyQuery;
  static constexpr ContextType kIndexedGetterContext =
      ExceptionContext::Context::kIndexedPropertyGet;
  static constexpr ContextType kIndexedSetterContext =
      ExceptionContext::Context::kIndexedPropertySet;
  static constexpr ContextType kIndexedDeletionContext =
      ExceptionContext::Context::kIndexedPropertyDelete;
  static constexpr ContextType kNamedGetterContext =
      ExceptionContext::Context::kNamedPropertyGet;
  static constexpr ContextType kNamedSetterContext =
      ExceptionContext::Context::kNamedPropertySet;
  static constexpr ContextType kNamedDeletionContext =
      ExceptionContext::Context::kNamedPropertyDelete;
  static constexpr ContextType kUnknownContext =
      ExceptionContext::Context::kUnknown;

  // ContextScope represents a stack of ExceptionContext in order to represent
  // nested exception contexts such like an IDL dictionary in another IDL
  // dictionary.
  class ContextScope {
    STACK_ALLOCATED();

   public:
    explicit ContextScope(const ExceptionContext& context,
                          ExceptionState& exception_state)
        : exception_state_(exception_state), context_(context) {
      exception_state_.PushContextScope(this);
    }
    ContextScope(const ContextScope&) = delete;
    ContextScope& operator=(const ContextScope&) = delete;

    ~ContextScope() { exception_state_.PopContextScope(); }

   private:
    void SetParent(const ContextScope* parent) { parent_ = parent; }
    const ContextScope* GetParent() const { return parent_; }
    const ExceptionContext& GetContext() const { return context_; }

    ExceptionState& exception_state_;
    const ContextScope* parent_ = nullptr;
    const ExceptionContext context_;

    friend class ExceptionState;
  };

  // A function pointer type that creates a DOMException.
  using CreateDOMExceptionFunction =
      v8::Local<v8::Value> (*)(v8::Isolate*,
                               DOMExceptionCode,
                               const String& sanitized_message,
                               const String& unsanitized_message);

  // Sets the function to create a DOMException. Must be called only once.
  static void SetCreateDOMExceptionFunction(CreateDOMExceptionFunction);

  ExceptionState(v8::Isolate* isolate, const ExceptionContext& context)
      : main_context_(context), isolate_(isolate) {}

  ExceptionState(v8::Isolate* isolate, ExceptionContext&& context)
      : main_context_(std::move(context)), isolate_(isolate) {}

  ExceptionState(v8::Isolate* isolate,
                 ContextType context_type,
                 const char* interface_name,
                 const char* property_name)
      : ExceptionState(
            isolate,
            ExceptionContext(context_type, interface_name, property_name)) {}

  ExceptionState(v8::Isolate* isolate,
                 ContextType context_type,
                 const char* interface_name)
      : ExceptionState(isolate,
                       ExceptionContext(context_type, interface_name)) {}

  ~ExceptionState() {
    if (!exception_.IsEmpty()) {
      V8ThrowException::ThrowException(isolate_, exception_.NewLocal(isolate_));
    }
  }

  // Throws an appropriate exception due to the given exception code. The
  // exception will be either of ECMAScript Error object or DOMException.
  void ThrowException(ExceptionCode, const String& message);

  // Throws a DOMException due to the given exception code.
  virtual void ThrowDOMException(DOMExceptionCode, const String& message);

  // Throws a DOMException with SECURITY_ERR.
  virtual void ThrowSecurityError(const String& sanitized_message,
                                  const String& unsanitized_message = String());

  // Throws an ECMAScript Error object.
  virtual void ThrowRangeError(const String& message);
  virtual void ThrowTypeError(const String& message);

  // Throws WebAssembly Error object.
  virtual void ThrowWasmCompileError(const String& message);

  // These overloads reduce the binary code size because the call sites do not
  // need the conversion by String::String(const char*) that is inlined at each
  // call site. As there are many call sites that pass in a const char*, this
  // size optimization is effective (32kb reduction as of June 2018).
  // See also https://crbug.com/849743
  void ThrowDOMException(DOMExceptionCode, const char* message);
  void ThrowSecurityError(const char* sanitized_message,
                          const char* unsanitized_message = nullptr);
  void ThrowRangeError(const char* message);
  void ThrowTypeError(const char* message);
  void ThrowWasmCompileError(const char* message);

  // Rethrows a v8::Value as an exception.
  virtual void RethrowV8Exception(v8::Local<v8::Value>);

  // Returns true if there is a pending exception.
  //
  // Note that this function returns true even when |exception_| is empty, and
  // that V8ThrowDOMException::CreateOrEmpty may return an empty handle.
  bool HadException() const { return code_; }

  void ClearException();

  ExceptionCode Code() const { return code_; }

  template <typename T>
  T CodeAs() const {
    return static_cast<T>(Code());
  }

  const String& Message() const { return message_; }

  v8::Local<v8::Value> GetException() {
    DCHECK(!exception_.IsEmpty());
    return exception_.NewLocal(isolate_);
  }

  // Returns the context of what Web API is currently being executed.
  const ExceptionContext& GetContext() const {
    DCHECK(!context_stack_top_);
    return main_context_;
  }

  // Deprecated APIs to get information about where this ExceptionState has
  // been created.
  ContextType Context() const { return GetContext().GetContext(); }
  const char* PropertyName() const { return GetContext().GetPropertyName(); }
  const char* InterfaceName() const { return GetContext().GetClassName(); }

 protected:
  void SetException(ExceptionCode, const String&, v8::Local<v8::Value>);

 private:
  void PushContextScope(ContextScope* scope);
  void PopContextScope();

  String AddExceptionContext(const String&) const;

  // Since DOMException is defined in core/, we need a dependency injection in
  // order to create a DOMException in platform/.
  static CreateDOMExceptionFunction s_create_dom_exception_func_;

  // The main context represents what Web API is currently being executed.
  // This is embedded without using ContextScope in order to avoid an overhead
  // of ContextScope.
  ExceptionContext main_context_;

  // `context_stack_top_` points to the top of the context stack which
  // represents additional (nested) contexts such as an IDL dictionary in a
  // member of another IDL dictionary.  nullptr means no additional context.
  const ContextScope* context_stack_top_ = nullptr;

  v8::Isolate* isolate_;
  ExceptionCode code_ = 0;
  String message_;
  // The exception is empty when it was thrown through
  // DummyExceptionStateForTesting.
  TraceWrapperV8Reference<v8::Value> exception_;

  friend class ContextScope;
  DISALLOW_COPY_AND_ASSIGN(ExceptionState);
};

// NonThrowableExceptionState never allow call sites to throw an exception.
// Should be used if an exception must not be thrown.
class PLATFORM_EXPORT NonThrowableExceptionState final : public ExceptionState {
 public:
  NonThrowableExceptionState();
  NonThrowableExceptionState(const char*, int);

  void ThrowDOMException(DOMExceptionCode, const String& message) override;
  void ThrowTypeError(const String& message) override;
  void ThrowSecurityError(const String& sanitized_message,
                          const String& unsanitized_message) override;
  void ThrowRangeError(const String& message) override;
  void ThrowWasmCompileError(const String& message) override;
  void RethrowV8Exception(v8::Local<v8::Value>) override;
  ExceptionState& ReturnThis() { return *this; }

 private:
  const char* file_;
  const int line_;
};

// Syntax sugar for NonThrowableExceptionState.
// This can be used as a default value of an ExceptionState parameter like this:
//
//     Node* removeChild(Node*, ExceptionState& = ASSERT_NO_EXCEPTION);
#if DCHECK_IS_ON()
#define ASSERT_NO_EXCEPTION \
  (::blink::NonThrowableExceptionState(__FILE__, __LINE__).ReturnThis())
#else
#define ASSERT_NO_EXCEPTION \
  (::blink::DummyExceptionStateForTesting().ReturnThis())
#endif

// DummyExceptionStateForTesting ignores all thrown exceptions. You should not
// use DummyExceptionStateForTesting in production code, where you need to
// handle all exceptions properly. If you really need to ignore exceptions in
// production code for some special reason, explicitly call clearException().
class PLATFORM_EXPORT DummyExceptionStateForTesting final
    : public ExceptionState {
 public:
  DummyExceptionStateForTesting()
      : ExceptionState(nullptr,
                       ExceptionState::kUnknownContext,
                       nullptr,
                       nullptr) {}
  ~DummyExceptionStateForTesting() {
    // Prevent the base class throw an exception.
    if (HadException()) {
      ClearException();
    }
  }
  void ThrowDOMException(DOMExceptionCode, const String& message) override;
  void ThrowTypeError(const String& message) override;
  void ThrowSecurityError(const String& sanitized_message,
                          const String& unsanitized_message) override;
  void ThrowRangeError(const String& message) override;
  void ThrowWasmCompileError(const String& message) override;
  void RethrowV8Exception(v8::Local<v8::Value>) override;
  ExceptionState& ReturnThis() { return *this; }
};

// Syntax sugar for DummyExceptionStateForTesting.
// This can be used as a default value of an ExceptionState parameter like this:
//
//     Node* removeChild(Node*, ExceptionState& = IGNORE_EXCEPTION_FOR_TESTING);
#define IGNORE_EXCEPTION_FOR_TESTING \
  (::blink::DummyExceptionStateForTesting().ReturnThis())

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_EXCEPTION_STATE_H_
