summaryrefslogtreecommitdiff
path: root/chromium/extensions/renderer/send_message_tester.cc
blob: 1732ea462d7e3edeb88fcf701a1de7858d367b48 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// 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,
                                        PortStatus expected_port_status) {
  SCOPED_TRACE(base::StringPrintf("Send Message Args: `%s`", args.c_str()));

  TestSendMessageOrRequest(args, expected_message, expected_target,
                           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,
                           expected_port_status, SEND_REQUEST);
}

void SendMessageTester::TestConnect(const std::string& args,
                                    const std::string& expected_channel,
                                    const MessageTarget& expected_target) {
  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));
  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,
    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));
  Message message(expected_message, false);
  EXPECT_CALL(*ipc_sender_, SendPostMessageToPort(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