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
) {
24 this.sandbox_
= sandbox
;
25 /** @type {?function(string):void}
27 this.onConnected_
= null;
28 /** @type {function(remoting.Error):void}
30 this.onError_ = function(error
) {};
31 /** @type {?function(string):void}
34 /** @type {Object.<number, XMLHttpRequest>}
36 this.pendingXhrs_
= {};
41 this.accessTokenRefreshTimerStarted_
= false;
43 window
.addEventListener('message', this.onMessage_
.bind(this), false);
45 if (base
.isAppsV2()) {
47 'command': 'proxyXhrs'
49 this.sandbox_
.postMessage(message
, '*');
54 * @param {function(string):void} onConnected Callback to be called when WCS is
55 * connected. May be called synchronously if WCS is already connected.
56 * @param {function(remoting.Error):void} onError called in case of an error.
57 * @return {void} Nothing.
59 remoting
.WcsSandboxContainer
.prototype.connect = function(
60 onConnected
, onError
) {
61 this.onError_
= onError
;
62 this.ensureAccessTokenRefreshTimer_();
64 onConnected(this.localJid_
);
66 this.onConnected_
= onConnected
;
71 * @param {?function(string):void} onIq Callback invoked when an IQ stanza is
73 * @return {void} Nothing.
75 remoting
.WcsSandboxContainer
.prototype.setOnIq = function(onIq
) {
80 * Refreshes access token and starts a timer to update it periodically.
84 remoting
.WcsSandboxContainer
.prototype.ensureAccessTokenRefreshTimer_
=
86 if (this.accessTokenRefreshTimerStarted_
) {
90 this.refreshAccessToken_();
91 setInterval(this.refreshAccessToken_
.bind(this), 60 * 1000);
92 this.accessTokenRefreshTimerStarted_
= true;
97 * @return {void} Nothing.
99 remoting
.WcsSandboxContainer
.prototype.refreshAccessToken_ = function() {
100 remoting
.identity
.callWithToken(
101 this.setAccessToken_
.bind(this), this.onError_
);
106 * @param {string} token The access token.
109 remoting
.WcsSandboxContainer
.prototype.setAccessToken_ = function(token
) {
111 'command': 'setAccessToken',
114 this.sandbox_
.postMessage(message
, '*');
118 * @param {string} stanza The IQ stanza to send.
121 remoting
.WcsSandboxContainer
.prototype.sendIq = function(stanza
) {
126 this.sandbox_
.postMessage(message
, '*');
130 * Event handler to process messages from the sandbox.
132 * @param {Event} event
134 remoting
.WcsSandboxContainer
.prototype.onMessage_ = function(event
) {
135 switch (event
.data
['command']) {
138 /** @type {string} */
139 var localJid
= event
.data
['localJid'];
140 if (localJid
=== undefined) {
141 console
.error('onReady: missing localJid');
144 this.localJid_
= localJid
;
145 if (this.onConnected_
) {
146 var callback
= this.onConnected_
;
147 this.onConnected_
= null;
153 /** @type {remoting.Error} */
154 var error
= event
.data
['error'];
155 if (error
=== undefined) {
156 console
.error('onError: missing error code');
159 this.onError_(error
);
163 /** @type {string} */
164 var stanza
= event
.data
['stanza'];
165 if (stanza
=== undefined) {
166 console
.error('onIq: missing IQ stanza');
175 /** @type {number} */
176 var id
= event
.data
['id'];
177 if (id
=== undefined) {
178 console
.error('sendXhr: missing id');
181 /** @type {Object} */
182 var parameters
= event
.data
['parameters'];
183 if (parameters
=== undefined) {
184 console
.error('sendXhr: missing parameters');
187 /** @type {string} */
188 var method
= parameters
['method'];
189 if (method
=== undefined) {
190 console
.error('sendXhr: missing method');
193 /** @type {string} */
194 var url
= parameters
['url'];
195 if (url
=== undefined) {
196 console
.error('sendXhr: missing url');
199 /** @type {string} */
200 var data
= parameters
['data'];
201 if (data
=== undefined) {
202 console
.error('sendXhr: missing data');
205 /** @type {string|undefined}*/
206 var user
= parameters
['user'];
207 /** @type {string|undefined}*/
208 var password
= parameters
['password'];
209 var xhr
= new XMLHttpRequest
;
210 this.pendingXhrs_
[id
] = xhr
;
211 xhr
.open(method
, url
, true, user
, password
);
212 /** @type {Object} */
213 var headers
= parameters
['headers'];
215 for (var header
in headers
) {
216 xhr
.setRequestHeader(header
, headers
[header
]);
219 xhr
.onreadystatechange
= this.onReadyStateChange_
.bind(this, id
);
224 var id
= event
.data
['id'];
225 if (id
=== undefined) {
226 console
.error('abortXhr: missing id');
229 var xhr
= this.pendingXhrs_
[id
]
231 // It's possible for an abort and a reply to cross each other on the
232 // IPC channel. In that case, we silently ignore the abort.
239 console
.error('Unexpected message:', event
.data
['command'], event
.data
);
244 * Return a "copy" of an XHR object suitable for postMessage. Specifically,
245 * remove all non-serializable members such as functions.
247 * @param {XMLHttpRequest} xhr The XHR to serialize.
248 * @return {Object} A serializable version of the input.
250 function sanitizeXhr_(xhr
) {
251 /** @type {Object} */
253 readyState
: xhr
.readyState
,
254 response
: xhr
.response
,
255 responseText
: xhr
.responseText
,
256 responseType
: xhr
.responseType
,
257 responseXML
: xhr
.responseXML
,
259 statusText
: xhr
.statusText
,
260 withCredentials
: xhr
.withCredentials
266 * @param {number} id The unique ID of the XHR for which the state has changed.
269 remoting
.WcsSandboxContainer
.prototype.onReadyStateChange_ = function(id
) {
270 var xhr
= this.pendingXhrs_
[id
];
272 // XHRs are only removed when they have completed, in which case no
273 // further callbacks should be received.
274 console
.error('Unexpected callback for xhr', id
);
278 'command': 'xhrStateChange',
280 'xhr': sanitizeXhr_(xhr
)
282 this.sandbox_
.postMessage(message
, '*');
283 if (xhr
.readyState
== 4) {
284 delete this.pendingXhrs_
[id
];
288 /** @type {remoting.WcsSandboxContainer} */
289 remoting
.wcsSandbox
= null;