summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/mock_render_thread.cc
blob: 0f9db0d0bb93b835a6024038ca248d8063e1e552 (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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright (c) 2008 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/mock_render_thread.h"

#include "base/logging.h"
#include "chrome/common/ipc_message_utils.h"
#include "chrome/common/render_messages.h"
#include "testing/gtest/include/gtest/gtest.h"

MockRenderThread::MockRenderThread()
    : routing_id_(0),
      opener_id_(0),
      widget_(NULL),
      reply_deserializer_(NULL) {
}

MockRenderThread::~MockRenderThread() {
  // Don't leak the allocated message bodies.
  ClearMessages();
}

// Called by the Widget. The routing_id must match the routing id assigned
// to the Widget in reply to ViewHostMsg_CreateWidget message.
void MockRenderThread::AddRoute(int32 routing_id,
                                IPC::Channel::Listener* listener) {
  EXPECT_EQ(routing_id_, routing_id);
  widget_ = listener;
}

// Called by the Widget. The routing id must match the routing id of AddRoute.
void MockRenderThread::RemoveRoute(int32 routing_id) {
  EXPECT_EQ(routing_id_, routing_id);
  widget_ = NULL;
}

// Called by the Widget. Used to send messages to the browser.
// We short-circuit the mechanim and handle the messages right here on this
// class.
bool MockRenderThread::Send(IPC::Message* msg) {
  // We need to simulate a synchronous channel, thus we are going to receive
  // through this function messages, messages with reply and reply messages.
  // We can only handle one synchronous message at a time.
  if (msg->is_reply()) {
    if (reply_deserializer_.get()) {
      reply_deserializer_->SerializeOutputParameters(*msg);
      reply_deserializer_.reset();
    }
  } else {
    if (msg->is_sync()) {
      // We actually need to handle deleting the reply dersializer for sync
      // messages.
      reply_deserializer_.reset(
          static_cast<IPC::SyncMessage*>(msg)->GetReplyDeserializer());
    }
    OnMessageReceived(*msg);
  }
  delete msg;
  return true;
}

void MockRenderThread::ClearMessages() {
  for (size_t i = 0; i < messages_.size(); i++)
    delete[] messages_[i].second;
  messages_.clear();
}

const IPC::Message* MockRenderThread::GetMessageAt(size_t index) const {
  if (index >= messages_.size())
    return NULL;
  return &messages_[index].first;
}

const IPC::Message* MockRenderThread::GetFirstMessageMatching(uint16 id) const {
  for (size_t i = 0; i < messages_.size(); i++) {
    if (messages_[i].first.type() == id)
      return &messages_[i].first;
  }
  return NULL;
}

const IPC::Message* MockRenderThread::GetUniqueMessageMatching(
    uint16 id) const {
  size_t found_index = 0;
  size_t found_count = 0;
  for (size_t i = 0; i < messages_.size(); i++) {
    if (messages_[i].first.type() == id) {
      found_count++;
      found_index = i;
    }
  }
  if (found_count != 1)
    return NULL;  // Didn't find a unique one.
  return &messages_[found_index].first;
}

void MockRenderThread::SendCloseMessage() {
  ViewMsg_Close msg(routing_id_);
  widget_->OnMessageReceived(msg);
}

void MockRenderThread::OnMessageReceived(const IPC::Message& msg) {
  // Copy the message into a pair. This is tricky since the message doesn't
  // manage its data itself.
  char* data_copy;
  if (msg.size()) {
    data_copy = new char[msg.size()];
    memcpy(data_copy, msg.data(), msg.size());
  } else {
    // Dummy data so we can treat everything the same.
    data_copy = new char[1];
    data_copy[0] = 0;
  }

  // Save the message.
  messages_.push_back(
      std::make_pair(IPC::Message(data_copy, msg.size()), data_copy));

  // Some messages we do special handling.
  bool handled = true;
  bool msg_is_ok = true;
  IPC_BEGIN_MESSAGE_MAP_EX(MockRenderThread, msg, msg_is_ok)
    IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnMsgCreateWidget);
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP_EX()
}

// The Widget expects to be returned valid route_id.
void MockRenderThread::OnMsgCreateWidget(int opener_id,
                                         bool focus_on_show,
                                         int* route_id) {
  opener_id_ = opener_id;
  *route_id = routing_id_;
}