This source file includes following definitions.
- GetInstance
- UpdateMessagePort
- OnMessagePortMessageFilterClosing
- Create
- Destroy
- Entangle
- PostMessage
- PostMessageTo
- QueueMessages
- SendQueuedMessages
- SendQueuedMessagesIfPossible
- Erase
#include "content/browser/message_port_service.h"
#include "content/browser/message_port_message_filter.h"
#include "content/common/message_port_messages.h"
namespace content {
struct MessagePortService::MessagePort {
MessagePortMessageFilter* filter;
int route_id;
int message_port_id;
int entangled_message_port_id;
bool queue_messages;
QueuedMessages queued_messages;
};
MessagePortService* MessagePortService::GetInstance() {
return Singleton<MessagePortService>::get();
}
MessagePortService::MessagePortService()
: next_message_port_id_(0) {
}
MessagePortService::~MessagePortService() {
}
void MessagePortService::UpdateMessagePort(
int message_port_id,
MessagePortMessageFilter* filter,
int routing_id) {
if (!message_ports_.count(message_port_id)) {
NOTREACHED();
return;
}
MessagePort& port = message_ports_[message_port_id];
port.filter = filter;
port.route_id = routing_id;
}
void MessagePortService::OnMessagePortMessageFilterClosing(
MessagePortMessageFilter* filter) {
for (MessagePorts::iterator iter = message_ports_.begin();
iter != message_ports_.end();) {
MessagePorts::iterator cur_item = iter++;
if (cur_item->second.filter == filter) {
Erase(cur_item->first);
}
}
}
void MessagePortService::Create(int route_id,
MessagePortMessageFilter* filter,
int* message_port_id) {
*message_port_id = ++next_message_port_id_;
MessagePort port;
port.filter = filter;
port.route_id = route_id;
port.message_port_id = *message_port_id;
port.entangled_message_port_id = MSG_ROUTING_NONE;
port.queue_messages = false;
message_ports_[*message_port_id] = port;
}
void MessagePortService::Destroy(int message_port_id) {
if (!message_ports_.count(message_port_id)) {
NOTREACHED();
return;
}
DCHECK(message_ports_[message_port_id].queued_messages.empty());
Erase(message_port_id);
}
void MessagePortService::Entangle(int local_message_port_id,
int remote_message_port_id) {
if (!message_ports_.count(local_message_port_id) ||
!message_ports_.count(remote_message_port_id)) {
NOTREACHED();
return;
}
DCHECK(message_ports_[remote_message_port_id].entangled_message_port_id ==
MSG_ROUTING_NONE);
message_ports_[remote_message_port_id].entangled_message_port_id =
local_message_port_id;
}
void MessagePortService::PostMessage(
int sender_message_port_id,
const base::string16& message,
const std::vector<int>& sent_message_port_ids) {
if (!message_ports_.count(sender_message_port_id)) {
NOTREACHED();
return;
}
int entangled_message_port_id =
message_ports_[sender_message_port_id].entangled_message_port_id;
if (entangled_message_port_id == MSG_ROUTING_NONE)
return;
if (!message_ports_.count(entangled_message_port_id)) {
NOTREACHED();
return;
}
PostMessageTo(entangled_message_port_id, message, sent_message_port_ids);
}
void MessagePortService::PostMessageTo(
int message_port_id,
const base::string16& message,
const std::vector<int>& sent_message_port_ids) {
if (!message_ports_.count(message_port_id)) {
NOTREACHED();
return;
}
for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
if (!message_ports_.count(sent_message_port_ids[i])) {
NOTREACHED();
return;
}
}
MessagePort& entangled_port = message_ports_[message_port_id];
std::vector<MessagePort*> sent_ports(sent_message_port_ids.size());
for (size_t i = 0; i < sent_message_port_ids.size(); ++i)
sent_ports[i] = &message_ports_[sent_message_port_ids[i]];
if (entangled_port.queue_messages) {
entangled_port.queued_messages.push_back(
std::make_pair(message, sent_message_port_ids));
return;
}
if (!entangled_port.filter) {
NOTREACHED();
return;
}
std::vector<int> new_routing_ids(sent_message_port_ids.size());
for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
new_routing_ids[i] = entangled_port.filter->GetNextRoutingID();
sent_ports[i]->filter = entangled_port.filter;
sent_ports[i]->route_id = new_routing_ids[i];
}
entangled_port.filter->Send(new MessagePortMsg_Message(
entangled_port.route_id, message, sent_message_port_ids,
new_routing_ids));
}
void MessagePortService::QueueMessages(int message_port_id) {
if (!message_ports_.count(message_port_id)) {
NOTREACHED();
return;
}
MessagePort& port = message_ports_[message_port_id];
if (port.filter) {
port.filter->Send(new MessagePortMsg_MessagesQueued(port.route_id));
port.queue_messages = true;
port.filter = NULL;
}
}
void MessagePortService::SendQueuedMessages(
int message_port_id,
const QueuedMessages& queued_messages) {
if (!message_ports_.count(message_port_id)) {
NOTREACHED();
return;
}
MessagePort& port = message_ports_[message_port_id];
port.queue_messages = false;
port.queued_messages.insert(port.queued_messages.begin(),
queued_messages.begin(),
queued_messages.end());
SendQueuedMessagesIfPossible(message_port_id);
}
void MessagePortService::SendQueuedMessagesIfPossible(int message_port_id) {
if (!message_ports_.count(message_port_id)) {
NOTREACHED();
return;
}
MessagePort& port = message_ports_[message_port_id];
if (port.queue_messages || !port.filter)
return;
for (QueuedMessages::iterator iter = port.queued_messages.begin();
iter != port.queued_messages.end(); ++iter) {
PostMessageTo(message_port_id, iter->first, iter->second);
}
port.queued_messages.clear();
}
void MessagePortService::Erase(int message_port_id) {
MessagePorts::iterator erase_item = message_ports_.find(message_port_id);
DCHECK(erase_item != message_ports_.end());
int entangled_id = erase_item->second.entangled_message_port_id;
if (entangled_id != MSG_ROUTING_NONE) {
if (message_ports_.count(entangled_id)) {
message_ports_[entangled_id].entangled_message_port_id = MSG_ROUTING_NONE;
}
}
message_ports_.erase(erase_item);
}
}