blob: 3e0901a5c230b626bc95958015c411e9b0c3431a [file] [log] [blame]
// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview A communications channel for exchanging messages with another
* window of the browser. Used to coordinate between the GUI window and the page
* being checked.
*/
goog.provide('bidichecker.gui.common.CommChannel');
goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('goog.json');
goog.require('goog.structs.Map');
/**
* A communications channel for exchanging messages with another window of the
* browser. On receipt of a message from the window, invokes a handler function
* corresponding to the message type.
* @param {Object} otherWindow The window to communicate with.
* @param {bidichecker.gui.common.CommChannel.MessageMap} messageMap Which
* handler to invoke for each type of message received.
* @constructor
*/
bidichecker.gui.common.CommChannel = function(otherWindow, messageMap) {
/**
* The window we communicate with.
* @private
*/
this.otherWindow_ = otherWindow;
/**
* A mapping from message types to message handlers.
* @type {bidichecker.gui.common.CommChannel.MessageMap}
* @private
*/
this.messageMap_ = messageMap;
/**
* Key used to stop listening to the event when the object is disposed.
* @type {?number}
* @private
*/
this.listenerKey_ = goog.events.listen(window, goog.events.EventType.MESSAGE,
this.handleMessageEvent_, false, this);
};
/**
* Send a message to the other site.
* @param {string} type The message type.
* @param {?*} opt_data Optional message data. Will be serialized as JSON
* so it should be a JSON compatible type. Generally an array, object, an
* atomic type or combinations thereof.
*/
bidichecker.gui.common.CommChannel.prototype.send = function(type, opt_data) {
var message = {
'type': type,
'data': opt_data
};
this.otherWindow_.postMessage(goog.json.serialize(message), '*');
};
/**
* Stop listening to messages. The object shouldn't be used after calling this
* method.
*/
bidichecker.gui.common.CommChannel.prototype.dispose = function() {
goog.events.unlistenByKey(this.listenerKey_);
};
/**
* Handle an incoming message.
* @param {goog.events.Event} event The message event that triggered this
* handler.
* @private
*/
bidichecker.gui.common.CommChannel.prototype.handleMessageEvent_ =
function(event) {
var underlyingEvent = event.getBrowserEvent();
// Parse the message data. It should be a JSON string describing an object
// with the following keys:
// * 'type' (string)
// * 'data' (any type)
var message = goog.json.parse(underlyingEvent.data);
var type = String(message.type);
var data = message.data;
// Get message handler from message map and call it. Query map using
// "hasOwnProperty" so we don't confuse built-in properties with map contents.
if (!this.messageMap_.hasOwnProperty(type)) {
throw 'Unknown message type received by CommChannel: ' + type;
}
var handler = this.messageMap_[type];
handler(type, data);
};
/**
* A message handler. Message handlers should always verify the message contents
* since the message may come from any site.
* @typedef {function(string, *)}
*/
bidichecker.gui.common.CommChannel.MessageHandler;
/**
* @typedef {Object.<string, bidichecker.gui.common.CommChannel.MessageHandler>}
*/
bidichecker.gui.common.CommChannel.MessageMap;