// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

// MSVC++ requires this to be set before any other includes to get M_PI.
// Otherwise there will be compile errors in wtf/MathExtras.h.
#define _USE_MATH_DEFINES

#include <map>
#include <string>

#include "base/command_line.h"
#include "base/compiler_specific.h"

// Enable deprecation warnings for MSVC and Clang. See http://crbug.com/585142.
#if defined(OS_WIN)
#if defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wdeprecated-declarations"
#else
#pragma warning(push)
#pragma warning(default : 4996)
#endif
#endif

#include "libcef/renderer/v8_impl.h"

#include "libcef/common/cef_switches.h"
#include "libcef/common/content_client.h"
#include "libcef/common/task_runner_impl.h"
#include "libcef/common/tracker.h"
#include "libcef/renderer/blink_glue.h"
#include "libcef/renderer/browser_impl.h"
#include "libcef/renderer/render_frame_util.h"
#include "libcef/renderer/thread_util.h"

#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_local.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/public/web/web_frame.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "url/gurl.h"

namespace {

static const char kCefTrackObject[] = "Cef::TrackObject";

void MessageListenerCallbackImpl(v8::Handle<v8::Message> message,
                                 v8::Handle<v8::Value> data);

// The following *Private functions are convenience wrappers for methods on
// v8::Object with the corresponding names.
// Based on extensions/renderer/object_backed_native_handler.cc.

void SetPrivate(v8::Local<v8::Context> context,
                v8::Local<v8::Object> obj,
                const char* key,
                v8::Local<v8::Value> value) {
  v8::Isolate* isolate = context->GetIsolate();
  obj->SetPrivate(context,
                  v8::Private::ForApi(
                      isolate, v8::String::NewFromUtf8(
                                   isolate, key, v8::NewStringType::kNormal)
                                   .ToLocalChecked()),
                  value)
      .FromJust();
}

bool GetPrivate(v8::Local<v8::Context> context,
                v8::Local<v8::Object> obj,
                const char* key,
                v8::Local<v8::Value>* result) {
  v8::Isolate* isolate = context->GetIsolate();
  return obj
      ->GetPrivate(context,
                   v8::Private::ForApi(
                       isolate, v8::String::NewFromUtf8(
                                    isolate, key, v8::NewStringType::kNormal)
                                    .ToLocalChecked()))
      .ToLocal(result);
}

// Manages memory and state information associated with a single Isolate.
class CefV8IsolateManager {
 public:
  CefV8IsolateManager()
      : isolate_(v8::Isolate::GetCurrent()),
        task_runner_(CefContentRendererClient::Get()->GetCurrentTaskRunner()),
        message_listener_registered_(false),
        worker_id_(0) {
    DCHECK(isolate_);
    DCHECK(task_runner_.get());
  }
  ~CefV8IsolateManager() {
    DCHECK_EQ(isolate_, v8::Isolate::GetCurrent());
    DCHECK(context_map_.empty());
  }

  scoped_refptr<CefV8ContextState> GetContextState(
      v8::Local<v8::Context> context) {
    DCHECK_EQ(isolate_, v8::Isolate::GetCurrent());
    DCHECK(context.IsEmpty() || isolate_ == context->GetIsolate());

    if (context.IsEmpty()) {
      if (isolate_->InContext())
        context = isolate_->GetCurrentContext();
      else
        return scoped_refptr<CefV8ContextState>();
    }

    int hash = context->Global()->GetIdentityHash();
    ContextMap::const_iterator it = context_map_.find(hash);
    if (it != context_map_.end())
      return it->second;

    scoped_refptr<CefV8ContextState> state = new CefV8ContextState();
    context_map_.insert(std::make_pair(hash, state));

    return state;
  }

  void ReleaseContext(v8::Local<v8::Context> context) {
    DCHECK_EQ(isolate_, v8::Isolate::GetCurrent());
    DCHECK_EQ(isolate_, context->GetIsolate());

    int hash = context->Global()->GetIdentityHash();
    ContextMap::iterator it = context_map_.find(hash);
    if (it != context_map_.end()) {
      it->second->Detach();
      context_map_.erase(it);
    }
  }

  void AddGlobalTrackObject(CefTrackNode* object) {
    DCHECK_EQ(isolate_, v8::Isolate::GetCurrent());
    global_manager_.Add(object);
  }

  void DeleteGlobalTrackObject(CefTrackNode* object) {
    DCHECK_EQ(isolate_, v8::Isolate::GetCurrent());
    global_manager_.Delete(object);
  }

  void SetUncaughtExceptionStackSize(int stack_size) {
    if (stack_size <= 0)
      return;

    if (!message_listener_registered_) {
      isolate_->AddMessageListener(&MessageListenerCallbackImpl);
      message_listener_registered_ = true;
    }

    isolate_->SetCaptureStackTraceForUncaughtExceptions(
        true, stack_size, v8::StackTrace::kDetailed);
  }

  void SetWorkerAttributes(int worker_id, const GURL& worker_url) {
    worker_id_ = worker_id;
    worker_url_ = worker_url;
  }

  v8::Isolate* isolate() const { return isolate_; }
  scoped_refptr<base::SingleThreadTaskRunner> task_runner() const {
    return task_runner_;
  }

  int worker_id() const { return worker_id_; }

  const GURL& worker_url() const { return worker_url_; }

 private:
  v8::Isolate* isolate_;
  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;

  typedef std::map<int, scoped_refptr<CefV8ContextState>> ContextMap;
  ContextMap context_map_;

  // Used for globally tracked objects that are not associated with a particular
  // context.
  CefTrackManager global_manager_;

  // True if the message listener has been registered.
  bool message_listener_registered_;

  // Attributes associated with WebWorker threads.
  int worker_id_;
  GURL worker_url_;
};

// Chromium uses the default Isolate for the main render process thread and a
// new Isolate for each WebWorker thread. Continue this pattern by tracking
// Isolate information on a per-thread basis. This implementation will need to
// be re-worked (perhaps using a map keyed on v8::Isolate::GetCurrent()) if
// in the future Chromium begins using the same Isolate across multiple threads.
class CefV8StateManager {
 public:
  CefV8StateManager() {}

  void CreateIsolateManager() {
    DCHECK(!current_tls_.Get());
    current_tls_.Set(new CefV8IsolateManager());
  }

  void DestroyIsolateManager() {
    DCHECK(current_tls_.Get());
    delete current_tls_.Get();
    current_tls_.Set(nullptr);
  }

  CefV8IsolateManager* GetIsolateManager() {
    CefV8IsolateManager* manager = current_tls_.Get();
    DCHECK(manager);
    return manager;
  }

 private:
  base::ThreadLocalPointer<CefV8IsolateManager> current_tls_;
};

base::LazyInstance<CefV8StateManager>::Leaky g_v8_state =
    LAZY_INSTANCE_INITIALIZER;

CefV8IsolateManager* GetIsolateManager() {
  return g_v8_state.Pointer()->GetIsolateManager();
}

class V8TrackObject : public CefTrackNode {
 public:
  explicit V8TrackObject(v8::Isolate* isolate)
      : isolate_(isolate), external_memory_(0) {
    DCHECK(isolate_);
    isolate_->AdjustAmountOfExternalAllocatedMemory(
        static_cast<int>(sizeof(V8TrackObject)));
  }
  ~V8TrackObject() {
    isolate_->AdjustAmountOfExternalAllocatedMemory(
        -static_cast<int>(sizeof(V8TrackObject)) - external_memory_);
  }

  inline int GetExternallyAllocatedMemory() { return external_memory_; }

  int AdjustExternallyAllocatedMemory(int change_in_bytes) {
    int new_value = external_memory_ + change_in_bytes;
    if (new_value < 0) {
      NOTREACHED() << "External memory usage cannot be less than 0 bytes";
      change_in_bytes = -(external_memory_);
      new_value = 0;
    }

    if (change_in_bytes != 0)
      isolate_->AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
    external_memory_ = new_value;

    return new_value;
  }

  inline void SetAccessor(CefRefPtr<CefV8Accessor> accessor) {
    accessor_ = accessor;
  }

  inline CefRefPtr<CefV8Accessor> GetAccessor() { return accessor_; }

  inline void SetInterceptor(CefRefPtr<CefV8Interceptor> interceptor) {
    interceptor_ = interceptor;
  }

  inline CefRefPtr<CefV8Interceptor> GetInterceptor() { return interceptor_; }

  inline void SetHandler(CefRefPtr<CefV8Handler> handler) {
    handler_ = handler;
  }

  inline CefRefPtr<CefV8Handler> GetHandler() { return handler_; }

  inline void SetUserData(CefRefPtr<CefBaseRefCounted> user_data) {
    user_data_ = user_data;
  }

  inline CefRefPtr<CefBaseRefCounted> GetUserData() { return user_data_; }

  // Attach this track object to the specified V8 object.
  void AttachTo(v8::Local<v8::Context> context, v8::Local<v8::Object> object) {
    SetPrivate(context, object, kCefTrackObject,
               v8::External::New(isolate_, this));
  }

  // Retrieve the track object for the specified V8 object.
  static V8TrackObject* Unwrap(v8::Local<v8::Context> context,
                               v8::Local<v8::Object> object) {
    v8::Local<v8::Value> value;
    if (GetPrivate(context, object, kCefTrackObject, &value))
      return static_cast<V8TrackObject*>(v8::External::Cast(*value)->Value());

    return nullptr;
  }

 private:
  v8::Isolate* isolate_;
  CefRefPtr<CefV8Accessor> accessor_;
  CefRefPtr<CefV8Interceptor> interceptor_;
  CefRefPtr<CefV8Handler> handler_;
  CefRefPtr<CefBaseRefCounted> user_data_;
  int external_memory_;
};

class V8TrackString : public CefTrackNode {
 public:
  explicit V8TrackString(const std::string& str) : string_(str) {}
  const char* GetString() { return string_.c_str(); }

 private:
  std::string string_;
};

class V8TrackArrayBuffer : public CefTrackNode {
 public:
  explicit V8TrackArrayBuffer(
      v8::Isolate* isolate,
      void* buffer,
      CefRefPtr<CefV8ArrayBufferReleaseCallback> release_callback)
      : isolate_(isolate),
        buffer_(buffer),
        release_callback_(release_callback) {
    DCHECK(isolate_);
    isolate_->AdjustAmountOfExternalAllocatedMemory(
        static_cast<int>(sizeof(V8TrackArrayBuffer)));
  }

  ~V8TrackArrayBuffer() {
    if (buffer_ != nullptr) {
      release_callback_->ReleaseBuffer(buffer_);
    }
    isolate_->AdjustAmountOfExternalAllocatedMemory(
        -static_cast<int>(sizeof(V8TrackArrayBuffer)));
  }

  CefRefPtr<CefV8ArrayBufferReleaseCallback> GetReleaseCallback() {
    return release_callback_;
  }

  void Detach() { buffer_ = nullptr; }

  // Attach this track object to the specified V8 object.
  void AttachTo(v8::Local<v8::Context> context,
                v8::Local<v8::ArrayBuffer> arrayBuffer) {
    SetPrivate(context, arrayBuffer, kCefTrackObject,
               v8::External::New(isolate_, this));
  }

  // Retrieve the track object for the specified V8 object.
  static V8TrackArrayBuffer* Unwrap(v8::Local<v8::Context> context,
                                    v8::Local<v8::Object> object) {
    v8::Local<v8::Value> value;
    if (GetPrivate(context, object, kCefTrackObject, &value))
      return static_cast<V8TrackArrayBuffer*>(
          v8::External::Cast(*value)->Value());

    return nullptr;
  }

 private:
  v8::Isolate* isolate_;
  void* buffer_;
  CefRefPtr<CefV8ArrayBufferReleaseCallback> release_callback_;
};

// Object wrapped in a v8::External and passed as the Data argument to
// v8::FunctionTemplate::New.
class V8FunctionData {
 public:
  static v8::Local<v8::External> Create(v8::Isolate* isolate,
                                        const CefString& function_name,
                                        CefRefPtr<CefV8Handler> handler) {
    // |data| will be deleted if/when the returned v8::External is GC'd.
    V8FunctionData* data = new V8FunctionData(isolate, function_name, handler);
    return data->CreateExternal();
  }

  static V8FunctionData* Unwrap(v8::Local<v8::Value> data) {
    DCHECK(data->IsExternal());
    return static_cast<V8FunctionData*>(v8::External::Cast(*data)->Value());
  }

  CefString function_name() const { return function_name_; }

  CefV8Handler* handler() const {
    if (!handler_)
      return nullptr;
    return handler_.get();
  }

 private:
  V8FunctionData(v8::Isolate* isolate,
                 const CefString& function_name,
                 CefRefPtr<CefV8Handler> handler)
      : isolate_(isolate), function_name_(function_name), handler_(handler) {
    DCHECK(isolate_);
    DCHECK(handler_);
  }

  ~V8FunctionData() {
    isolate_->AdjustAmountOfExternalAllocatedMemory(
        -static_cast<int>(sizeof(V8FunctionData)));
    handler_ = nullptr;
    function_name_ = "FreedFunction";
  }

  v8::Local<v8::External> CreateExternal() {
    v8::Local<v8::External> external = v8::External::New(isolate_, this);

    isolate_->AdjustAmountOfExternalAllocatedMemory(
        static_cast<int>(sizeof(V8FunctionData)));

    handle_.Reset(isolate_, external);
    handle_.SetWeak(this, FirstWeakCallback, v8::WeakCallbackType::kParameter);

    return external;
  }

  static void FirstWeakCallback(
      const v8::WeakCallbackInfo<V8FunctionData>& data) {
    V8FunctionData* wrapper = data.GetParameter();
    wrapper->handle_.Reset();
    data.SetSecondPassCallback(SecondWeakCallback);
  }

  static void SecondWeakCallback(
      const v8::WeakCallbackInfo<V8FunctionData>& data) {
    V8FunctionData* wrapper = data.GetParameter();
    delete wrapper;
  }

  v8::Isolate* isolate_;
  CefString function_name_;
  CefRefPtr<CefV8Handler> handler_;
  v8::Persistent<v8::External> handle_;
};

// Convert a CefString to a V8::String.
v8::Local<v8::String> GetV8String(v8::Isolate* isolate, const CefString& str) {
#if defined(CEF_STRING_TYPE_UTF16)
  // Already a UTF16 string.
  return v8::String::NewFromTwoByte(
             isolate,
             reinterpret_cast<uint16_t*>(
                 const_cast<CefString::char_type*>(str.c_str())),
             v8::NewStringType::kNormal, str.length())
      .ToLocalChecked();
#elif defined(CEF_STRING_TYPE_UTF8)
  // Already a UTF8 string.
  return v8::String::NewFromUtf8(isolate, const_cast<char*>(str.c_str()),
                                 v8::NewStringType::kNormal, str.length())
      .ToLocalChecked();
#else
  // Convert the string to UTF8.
  std::string tmpStr = str;
  return v8::String::NewFromUtf8(isolate, tmpStr.c_str(),
                                 v8::NewStringType::kNormal, tmpStr.length())
      .ToLocalChecked();
#endif
}

#if defined(CEF_STRING_TYPE_UTF16)
void v8impl_string_dtor(char16* str) {
  delete[] str;
}
#elif defined(CEF_STRING_TYPE_UTF8)
void v8impl_string_dtor(char* str) {
  delete[] str;
}
#endif

// Convert a v8::String to CefString.
void GetCefString(v8::Isolate* isolate,
                  v8::Local<v8::String> str,
                  CefString& out) {
  if (str.IsEmpty())
    return;

#if defined(CEF_STRING_TYPE_WIDE)
  // Allocate enough space for a worst-case conversion.
  int len = str->Utf8Length();
  if (len == 0)
    return;
  char* buf = new char[len + 1];
  str->WriteUtf8(isolate, buf, len + 1);

  // Perform conversion to the wide type.
  cef_string_t* retws = out.GetWritableStruct();
  cef_string_utf8_to_wide(buf, len, retws);

  delete[] buf;
#else  // !defined(CEF_STRING_TYPE_WIDE)
#if defined(CEF_STRING_TYPE_UTF16)
  int len = str->Length();
  if (len == 0)
    return;
  char16* buf = new char16[len + 1];
  str->Write(isolate, reinterpret_cast<uint16_t*>(buf), 0, len + 1);
#else
  // Allocate enough space for a worst-case conversion.
  int len = str->Utf8Length();
  if (len == 0)
    return;
  char* buf = new char[len + 1];
  str->WriteUtf8(isolate, buf, len + 1);
#endif

  // Don't perform an extra string copy.
  out.clear();
  cef_string_t* retws = out.GetWritableStruct();
  retws->str = buf;
  retws->length = len;
  retws->dtor = v8impl_string_dtor;
#endif  // !defined(CEF_STRING_TYPE_WIDE)
}

// V8 function callback.
void FunctionCallbackImpl(const v8::FunctionCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Context> context = isolate->GetCurrentContext();

  V8FunctionData* data = V8FunctionData::Unwrap(info.Data());
  if (!data->handler()) {
    // handler has gone away, bail!
    info.GetReturnValue().SetUndefined();
    return;
  }
  CefV8ValueList params;
  for (int i = 0; i < info.Length(); i++)
    params.push_back(new CefV8ValueImpl(isolate, context, info[i]));

  CefRefPtr<CefV8Value> object =
      new CefV8ValueImpl(isolate, context, info.This());
  CefRefPtr<CefV8Value> retval;
  CefString exception;

  if (data->handler()->Execute(data->function_name(), object, params, retval,
                               exception)) {
    if (!exception.empty()) {
      info.GetReturnValue().Set(isolate->ThrowException(
          v8::Exception::Error(GetV8String(isolate, exception))));
      return;
    } else {
      CefV8ValueImpl* rv = static_cast<CefV8ValueImpl*>(retval.get());
      if (rv && rv->IsValid()) {
        info.GetReturnValue().Set(rv->GetV8Value(true));
        return;
      }
    }
  }

  info.GetReturnValue().SetUndefined();
}

// V8 Accessor callbacks
void AccessorNameGetterCallbackImpl(
    v8::Local<v8::Name> property,
    const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Context> context = isolate->GetCurrentContext();

  v8::Local<v8::Object> obj = info.This();

  CefRefPtr<CefV8Accessor> accessorPtr;

  V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
  if (tracker)
    accessorPtr = tracker->GetAccessor();

  if (accessorPtr.get()) {
    CefRefPtr<CefV8Value> retval;
    CefRefPtr<CefV8Value> object = new CefV8ValueImpl(isolate, context, obj);
    CefString name, exception;
    GetCefString(isolate, v8::Local<v8::String>::Cast(property), name);
    if (accessorPtr->Get(name, object, retval, exception)) {
      if (!exception.empty()) {
        info.GetReturnValue().Set(isolate->ThrowException(
            v8::Exception::Error(GetV8String(isolate, exception))));
        return;
      } else {
        CefV8ValueImpl* rv = static_cast<CefV8ValueImpl*>(retval.get());
        if (rv && rv->IsValid()) {
          info.GetReturnValue().Set(rv->GetV8Value(true));
          return;
        }
      }
    }
  }

  return info.GetReturnValue().SetUndefined();
}

void AccessorNameSetterCallbackImpl(
    v8::Local<v8::Name> property,
    v8::Local<v8::Value> value,
    const v8::PropertyCallbackInfo<void>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Context> context = isolate->GetCurrentContext();

  v8::Local<v8::Object> obj = info.This();

  CefRefPtr<CefV8Accessor> accessorPtr;

  V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
  if (tracker)
    accessorPtr = tracker->GetAccessor();

  if (accessorPtr.get()) {
    CefRefPtr<CefV8Value> object = new CefV8ValueImpl(isolate, context, obj);
    CefRefPtr<CefV8Value> cefValue =
        new CefV8ValueImpl(isolate, context, value);
    CefString name, exception;
    GetCefString(isolate, v8::Local<v8::String>::Cast(property), name);
    accessorPtr->Set(name, object, cefValue, exception);
    if (!exception.empty()) {
      isolate->ThrowException(
          v8::Exception::Error(GetV8String(isolate, exception)));
      return;
    }
  }
}

// Two helper functions for V8 Interceptor callbacks.
CefString PropertyToIndex(v8::Isolate* isolate, v8::Local<v8::Name> property) {
  CefString name;
  GetCefString(isolate, property.As<v8::String>(), name);
  return name;
}

int PropertyToIndex(v8::Isolate* isolate, uint32_t index) {
  return static_cast<int>(index);
}

// V8 Interceptor callbacks.
// T == v8::Local<v8::Name> for named property handlers and
// T == uint32_t for indexed property handlers
template <typename T>
void InterceptorGetterCallbackImpl(
    T property,
    const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Context> context = isolate->GetCurrentContext();

  v8::Handle<v8::Object> obj = info.This();
  CefRefPtr<CefV8Interceptor> interceptorPtr;

  V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
  if (tracker)
    interceptorPtr = tracker->GetInterceptor();
  if (!interceptorPtr.get())
    return;

  CefRefPtr<CefV8Value> object = new CefV8ValueImpl(isolate, context, obj);
  CefRefPtr<CefV8Value> retval;
  CefString exception;
  interceptorPtr->Get(PropertyToIndex(isolate, property), object, retval,
                      exception);
  if (!exception.empty()) {
    info.GetReturnValue().Set(isolate->ThrowException(
        v8::Exception::Error(GetV8String(isolate, exception))));
  } else {
    CefV8ValueImpl* retval_impl = static_cast<CefV8ValueImpl*>(retval.get());
    if (retval_impl && retval_impl->IsValid()) {
      info.GetReturnValue().Set(retval_impl->GetV8Value(true));
    }
  }
}

template <typename T>
void InterceptorSetterCallbackImpl(
    T property,
    v8::Local<v8::Value> value,
    const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  v8::Handle<v8::Object> obj = info.This();
  CefRefPtr<CefV8Interceptor> interceptorPtr;

  V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
  if (tracker)
    interceptorPtr = tracker->GetInterceptor();

  if (!interceptorPtr.get())
    return;
  CefRefPtr<CefV8Value> object = new CefV8ValueImpl(isolate, context, obj);
  CefRefPtr<CefV8Value> cefValue = new CefV8ValueImpl(isolate, context, value);
  CefString exception;
  interceptorPtr->Set(PropertyToIndex(isolate, property), object, cefValue,
                      exception);
  if (!exception.empty()) {
    isolate->ThrowException(
        v8::Exception::Error(GetV8String(isolate, exception)));
  }
}

// V8 extension registration.

class ExtensionWrapper : public v8::Extension {
 public:
  ExtensionWrapper(const char* extension_name,
                   const char* javascript_code,
                   CefV8Handler* handler)
      : v8::Extension(extension_name, javascript_code), handler_(handler) {}

  v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
      v8::Isolate* isolate,
      v8::Handle<v8::String> name) override {
    if (!handler_)
      return v8::Local<v8::FunctionTemplate>();

    CefString func_name;
    GetCefString(isolate, name, func_name);

    v8::Local<v8::External> function_data =
        V8FunctionData::Create(isolate, func_name, handler_);

    return v8::FunctionTemplate::New(isolate, FunctionCallbackImpl,
                                     function_data);
  }

 private:
  CefV8Handler* handler_;
};

class CefV8ExceptionImpl : public CefV8Exception {
 public:
  CefV8ExceptionImpl(v8::Local<v8::Context> context,
                     v8::Local<v8::Message> message)
      : line_number_(0),
        start_position_(0),
        end_position_(0),
        start_column_(0),
        end_column_(0) {
    if (message.IsEmpty())
      return;

    v8::Isolate* isolate = context->GetIsolate();
    GetCefString(isolate, message->Get(), message_);
    v8::MaybeLocal<v8::String> source_line = message->GetSourceLine(context);
    if (!source_line.IsEmpty())
      GetCefString(isolate, source_line.ToLocalChecked(), source_line_);

    if (!message->GetScriptResourceName().IsEmpty()) {
      GetCefString(
          isolate,
          message->GetScriptResourceName()->ToString(context).ToLocalChecked(),
          script_);
    }

    v8::Maybe<int> line_number = message->GetLineNumber(context);
    if (!line_number.IsNothing())
      line_number_ = line_number.ToChecked();
    start_position_ = message->GetStartPosition();
    end_position_ = message->GetEndPosition();
    start_column_ = message->GetStartColumn(context).FromJust();
    end_column_ = message->GetEndColumn(context).FromJust();
  }

  CefString GetMessage() override { return message_; }
  CefString GetSourceLine() override { return source_line_; }
  CefString GetScriptResourceName() override { return script_; }
  int GetLineNumber() override { return line_number_; }
  int GetStartPosition() override { return start_position_; }
  int GetEndPosition() override { return end_position_; }
  int GetStartColumn() override { return start_column_; }
  int GetEndColumn() override { return end_column_; }

 protected:
  CefString message_;
  CefString source_line_;
  CefString script_;
  int line_number_;
  int start_position_;
  int end_position_;
  int start_column_;
  int end_column_;

  IMPLEMENT_REFCOUNTING(CefV8ExceptionImpl);
};

void MessageListenerCallbackImpl(v8::Handle<v8::Message> message,
                                 v8::Handle<v8::Value> data) {
  CefRefPtr<CefApp> application = CefContentClient::Get()->application();
  if (!application.get())
    return;

  CefRefPtr<CefRenderProcessHandler> handler =
      application->GetRenderProcessHandler();
  if (!handler.get())
    return;

  v8::Isolate* isolate = GetIsolateManager()->isolate();
  CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
  v8::Local<v8::StackTrace> v8Stack = message->GetStackTrace();
  CefRefPtr<CefV8StackTrace> stackTrace =
      new CefV8StackTraceImpl(isolate, v8Stack);

  CefRefPtr<CefV8Exception> exception = new CefV8ExceptionImpl(
      static_cast<CefV8ContextImpl*>(context.get())->GetV8Context(), message);

  CefRefPtr<CefBrowser> browser = context->GetBrowser();
  if (browser) {
    handler->OnUncaughtException(browser, context->GetFrame(), context,
                                 exception, stackTrace);
  }
}

}  // namespace

// Global functions.

void CefV8IsolateCreated() {
  g_v8_state.Pointer()->CreateIsolateManager();
}

void CefV8IsolateDestroyed() {
  g_v8_state.Pointer()->DestroyIsolateManager();
}

void CefV8ReleaseContext(v8::Local<v8::Context> context) {
  GetIsolateManager()->ReleaseContext(context);
}

void CefV8SetUncaughtExceptionStackSize(int stack_size) {
  GetIsolateManager()->SetUncaughtExceptionStackSize(stack_size);
}

void CefV8SetWorkerAttributes(int worker_id, const GURL& worker_url) {
  GetIsolateManager()->SetWorkerAttributes(worker_id, worker_url);
}

bool CefRegisterExtension(const CefString& extension_name,
                          const CefString& javascript_code,
                          CefRefPtr<CefV8Handler> handler) {
  // Verify that this method was called on the correct thread.
  CEF_REQUIRE_RT_RETURN(false);

  CefV8IsolateManager* isolate_manager = GetIsolateManager();

  V8TrackString* name = new V8TrackString(extension_name);
  isolate_manager->AddGlobalTrackObject(name);
  V8TrackString* code = new V8TrackString(javascript_code);
  isolate_manager->AddGlobalTrackObject(code);

  if (handler.get()) {
    // The reference will be released when the process exits.
    V8TrackObject* object = new V8TrackObject(isolate_manager->isolate());
    object->SetHandler(handler);
    isolate_manager->AddGlobalTrackObject(object);
  }

  std::unique_ptr<v8::Extension> wrapper(new ExtensionWrapper(
      name->GetString(), code->GetString(), handler.get()));

  content::RenderThread::Get()->RegisterExtension(std::move(wrapper));
  return true;
}

// Helper macros

#define CEF_V8_HAS_ISOLATE() (!!GetIsolateManager())
#define CEF_V8_REQUIRE_ISOLATE_RETURN(var)     \
  if (!CEF_V8_HAS_ISOLATE()) {                 \
    NOTREACHED() << "V8 isolate is not valid"; \
    return var;                                \
  }

#define CEF_V8_CURRENTLY_ON_MLT() \
  (!handle_.get() || handle_->BelongsToCurrentThread())
#define CEF_V8_REQUIRE_MLT_RETURN(var)            \
  CEF_V8_REQUIRE_ISOLATE_RETURN(var);             \
  if (!CEF_V8_CURRENTLY_ON_MLT()) {               \
    NOTREACHED() << "called on incorrect thread"; \
    return var;                                   \
  }

#define CEF_V8_HANDLE_IS_VALID() (handle_.get() && handle_->IsValid())
#define CEF_V8_REQUIRE_VALID_HANDLE_RETURN(ret) \
  CEF_V8_REQUIRE_MLT_RETURN(ret);               \
  if (!CEF_V8_HANDLE_IS_VALID()) {              \
    NOTREACHED() << "V8 handle is not valid";   \
    return ret;                                 \
  }

#define CEF_V8_IS_VALID()                               \
  (CEF_V8_HAS_ISOLATE() && CEF_V8_CURRENTLY_ON_MLT() && \
   CEF_V8_HANDLE_IS_VALID())

#define CEF_V8_REQUIRE_OBJECT_RETURN(ret)        \
  CEF_V8_REQUIRE_VALID_HANDLE_RETURN(ret);       \
  if (type_ != TYPE_OBJECT) {                    \
    NOTREACHED() << "V8 value is not an object"; \
    return ret;                                  \
  }

// CefV8HandleBase

CefV8HandleBase::~CefV8HandleBase() {
  DCHECK(BelongsToCurrentThread());
}

bool CefV8HandleBase::BelongsToCurrentThread() const {
  return task_runner_->RunsTasksInCurrentSequence();
}

CefV8HandleBase::CefV8HandleBase(v8::Isolate* isolate,
                                 v8::Local<v8::Context> context)
    : isolate_(isolate) {
  DCHECK(isolate_);

  CefV8IsolateManager* manager = GetIsolateManager();
  DCHECK(manager);
  DCHECK_EQ(isolate_, manager->isolate());

  task_runner_ = manager->task_runner();
  context_state_ = manager->GetContextState(context);
}

// CefV8Context

// static
CefRefPtr<CefV8Context> CefV8Context::GetCurrentContext() {
  CefRefPtr<CefV8Context> context;
  CEF_V8_REQUIRE_ISOLATE_RETURN(context);
  v8::Isolate* isolate = GetIsolateManager()->isolate();
  if (isolate->InContext()) {
    v8::HandleScope handle_scope(isolate);
    context = new CefV8ContextImpl(isolate, isolate->GetCurrentContext());
  }
  return context;
}

// static
CefRefPtr<CefV8Context> CefV8Context::GetEnteredContext() {
  CefRefPtr<CefV8Context> context;
  CEF_V8_REQUIRE_ISOLATE_RETURN(context);
  v8::Isolate* isolate = GetIsolateManager()->isolate();
  if (isolate->InContext()) {
    v8::HandleScope handle_scope(isolate);
    context =
        new CefV8ContextImpl(isolate, isolate->GetEnteredOrMicrotaskContext());
  }
  return context;
}

// static
bool CefV8Context::InContext() {
  CEF_V8_REQUIRE_ISOLATE_RETURN(false);
  v8::Isolate* isolate = GetIsolateManager()->isolate();
  return isolate->InContext();
}

// CefV8ContextImpl

CefV8ContextImpl::CefV8ContextImpl(v8::Isolate* isolate,
                                   v8::Local<v8::Context> context)
    : handle_(new Handle(isolate, context, context)), enter_count_(0) {}

CefV8ContextImpl::~CefV8ContextImpl() {
  DLOG_ASSERT(0 == enter_count_);
}

CefRefPtr<CefTaskRunner> CefV8ContextImpl::GetTaskRunner() {
  return new CefTaskRunnerImpl(handle_->task_runner());
}

bool CefV8ContextImpl::IsValid() {
  return CEF_V8_IS_VALID();
}

CefRefPtr<CefBrowser> CefV8ContextImpl::GetBrowser() {
  CefRefPtr<CefBrowser> browser;
  CEF_V8_REQUIRE_VALID_HANDLE_RETURN(browser);

  blink::WebLocalFrame* webframe = GetWebFrame();
  if (webframe)
    browser = CefBrowserImpl::GetBrowserForMainFrame(webframe->Top());

  return browser;
}

CefRefPtr<CefFrame> CefV8ContextImpl::GetFrame() {
  CefRefPtr<CefFrame> frame;
  CEF_V8_REQUIRE_VALID_HANDLE_RETURN(frame);

  blink::WebLocalFrame* webframe = GetWebFrame();
  if (webframe) {
    CefRefPtr<CefBrowserImpl> browser =
        CefBrowserImpl::GetBrowserForMainFrame(webframe->Top());
    if (browser) {
      frame = browser->GetFrame(render_frame_util::GetIdentifier(webframe));
    }
  }

  return frame;
}

CefRefPtr<CefV8Value> CefV8ContextImpl::GetGlobal() {
  CEF_V8_REQUIRE_VALID_HANDLE_RETURN(nullptr);

  if (blink_glue::IsScriptForbidden())
    return nullptr;

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);
  v8::Local<v8::Context> context = GetV8Context();
  v8::Context::Scope context_scope(context);
  return new CefV8ValueImpl(isolate, context, context->Global());
}

bool CefV8ContextImpl::Enter() {
  CEF_V8_REQUIRE_VALID_HANDLE_RETURN(false);

  if (blink_glue::IsScriptForbidden())
    return false;

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  if (!microtasks_scope_) {
    // Increment the MicrotasksScope recursion level.
    microtasks_scope_.reset(
        new v8::MicrotasksScope(isolate, v8::MicrotasksScope::kRunMicrotasks));
  }

  ++enter_count_;
  handle_->GetNewV8Handle()->Enter();

  return true;
}

bool CefV8ContextImpl::Exit() {
  CEF_V8_REQUIRE_VALID_HANDLE_RETURN(false);

  if (blink_glue::IsScriptForbidden())
    return false;

  if (enter_count_ <= 0) {
    LOG(ERROR) << "Call to CefV8Context::Exit() without matching call to "
                  "CefV8Context::Enter()";
    return false;
  }

  v8::HandleScope handle_scope(handle_->isolate());

  handle_->GetNewV8Handle()->Exit();

  if (--enter_count_ == 0) {
    // Decrement the MicrotasksScope recursion level.
    microtasks_scope_.reset(nullptr);
  }

  return true;
}

bool CefV8ContextImpl::IsSame(CefRefPtr<CefV8Context> that) {
  CEF_V8_REQUIRE_VALID_HANDLE_RETURN(false);

  CefV8ContextImpl* impl = static_cast<CefV8ContextImpl*>(that.get());
  if (!impl || !impl->IsValid())
    return false;

  return (handle_->GetPersistentV8Handle() ==
          impl->handle_->GetPersistentV8Handle());
}

bool CefV8ContextImpl::Eval(const CefString& code,
                            const CefString& script_url,
                            int start_line,
                            CefRefPtr<CefV8Value>& retval,
                            CefRefPtr<CefV8Exception>& exception) {
  retval = nullptr;
  exception = nullptr;

  CEF_V8_REQUIRE_VALID_HANDLE_RETURN(false);

  if (blink_glue::IsScriptForbidden())
    return false;

  if (code.empty()) {
    NOTREACHED() << "invalid input parameter";
    return false;
  }

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);
  v8::Local<v8::Context> context = GetV8Context();
  v8::Context::Scope context_scope(context);

  const blink::WebString& source =
      blink::WebString::FromUTF16(code.ToString16());
  const blink::WebString& source_url =
      blink::WebString::FromUTF16(script_url.ToString16());

  v8::TryCatch try_catch(isolate);
  try_catch.SetVerbose(true);

  v8::MaybeLocal<v8::Value> func_rv = blink_glue::ExecuteV8ScriptAndReturnValue(
      source, source_url, start_line, context, isolate, try_catch,
      blink::SanitizeScriptErrors::kSanitize);

  if (try_catch.HasCaught()) {
    exception = new CefV8ExceptionImpl(context, try_catch.Message());
    return false;
  } else if (!func_rv.IsEmpty()) {
    retval = new CefV8ValueImpl(isolate, context, func_rv.ToLocalChecked());
    return true;
  }

  NOTREACHED();
  return false;
}

v8::Local<v8::Context> CefV8ContextImpl::GetV8Context() {
  return handle_->GetNewV8Handle();
}

blink::WebLocalFrame* CefV8ContextImpl::GetWebFrame() {
  CEF_REQUIRE_RT();

  if (blink_glue::IsScriptForbidden())
    return nullptr;

  v8::HandleScope handle_scope(handle_->isolate());
  v8::Local<v8::Context> context = GetV8Context();
  v8::Context::Scope context_scope(context);
  return blink::WebLocalFrame::FrameForContext(context);
}

// CefV8ValueImpl::Handle

CefV8ValueImpl::Handle::Handle(v8::Isolate* isolate,
                               v8::Local<v8::Context> context,
                               handleType v,
                               CefTrackNode* tracker)
    : CefV8HandleBase(isolate, context),
      handle_(isolate, v),
      tracker_(tracker),
      should_persist_(false),
      is_set_weak_(false) {}

CefV8ValueImpl::Handle::~Handle() {
  DCHECK(BelongsToCurrentThread());

  if (tracker_) {
    if (is_set_weak_) {
      if (context_state_.get()) {
        // If the associated context is still valid then delete |tracker_|.
        // Otherwise, |tracker_| will already have been deleted.
        if (context_state_->IsValid())
          context_state_->DeleteTrackObject(tracker_);
      } else {
        GetIsolateManager()->DeleteGlobalTrackObject(tracker_);
      }
    } else {
      delete tracker_;
    }
  }

  if (is_set_weak_) {
    isolate_->AdjustAmountOfExternalAllocatedMemory(
        -static_cast<int>(sizeof(Handle)));
  } else {
    // SetWeak was not called so reset now.
    handle_.Reset();
  }
}

CefV8ValueImpl::Handle::handleType CefV8ValueImpl::Handle::GetNewV8Handle(
    bool should_persist) {
  DCHECK(IsValid());
  if (should_persist && !should_persist_)
    should_persist_ = true;
  return handleType::New(isolate(), handle_);
}

CefV8ValueImpl::Handle::persistentType&
CefV8ValueImpl::Handle::GetPersistentV8Handle() {
  return handle_;
}

void CefV8ValueImpl::Handle::SetWeakIfNecessary() {
  if (!BelongsToCurrentThread()) {
    task_runner()->PostTask(
        FROM_HERE,
        base::Bind(&CefV8ValueImpl::Handle::SetWeakIfNecessary, this));
    return;
  }

  // Persist the handle (call SetWeak) if:
  // A. The handle has been passed into a V8 function or used as a return value
  //    from a V8 callback, and
  // B. The associated context, if any, is still valid.
  if (should_persist_ && (!context_state_.get() || context_state_->IsValid())) {
    is_set_weak_ = true;

    if (tracker_) {
      if (context_state_.get()) {
        // |tracker_| will be deleted when:
        // A. The associated context is released, or
        // B. SecondWeakCallback is called for the weak handle.
        DCHECK(context_state_->IsValid());
        context_state_->AddTrackObject(tracker_);
      } else {
        // |tracker_| will be deleted when:
        // A. The process shuts down, or
        // B. SecondWeakCallback is called for the weak handle.
        GetIsolateManager()->AddGlobalTrackObject(tracker_);
      }
    }

    isolate_->AdjustAmountOfExternalAllocatedMemory(
        static_cast<int>(sizeof(Handle)));

    // The added reference will be released in SecondWeakCallback.
    AddRef();
    handle_.SetWeak(this, FirstWeakCallback, v8::WeakCallbackType::kParameter);
  }
}

// static
void CefV8ValueImpl::Handle::FirstWeakCallback(
    const v8::WeakCallbackInfo<Handle>& data) {
  Handle* wrapper = data.GetParameter();
  wrapper->handle_.Reset();
  data.SetSecondPassCallback(SecondWeakCallback);
}

// static
void CefV8ValueImpl::Handle::SecondWeakCallback(
    const v8::WeakCallbackInfo<Handle>& data) {
  Handle* wrapper = data.GetParameter();
  wrapper->Release();
}

// CefV8Value

// static
CefRefPtr<CefV8Value> CefV8Value::CreateUndefined() {
  CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
  v8::Isolate* isolate = GetIsolateManager()->isolate();
  CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
  impl->InitUndefined();
  return impl.get();
}

// static
CefRefPtr<CefV8Value> CefV8Value::CreateNull() {
  CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
  v8::Isolate* isolate = GetIsolateManager()->isolate();
  CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
  impl->InitNull();
  return impl.get();
}

// static
CefRefPtr<CefV8Value> CefV8Value::CreateBool(bool value) {
  CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
  v8::Isolate* isolate = GetIsolateManager()->isolate();
  CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
  impl->InitBool(value);
  return impl.get();
}

// static
CefRefPtr<CefV8Value> CefV8Value::CreateInt(int32 value) {
  CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
  v8::Isolate* isolate = GetIsolateManager()->isolate();
  CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
  impl->InitInt(value);
  return impl.get();
}

// static
CefRefPtr<CefV8Value> CefV8Value::CreateUInt(uint32 value) {
  CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
  v8::Isolate* isolate = GetIsolateManager()->isolate();
  CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
  impl->InitUInt(value);
  return impl.get();
}

// static
CefRefPtr<CefV8Value> CefV8Value::CreateDouble(double value) {
  CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
  v8::Isolate* isolate = GetIsolateManager()->isolate();
  CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
  impl->InitDouble(value);
  return impl.get();
}

// static
CefRefPtr<CefV8Value> CefV8Value::CreateDate(const CefTime& value) {
  CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
  v8::Isolate* isolate = GetIsolateManager()->isolate();
  CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
  impl->InitDate(value);
  return impl.get();
}

// static
CefRefPtr<CefV8Value> CefV8Value::CreateString(const CefString& value) {
  CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);
  v8::Isolate* isolate = GetIsolateManager()->isolate();
  CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
  CefString str(value);
  impl->InitString(str);
  return impl.get();
}

// static
CefRefPtr<CefV8Value> CefV8Value::CreateObject(
    CefRefPtr<CefV8Accessor> accessor,
    CefRefPtr<CefV8Interceptor> interceptor) {
  CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);

  v8::Isolate* isolate = GetIsolateManager()->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return nullptr;
  }

  // Create the new V8 object. If an interceptor is passed, create object from
  // template and set property handlers.
  v8::Local<v8::Object> obj;
  if (interceptor.get()) {
    v8::Local<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
    tmpl->SetHandler(v8::NamedPropertyHandlerConfiguration(
        InterceptorGetterCallbackImpl<v8::Local<v8::Name>>,
        InterceptorSetterCallbackImpl<v8::Local<v8::Name>>, nullptr, nullptr,
        nullptr, v8::Local<v8::Value>(),
        v8::PropertyHandlerFlags::kOnlyInterceptStrings));

    tmpl->SetIndexedPropertyHandler(InterceptorGetterCallbackImpl<uint32_t>,
                                    InterceptorSetterCallbackImpl<uint32_t>);

    v8::MaybeLocal<v8::Object> maybe_object = tmpl->NewInstance(context);
    if (!maybe_object.ToLocal<v8::Object>(&obj)) {
      NOTREACHED() << "Failed to create V8 Object with interceptor";
      return nullptr;
    }
  } else {
    obj = v8::Object::New(isolate);
  }

  // Create a tracker object that will cause the user data and/or accessor
  // and/or interceptor reference to be released when the V8 object is
  // destroyed.
  V8TrackObject* tracker = new V8TrackObject(isolate);
  tracker->SetAccessor(accessor);
  tracker->SetInterceptor(interceptor);

  // Attach the tracker object.
  tracker->AttachTo(context, obj);

  CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
  impl->InitObject(obj, tracker);
  return impl.get();
}

// static
CefRefPtr<CefV8Value> CefV8Value::CreateArray(int length) {
  CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);

  v8::Isolate* isolate = GetIsolateManager()->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return nullptr;
  }

  // Create a tracker object that will cause the user data reference to be
  // released when the V8 object is destroyed.
  V8TrackObject* tracker = new V8TrackObject(isolate);

  // Create the new V8 array.
  v8::Local<v8::Array> arr = v8::Array::New(isolate, length);

  // Attach the tracker object.
  tracker->AttachTo(context, arr);

  CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
  impl->InitObject(arr, tracker);
  return impl.get();
}

// static
CefRefPtr<CefV8Value> CefV8Value::CreateArrayBuffer(
    void* buffer,
    size_t length,
    CefRefPtr<CefV8ArrayBufferReleaseCallback> release_callback) {
  CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);

  v8::Isolate* isolate = GetIsolateManager()->isolate();
  v8::HandleScope handle_scope(isolate);
  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return nullptr;
  }

  // Create a tracker object that will cause the user data reference to be
  // released when the V8 object is destroyed.
  V8TrackArrayBuffer* tracker =
      new V8TrackArrayBuffer(isolate, buffer, release_callback);
  v8::Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, buffer, length);

  // Attach the tracker object.
  tracker->AttachTo(context, ab);

  CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
  impl->InitObject(ab, tracker);
  return impl.get();
}

// static
CefRefPtr<CefV8Value> CefV8Value::CreateFunction(
    const CefString& name,
    CefRefPtr<CefV8Handler> handler) {
  CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);

  if (!handler.get()) {
    NOTREACHED() << "invalid parameter";
    return nullptr;
  }

  v8::Isolate* isolate = GetIsolateManager()->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return nullptr;
  }

  v8::Local<v8::External> function_data =
      V8FunctionData::Create(isolate, name, handler);

  // Create a new V8 function template.
  v8::Local<v8::FunctionTemplate> tmpl =
      v8::FunctionTemplate::New(isolate, FunctionCallbackImpl, function_data);

  // Retrieve the function object and set the name.
  v8::MaybeLocal<v8::Function> maybe_func = tmpl->GetFunction(context);
  v8::Local<v8::Function> func;
  if (!maybe_func.ToLocal(&func)) {
    NOTREACHED() << "failed to create V8 function";
    return nullptr;
  }

  func->SetName(GetV8String(isolate, name));

  // Create a tracker object that will cause the user data and/or handler
  // reference to be released when the V8 object is destroyed.
  V8TrackObject* tracker = new V8TrackObject(isolate);
  tracker->SetHandler(handler);

  // Attach the tracker object.
  tracker->AttachTo(context, func);

  // Create the CefV8ValueImpl and provide a tracker object that will cause
  // the handler reference to be released when the V8 object is destroyed.
  CefRefPtr<CefV8ValueImpl> impl = new CefV8ValueImpl(isolate);
  impl->InitObject(func, tracker);
  return impl.get();
}

// CefV8ValueImpl

CefV8ValueImpl::CefV8ValueImpl(v8::Isolate* isolate)
    : isolate_(isolate), type_(TYPE_INVALID), rethrow_exceptions_(false) {
  DCHECK(isolate_);
}

CefV8ValueImpl::CefV8ValueImpl(v8::Isolate* isolate,
                               v8::Local<v8::Context> context,
                               v8::Local<v8::Value> value)
    : isolate_(isolate), type_(TYPE_INVALID), rethrow_exceptions_(false) {
  DCHECK(isolate_);
  InitFromV8Value(context, value);
}

CefV8ValueImpl::~CefV8ValueImpl() {
  if (type_ == TYPE_STRING)
    cef_string_clear(&string_value_);
  if (handle_.get())
    handle_->SetWeakIfNecessary();
}

void CefV8ValueImpl::InitFromV8Value(v8::Local<v8::Context> context,
                                     v8::Local<v8::Value> value) {
  if (value->IsUndefined()) {
    InitUndefined();
  } else if (value->IsNull()) {
    InitNull();
  } else if (value->IsTrue()) {
    InitBool(true);
  } else if (value->IsFalse()) {
    InitBool(false);
  } else if (value->IsBoolean()) {
    InitBool(value->ToBoolean(context->GetIsolate())->Value());
  } else if (value->IsInt32()) {
    InitInt(value->ToInt32(context).ToLocalChecked()->Value());
  } else if (value->IsUint32()) {
    InitUInt(value->ToUint32(context).ToLocalChecked()->Value());
  } else if (value->IsNumber()) {
    InitDouble(value->ToNumber(context).ToLocalChecked()->Value());
  } else if (value->IsDate()) {
    // Convert from milliseconds to seconds.
    InitDate(
        CefTime(value->ToNumber(context).ToLocalChecked()->Value() / 1000));
  } else if (value->IsString()) {
    CefString rv;
    GetCefString(context->GetIsolate(),
                 value->ToString(context).ToLocalChecked(), rv);
    InitString(rv);
  } else if (value->IsObject()) {
    InitObject(value, nullptr);
  }
}

void CefV8ValueImpl::InitUndefined() {
  DCHECK_EQ(type_, TYPE_INVALID);
  type_ = TYPE_UNDEFINED;
}

void CefV8ValueImpl::InitNull() {
  DCHECK_EQ(type_, TYPE_INVALID);
  type_ = TYPE_NULL;
}

void CefV8ValueImpl::InitBool(bool value) {
  DCHECK_EQ(type_, TYPE_INVALID);
  type_ = TYPE_BOOL;
  bool_value_ = value;
}

void CefV8ValueImpl::InitInt(int32 value) {
  DCHECK_EQ(type_, TYPE_INVALID);
  type_ = TYPE_INT;
  int_value_ = value;
}

void CefV8ValueImpl::InitUInt(uint32 value) {
  DCHECK_EQ(type_, TYPE_INVALID);
  type_ = TYPE_UINT;
  uint_value_ = value;
}

void CefV8ValueImpl::InitDouble(double value) {
  DCHECK_EQ(type_, TYPE_INVALID);
  type_ = TYPE_DOUBLE;
  double_value_ = value;
}

void CefV8ValueImpl::InitDate(const CefTime& value) {
  DCHECK_EQ(type_, TYPE_INVALID);
  type_ = TYPE_DATE;
  date_value_ = value;
}

void CefV8ValueImpl::InitString(CefString& value) {
  DCHECK_EQ(type_, TYPE_INVALID);
  type_ = TYPE_STRING;
  // Take ownership of the underling string value.
  const cef_string_t* str = value.GetStruct();
  if (str) {
    string_value_ = *str;
    cef_string_t* writable_struct = value.GetWritableStruct();
    writable_struct->str = nullptr;
    writable_struct->length = 0;
  } else {
    string_value_.str = nullptr;
    string_value_.length = 0;
  }
}

void CefV8ValueImpl::InitObject(v8::Local<v8::Value> value,
                                CefTrackNode* tracker) {
  DCHECK_EQ(type_, TYPE_INVALID);
  type_ = TYPE_OBJECT;
  handle_ = new Handle(isolate_, v8::Local<v8::Context>(), value, tracker);
}

v8::Local<v8::Value> CefV8ValueImpl::GetV8Value(bool should_persist) {
  switch (type_) {
    case TYPE_UNDEFINED:
      return v8::Undefined(isolate_);
    case TYPE_NULL:
      return v8::Null(isolate_);
    case TYPE_BOOL:
      return v8::Boolean::New(isolate_, bool_value_);
    case TYPE_INT:
      return v8::Int32::New(isolate_, int_value_);
    case TYPE_UINT:
      return v8::Uint32::New(isolate_, uint_value_);
    case TYPE_DOUBLE:
      return v8::Number::New(isolate_, double_value_);
    case TYPE_DATE:
      // Convert from seconds to milliseconds.
      return v8::Date::New(isolate_->GetCurrentContext(),
                           CefTime(date_value_).GetDoubleT() * 1000)
          .ToLocalChecked();
    case TYPE_STRING:
      return GetV8String(isolate_, CefString(&string_value_));
    case TYPE_OBJECT:
      return handle_->GetNewV8Handle(should_persist);
    default:
      break;
  }

  NOTREACHED() << "Invalid type for CefV8ValueImpl";
  return v8::Local<v8::Value>();
}

bool CefV8ValueImpl::IsValid() {
  if (!CEF_V8_HAS_ISOLATE() || type_ == TYPE_INVALID ||
      (type_ == TYPE_OBJECT &&
       (!handle_->BelongsToCurrentThread() || !handle_->IsValid()))) {
    return false;
  }
  return true;
}

bool CefV8ValueImpl::IsUndefined() {
  CEF_V8_REQUIRE_ISOLATE_RETURN(false);
  return (type_ == TYPE_UNDEFINED);
}

bool CefV8ValueImpl::IsNull() {
  CEF_V8_REQUIRE_ISOLATE_RETURN(false);
  return (type_ == TYPE_NULL);
}

bool CefV8ValueImpl::IsBool() {
  CEF_V8_REQUIRE_ISOLATE_RETURN(false);
  return (type_ == TYPE_BOOL);
}

bool CefV8ValueImpl::IsInt() {
  CEF_V8_REQUIRE_ISOLATE_RETURN(false);
  return (type_ == TYPE_INT || type_ == TYPE_UINT);
}

bool CefV8ValueImpl::IsUInt() {
  CEF_V8_REQUIRE_ISOLATE_RETURN(false);
  return (type_ == TYPE_INT || type_ == TYPE_UINT);
}

bool CefV8ValueImpl::IsDouble() {
  CEF_V8_REQUIRE_ISOLATE_RETURN(false);
  return (type_ == TYPE_INT || type_ == TYPE_UINT || type_ == TYPE_DOUBLE);
}

bool CefV8ValueImpl::IsDate() {
  CEF_V8_REQUIRE_ISOLATE_RETURN(false);
  return (type_ == TYPE_DATE);
}

bool CefV8ValueImpl::IsString() {
  CEF_V8_REQUIRE_ISOLATE_RETURN(false);
  return (type_ == TYPE_STRING);
}

bool CefV8ValueImpl::IsObject() {
  CEF_V8_REQUIRE_ISOLATE_RETURN(false);
  return (type_ == TYPE_OBJECT);
}

bool CefV8ValueImpl::IsArray() {
  CEF_V8_REQUIRE_MLT_RETURN(false);
  if (type_ == TYPE_OBJECT) {
    v8::HandleScope handle_scope(handle_->isolate());
    return handle_->GetNewV8Handle(false)->IsArray();
  } else {
    return false;
  }
}

bool CefV8ValueImpl::IsArrayBuffer() {
  CEF_V8_REQUIRE_MLT_RETURN(false);
  if (type_ == TYPE_OBJECT) {
    v8::HandleScope handle_scope(handle_->isolate());
    return handle_->GetNewV8Handle(false)->IsArrayBuffer();
  } else {
    return false;
  }
}

bool CefV8ValueImpl::IsFunction() {
  CEF_V8_REQUIRE_MLT_RETURN(false);
  if (type_ == TYPE_OBJECT) {
    v8::HandleScope handle_scope(handle_->isolate());
    return handle_->GetNewV8Handle(false)->IsFunction();
  } else {
    return false;
  }
}

bool CefV8ValueImpl::IsSame(CefRefPtr<CefV8Value> that) {
  CEF_V8_REQUIRE_MLT_RETURN(false);

  CefV8ValueImpl* thatValue = static_cast<CefV8ValueImpl*>(that.get());
  if (!thatValue || !thatValue->IsValid() || type_ != thatValue->type_)
    return false;

  switch (type_) {
    case TYPE_UNDEFINED:
    case TYPE_NULL:
      return true;
    case TYPE_BOOL:
      return (bool_value_ == thatValue->bool_value_);
    case TYPE_INT:
      return (int_value_ == thatValue->int_value_);
    case TYPE_UINT:
      return (uint_value_ == thatValue->uint_value_);
    case TYPE_DOUBLE:
      return (double_value_ == thatValue->double_value_);
    case TYPE_DATE:
      return (CefTime(date_value_).GetTimeT() ==
              CefTime(thatValue->date_value_).GetTimeT());
    case TYPE_STRING:
      return (CefString(&string_value_) ==
              CefString(&thatValue->string_value_));
    case TYPE_OBJECT: {
      return (handle_->GetPersistentV8Handle() ==
              thatValue->handle_->GetPersistentV8Handle());
    }
    default:
      break;
  }

  return false;
}

bool CefV8ValueImpl::GetBoolValue() {
  CEF_V8_REQUIRE_ISOLATE_RETURN(false);
  if (type_ == TYPE_BOOL)
    return bool_value_;
  return false;
}

int32 CefV8ValueImpl::GetIntValue() {
  CEF_V8_REQUIRE_ISOLATE_RETURN(0);
  if (type_ == TYPE_INT || type_ == TYPE_UINT)
    return int_value_;
  return 0;
}

uint32 CefV8ValueImpl::GetUIntValue() {
  CEF_V8_REQUIRE_ISOLATE_RETURN(0);
  if (type_ == TYPE_INT || type_ == TYPE_UINT)
    return uint_value_;
  return 0;
}

double CefV8ValueImpl::GetDoubleValue() {
  CEF_V8_REQUIRE_ISOLATE_RETURN(0.);
  if (type_ == TYPE_DOUBLE)
    return double_value_;
  else if (type_ == TYPE_INT)
    return int_value_;
  else if (type_ == TYPE_UINT)
    return uint_value_;
  return 0.;
}

CefTime CefV8ValueImpl::GetDateValue() {
  CEF_V8_REQUIRE_ISOLATE_RETURN(CefTime(0.));
  if (type_ == TYPE_DATE)
    return date_value_;
  return CefTime(0.);
}

CefString CefV8ValueImpl::GetStringValue() {
  CefString rv;
  CEF_V8_REQUIRE_ISOLATE_RETURN(rv);
  if (type_ == TYPE_STRING)
    rv = CefString(&string_value_);
  return rv;
}

bool CefV8ValueImpl::IsUserCreated() {
  CEF_V8_REQUIRE_OBJECT_RETURN(false);

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return false;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();

  V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
  return (tracker != nullptr);
}

bool CefV8ValueImpl::HasException() {
  CEF_V8_REQUIRE_OBJECT_RETURN(false);

  return (last_exception_.get() != nullptr);
}

CefRefPtr<CefV8Exception> CefV8ValueImpl::GetException() {
  CEF_V8_REQUIRE_OBJECT_RETURN(nullptr);

  return last_exception_;
}

bool CefV8ValueImpl::ClearException() {
  CEF_V8_REQUIRE_OBJECT_RETURN(false);

  last_exception_ = nullptr;
  return true;
}

bool CefV8ValueImpl::WillRethrowExceptions() {
  CEF_V8_REQUIRE_OBJECT_RETURN(false);

  return rethrow_exceptions_;
}

bool CefV8ValueImpl::SetRethrowExceptions(bool rethrow) {
  CEF_V8_REQUIRE_OBJECT_RETURN(false);

  rethrow_exceptions_ = rethrow;
  return true;
}

bool CefV8ValueImpl::HasValue(const CefString& key) {
  CEF_V8_REQUIRE_OBJECT_RETURN(false);

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return false;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
  return obj->Has(context, GetV8String(isolate, key)).FromJust();
}

bool CefV8ValueImpl::HasValue(int index) {
  CEF_V8_REQUIRE_OBJECT_RETURN(false);

  if (index < 0) {
    NOTREACHED() << "invalid input parameter";
    return false;
  }

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return false;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
  return obj->Has(context, index).FromJust();
}

bool CefV8ValueImpl::DeleteValue(const CefString& key) {
  CEF_V8_REQUIRE_OBJECT_RETURN(false);

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return false;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();

  v8::TryCatch try_catch(isolate);
  try_catch.SetVerbose(true);
  v8::Maybe<bool> del = obj->Delete(context, GetV8String(isolate, key));
  return (!HasCaught(context, try_catch) && del.FromJust());
}

bool CefV8ValueImpl::DeleteValue(int index) {
  CEF_V8_REQUIRE_OBJECT_RETURN(false);

  if (index < 0) {
    NOTREACHED() << "invalid input parameter";
    return false;
  }

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return false;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();

  v8::TryCatch try_catch(isolate);
  try_catch.SetVerbose(true);
  v8::Maybe<bool> del = obj->Delete(context, index);
  return (!HasCaught(context, try_catch) && del.FromJust());
}

CefRefPtr<CefV8Value> CefV8ValueImpl::GetValue(const CefString& key) {
  CEF_V8_REQUIRE_OBJECT_RETURN(nullptr);

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return nullptr;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();

  v8::TryCatch try_catch(isolate);
  try_catch.SetVerbose(true);
  v8::MaybeLocal<v8::Value> ret_value =
      obj->Get(context, GetV8String(isolate, key));
  if (!HasCaught(context, try_catch) && !ret_value.IsEmpty()) {
    return new CefV8ValueImpl(isolate, context, ret_value.ToLocalChecked());
  }
  return nullptr;
}

CefRefPtr<CefV8Value> CefV8ValueImpl::GetValue(int index) {
  CEF_V8_REQUIRE_OBJECT_RETURN(nullptr);

  if (index < 0) {
    NOTREACHED() << "invalid input parameter";
    return nullptr;
  }

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return nullptr;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();

  v8::TryCatch try_catch(isolate);
  try_catch.SetVerbose(true);
  v8::MaybeLocal<v8::Value> ret_value =
      obj->Get(context, v8::Number::New(isolate, index));
  if (!HasCaught(context, try_catch) && !ret_value.IsEmpty()) {
    return new CefV8ValueImpl(isolate, context, ret_value.ToLocalChecked());
  }
  return nullptr;
}

bool CefV8ValueImpl::SetValue(const CefString& key,
                              CefRefPtr<CefV8Value> value,
                              PropertyAttribute attribute) {
  CEF_V8_REQUIRE_OBJECT_RETURN(false);

  CefV8ValueImpl* impl = static_cast<CefV8ValueImpl*>(value.get());
  if (impl && impl->IsValid()) {
    v8::Isolate* isolate = handle_->isolate();
    v8::HandleScope handle_scope(isolate);

    v8::Local<v8::Context> context = isolate->GetCurrentContext();
    if (context.IsEmpty()) {
      NOTREACHED() << "not currently in a V8 context";
      return false;
    }

    v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
    v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();

    v8::TryCatch try_catch(isolate);
    try_catch.SetVerbose(true);
    // TODO(cef): This usage may not exactly match the previous implementation.
    // Set will trigger interceptors and/or accessors whereas DefineOwnProperty
    // will not. It might be better to split this functionality into separate
    // methods.
    if (attribute == V8_PROPERTY_ATTRIBUTE_NONE) {
      v8::Maybe<bool> set =
          obj->Set(context, GetV8String(isolate, key), impl->GetV8Value(true));
      return (!HasCaught(context, try_catch) && set.FromJust());
    } else {
      v8::Maybe<bool> set = obj->DefineOwnProperty(
          context, GetV8String(isolate, key), impl->GetV8Value(true),
          static_cast<v8::PropertyAttribute>(attribute));
      return (!HasCaught(context, try_catch) && set.FromJust());
    }
  } else {
    NOTREACHED() << "invalid input parameter";
    return false;
  }
}

bool CefV8ValueImpl::SetValue(int index, CefRefPtr<CefV8Value> value) {
  CEF_V8_REQUIRE_OBJECT_RETURN(false);

  if (index < 0) {
    NOTREACHED() << "invalid input parameter";
    return false;
  }

  CefV8ValueImpl* impl = static_cast<CefV8ValueImpl*>(value.get());
  if (impl && impl->IsValid()) {
    v8::Isolate* isolate = handle_->isolate();
    v8::HandleScope handle_scope(isolate);

    v8::Local<v8::Context> context = isolate->GetCurrentContext();
    if (context.IsEmpty()) {
      NOTREACHED() << "not currently in a V8 context";
      return false;
    }

    v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
    v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();

    v8::TryCatch try_catch(isolate);
    try_catch.SetVerbose(true);
    v8::Maybe<bool> set = obj->Set(context, index, impl->GetV8Value(true));
    return (!HasCaught(context, try_catch) && set.FromJust());
  } else {
    NOTREACHED() << "invalid input parameter";
    return false;
  }
}

bool CefV8ValueImpl::SetValue(const CefString& key,
                              AccessControl settings,
                              PropertyAttribute attribute) {
  CEF_V8_REQUIRE_OBJECT_RETURN(false);

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return false;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();

  CefRefPtr<CefV8Accessor> accessorPtr;

  V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
  if (tracker)
    accessorPtr = tracker->GetAccessor();

  // Verify that an accessor exists for this object.
  if (!accessorPtr.get())
    return false;

  v8::AccessorNameGetterCallback getter = AccessorNameGetterCallbackImpl;
  v8::AccessorNameSetterCallback setter =
      (attribute & V8_PROPERTY_ATTRIBUTE_READONLY)
          ? nullptr
          : AccessorNameSetterCallbackImpl;

  v8::TryCatch try_catch(isolate);
  try_catch.SetVerbose(true);
  v8::Maybe<bool> set =
      obj->SetAccessor(context, GetV8String(isolate, key), getter, setter, obj,
                       static_cast<v8::AccessControl>(settings),
                       static_cast<v8::PropertyAttribute>(attribute));
  return (!HasCaught(context, try_catch) && set.FromJust());
}

bool CefV8ValueImpl::GetKeys(std::vector<CefString>& keys) {
  CEF_V8_REQUIRE_OBJECT_RETURN(false);

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return false;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
  v8::Local<v8::Array> arr_keys =
      obj->GetPropertyNames(context).ToLocalChecked();

  uint32_t len = arr_keys->Length();
  for (uint32_t i = 0; i < len; ++i) {
    v8::Local<v8::Value> value =
        arr_keys->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked();
    CefString str;
    GetCefString(isolate, value->ToString(context).ToLocalChecked(), str);
    keys.push_back(str);
  }
  return true;
}

bool CefV8ValueImpl::SetUserData(CefRefPtr<CefBaseRefCounted> user_data) {
  CEF_V8_REQUIRE_OBJECT_RETURN(false);

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return false;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();

  V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
  if (tracker) {
    tracker->SetUserData(user_data);
    return true;
  }

  return false;
}

CefRefPtr<CefBaseRefCounted> CefV8ValueImpl::GetUserData() {
  CEF_V8_REQUIRE_OBJECT_RETURN(nullptr);

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return nullptr;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();

  V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
  if (tracker)
    return tracker->GetUserData();

  return nullptr;
}

int CefV8ValueImpl::GetExternallyAllocatedMemory() {
  CEF_V8_REQUIRE_OBJECT_RETURN(0);

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return 0;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();

  V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
  if (tracker)
    return tracker->GetExternallyAllocatedMemory();

  return 0;
}

int CefV8ValueImpl::AdjustExternallyAllocatedMemory(int change_in_bytes) {
  CEF_V8_REQUIRE_OBJECT_RETURN(0);

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return 0;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();

  V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
  if (tracker)
    return tracker->AdjustExternallyAllocatedMemory(change_in_bytes);

  return 0;
}

int CefV8ValueImpl::GetArrayLength() {
  CEF_V8_REQUIRE_OBJECT_RETURN(0);

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return 0;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  if (!value->IsArray()) {
    NOTREACHED() << "V8 value is not an array";
    return 0;
  }

  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
  v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(obj);
  return arr->Length();
}

CefRefPtr<CefV8ArrayBufferReleaseCallback>
CefV8ValueImpl::GetArrayBufferReleaseCallback() {
  CEF_V8_REQUIRE_OBJECT_RETURN(nullptr);

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return nullptr;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  if (!value->IsArrayBuffer()) {
    NOTREACHED() << "V8 value is not an array buffer";
    return nullptr;
  }

  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();

  V8TrackArrayBuffer* tracker = V8TrackArrayBuffer::Unwrap(context, obj);
  if (tracker)
    return tracker->GetReleaseCallback();

  return nullptr;
}

bool CefV8ValueImpl::NeuterArrayBuffer() {
  CEF_V8_REQUIRE_OBJECT_RETURN(0);

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return false;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  if (!value->IsArrayBuffer()) {
    NOTREACHED() << "V8 value is not an array buffer";
    return false;
  }
  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
  v8::Local<v8::ArrayBuffer> arr = v8::Local<v8::ArrayBuffer>::Cast(obj);
  if (!arr->IsDetachable()) {
    return false;
  }
  arr->Detach();
  V8TrackArrayBuffer* tracker = V8TrackArrayBuffer::Unwrap(context, obj);
  tracker->Detach();

  return true;
}

CefString CefV8ValueImpl::GetFunctionName() {
  CefString rv;
  CEF_V8_REQUIRE_OBJECT_RETURN(rv);

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return rv;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  if (!value->IsFunction()) {
    NOTREACHED() << "V8 value is not a function";
    return rv;
  }

  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
  v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(obj);
  GetCefString(handle_->isolate(),
               v8::Handle<v8::String>::Cast(func->GetName()), rv);
  return rv;
}

CefRefPtr<CefV8Handler> CefV8ValueImpl::GetFunctionHandler() {
  CEF_V8_REQUIRE_OBJECT_RETURN(nullptr);

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = isolate->GetCurrentContext();
  if (context.IsEmpty()) {
    NOTREACHED() << "not currently in a V8 context";
    return nullptr;
  }

  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  if (!value->IsFunction()) {
    NOTREACHED() << "V8 value is not a function";
    return nullptr;
  }

  v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
  V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
  if (tracker)
    return tracker->GetHandler();

  return nullptr;
}

CefRefPtr<CefV8Value> CefV8ValueImpl::ExecuteFunction(
    CefRefPtr<CefV8Value> object,
    const CefV8ValueList& arguments) {
  // An empty context value defaults to the current context.
  CefRefPtr<CefV8Context> context;
  return ExecuteFunctionWithContext(context, object, arguments);
}

CefRefPtr<CefV8Value> CefV8ValueImpl::ExecuteFunctionWithContext(
    CefRefPtr<CefV8Context> context,
    CefRefPtr<CefV8Value> object,
    const CefV8ValueList& arguments) {
  CEF_V8_REQUIRE_OBJECT_RETURN(nullptr);

  v8::Isolate* isolate = handle_->isolate();
  v8::HandleScope handle_scope(isolate);
  v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
  if (!value->IsFunction()) {
    NOTREACHED() << "V8 value is not a function";
    return nullptr;
  }

  if (context.get() && !context->IsValid()) {
    NOTREACHED() << "invalid V8 context parameter";
    return nullptr;
  }
  if (object.get() && (!object->IsValid() || !object->IsObject())) {
    NOTREACHED() << "invalid V8 object parameter";
    return nullptr;
  }

  int argc = arguments.size();
  if (argc > 0) {
    for (int i = 0; i < argc; ++i) {
      if (!arguments[i].get() || !arguments[i]->IsValid()) {
        NOTREACHED() << "invalid V8 arguments parameter";
        return nullptr;
      }
    }
  }

  v8::Local<v8::Context> context_local;
  if (context.get()) {
    CefV8ContextImpl* context_impl =
        static_cast<CefV8ContextImpl*>(context.get());
    context_local = context_impl->GetV8Context();
  } else {
    context_local = isolate->GetCurrentContext();
  }

  v8::Context::Scope context_scope(context_local);

  v8::Local<v8::Object> obj = value->ToObject(context_local).ToLocalChecked();
  v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(obj);
  v8::Local<v8::Object> recv;

  // Default to the global object if no object was provided.
  if (object.get()) {
    CefV8ValueImpl* recv_impl = static_cast<CefV8ValueImpl*>(object.get());
    recv = v8::Local<v8::Object>::Cast(recv_impl->GetV8Value(true));
  } else {
    recv = context_local->Global();
  }

  v8::Local<v8::Value>* argv = nullptr;
  if (argc > 0) {
    argv = new v8::Local<v8::Value>[argc];
    for (int i = 0; i < argc; ++i) {
      argv[i] =
          static_cast<CefV8ValueImpl*>(arguments[i].get())->GetV8Value(true);
    }
  }

  CefRefPtr<CefV8Value> retval;

  {
    v8::TryCatch try_catch(isolate);
    try_catch.SetVerbose(true);

    v8::MaybeLocal<v8::Value> func_rv = blink_glue::CallV8Function(
        context_local, func, recv, argc, argv, handle_->isolate());

    if (!HasCaught(context_local, try_catch) && !func_rv.IsEmpty()) {
      retval =
          new CefV8ValueImpl(isolate, context_local, func_rv.ToLocalChecked());
    }
  }

  if (argv)
    delete[] argv;

  return retval;
}

bool CefV8ValueImpl::HasCaught(v8::Local<v8::Context> context,
                               v8::TryCatch& try_catch) {
  if (try_catch.HasCaught()) {
    last_exception_ = new CefV8ExceptionImpl(context, try_catch.Message());
    if (rethrow_exceptions_)
      try_catch.ReThrow();
    return true;
  } else {
    if (last_exception_.get())
      last_exception_ = nullptr;
    return false;
  }
}

// CefV8StackTrace

// static
CefRefPtr<CefV8StackTrace> CefV8StackTrace::GetCurrent(int frame_limit) {
  CEF_V8_REQUIRE_ISOLATE_RETURN(nullptr);

  v8::Isolate* isolate = GetIsolateManager()->isolate();
  v8::HandleScope handle_scope(isolate);
  v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
      isolate, frame_limit, v8::StackTrace::kDetailed);
  if (stackTrace.IsEmpty())
    return nullptr;
  return new CefV8StackTraceImpl(isolate, stackTrace);
}

// CefV8StackTraceImpl

CefV8StackTraceImpl::CefV8StackTraceImpl(v8::Isolate* isolate,
                                         v8::Local<v8::StackTrace> handle) {
  if (!handle.IsEmpty()) {
    int frame_count = handle->GetFrameCount();
    if (frame_count > 0) {
      frames_.reserve(frame_count);
      for (int i = 0; i < frame_count; ++i)
        frames_.push_back(
            new CefV8StackFrameImpl(isolate, handle->GetFrame(isolate, i)));
    }
  }
}

CefV8StackTraceImpl::~CefV8StackTraceImpl() {}

bool CefV8StackTraceImpl::IsValid() {
  return true;
}

int CefV8StackTraceImpl::GetFrameCount() {
  return frames_.size();
}

CefRefPtr<CefV8StackFrame> CefV8StackTraceImpl::GetFrame(int index) {
  if (index < 0 || index >= static_cast<int>(frames_.size()))
    return nullptr;
  return frames_[index];
}

// CefV8StackFrameImpl

CefV8StackFrameImpl::CefV8StackFrameImpl(v8::Isolate* isolate,
                                         v8::Local<v8::StackFrame> handle)
    : line_number_(0), column_(0), is_eval_(false), is_constructor_(false) {
  if (handle.IsEmpty())
    return;
  GetCefString(isolate, handle->GetScriptName(), script_name_);
  GetCefString(isolate, handle->GetScriptNameOrSourceURL(),
               script_name_or_source_url_);
  GetCefString(isolate, handle->GetFunctionName(), function_name_);
  line_number_ = handle->GetLineNumber();
  column_ = handle->GetColumn();
  is_eval_ = handle->IsEval();
  is_constructor_ = handle->IsConstructor();
}

CefV8StackFrameImpl::~CefV8StackFrameImpl() {}

bool CefV8StackFrameImpl::IsValid() {
  return true;
}

CefString CefV8StackFrameImpl::GetScriptName() {
  return script_name_;
}

CefString CefV8StackFrameImpl::GetScriptNameOrSourceURL() {
  return script_name_or_source_url_;
}

CefString CefV8StackFrameImpl::GetFunctionName() {
  return function_name_;
}

int CefV8StackFrameImpl::GetLineNumber() {
  return line_number_;
}

int CefV8StackFrameImpl::GetColumn() {
  return column_;
}

bool CefV8StackFrameImpl::IsEval() {
  return is_eval_;
}

bool CefV8StackFrameImpl::IsConstructor() {
  return is_constructor_;
}

// Enable deprecation warnings on Windows. See http://crbug.com/585142.
#if defined(OS_WIN)
#if defined(__clang__)
#pragma GCC diagnostic pop
#else
#pragma warning(pop)
#endif
#endif
