| // 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/send_message_tester.h" |
| |
| #include "base/strings/stringprintf.h" |
| #include "extensions/renderer/bindings/api_binding_test_util.h" |
| #include "extensions/renderer/messaging_util.h" |
| #include "extensions/renderer/native_extension_bindings_system_test_base.h" |
| #include "extensions/renderer/script_context.h" |
| #include "ipc/ipc_message.h" |
| #include "v8/include/v8.h" |
| |
| namespace extensions { |
| |
| SendMessageTester::SendMessageTester(TestIPCMessageSender* ipc_sender, |
| ScriptContext* script_context, |
| int next_port_id, |
| const std::string& api_namespace) |
| : ipc_sender_(ipc_sender), |
| script_context_(script_context), |
| next_port_id_(next_port_id), |
| api_namespace_(api_namespace) {} |
| |
| SendMessageTester::~SendMessageTester() {} |
| |
| void SendMessageTester::TestSendMessage(const std::string& args, |
| const std::string& expected_message, |
| const MessageTarget& expected_target, |
| bool expected_include_tls_channel_id, |
| PortStatus expected_port_status) { |
| SCOPED_TRACE(base::StringPrintf("Send Message Args: `%s`", args.c_str())); |
| |
| TestSendMessageOrRequest(args, expected_message, expected_target, |
| expected_include_tls_channel_id, |
| expected_port_status, SEND_MESSAGE); |
| } |
| |
| void SendMessageTester::TestSendRequest(const std::string& args, |
| const std::string& expected_message, |
| const MessageTarget& expected_target, |
| PortStatus expected_port_status) { |
| SCOPED_TRACE(base::StringPrintf("Send Request Args: `%s`", args.c_str())); |
| |
| TestSendMessageOrRequest(args, expected_message, expected_target, false, |
| expected_port_status, SEND_REQUEST); |
| } |
| |
| void SendMessageTester::TestConnect(const std::string& args, |
| const std::string& expected_channel, |
| const MessageTarget& expected_target, |
| bool expected_include_tls_channel_id) { |
| SCOPED_TRACE(base::StringPrintf("Connect Args: `%s`", args.c_str())); |
| |
| v8::Local<v8::Context> v8_context = script_context_->v8_context(); |
| |
| constexpr char kAddPortTemplate[] = |
| "(function() { return chrome.%s.connect(%s); })"; |
| PortId expected_port_id(script_context_->context_id(), next_port_id_++, true); |
| EXPECT_CALL(*ipc_sender_, |
| SendOpenMessageChannel(script_context_, expected_port_id, |
| expected_target, expected_channel, |
| expected_include_tls_channel_id)); |
| v8::Local<v8::Function> add_port = FunctionFromString( |
| v8_context, base::StringPrintf(kAddPortTemplate, api_namespace_.c_str(), |
| args.c_str())); |
| v8::Local<v8::Value> port = RunFunction(add_port, v8_context, 0, nullptr); |
| ::testing::Mock::VerifyAndClearExpectations(ipc_sender_); |
| ASSERT_FALSE(port.IsEmpty()); |
| ASSERT_TRUE(port->IsObject()); |
| v8::Local<v8::Object> port_obj = port.As<v8::Object>(); |
| EXPECT_EQ(base::StringPrintf(R"("%s")", expected_channel.c_str()), |
| GetStringPropertyFromObject(port_obj, v8_context, "name")); |
| } |
| |
| void SendMessageTester::TestSendMessageOrRequest( |
| const std::string& args, |
| const std::string& expected_message, |
| const MessageTarget& expected_target, |
| bool expected_include_tls_channel_id, |
| PortStatus expected_port_status, |
| Method method) { |
| constexpr char kSendMessageTemplate[] = "(function() { chrome.%s.%s(%s); })"; |
| |
| std::string expected_channel; |
| const char* method_name = nullptr; |
| switch (method) { |
| case SEND_MESSAGE: |
| method_name = "sendMessage"; |
| expected_channel = messaging_util::kSendMessageChannel; |
| break; |
| case SEND_REQUEST: |
| method_name = "sendRequest"; |
| expected_channel = messaging_util::kSendRequestChannel; |
| break; |
| } |
| |
| PortId expected_port_id(script_context_->context_id(), next_port_id_++, true); |
| |
| EXPECT_CALL(*ipc_sender_, |
| SendOpenMessageChannel(script_context_, expected_port_id, |
| expected_target, expected_channel, |
| expected_include_tls_channel_id)); |
| Message message(expected_message, false); |
| EXPECT_CALL(*ipc_sender_, SendPostMessageToPort(MSG_ROUTING_NONE, |
| expected_port_id, message)); |
| |
| if (expected_port_status == CLOSED) { |
| EXPECT_CALL(*ipc_sender_, |
| SendCloseMessagePort(MSG_ROUTING_NONE, expected_port_id, true)); |
| } |
| |
| v8::Local<v8::Context> v8_context = script_context_->v8_context(); |
| v8::Local<v8::Function> send_message = FunctionFromString( |
| v8_context, |
| base::StringPrintf(kSendMessageTemplate, api_namespace_.c_str(), |
| method_name, args.c_str())); |
| RunFunction(send_message, v8_context, 0, nullptr); |
| ::testing::Mock::VerifyAndClearExpectations(ipc_sender_); |
| } |
| |
| } // namespace extensions |