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
);