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