1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 function NaClAMMessage() {
7 this.frames = new Array();
10 NaClAMMessage.prototype.reset = function() {
12 this.frames = new Array();
15 function NaClAM(embedId) {
16 this.embedId = embedId;
18 this.message = new NaClAMMessage();
21 this.listeners_ = Object.create(null);
22 this.handleMesssage_ = this.handleMesssage_.bind(this);
25 NaClAM.prototype.enable = function() {
26 window.addEventListener('message', this.handleMesssage_, true);
29 NaClAM.prototype.disable = function() {
30 window.removeEventListener('message', this.handleMesssage_, true);
33 NaClAM.prototype.log_ = function(msg) {
37 NaClAM.prototype.handleMesssage_ = function(event) {
38 var STATE_WAITING_FOR_HEADER = 0;
39 var STATE_COLLECTING_FRAMES = 1;
40 if (this.state == STATE_WAITING_FOR_HEADER) {
43 header = JSON.parse(String(event.data));
46 console.log(event.data);
49 // Special case our log print command
50 if (header['cmd'] == 'NaClAMPrint') {
51 this.log_(header['print'])
54 if (typeof(header['request']) != "number") {
55 console.log('Header message requestId is not a number.');
58 if (typeof(header['frames']) != "number") {
59 console.log('Header message frames is not a number.');
62 this.framesLeft = header['frames'];
63 this.state = STATE_COLLECTING_FRAMES;
64 this.message.header = header;
65 } else if (this.state == STATE_COLLECTING_FRAMES) {
67 this.message.frames.push(event.data);
69 if (this.state == STATE_COLLECTING_FRAMES && this.framesLeft == 0) {
70 this.dispatchEvent(this.message);
72 this.state = STATE_WAITING_FOR_HEADER;
76 NaClAM.prototype.messageHeaderIsValid_ = function(header) {
77 if (header['cmd'] == undefined) {
78 console.log('NaClAM: Message header does not contain cmd.');
81 if (typeof(header['cmd']) != "string") {
82 console.log('NaClAm: Message cmd is not a string.');
85 if (header['frames'] == undefined) {
86 console.log('NaClAM: Message header does not contain frames.');
89 if (typeof(header['frames']) != "number") {
90 console.log('NaClAm: Message frames is not a number.');
93 if (header['request'] == undefined) {
94 console.log('NaClAM: Message header does not contain request.');
97 if (typeof(header['request']) != "number") {
98 console.log('NaClAm: Message request is not a number.');
104 NaClAM.prototype.framesIsValid_ = function(frames) {
110 if (Array.isArray(frames) == false) {
111 console.log('NaClAM: Frames must be an array.');
114 for (i = 0; i < frames.length; i++) {
116 if (typeof(e) == "string") {
119 if ((e instanceof ArrayBuffer) == false) {
120 console.log('NaClAM: Frame is not a string or ArrayBuffer');
127 NaClAM.prototype.framesLength_ = function(frames) {
132 return frames.length;
135 NaClAM.prototype.sendMessage = function(cmdName, arguments, frames) {
136 if (this.framesIsValid_(frames) == false) {
137 console.log('NaClAM: Not sending message because frames is invalid.');
140 var numFrames = this.framesLength_(frames);
145 request: this.requestId,
148 if (this.messageHeaderIsValid_(msgHeader) == false) {
149 console.log('NaClAM: Not sending message because header is invalid.');
152 var AM = document.getElementById(this.embedId);
154 console.log('NaClAM: Not sending message because Acceleration Module is not there.');
157 AM.postMessage(JSON.stringify(msgHeader));
159 for (i = 0; i < numFrames; i++) {
160 AM.postMessage(frames[i]);
162 return this.requestId;
166 * Adds an event listener to this Acceleration Module.
167 * @param {string} type The name of the command.
168 * @param handler The handler for the cmomand. This is called whenever the command is received.
170 NaClAM.prototype.addEventListener = function(type, handler) {
171 if (!this.listeners_) {
172 this.listeners_ = Object.create(null);
174 if (!(type in this.listeners_)) {
175 this.listeners_[type] = [handler];
177 var handlers = this.listeners_[type];
178 if (handlers.indexOf(handler) < 0) {
179 handlers.push(handler);
185 * Removes an event listener from this Acceleration Module.
186 * @param {string} type The name of the command.
187 * @param handler The handler for the cmomand. This is called whenever the command is received.
189 NaClAM.prototype.removeEventListener = function(type, handler) {
190 if (!this.listeners_) {
194 if (type in this.listeners_) {
195 var handlers = this.listeners_[type];
196 var index = handlers.indexOf(handler);
198 if (handlers.length == 1) {
199 // Listeners list would be empty, delete it
200 delete this.listeners_[type];
202 // Remove the handler
203 handlers.splice(index, 1);
212 NaClAM.prototype.dispatchEvent = function(event) {
213 if (!this.listeners_) {
216 var type = event.header.cmd;
217 if (type in this.listeners_) {
218 // Make a copy to walk over
219 var handlers = this.listeners_[type].concat();
220 for (var i = 0, handler; handler = handlers[i]; i++) {
221 handler.call(this, event);