// Copyright 2013 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.
/**
* Channel to the background script.
*/
function Channel() {
}
/** @const */
Channel.INTERNAL_REQUEST_MESSAGE = 'internal-request-message';
/** @const */
Channel.INTERNAL_REPLY_MESSAGE = 'internal-reply-message';
Channel.prototype = {
// Message port to use to communicate with background script.
port_: null,
// Registered message callbacks.
messageCallbacks_: {},
// Internal request id to track pending requests.
nextInternalRequestId_: 0,
// Pending internal request callbacks.
internalRequestCallbacks_: {},
/**
* Initialize the channel with given port for the background script.
*/
init: function(port) {
this.port_ = port;
this.port_.onMessage.addListener(this.onMessage_.bind(this));
},
/**
* Connects to the background script with the given name.
*/
connect: function(name) {
this.port_ = chrome.runtime.connect({name: name});
this.port_.onMessage.addListener(this.onMessage_.bind(this));
},
/**
* Associates a message name with a callback. When a message with the name
* is received, the callback will be invoked with the message as its arg.
* Note only the last registered callback will be invoked.
*/
registerMessage: function(name, callback) {
this.messageCallbacks_[name] = callback;
},
/**
* Sends a message to the other side of the channel.
*/
send: function(msg) {
this.port_.postMessage(msg);
},
/**
* Sends a message to the other side and invokes the callback with
* the replied object. Useful for message that expects a returned result.
*/
sendWithCallback: function(msg, callback) {
var requestId = this.nextInternalRequestId_++;
this.internalRequestCallbacks_[requestId] = callback;
this.send({
name: Channel.INTERNAL_REQUEST_MESSAGE,
requestId: requestId,
payload: msg
});
},
/**
* Invokes message callback using given message.
* @return {*} The return value of the message callback or null.
*/
invokeMessageCallbacks_: function(msg) {
var name = msg.name;
if (this.messageCallbacks_[name])
return this.messageCallbacks_[name](msg);
console.error('Error: Unexpected message, name=' + name);
return null;
},
/**
* Invoked when a message is received.
*/
onMessage_: function(msg) {
var name = msg.name;
if (name == Channel.INTERNAL_REQUEST_MESSAGE) {
var payload = msg.payload;
var result = this.invokeMessageCallbacks_(payload);
this.send({
name: Channel.INTERNAL_REPLY_MESSAGE,
requestId: msg.requestId,
result: result
});
} else if (name == Channel.INTERNAL_REPLY_MESSAGE) {
var callback = this.internalRequestCallbacks_[msg.requestId];
delete this.internalRequestCallbacks_[msg.requestId];
if (callback)
callback(msg.result);
} else {
this.invokeMessageCallbacks_(msg);
}
}
};