1 /* Copyright 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.
8 * The application side of the application/sandbox WCS interface, used by the
9 * application to exchange messages with the sandbox.
14 /** @suppress {duplicate} */
15 var remoting = remoting || {};
18 * @param {Window} sandbox The Javascript Window object representing the
19 * sandboxed WCS driver.
22 remoting.WcsSandboxContainer = function(sandbox) {
23 this.sandbox_ = sandbox;
24 /** @type {?function(string):void} */
26 /** @type {?function(remoting.Error):void} */
28 /** @type {?function(string):void} */
30 /** @type {Object.<number, XMLHttpRequest>} */
31 this.pendingXhrs_ = {};
33 window.addEventListener('message', this.onMessage_.bind(this), false);
37 * @param {?function(string):void} onReady Callback invoked with the client JID
38 * when the WCS code has loaded.
39 * @return {void} Nothing.
41 remoting.WcsSandboxContainer.prototype.setOnReady = function(onReady) {
42 this.onReady_ = onReady;
46 * @param {?function(remoting.Error):void} onError Callback invoked if the WCS
47 * code cannot be loaded.
48 * @return {void} Nothing.
50 remoting.WcsSandboxContainer.prototype.setOnError = function(onError) {
51 this.onError_ = onError;
55 * @param {?function(string):void} onIq Callback invoked when an IQ stanza is
57 * @return {void} Nothing.
59 remoting.WcsSandboxContainer.prototype.setOnIq = function(onIq) {
64 * @param {string} token The access token.
67 remoting.WcsSandboxContainer.prototype.setAccessToken = function(token) {
69 'command': 'setAccessToken',
72 this.sandbox_.postMessage(message, '*');
76 * @param {string} stanza The IQ stanza to send.
79 remoting.WcsSandboxContainer.prototype.sendIq = function(stanza) {
84 this.sandbox_.postMessage(message, '*');
88 * Event handler to process messages from the sandbox.
90 * @param {Event} event
92 remoting.WcsSandboxContainer.prototype.onMessage_ = function(event) {
93 switch (event.data['command']) {
97 var clientJid = event.data['clientJid'];
98 if (clientJid === undefined) {
99 console.error('onReady: missing client JID');
103 this.onReady_(clientJid);
108 /** @type {remoting.Error} */
109 var error = event.data['error'];
110 if (error === undefined) {
111 console.error('onError: missing error code');
114 this.onError_(error);
118 /** @type {string} */
119 var stanza = event.data['stanza'];
120 if (stanza === undefined) {
121 console.error('onIq: missing IQ stanza');
130 /** @type {number} */
131 var id = event.data['id'];
132 if (id === undefined) {
133 console.error('sendXhr: missing id');
136 /** @type {Object} */
137 var parameters = event.data['parameters'];
138 if (parameters === undefined) {
139 console.error('sendXhr: missing parameters');
142 /** @type {string} */
143 var method = parameters['method'];
144 if (method === undefined) {
145 console.error('sendXhr: missing method');
148 /** @type {string} */
149 var url = parameters['url'];
150 if (url === undefined) {
151 console.error('sendXhr: missing url');
154 /** @type {string} */
155 var data = parameters['data'];
156 if (data === undefined) {
157 console.error('sendXhr: missing data');
160 /** @type {string|undefined}*/
161 var user = parameters['user'];
162 /** @type {string|undefined}*/
163 var password = parameters['password'];
164 var xhr = new XMLHttpRequest;
165 this.pendingXhrs_[id] = xhr;
166 xhr.open(method, url, true, user, password);
167 /** @type {Object} */
168 var headers = parameters['headers'];
170 for (var header in headers) {
171 xhr.setRequestHeader(header, headers[header]);
174 xhr.onreadystatechange = this.onReadyStateChange_.bind(this, id);
179 var id = event.data['id'];
180 if (id === undefined) {
181 console.error('abortXhr: missing id');
184 var xhr = this.pendingXhrs_[id]
186 // It's possible for an abort and a reply to cross each other on the
187 // IPC channel. In that case, we silently ignore the abort.
194 console.error('Unexpected message:', event.data['command'], event.data);
199 * Return a "copy" of an XHR object suitable for postMessage. Specifically,
200 * remove all non-serializable members such as functions.
202 * @param {XMLHttpRequest} xhr The XHR to serialize.
203 * @return {Object} A serializable version of the input.
205 function sanitizeXhr_(xhr) {
206 /** @type {Object} */
208 readyState: xhr.readyState,
209 response: xhr.response,
210 responseText: xhr.responseText,
211 responseType: xhr.responseType,
212 responseXML: xhr.responseXML,
214 statusText: xhr.statusText,
215 withCredentials: xhr.withCredentials
221 * @param {number} id The unique ID of the XHR for which the state has changed.
224 remoting.WcsSandboxContainer.prototype.onReadyStateChange_ = function(id) {
225 var xhr = this.pendingXhrs_[id];
227 // XHRs are only removed when they have completed, in which case no
228 // further callbacks should be received.
229 console.error('Unexpected callback for xhr', id);
233 'command': 'xhrStateChange',
235 'xhr': sanitizeXhr_(xhr)
237 this.sandbox_.postMessage(message, '*');
238 if (xhr.readyState == 4) {
239 delete this.pendingXhrs_[id];
243 /** @type {remoting.WcsSandboxContainer} */
244 remoting.wcsSandbox = null;