// Copyright 2017 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 "chrome/renderer/extensions/extension_hooks_delegate.h"

#include "content/public/renderer/v8_value_converter.h"
#include "extensions/common/api/messaging/message.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest.h"
#include "extensions/common/mojom/view_type.mojom.h"
#include "extensions/common/view_type_util.h"
#include "extensions/renderer/bindings/api_signature.h"
#include "extensions/renderer/extension_frame_helper.h"
#include "extensions/renderer/extensions_renderer_client.h"
#include "extensions/renderer/get_script_context.h"
#include "extensions/renderer/message_target.h"
#include "extensions/renderer/messaging_util.h"
#include "extensions/renderer/native_renderer_messaging_service.h"
#include "extensions/renderer/runtime_hooks_delegate.h"
#include "extensions/renderer/script_context.h"
#include "gin/converter.h"
#include "gin/dictionary.h"

namespace extensions {

namespace {

using RequestResult = APIBindingHooks::RequestResult;

constexpr char kSendExtensionRequest[] = "extension.sendRequest";
constexpr char kGetURL[] = "extension.getURL";
constexpr char kGetBackgroundPage[] = "extension.getBackgroundPage";
constexpr char kGetViews[] = "extension.getViews";
constexpr char kGetExtensionTabs[] = "extension.getExtensionTabs";

// We alias a bunch of chrome.extension APIs to their chrome.runtime
// counterparts.
// NOTE(devlin): This is a very simple alias, in which we just return the
// runtime version from the chrome.runtime object. This is important to note
// for a few reasons:
// - Modifications to the chrome.runtime object will affect the return result
//   here. i.e., if script does chrome.runtime.sendMessage = 'some string',
//   then chrome.extension.sendMessage will also be 'some string'.
// - Events will share listeners. i.e., a listener added to
//   chrome.extension.onMessage will fire from a runtime.onMessage event, and
//   vice versa.
// All of these APIs have been deprecated, and are no longer even documented,
// but still have usage. This is the cheap workaround that JS bindings have been
// using, and, while not robust, it should be secure, so use it native bindings,
// too.
void GetAliasedFeature(v8::Local<v8::Name> property_name,
                       const v8::PropertyCallbackInfo<v8::Value>& info) {
  v8::Isolate* isolate = info.GetIsolate();
  v8::HandleScope handle_scope(isolate);
  v8::Local<v8::Context> context = info.Holder()->CreationContext();

  v8::TryCatch try_catch(isolate);
  v8::Local<v8::Value> chrome;
  if (!context->Global()
           ->Get(context, gin::StringToSymbol(isolate, "chrome"))
           .ToLocal(&chrome) ||
      !chrome->IsObject()) {
    return;
  }

  v8::Local<v8::Value> runtime;
  if (!chrome.As<v8::Object>()
           ->Get(context, gin::StringToSymbol(isolate, "runtime"))
           .ToLocal(&runtime) ||
      !runtime->IsObject()) {
    return;
  }

  v8::Local<v8::Object> runtime_obj = runtime.As<v8::Object>();
  v8::Maybe<bool> has_property =
      runtime_obj->HasRealNamedProperty(context, property_name);
  if (!has_property.IsJust() || !has_property.FromJust())
    return;

  v8::Local<v8::Value> property_value;
  // Try and grab the chrome.runtime version. It's possible this has been
  // tampered with, so early-out if an exception is thrown.
  if (!runtime_obj->Get(context, property_name).ToLocal(&property_value))
    return;

  info.GetReturnValue().Set(property_value);
}

// A helper method to throw a deprecation error on access.
void ThrowDeprecatedAccessError(
    v8::Local<v8::Name> name,
    const v8::PropertyCallbackInfo<v8::Value>& info) {
  static constexpr char kError[] =
      "extension.sendRequest, extension.onRequest, and "
      "extension.onRequestExternal are deprecated. Please use "
      "runtime.sendMessage, runtime.onMessage, and runtime.onMessageExternal "
      "instead.";
  v8::Isolate* isolate = info.GetIsolate();
  isolate->ThrowException(
      v8::Exception::Error(gin::StringToV8(isolate, kError)));
}

}  // namespace

ExtensionHooksDelegate::ExtensionHooksDelegate(
    NativeRendererMessagingService* messaging_service)
    : messaging_service_(messaging_service) {}
ExtensionHooksDelegate::~ExtensionHooksDelegate() {}

RequestResult ExtensionHooksDelegate::HandleRequest(
    const std::string& method_name,
    const APISignature* signature,
    v8::Local<v8::Context> context,
    std::vector<v8::Local<v8::Value>>* arguments,
    const APITypeReferenceMap& refs) {
  // TODO(devlin): This logic is the same in the RuntimeCustomHooksDelegate -
  // would it make sense to share it?
  using Handler = RequestResult (ExtensionHooksDelegate::*)(
      ScriptContext*, const std::vector<v8::Local<v8::Value>>&);
  static struct {
    Handler handler;
    base::StringPiece method;
  } kHandlers[] = {
      {&ExtensionHooksDelegate::HandleSendRequest, kSendExtensionRequest},
      {&ExtensionHooksDelegate::HandleGetURL, kGetURL},
      {&ExtensionHooksDelegate::HandleGetBackgroundPage, kGetBackgroundPage},
      {&ExtensionHooksDelegate::HandleGetExtensionTabs, kGetExtensionTabs},
      {&ExtensionHooksDelegate::HandleGetViews, kGetViews},
  };

  ScriptContext* script_context = GetScriptContextFromV8ContextChecked(context);

  Handler handler = nullptr;
  for (const auto& handler_entry : kHandlers) {
    if (handler_entry.method == method_name) {
      handler = handler_entry.handler;
      break;
    }
  }

  if (!handler)
    return RequestResult(RequestResult::NOT_HANDLED);

  if (method_name == kSendExtensionRequest) {
    messaging_util::MassageSendMessageArguments(context->GetIsolate(), false,
                                                arguments);
  }

  APISignature::V8ParseResult parse_result =
      signature->ParseArgumentsToV8(context, *arguments, refs);
  if (!parse_result.succeeded()) {
    RequestResult result(RequestResult::INVALID_INVOCATION);
    result.error = std::move(*parse_result.error);
    return result;
  }

  return (this->*handler)(script_context, *parse_result.arguments);
}

void ExtensionHooksDelegate::InitializeTemplate(
    v8::Isolate* isolate,
    v8::Local<v8::ObjectTemplate> object_template,
    const APITypeReferenceMap& type_refs) {
  bool is_incognito = ExtensionsRendererClient::Get()->IsIncognitoProcess();
  object_template->Set(isolate, "inIncognitoContext",
                       v8::Boolean::New(isolate, is_incognito));
}

void ExtensionHooksDelegate::InitializeInstance(
    v8::Local<v8::Context> context,
    v8::Local<v8::Object> instance) {
  v8::Isolate* isolate = context->GetIsolate();
  ScriptContext* script_context = GetScriptContextFromV8ContextChecked(context);

  // Throw access errors for deprecated sendRequest-related properties. This
  // isn't terribly efficient, but is only done for certain unpacked extensions
  // and only if they access the chrome.extension module.
  if (messaging_util::IsSendRequestDisabled(script_context)) {
    static constexpr const char* kDeprecatedSendRequestProperties[] = {
        "sendRequest", "onRequest", "onRequestExternal"};
    for (const char* property : kDeprecatedSendRequestProperties) {
      v8::Maybe<bool> success =
          instance->SetAccessor(context, gin::StringToV8(isolate, property),
                                &ThrowDeprecatedAccessError);
      DCHECK(success.IsJust());
      DCHECK(success.FromJust());
    }
  }

  constexpr int kMaxManifestVersionForAliases = 2;

  if (script_context->extension() &&
      script_context->extension()->manifest_version() <=
          kMaxManifestVersionForAliases) {
    static constexpr const char* kAliases[] = {
        "connect",   "connectNative",     "sendMessage", "sendNativeMessage",
        "onConnect", "onConnectExternal", "onMessage",   "onMessageExternal",
    };

    for (const auto* alias : kAliases) {
      v8::Maybe<bool> success = instance->SetAccessor(
          context, gin::StringToV8(isolate, alias), &GetAliasedFeature);
      DCHECK(success.IsJust());
      DCHECK(success.FromJust());
    }
  }
}

RequestResult ExtensionHooksDelegate::HandleSendRequest(
    ScriptContext* script_context,
    const std::vector<v8::Local<v8::Value>>& arguments) {
  DCHECK_EQ(3u, arguments.size());
  // This DCHECK() is correct because no context with sendRequest-related
  // APIs disabled should have scriptable access to a context with them
  // enabled.
  DCHECK(!messaging_util::IsSendRequestDisabled(script_context));

  std::string target_id;
  std::string error;
  if (!messaging_util::GetTargetExtensionId(script_context, arguments[0],
                                            "extension.sendRequest", &target_id,
                                            &error)) {
    RequestResult result(RequestResult::INVALID_INVOCATION);
    result.error = std::move(error);
    return result;
  }

  v8::Local<v8::Value> v8_message = arguments[1];

  std::unique_ptr<Message> message = messaging_util::MessageFromV8(
      script_context->v8_context(), v8_message,
      messaging_util::GetSerializationFormat(*script_context), &error);
  if (!message) {
    RequestResult result(RequestResult::INVALID_INVOCATION);
    result.error = std::move(error);
    return result;
  }

  v8::Local<v8::Function> response_callback;
  if (!arguments[2]->IsNull())
    response_callback = arguments[2].As<v8::Function>();

  messaging_service_->SendOneTimeMessage(
      script_context, MessageTarget::ForExtension(target_id),
      messaging_util::kSendRequestChannel, *message, response_callback);

  return RequestResult(RequestResult::HANDLED);
}

RequestResult ExtensionHooksDelegate::HandleGetURL(
    ScriptContext* script_context,
    const std::vector<v8::Local<v8::Value>>& arguments) {
  // We call a static implementation here rather using an alias due to not being
  // able to remove the extension.json GetURL entry, as it is used for generated
  // documentation and api feature lists some other methods refer to.
  return RuntimeHooksDelegate::GetURL(script_context, arguments);
}

APIBindingHooks::RequestResult ExtensionHooksDelegate::HandleGetViews(
    ScriptContext* script_context,
    const std::vector<v8::Local<v8::Value>>& arguments) {
  const Extension* extension = script_context->extension();
  DCHECK(extension);

  mojom::ViewType view_type = mojom::ViewType::kInvalid;
  int window_id = extension_misc::kUnknownWindowId;
  int tab_id = extension_misc::kUnknownTabId;

  if (!arguments[0]->IsNull()) {
    gin::Dictionary options_dict(script_context->isolate(),
                                 arguments[0].As<v8::Object>());
    v8::Local<v8::Value> v8_window_id;
    v8::Local<v8::Value> v8_tab_id;
    v8::Local<v8::Value> v8_view_type;
    if (!options_dict.Get("windowId", &v8_window_id) ||
        !options_dict.Get("tabId", &v8_tab_id) ||
        !options_dict.Get("type", &v8_view_type)) {
      NOTREACHED()
          << "Unexpected exception: argument parsing produces plain objects";
      return RequestResult(RequestResult::THROWN);
    }

    if (!v8_window_id->IsUndefined()) {
      DCHECK(v8_window_id->IsInt32());
      window_id = v8_window_id.As<v8::Int32>()->Value();
    }

    if (!v8_tab_id->IsUndefined()) {
      DCHECK(v8_tab_id->IsInt32());
      tab_id = v8_tab_id.As<v8::Int32>()->Value();
    }

    if (!v8_view_type->IsUndefined()) {
      DCHECK(v8_view_type->IsString());
      std::string view_type_string = base::ToUpperASCII(
          gin::V8ToString(script_context->isolate(), v8_view_type));
      if (view_type_string != "ALL") {
        bool success = GetViewTypeFromString(view_type_string, &view_type);
        DCHECK(success);
      }
    }
  }

  RequestResult result(RequestResult::HANDLED);
  result.return_value = ExtensionFrameHelper::GetV8MainFrames(
      script_context->v8_context(), extension->id(), window_id, tab_id,
      view_type);
  return result;
}

RequestResult ExtensionHooksDelegate::HandleGetExtensionTabs(
    ScriptContext* script_context,
    const std::vector<v8::Local<v8::Value>>& arguments) {
  const Extension* extension = script_context->extension();
  DCHECK(extension);

  mojom::ViewType view_type = mojom::ViewType::kTabContents;
  int window_id = extension_misc::kUnknownWindowId;
  int tab_id = extension_misc::kUnknownTabId;

  if (!arguments[0]->IsNull())
    window_id = arguments[0].As<v8::Int32>()->Value();

  RequestResult result(RequestResult::HANDLED);
  result.return_value = ExtensionFrameHelper::GetV8MainFrames(
      script_context->v8_context(), extension->id(), window_id, tab_id,
      view_type);
  return result;
}

RequestResult ExtensionHooksDelegate::HandleGetBackgroundPage(
    ScriptContext* script_context,
    const std::vector<v8::Local<v8::Value>>& arguments) {
  const Extension* extension = script_context->extension();
  DCHECK(extension);

  RequestResult result(RequestResult::HANDLED);
  result.return_value = ExtensionFrameHelper::GetV8BackgroundPageMainFrame(
      script_context->isolate(), extension->id());
  return result;
}

}  // namespace extensions
