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

#include "extensions/renderer/v8_schema_registry.h"

#include <stddef.h>

#include <utility>

#include "base/bind.h"
#include "base/check.h"
#include "base/values.h"
#include "content/public/renderer/v8_value_converter.h"
#include "extensions/common/extension_api.h"
#include "extensions/renderer/object_backed_native_handler.h"
#include "extensions/renderer/script_context.h"
#include "extensions/renderer/static_v8_external_one_byte_string_resource.h"
#include "extensions/renderer/v8_helpers.h"

using content::V8ValueConverter;

namespace extensions {

namespace {

// Recursively freezes every v8 object on |object|.
void DeepFreeze(const v8::Local<v8::Object>& object,
                const v8::Local<v8::Context>& context) {
  // Don't let the object trace upwards via the prototype.
  v8::Maybe<bool> maybe =
      object->SetPrototype(context, v8::Null(context->GetIsolate()));
  CHECK(maybe.IsJust() && maybe.FromJust());
  v8::Local<v8::Array> property_names =
      object->GetOwnPropertyNames(context).ToLocalChecked();
  for (uint32_t i = 0; i < property_names->Length(); ++i) {
    v8::Local<v8::Value> child =
        object->Get(context, property_names->Get(context, i).ToLocalChecked())
            .ToLocalChecked();
    if (child->IsObject())
      DeepFreeze(v8::Local<v8::Object>::Cast(child), context);
  }
  object->SetIntegrityLevel(context, v8::IntegrityLevel::kFrozen);
}

class SchemaRegistryNativeHandler : public ObjectBackedNativeHandler {
 public:
  SchemaRegistryNativeHandler(V8SchemaRegistry* registry,
                              std::unique_ptr<ScriptContext> context)
      : ObjectBackedNativeHandler(context.get()),
        context_(std::move(context)),
        registry_(registry) {}

  // ObjectBackedNativeHandler:
  void AddRoutes() override {
    RouteHandlerFunction(
        "GetSchema",
        base::BindRepeating(&SchemaRegistryNativeHandler::GetSchema,
                            base::Unretained(this)));
    RouteHandlerFunction(
        "GetObjectType",
        base::BindRepeating(&SchemaRegistryNativeHandler::GetObjectType,
                            base::Unretained(this)));
  }

  ~SchemaRegistryNativeHandler() override { context_->Invalidate(); }

 private:
  void GetSchema(const v8::FunctionCallbackInfo<v8::Value>& args) {
    args.GetReturnValue().Set(registry_->GetSchema(
        *v8::String::Utf8Value(args.GetIsolate(), args[0])));
  }

  void GetObjectType(const v8::FunctionCallbackInfo<v8::Value>& args) {
    CHECK(args.Length() == 1 && args[0]->IsObject());
    std::string type;
    if (args[0]->IsArray())
      type = "array";
    else if (args[0]->IsArrayBuffer() || args[0]->IsArrayBufferView())
      type = "binary";
    else
      type = "object";
    args.GetReturnValue().Set(
        v8_helpers::ToV8StringUnsafe(context()->isolate(), type.c_str()));
  }

  std::unique_ptr<ScriptContext> context_;
  V8SchemaRegistry* registry_;
};

}  // namespace

V8SchemaRegistry::V8SchemaRegistry() {
}

V8SchemaRegistry::~V8SchemaRegistry() {
}

std::unique_ptr<NativeHandler> V8SchemaRegistry::AsNativeHandler() {
  std::unique_ptr<ScriptContext> context(
      new ScriptContext(GetOrCreateContext(v8::Isolate::GetCurrent()),
                        NULL,  // no frame
                        NULL,  // no extension
                        Feature::UNSPECIFIED_CONTEXT,
                        NULL,  // no effective extension
                        Feature::UNSPECIFIED_CONTEXT));
  return std::unique_ptr<NativeHandler>(
      new SchemaRegistryNativeHandler(this, std::move(context)));
}

v8::Local<v8::Array> V8SchemaRegistry::GetSchemas(
    const std::vector<std::string>& apis) {
  v8::Isolate* isolate = v8::Isolate::GetCurrent();
  v8::EscapableHandleScope handle_scope(isolate);
  v8::Local<v8::Context> context = GetOrCreateContext(isolate);
  v8::Context::Scope context_scope(context);

  v8::Local<v8::Array> v8_apis(v8::Array::New(isolate, apis.size()));
  size_t api_index = 0;
  for (auto i = apis.cbegin(); i != apis.cend(); ++i) {
    bool set_result =
        v8_apis->Set(context, api_index++, GetSchema(*i)).ToChecked();
    // Set() should never return false without throwing an exception (which
    // would be caught by the ToChecked() above).
    DCHECK(set_result);
  }
  return handle_scope.Escape(v8_apis);
}

v8::Local<v8::Object> V8SchemaRegistry::GetSchema(const std::string& api) {
  if (schema_cache_ != NULL) {
    v8::Local<v8::Object> cached_schema = schema_cache_->Get(api);
    if (!cached_schema.IsEmpty()) {
      return cached_schema;
    }
  }

  // Slow path: Need to build schema first.

  v8::Isolate* isolate = v8::Isolate::GetCurrent();
  v8::EscapableHandleScope handle_scope(isolate);
  v8::Local<v8::Context> context = GetOrCreateContext(isolate);
  v8::Context::Scope context_scope(context);

  base::StringPiece schema_string =
      ExtensionAPI::GetSharedInstance()->GetSchemaStringPiece(api);
  CHECK(!schema_string.empty());
  v8::MaybeLocal<v8::String> v8_maybe_string = v8::String::NewExternalOneByte(
      isolate, new StaticV8ExternalOneByteStringResource(schema_string));
  v8::Local<v8::String> v8_schema_string;
  CHECK(v8_maybe_string.ToLocal(&v8_schema_string));

  v8::MaybeLocal<v8::Value> v8_maybe_schema_value =
      v8::JSON::Parse(context, v8_schema_string);
  v8::Local<v8::Value> v8_schema_value;
  CHECK(v8_maybe_schema_value.ToLocal(&v8_schema_value));
  CHECK(v8_schema_value->IsObject());

  v8::Local<v8::Object> v8_schema_object(
      v8::Local<v8::Object>::Cast(v8_schema_value));
  DeepFreeze(v8_schema_object, context);

  schema_cache_->Set(api, v8_schema_object);

  return handle_scope.Escape(v8_schema_object);
}

v8::Local<v8::Context> V8SchemaRegistry::GetOrCreateContext(
    v8::Isolate* isolate) {
  // It's ok to create local handles in this function, since this is only called
  // when we have a HandleScope.
  if (!context_holder_) {
    context_holder_.reset(new gin::ContextHolder(isolate));
    context_holder_->SetContext(v8::Context::New(isolate));
    schema_cache_.reset(new SchemaCache(isolate));
    return context_holder_->context();
  }
  return context_holder_->context();
}

}  // namespace extensions
