// 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 "extensions/renderer/native_renderer_messaging_service.h"

#include <memory>

#include "base/macros.h"
#include "base/stl_util.h"
#include "components/crx_file/id_util.h"
#include "content/public/common/child_process_host.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/value_builder.h"
#include "extensions/renderer/bindings/api_binding_test_util.h"
#include "extensions/renderer/message_target.h"
#include "extensions/renderer/messaging_util.h"
#include "extensions/renderer/native_extension_bindings_system.h"
#include "extensions/renderer/native_extension_bindings_system_test_base.h"
#include "extensions/renderer/script_context.h"
#include "extensions/renderer/script_context_set.h"

namespace extensions {

class NativeRendererMessagingServiceTest
    : public NativeExtensionBindingsSystemUnittest {
 public:
  NativeRendererMessagingServiceTest() {}
  ~NativeRendererMessagingServiceTest() override {}

  // NativeExtensionBindingsSystemUnittest:
  void SetUp() override {
    NativeExtensionBindingsSystemUnittest::SetUp();
    messaging_service_ =
        std::make_unique<NativeRendererMessagingService>(bindings_system());

    extension_ = ExtensionBuilder("foo").Build();
    RegisterExtension(extension_);

    v8::HandleScope handle_scope(isolate());
    v8::Local<v8::Context> context = MainContext();

    script_context_ = CreateScriptContext(context, extension_.get(),
                                          Feature::BLESSED_EXTENSION_CONTEXT);
    script_context_->set_url(extension_->url());
    bindings_system()->UpdateBindingsForContext(script_context_);
  }
  void TearDown() override {
    script_context_ = nullptr;
    extension_ = nullptr;
    messaging_service_.reset();
    NativeExtensionBindingsSystemUnittest::TearDown();
  }
  bool UseStrictIPCMessageSender() override { return true; }

  NativeRendererMessagingService* messaging_service() {
    return messaging_service_.get();
  }
  ScriptContext* script_context() { return script_context_; }
  const Extension* extension() { return extension_.get(); }

 private:
  std::unique_ptr<NativeRendererMessagingService> messaging_service_;

  ScriptContext* script_context_ = nullptr;
  scoped_refptr<const Extension> extension_;

  DISALLOW_COPY_AND_ASSIGN(NativeRendererMessagingServiceTest);
};

TEST_F(NativeRendererMessagingServiceTest, ValidateMessagePort) {
  v8::HandleScope handle_scope(isolate());

  base::UnguessableToken other_context_id = base::UnguessableToken::Create();
  const PortId port_id(other_context_id, 0, false);

  EXPECT_FALSE(
      messaging_service()->HasPortForTesting(script_context(), port_id));
  EXPECT_CALL(*ipc_message_sender(),
              SendCloseMessagePort(MSG_ROUTING_NONE, port_id, false));
  messaging_service()->ValidateMessagePort(*script_context_set(), port_id,
                                           nullptr);
  ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());

  messaging_service()->CreatePortForTesting(script_context(), "channel",
                                            port_id);
  EXPECT_TRUE(
      messaging_service()->HasPortForTesting(script_context(), port_id));

  // With a valid port, we shouldn't dispatch a message to close it.
  messaging_service()->ValidateMessagePort(*script_context_set(), port_id,
                                           nullptr);
}

TEST_F(NativeRendererMessagingServiceTest, OpenMessagePort) {
  v8::HandleScope handle_scope(isolate());
  v8::Local<v8::Context> context = MainContext();

  base::UnguessableToken other_context_id = base::UnguessableToken::Create();
  const PortId port_id(other_context_id, 0, false);
  EXPECT_FALSE(
      messaging_service()->HasPortForTesting(script_context(), port_id));

  const std::string channel_name = "some channel";
  ExtensionMsg_TabConnectionInfo tab_connection_info;
  tab_connection_info.frame_id = 0;
  const int tab_id = 10;
  GURL source_url("http://example.com");
  tab_connection_info.tab.Swap(
      DictionaryBuilder().Set("tabId", tab_id).Build().get());
  ExtensionMsg_ExternalConnectionInfo external_connection_info;
  external_connection_info.target_id = extension()->id();
  external_connection_info.source_id = extension()->id();
  external_connection_info.source_url = source_url;
  external_connection_info.guest_process_id =
      content::ChildProcessHost::kInvalidUniqueID;
  external_connection_info.guest_render_frame_routing_id = 0;

  const char kAddListener[] =
      "(function() {\n"
      "  chrome.runtime.onConnect.addListener(function(port) {\n"
      "    this.eventFired = true;\n"
      "    this.sender = port.sender\n"
      "  });\n"
      "})";
  v8::Local<v8::Function> add_listener =
      FunctionFromString(context, kAddListener);
  RunFunctionOnGlobal(add_listener, context, 0, nullptr);

  EXPECT_CALL(*ipc_message_sender(),
              SendOpenMessagePort(MSG_ROUTING_NONE, port_id));
  messaging_service()->DispatchOnConnect(*script_context_set(), port_id,
                                         channel_name, tab_connection_info,
                                         external_connection_info, nullptr);
  ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());

  ASSERT_TRUE(
      messaging_service()->HasPortForTesting(script_context(), port_id));

  EXPECT_EQ("true", GetStringPropertyFromObject(context->Global(), context,
                                                "eventFired"));
  std::unique_ptr<base::DictionaryValue> expected_sender =
      DictionaryBuilder()
          .Set("frameId", 0)
          .Set("tab", DictionaryBuilder().Set("tabId", tab_id).Build())
          .Set("url", source_url.spec())
          .Set("id", extension()->id())
          .Build();
  EXPECT_EQ(ValueToString(*expected_sender),
            GetStringPropertyFromObject(context->Global(), context, "sender"));
}

TEST_F(NativeRendererMessagingServiceTest, DeliverMessageToPort) {
  v8::HandleScope handle_scope(isolate());
  v8::Local<v8::Context> context = MainContext();

  base::UnguessableToken other_context_id = base::UnguessableToken::Create();
  const PortId port_id1(other_context_id, 0, false);
  const PortId port_id2(other_context_id, 1, false);

  gin::Handle<GinPort> port1 = messaging_service()->CreatePortForTesting(
      script_context(), "channel1", port_id1);
  gin::Handle<GinPort> port2 = messaging_service()->CreatePortForTesting(
      script_context(), "channel2", port_id2);
  ASSERT_FALSE(port1.IsEmpty());

  const char kOnMessageListenerTemplate[] =
      "(function(port) {\n"
      "  port.onMessage.addListener((message) => {\n"
      "    this.%s = message;\n"
      "  });\n"
      "})";
  const char kPort1Message[] = "port1Message";
  const char kPort2Message[] = "port2Message";
  {
    v8::Local<v8::Function> add_on_message_listener = FunctionFromString(
        context, base::StringPrintf(kOnMessageListenerTemplate, kPort1Message));
    v8::Local<v8::Value> args[] = {port1.ToV8()};
    RunFunctionOnGlobal(add_on_message_listener, context, base::size(args),
                        args);
  }
  {
    v8::Local<v8::Function> add_on_message_listener = FunctionFromString(
        context, base::StringPrintf(kOnMessageListenerTemplate, kPort2Message));
    v8::Local<v8::Value> args[] = {port2.ToV8()};
    RunFunctionOnGlobal(add_on_message_listener, context, base::size(args),
                        args);
  }

  // We've only added listeners (not dispatched any messages), so neither
  // listener should have been triggered.
  v8::Local<v8::Object> global = context->Global();
  EXPECT_EQ("undefined",
            GetStringPropertyFromObject(global, context, kPort1Message));
  EXPECT_EQ("undefined",
            GetStringPropertyFromObject(global, context, kPort2Message));

  const char kMessageString[] = R"({"data":"hello"})";
  messaging_service()->DeliverMessage(*script_context_set(), port_id1,
                                      Message(kMessageString, false), nullptr);

  // Only port1 should have been notified of the message (ports only receive
  // messages directed to themselves).
  EXPECT_EQ(kMessageString,
            GetStringPropertyFromObject(global, context, kPort1Message));
  EXPECT_EQ("undefined",
            GetStringPropertyFromObject(global, context, kPort2Message));
}

TEST_F(NativeRendererMessagingServiceTest, DisconnectMessagePort) {
  v8::HandleScope handle_scope(isolate());
  v8::Local<v8::Context> context = MainContext();

  base::UnguessableToken other_context_id = base::UnguessableToken::Create();
  const PortId port_id1(other_context_id, 0, false);
  const PortId port_id2(other_context_id, 1, false);

  gin::Handle<GinPort> port1 = messaging_service()->CreatePortForTesting(
      script_context(), "channel1", port_id1);
  gin::Handle<GinPort> port2 = messaging_service()->CreatePortForTesting(
      script_context(), "channel2", port_id2);

  const char kOnDisconnectListenerTemplate[] =
      "(function(port) {\n"
      "  port.onDisconnect.addListener(() => {\n"
      "    this.%s = true;\n"
      "  });\n"
      "})";
  const char kPort1Disconnect[] = "port1Disconnect";
  const char kPort2Disconnect[] = "port2Disconnect";
  {
    v8::Local<v8::Function> add_on_disconnect_listener = FunctionFromString(
        context,
        base::StringPrintf(kOnDisconnectListenerTemplate, kPort1Disconnect));
    v8::Local<v8::Value> args[] = {port1.ToV8()};
    RunFunctionOnGlobal(add_on_disconnect_listener, context, base::size(args),
                        args);
  }
  {
    v8::Local<v8::Function> add_on_disconnect_listener = FunctionFromString(
        context,
        base::StringPrintf(kOnDisconnectListenerTemplate, kPort2Disconnect));
    v8::Local<v8::Value> args[] = {port2.ToV8()};
    RunFunctionOnGlobal(add_on_disconnect_listener, context, base::size(args),
                        args);
  }

  v8::Local<v8::Object> global = context->Global();
  EXPECT_EQ("undefined",
            GetStringPropertyFromObject(global, context, kPort1Disconnect));
  EXPECT_EQ("undefined",
            GetStringPropertyFromObject(global, context, kPort2Disconnect));

  messaging_service()->DispatchOnDisconnect(*script_context_set(), port_id1,
                                            std::string(), nullptr);

  EXPECT_EQ("true",
            GetStringPropertyFromObject(global, context, kPort1Disconnect));
  EXPECT_EQ("undefined",
            GetStringPropertyFromObject(global, context, kPort2Disconnect));
}

TEST_F(NativeRendererMessagingServiceTest, PostMessageFromJS) {
  v8::HandleScope handle_scope(isolate());
  v8::Local<v8::Context> context = MainContext();

  base::UnguessableToken other_context_id = base::UnguessableToken::Create();
  const PortId port_id(other_context_id, 0, false);

  gin::Handle<GinPort> port = messaging_service()->CreatePortForTesting(
      script_context(), "channel", port_id);
  v8::Local<v8::Object> port_object = port.ToV8().As<v8::Object>();

  const char kDispatchMessage[] =
      "(function(port) {\n"
      "  port.postMessage({data: 'hello'});\n"
      "})";
  v8::Local<v8::Function> post_message =
      FunctionFromString(context, kDispatchMessage);
  v8::Local<v8::Value> args[] = {port_object};

  EXPECT_CALL(*ipc_message_sender(),
              SendPostMessageToPort(MSG_ROUTING_NONE, port_id,
                                    Message(R"({"data":"hello"})", false)));
  RunFunctionOnGlobal(post_message, context, base::size(args), args);
  ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());
}

TEST_F(NativeRendererMessagingServiceTest, DisconnectFromJS) {
  v8::HandleScope handle_scope(isolate());
  v8::Local<v8::Context> context = MainContext();

  base::UnguessableToken other_context_id = base::UnguessableToken::Create();
  const PortId port_id(other_context_id, 0, false);

  gin::Handle<GinPort> port = messaging_service()->CreatePortForTesting(
      script_context(), "channel", port_id);
  v8::Local<v8::Object> port_object = port.ToV8().As<v8::Object>();

  const char kDispatchMessage[] =
      "(function(port) {\n"
      "  port.disconnect();\n"
      "})";
  v8::Local<v8::Function> post_message =
      FunctionFromString(context, kDispatchMessage);
  v8::Local<v8::Value> args[] = {port_object};

  EXPECT_CALL(*ipc_message_sender(),
              SendCloseMessagePort(MSG_ROUTING_NONE, port_id, true));
  RunFunctionOnGlobal(post_message, context, base::size(args), args);
  ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());
}

TEST_F(NativeRendererMessagingServiceTest, Connect) {
  v8::HandleScope handle_scope(isolate());

  const std::string kChannel = "channel";
  PortId expected_port_id(script_context()->context_id(), 0, true);
  MessageTarget target(MessageTarget::ForExtension(extension()->id()));
  EXPECT_CALL(*ipc_message_sender(),
              SendOpenMessageChannel(script_context(), expected_port_id, target,
                                     kChannel, false));
  gin::Handle<GinPort> new_port =
      messaging_service()->Connect(script_context(), target, "channel", false);
  ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());
  ASSERT_FALSE(new_port.IsEmpty());

  EXPECT_EQ(expected_port_id, new_port->port_id());
  EXPECT_EQ(kChannel, new_port->name());
  EXPECT_FALSE(new_port->is_closed_for_testing());
}

// Tests sending a one-time message through the messaging service. Note that
// this is more thoroughly tested in the OneTimeMessageHandler tests; this is
// just to ensure NativeRendererMessagingService correctly forwards the calls.
TEST_F(NativeRendererMessagingServiceTest, SendOneTimeMessage) {
  v8::HandleScope handle_scope(isolate());
  v8::Local<v8::Context> context = MainContext();

  const std::string kChannel = "chrome.runtime.sendMessage";
  PortId port_id(script_context()->context_id(), 0, true);
  const char kEchoArgs[] =
      "(function() { this.replyArgs = Array.from(arguments); })";
  v8::Local<v8::Function> response_callback =
      FunctionFromString(context, kEchoArgs);

  // Send a message and expect a reply. A new port should be created, and should
  // remain open (waiting for the response).
  const Message message("\"hi\"", false);
  bool include_tls_channel_id = false;
  MessageTarget target(MessageTarget::ForExtension(extension()->id()));
  EXPECT_CALL(*ipc_message_sender(),
              SendOpenMessageChannel(script_context(), port_id, target,
                                     kChannel, include_tls_channel_id));
  EXPECT_CALL(*ipc_message_sender(),
              SendPostMessageToPort(MSG_ROUTING_NONE, port_id, message));
  messaging_service()->SendOneTimeMessage(script_context(), target, kChannel,
                                          include_tls_channel_id, message,
                                          response_callback);
  ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());
  EXPECT_TRUE(
      messaging_service()->HasPortForTesting(script_context(), port_id));

  // Respond to the message. The response callback should be triggered, and the
  // port should be closed.
  EXPECT_CALL(*ipc_message_sender(),
              SendCloseMessagePort(MSG_ROUTING_NONE, port_id, true));
  messaging_service()->DeliverMessage(*script_context_set(), port_id,
                                      Message("\"reply\"", false), nullptr);
  ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());
  EXPECT_EQ("[\"reply\"]", GetStringPropertyFromObject(context->Global(),
                                                       context, "replyArgs"));
  EXPECT_FALSE(
      messaging_service()->HasPortForTesting(script_context(), port_id));
}

// Tests receiving a one-time message through the messaging service. Note that
// this is more thoroughly tested in the OneTimeMessageHandler tests; this is
// just to ensure NativeRendererMessagingService correctly forwards the calls.
TEST_F(NativeRendererMessagingServiceTest, ReceiveOneTimeMessage) {
  v8::HandleScope handle_scope(isolate());
  v8::Local<v8::Context> context = MainContext();

  constexpr char kRegisterListener[] =
      "(function() {\n"
      "  chrome.runtime.onMessage.addListener(\n"
      "      function(message, sender, reply) {\n"
      "    this.eventMessage = message;\n"
      "    reply({data: 'hi'});\n"
      "  });\n"
      "})";
  v8::Local<v8::Function> add_listener =
      FunctionFromString(context, kRegisterListener);
  RunFunctionOnGlobal(add_listener, context, 0, nullptr);

  const std::string kChannel = "chrome.runtime.sendMessage";
  base::UnguessableToken other_context_id = base::UnguessableToken::Create();
  const PortId port_id(other_context_id, 0, false);

  ExtensionMsg_TabConnectionInfo tab_connection_info;
  tab_connection_info.frame_id = 0;
  const int tab_id = 10;
  GURL source_url("http://example.com");
  tab_connection_info.tab.Swap(
      DictionaryBuilder().Set("tabId", tab_id).Build().get());
  ExtensionMsg_ExternalConnectionInfo external_connection_info;
  external_connection_info.target_id = extension()->id();
  external_connection_info.source_id = extension()->id();
  external_connection_info.source_url = source_url;
  external_connection_info.guest_process_id =
      content::ChildProcessHost::kInvalidUniqueID;
  external_connection_info.guest_render_frame_routing_id = 0;

  // Open a receiver for the message.
  EXPECT_CALL(*ipc_message_sender(),
              SendOpenMessagePort(MSG_ROUTING_NONE, port_id));
  messaging_service()->DispatchOnConnect(*script_context_set(), port_id,
                                         kChannel, tab_connection_info,
                                         external_connection_info, nullptr);
  ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());
  EXPECT_TRUE(
      messaging_service()->HasPortForTesting(script_context(), port_id));

  // Post the message to the receiver. The receiver should respond, and the
  // port should close.
  EXPECT_CALL(*ipc_message_sender(),
              SendPostMessageToPort(MSG_ROUTING_NONE, port_id,
                                    Message(R"({"data":"hi"})", false)));
  EXPECT_CALL(*ipc_message_sender(),
              SendCloseMessagePort(MSG_ROUTING_NONE, port_id, true));
  messaging_service()->DeliverMessage(*script_context_set(), port_id,
                                      Message("\"message\"", false), nullptr);
  ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());
  EXPECT_FALSE(
      messaging_service()->HasPortForTesting(script_context(), port_id));
}

// Test sending a one-time message from an external source (e.g., a different
// extension). This shouldn't conflict with messages sent from the same source.
TEST_F(NativeRendererMessagingServiceTest, TestExternalOneTimeMessages) {
  v8::HandleScope handle_scope(isolate());
  v8::Local<v8::Context> context = MainContext();

  constexpr char kListeners[] =
      R"((function() {
           chrome.runtime.onMessage.addListener((message) => {
             this.onMessageReceived = message;
             return true;  // Keep the channel open.
           });
           chrome.runtime.onMessageExternal.addListener((message) => {
             this.onMessageExternalReceived = message;
             return true;  // Keep the channel open.
           });
         }))";

  v8::Local<v8::Function> add_listener =
      FunctionFromString(context, kListeners);
  RunFunctionOnGlobal(add_listener, context, 0, nullptr);

  base::UnguessableToken other_context_id = base::UnguessableToken::Create();
  int next_port_id = 0;
  const PortId on_message_port_id(other_context_id, ++next_port_id, false);
  const PortId on_message_external_port_id(other_context_id, ++next_port_id,
                                           false);

  auto open_port = [this](const PortId& port_id, const ExtensionId& source_id) {
    ExtensionMsg_TabConnectionInfo tab_connection_info;
    tab_connection_info.frame_id = 0;
    const int tab_id = 10;
    GURL source_url("http://example.com");
    tab_connection_info.tab.Swap(
        DictionaryBuilder().Set("tabId", tab_id).Build().get());

    ExtensionMsg_ExternalConnectionInfo external_connection_info;
    external_connection_info.target_id = extension()->id();
    external_connection_info.source_id = source_id;
    external_connection_info.source_url = source_url;
    external_connection_info.guest_process_id =
        content::ChildProcessHost::kInvalidUniqueID;
    external_connection_info.guest_render_frame_routing_id = 0;

    // Open a receiver for the message.
    EXPECT_CALL(*ipc_message_sender(),
                SendOpenMessagePort(MSG_ROUTING_NONE, port_id));
    messaging_service()->DispatchOnConnect(
        *script_context_set(), port_id, messaging_util::kSendMessageChannel,
        tab_connection_info, external_connection_info, nullptr);
    ::testing::Mock::VerifyAndClearExpectations(ipc_message_sender());
    EXPECT_TRUE(
        messaging_service()->HasPortForTesting(script_context(), port_id));
  };

  open_port(on_message_port_id, extension()->id());
  const ExtensionId other_extension =
      crx_file::id_util::GenerateId("different");
  open_port(on_message_external_port_id, other_extension);

  messaging_service()->DeliverMessage(*script_context_set(), on_message_port_id,
                                      Message("\"onMessage\"", false), nullptr);
  EXPECT_EQ("\"onMessage\"",
            GetStringPropertyFromObject(context->Global(), context,
                                        "onMessageReceived"));
  EXPECT_EQ("undefined",
            GetStringPropertyFromObject(context->Global(), context,
                                        "onMessageExternalReceived"));

  messaging_service()->DeliverMessage(
      *script_context_set(), on_message_external_port_id,
      Message("\"onMessageExternal\"", false), nullptr);
  EXPECT_EQ("\"onMessage\"",
            GetStringPropertyFromObject(context->Global(), context,
                                        "onMessageReceived"));
  EXPECT_EQ("\"onMessageExternal\"",
            GetStringPropertyFromObject(context->Global(), context,
                                        "onMessageExternalReceived"));
}

}  // namespace extensions
