| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * @fileoverview | 6 * @fileoverview |
| 7 * Provides a HTML5 postMessage channel to the injected JS to talk back | 7 * Provides a HTML5 postMessage channel to the injected JS to talk back |
| 8 * to Authenticator. | 8 * to Authenticator. |
| 9 */ | 9 */ |
| 10 'use strict'; | 10 'use strict'; |
| 11 | 11 |
| 12 <include src="../gaia_auth/channel.js"> | 12 // <include src="../gaia_auth/channel.js"> |
| 13 | 13 |
| 14 var PostMessageChannel = (function() { | 14 var PostMessageChannel = (function() { |
| 15 /** | 15 /** |
| 16 * Allowed origins of the hosting page. | 16 * Allowed origins of the hosting page. |
| 17 * @type {Array<string>} | 17 * @type {Array<string>} |
| 18 */ | 18 */ |
| 19 var ALLOWED_ORIGINS = [ | 19 var ALLOWED_ORIGINS = ['chrome://oobe', 'chrome://chrome-signin']; |
| 20 'chrome://oobe', | |
| 21 'chrome://chrome-signin' | |
| 22 ]; | |
| 23 | 20 |
| 24 /** @const */ | 21 /** @const */ |
| 25 var PORT_MESSAGE = 'post-message-port-message'; | 22 var PORT_MESSAGE = 'post-message-port-message'; |
| 26 | 23 |
| 27 /** @const */ | 24 /** @const */ |
| 28 var CHANNEL_INIT_MESSAGE = 'post-message-channel-init'; | 25 var CHANNEL_INIT_MESSAGE = 'post-message-channel-init'; |
| 29 | 26 |
| 30 /** @const */ | 27 /** @const */ |
| 31 var CHANNEL_CONNECT_MESSAGE = 'post-message-channel-connect'; | 28 var CHANNEL_CONNECT_MESSAGE = 'post-message-channel-connect'; |
| 32 | 29 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 port.setTarget(opt_targetWindow, opt_targetOrigin); | 139 port.setTarget(opt_targetWindow, opt_targetOrigin); |
| 143 this.channels_[channelId] = port; | 140 this.channels_[channelId] = port; |
| 144 return port; | 141 return port; |
| 145 }, | 142 }, |
| 146 | 143 |
| 147 /* | 144 /* |
| 148 * Returns a message forward handler for the given proxy port. | 145 * Returns a message forward handler for the given proxy port. |
| 149 * @private | 146 * @private |
| 150 */ | 147 */ |
| 151 getProxyPortForwardHandler_: function(proxyPort) { | 148 getProxyPortForwardHandler_: function(proxyPort) { |
| 152 return function(msg) { proxyPort.postMessage(msg); }; | 149 return function(msg) { |
| 150 proxyPort.postMessage(msg); |
| 151 }; |
| 153 }, | 152 }, |
| 154 | 153 |
| 155 /** | 154 /** |
| 156 * Creates a forwarding porxy port. | 155 * Creates a forwarding porxy port. |
| 157 * @param {number} channelId | 156 * @param {number} channelId |
| 158 * @param {string} channelName | 157 * @param {string} channelName |
| 159 * @param {!DOMWindow} targetWindow | 158 * @param {!DOMWindow} targetWindow |
| 160 * @param {!string} targetOrigin | 159 * @param {!string} targetOrigin |
| 161 */ | 160 */ |
| 162 createProxyPort: function( | 161 createProxyPort: function( |
| 163 channelId, channelName, targetWindow, targetOrigin) { | 162 channelId, channelName, targetWindow, targetOrigin) { |
| 164 var port = this.createPort( | 163 var port = |
| 165 channelId, channelName, targetWindow, targetOrigin); | 164 this.createPort(channelId, channelName, targetWindow, targetOrigin); |
| 166 port.onMessage.addListener(this.getProxyPortForwardHandler_(port)); | 165 port.onMessage.addListener(this.getProxyPortForwardHandler_(port)); |
| 167 return port; | 166 return port; |
| 168 }, | 167 }, |
| 169 | 168 |
| 170 /** | 169 /** |
| 171 * Creates a connecting port to the daemon and request connection. | 170 * Creates a connecting port to the daemon and request connection. |
| 172 * @param {string} name | 171 * @param {string} name |
| 173 * @return {PostMessagePort} | 172 * @return {PostMessagePort} |
| 174 */ | 173 */ |
| 175 connectToDaemon: function(name) { | 174 connectToDaemon: function(name) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 206 return; | 205 return; |
| 207 } | 206 } |
| 208 | 207 |
| 209 port.handleWindowMessage(e); | 208 port.handleWindowMessage(e); |
| 210 }, | 209 }, |
| 211 | 210 |
| 212 /** | 211 /** |
| 213 * Window 'message' handler. | 212 * Window 'message' handler. |
| 214 */ | 213 */ |
| 215 onMessage_: function(e) { | 214 onMessage_: function(e) { |
| 216 if (typeof e.data != 'object' || | 215 if (typeof e.data != 'object' || !e.data.hasOwnProperty('type')) { |
| 217 !e.data.hasOwnProperty('type')) { | |
| 218 return; | 216 return; |
| 219 } | 217 } |
| 220 | 218 |
| 221 if (e.data.type === PORT_MESSAGE) { | 219 if (e.data.type === PORT_MESSAGE) { |
| 222 // Dispatch port message to ports if this is the daemon page or | 220 // Dispatch port message to ports if this is the daemon page or |
| 223 // the message is from upperWindow. In case of null upperWindow, | 221 // the message is from upperWindow. In case of null upperWindow, |
| 224 // the message is assumed to be forwarded to upperWindow and queued. | 222 // the message is assumed to be forwarded to upperWindow and queued. |
| 225 if (this.isDaemon || | 223 if (this.isDaemon || |
| 226 (this.upperWindow && e.source === this.upperWindow)) { | 224 (this.upperWindow && e.source === this.upperWindow)) { |
| 227 this.dispatchMessageToPort_(e); | 225 this.dispatchMessageToPort_(e); |
| 228 } else { | 226 } else { |
| 229 this.postToUpperWindow(e.data); | 227 this.postToUpperWindow(e.data); |
| 230 } | 228 } |
| 231 } else if (e.data.type === CHANNEL_CONNECT_MESSAGE) { | 229 } else if (e.data.type === CHANNEL_CONNECT_MESSAGE) { |
| 232 var channelId = e.data.channelId; | 230 var channelId = e.data.channelId; |
| 233 var channelName = e.data.channelName; | 231 var channelName = e.data.channelName; |
| 234 | 232 |
| 235 if (this.isDaemon) { | 233 if (this.isDaemon) { |
| 236 var port = this.createPort( | 234 var port = |
| 237 channelId, channelName, e.source, e.origin); | 235 this.createPort(channelId, channelName, e.source, e.origin); |
| 238 this.onConnect.dispatch(port); | 236 this.onConnect.dispatch(port); |
| 239 } else { | 237 } else { |
| 240 this.createProxyPort(channelId, channelName, e.source, e.origin); | 238 this.createProxyPort(channelId, channelName, e.source, e.origin); |
| 241 this.postToUpperWindow(e.data); | 239 this.postToUpperWindow(e.data); |
| 242 } | 240 } |
| 243 } else if (e.data.type === CHANNEL_INIT_MESSAGE) { | 241 } else if (e.data.type === CHANNEL_INIT_MESSAGE) { |
| 244 if (ALLOWED_ORIGINS.indexOf(e.origin) == -1) | 242 if (ALLOWED_ORIGINS.indexOf(e.origin) == -1) |
| 245 return; | 243 return; |
| 246 | 244 |
| 247 this.upperWindow = e.source; | 245 this.upperWindow = e.source; |
| 248 this.upperOrigin = e.origin; | 246 this.upperOrigin = e.origin; |
| 249 | 247 |
| 250 for (var i = 0; i < this.deferredUpperWindowMessages_.length; ++i) { | 248 for (var i = 0; i < this.deferredUpperWindowMessages_.length; ++i) { |
| 251 this.upperWindow.postMessage(this.deferredUpperWindowMessages_[i], | 249 this.upperWindow.postMessage( |
| 252 this.upperOrigin); | 250 this.deferredUpperWindowMessages_[i], this.upperOrigin); |
| 253 } | 251 } |
| 254 this.deferredUpperWindowMessages_ = []; | 252 this.deferredUpperWindowMessages_ = []; |
| 255 | 253 |
| 256 for (var i = 0; i < this.deferredUpperWindowPorts_.length; ++i) { | 254 for (var i = 0; i < this.deferredUpperWindowPorts_.length; ++i) { |
| 257 this.deferredUpperWindowPorts_[i].setTarget(this.upperWindow, | 255 this.deferredUpperWindowPorts_[i].setTarget( |
| 258 this.upperOrigin); | 256 this.upperWindow, this.upperOrigin); |
| 259 } | 257 } |
| 260 this.deferredUpperWindowPorts_ = []; | 258 this.deferredUpperWindowPorts_ = []; |
| 261 } | 259 } |
| 262 } | 260 } |
| 263 }; | 261 }; |
| 264 | 262 |
| 265 /** | 263 /** |
| 266 * Singleton instance of ChannelManager. | 264 * Singleton instance of ChannelManager. |
| 267 * @type {ChannelManager} | 265 * @type {ChannelManager} |
| 268 */ | 266 */ |
| (...skipping 30 matching lines...) Expand all Loading... |
| 299 } | 297 } |
| 300 this.deferredMessages_ = []; | 298 this.deferredMessages_ = []; |
| 301 }, | 299 }, |
| 302 | 300 |
| 303 postMessage: function(msg) { | 301 postMessage: function(msg) { |
| 304 if (!this.targetWindow) { | 302 if (!this.targetWindow) { |
| 305 this.deferredMessages_.push(msg); | 303 this.deferredMessages_.push(msg); |
| 306 return; | 304 return; |
| 307 } | 305 } |
| 308 | 306 |
| 309 this.targetWindow.postMessage({ | 307 this.targetWindow.postMessage( |
| 310 type: PORT_MESSAGE, | 308 {type: PORT_MESSAGE, channelId: this.channelId, payload: msg}, |
| 311 channelId: this.channelId, | 309 this.targetOrigin); |
| 312 payload: msg | |
| 313 }, this.targetOrigin); | |
| 314 }, | 310 }, |
| 315 | 311 |
| 316 handleWindowMessage: function(e) { | 312 handleWindowMessage: function(e) { |
| 317 this.onMessage.dispatch(e.data.payload); | 313 this.onMessage.dispatch(e.data.payload); |
| 318 } | 314 } |
| 319 }; | 315 }; |
| 320 | 316 |
| 321 /** | 317 /** |
| 322 * A message channel based on PostMessagePort. | 318 * A message channel based on PostMessagePort. |
| 323 * @extends {Channel} | 319 * @extends {Channel} |
| (...skipping 11 matching lines...) Expand all Loading... |
| 335 this.port_ = channelManager.connectToDaemon(name); | 331 this.port_ = channelManager.connectToDaemon(name); |
| 336 this.port_.onMessage.addListener(this.onMessage_.bind(this)); | 332 this.port_.onMessage.addListener(this.onMessage_.bind(this)); |
| 337 }, | 333 }, |
| 338 }; | 334 }; |
| 339 | 335 |
| 340 /** | 336 /** |
| 341 * Initialize webview content window for postMessage channel. | 337 * Initialize webview content window for postMessage channel. |
| 342 * @param {DOMWindow} webViewContentWindow Content window of the webview. | 338 * @param {DOMWindow} webViewContentWindow Content window of the webview. |
| 343 */ | 339 */ |
| 344 PostMessageChannel.init = function(webViewContentWindow) { | 340 PostMessageChannel.init = function(webViewContentWindow) { |
| 345 webViewContentWindow.postMessage({ | 341 webViewContentWindow.postMessage({type: CHANNEL_INIT_MESSAGE}, '*'); |
| 346 type: CHANNEL_INIT_MESSAGE | |
| 347 }, '*'); | |
| 348 }; | 342 }; |
| 349 | 343 |
| 350 /** | 344 /** |
| 351 * Run in daemon mode and listen for incoming connections. Note that the | 345 * Run in daemon mode and listen for incoming connections. Note that the |
| 352 * current implementation assumes the daemon runs in the hosting page | 346 * current implementation assumes the daemon runs in the hosting page |
| 353 * at the upper layer of the DOM tree. That is, all connect requests go | 347 * at the upper layer of the DOM tree. That is, all connect requests go |
| 354 * up the DOM tree instead of going into sub frames. | 348 * up the DOM tree instead of going into sub frames. |
| 355 * @param {function(PostMessagePort)} callback Invoked when a connection is | 349 * @param {function(PostMessagePort)} callback Invoked when a connection is |
| 356 * made. | 350 * made. |
| 357 */ | 351 */ |
| 358 PostMessageChannel.runAsDaemon = function(callback) { | 352 PostMessageChannel.runAsDaemon = function(callback) { |
| 359 channelManager.isDaemon = true; | 353 channelManager.isDaemon = true; |
| 360 | 354 |
| 361 var onConnect = function(port) { | 355 var onConnect = function(port) { |
| 362 callback(port); | 356 callback(port); |
| 363 }; | 357 }; |
| 364 channelManager.onConnect.addListener(onConnect); | 358 channelManager.onConnect.addListener(onConnect); |
| 365 }; | 359 }; |
| 366 | 360 |
| 367 return PostMessageChannel; | 361 return PostMessageChannel; |
| 368 })(); | 362 })(); |
| 369 | 363 |
| 370 /** @override */ | 364 /** @override */ |
| 371 Channel.create = function() { | 365 Channel.create = function() { |
| 372 return new PostMessageChannel(); | 366 return new PostMessageChannel(); |
| 373 }; | 367 }; |
| OLD | NEW |