Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / remoting / webapp / crd / js / wcs_sandbox_content.js
blob0b48c6b067241f443d04e1d931f59fc11cc48a17
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.
4  */
6 /**
7  * @fileoverview
8  * The sandbox side of the application/sandbox WCS interface, used by the
9  * sandbox to exchange messages with the application.
10  */
12 'use strict';
14 /** @suppress {duplicate} */
15 var remoting = remoting || {};
17 /** @constructor */
18 remoting.WcsSandboxContent = function() {
19   /** @private {Window} */
20   this.parentWindow_ = null;
21   /** @private {number} */
22   this.nextXhrId_ = 0;
23   /** @private {Object<number, XMLHttpRequest>} */
24   this.pendingXhrs_ = {};
26   window.addEventListener('message', this.onMessage_.bind(this), false);
29 /**
30  * Event handler to process messages from the application.
31  *
32  * @param {Event} event
33  */
34 remoting.WcsSandboxContent.prototype.onMessage_ = function(event) {
35   this.parentWindow_ = event.source;
37   switch (event.data['command']) {
39     case 'proxyXhrs':
40       // Since the WCS driver code constructs XHRs directly, the only
41       // mechanism for proxying them is to replace the XMLHttpRequest
42       // constructor.
43       XMLHttpRequest = remoting.XMLHttpRequestProxy;
44       break;
46     case 'sendIq':
47       /** @type {string} */
48       var stanza = event.data['stanza'];
49       if (stanza === undefined) {
50         console.error('sendIq: missing IQ stanza.');
51         break;
52       }
53       if (remoting.wcs) {
54         remoting.wcs.sendIq(stanza);
55       } else {
56         console.error('Dropping IQ stanza:', stanza);
57       }
58       break;
60     case 'setAccessToken':
61       /** @type {string} */
62       var token = event.data['token'];
63       if (token === undefined) {
64         console.error('setAccessToken: missing access token.');
65         break;
66       }
67       // The WCS driver JS requires that remoting.wcsLoader be a global
68       // variable, so it can't be a member of this class.
69       // TODO(jamiewalch): remoting.wcs doesn't need to be global and should
70       // be made a member (http://crbug.com/172348).
71       if (remoting.wcs) {
72         remoting.wcs.updateAccessToken(token);
73       } else if (!remoting.wcsLoader) {
74         remoting.wcsLoader = new remoting.WcsLoader();
75         remoting.wcsLoader.start(token,
76                                  this.onLocalJid_.bind(this),
77                                  this.onError_.bind(this));
78       }
79       break;
81     case 'xhrStateChange':
82       /** @type {number} */
83       var id = event.data['id'];
84       if (id === undefined) {
85         console.error('xhrStateChange: missing id.');
86         break;
87       }
88       var pendingXhr = this.pendingXhrs_[id];
89       if (!pendingXhr) {
90         console.error('xhrStateChange: unrecognized id:', id);
91         break;
92       }
93       /** @type {XMLHttpRequest} */
94       var xhr = event.data['xhr'];
95       if (xhr === undefined) {
96         console.error('xhrStateChange: missing xhr');
97         break;
98       }
99       for (var member in xhr) {
100         pendingXhr[member] = xhr[member];
101       }
102       if (xhr.readyState == 4) {
103         delete this.pendingXhrs_[id];
104       }
105       if (pendingXhr.onreadystatechange) {
106         pendingXhr.onreadystatechange();
107       }
108       break;
110     default:
111       console.error('Unexpected message:', event.data['command'], event.data);
112   }
116  * Callback method to indicate that the WCS driver has loaded and provide the
117  * full JID of the client.
119  * @param {string} localJid The full JID of the WCS client.
120  * @private
121  */
122 remoting.WcsSandboxContent.prototype.onLocalJid_ = function(localJid) {
123   remoting.wcs.setOnIq(this.onIq_.bind(this));
124   var message = {
125     'source': 'wcs-sandbox',
126     'command': 'onLocalJid',
127     'localJid': localJid
128   };
129   this.parentWindow_.postMessage(message, '*');
133  * Callback method to indicate that something went wrong loading the WCS driver.
135  * @param {!remoting.Error} error Details of the error.
136  * @private
137  */
138 remoting.WcsSandboxContent.prototype.onError_ = function(error) {
139   var message = {
140     'source': 'wcs-sandbox',
141     'command': 'onError',
142     'error': error
143   };
144   this.parentWindow_.postMessage(message, '*');
148  * Forward an XHR to the container process to send. This is analogous to XHR's
149  * send method.
151  * @param {remoting.XMLHttpRequestProxy} xhr The XHR to send.
152  * @return {number} The unique ID allocated to the XHR. Used to abort it.
153  */
154 remoting.WcsSandboxContent.prototype.sendXhr = function(xhr) {
155   var id = this.nextXhrId_++;
156   this.pendingXhrs_[id] = xhr;
157   var message = {
158     'source': 'wcs-sandbox',
159     'command': 'sendXhr',
160     'id': id,
161     'parameters': xhr.sandboxIpc
162   };
163   this.parentWindow_.postMessage(message, '*');
164   delete xhr.sandboxIpc;
165   return id;
169  * Abort a forwarded XHR. This is analogous to XHR's abort method.
171  * @param {number} id The unique ID of the XHR to abort, as returned by sendXhr.
172  */
173 remoting.WcsSandboxContent.prototype.abortXhr = function(id) {
174   if (!this.pendingXhrs_[id]) {
175     // The XHR is removed when it reaches the "ready" state. Calling abort
176     // subsequently is unusual, but legal, so just silently ignore the request
177     // in this case.
178     return;
179   }
180   var message = {
181     'source': 'wcs-sandbox',
182     'command': 'abortXhr',
183     'id': id
184   };
185   this.parentWindow_.postMessage(message, '*');
189  * Callback to indicate than an IQ stanza has been received from the WCS
190  * driver, and should be forwarded to the main process.
192  * @param {string} stanza
193  * @private
194  */
195 remoting.WcsSandboxContent.prototype.onIq_ = function(stanza) {
196   remoting.wcs.setOnIq(this.onIq_.bind(this));
197   var message = {
198     'source': 'wcs-sandbox',
199     'command': 'onIq',
200     'stanza': stanza
201   };
202   this.parentWindow_.postMessage(message, '*');
206  * Entry point for the WCS sandbox process.
207  */
208 function onSandboxInit() {
209   // The WCS code registers for a couple of events that aren't supported in
210   // Apps V2, so ignore those for now.
211   var oldAEL = window.addEventListener;
212   window.addEventListener = function(type, listener, useCapture) {
213     if (type == 'beforeunload' || type == 'unload') {
214       return;
215     }
216     oldAEL(type, listener, useCapture);
217   };
219   remoting.settings = new remoting.Settings();
220   remoting.sandboxContent = new remoting.WcsSandboxContent();
223 window.addEventListener('load', onSandboxInit, false);
225 /** @type {remoting.WcsSandboxContent} */
226 remoting.sandboxContent = null;