| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 Tools for interframe communication. To use this class, every | 6 * @fileoverview Tools for interframe communication. To use this class, every |
| 7 * window that wants to communicate with its child iframes should enumerate | 7 * window that wants to communicate with its child iframes should enumerate |
| 8 * them using document.getElementsByTagName('iframe'), create an ID to | 8 * them using document.getElementsByTagName('iframe'), create an ID to |
| 9 * associate with that iframe, then call cvox.Interframe.sendIdToIFrame | 9 * associate with that iframe, then call cvox.Interframe.sendIdToIFrame |
| 10 * on each of them. Then use cvox.Interframe.sendMessageToIFrame to send | 10 * on each of them. Then use cvox.Interframe.sendMessageToIFrame to send |
| 11 * messages to that iframe and cvox.Interframe.addListener to receive | 11 * messages to that iframe and cvox.Interframe.addListener to receive |
| 12 * replies. When a reply is received, it will automatically contain the ID of | 12 * replies. When a reply is received, it will automatically contain the ID of |
| 13 * that iframe as a parameter. | 13 * that iframe as a parameter. |
| 14 * | 14 * |
| 15 */ | 15 */ |
| 16 | 16 |
| 17 goog.provide('cvox.Interframe'); | 17 goog.provide('cvox.Interframe'); |
| 18 | 18 |
| 19 goog.require('cvox.ChromeVoxJSON'); | 19 goog.require('cvox.ChromeVoxJSON'); |
| 20 goog.require('cvox.DomUtil'); | 20 goog.require('cvox.DomUtil'); |
| 21 | 21 |
| 22 /** | 22 /** |
| 23 * @constructor | 23 * @constructor |
| 24 */ | 24 */ |
| 25 cvox.Interframe = function() { | 25 cvox.Interframe = function() {}; |
| 26 }; | |
| 27 | 26 |
| 28 /** | 27 /** |
| 29 * The prefix of all interframe messages. | 28 * The prefix of all interframe messages. |
| 30 * @type {string} | 29 * @type {string} |
| 31 * @const | 30 * @const |
| 32 */ | 31 */ |
| 33 cvox.Interframe.IF_MSG_PREFIX = 'cvox.INTERFRAME:'; | 32 cvox.Interframe.IF_MSG_PREFIX = 'cvox.INTERFRAME:'; |
| 34 | 33 |
| 35 /** | 34 /** |
| 36 * The message used to set the ID of a child frame so that it can send replies | 35 * The message used to set the ID of a child frame so that it can send replies |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 cvox.Interframe.allowAccessToIframeContentWindow = true; | 78 cvox.Interframe.allowAccessToIframeContentWindow = true; |
| 80 | 79 |
| 81 /** | 80 /** |
| 82 * Initializes the cvox.Interframe module. (This is called automatically.) | 81 * Initializes the cvox.Interframe module. (This is called automatically.) |
| 83 */ | 82 */ |
| 84 cvox.Interframe.init = function() { | 83 cvox.Interframe.init = function() { |
| 85 cvox.Interframe.messageListener = function(event) { | 84 cvox.Interframe.messageListener = function(event) { |
| 86 if (typeof event.data === 'string' && | 85 if (typeof event.data === 'string' && |
| 87 event.data.startsWith(cvox.Interframe.IF_MSG_PREFIX)) { | 86 event.data.startsWith(cvox.Interframe.IF_MSG_PREFIX)) { |
| 88 var suffix = event.data.substr(cvox.Interframe.IF_MSG_PREFIX.length); | 87 var suffix = event.data.substr(cvox.Interframe.IF_MSG_PREFIX.length); |
| 89 var message = /** @type {Object} */ ( | 88 var message = /** @type {Object} */ (cvox.ChromeVoxJSON.parse(suffix)); |
| 90 cvox.ChromeVoxJSON.parse(suffix)); | |
| 91 if (message['command'] == cvox.Interframe.SET_ID) { | 89 if (message['command'] == cvox.Interframe.SET_ID) { |
| 92 cvox.Interframe.id = message['id']; | 90 cvox.Interframe.id = message['id']; |
| 93 message['command'] = cvox.Interframe.ACK_SET_ID; | 91 message['command'] = cvox.Interframe.ACK_SET_ID; |
| 94 cvox.Interframe.sendMessageToParentWindow(message); | 92 cvox.Interframe.sendMessageToParentWindow(message); |
| 95 } else if (message['command'] == cvox.Interframe.ACK_SET_ID) { | 93 } else if (message['command'] == cvox.Interframe.ACK_SET_ID) { |
| 96 cvox.Interframe.id = message['id']; | 94 cvox.Interframe.id = message['id']; |
| 97 var callback = cvox.Interframe.idToCallback_[cvox.Interframe.id]; | 95 var callback = cvox.Interframe.idToCallback_[cvox.Interframe.id]; |
| 98 callback(); | 96 callback(); |
| 99 } | 97 } |
| 100 for (var i = 0, listener; listener = cvox.Interframe.listeners[i]; i++) { | 98 for (var i = 0, listener; listener = cvox.Interframe.listeners[i]; i++) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 var encodedMessage = cvox.Interframe.IF_MSG_PREFIX + | 151 var encodedMessage = cvox.Interframe.IF_MSG_PREFIX + |
| 154 cvox.ChromeVoxJSON.stringify(message, null, null); | 152 cvox.ChromeVoxJSON.stringify(message, null, null); |
| 155 var script = document.createElement('script'); | 153 var script = document.createElement('script'); |
| 156 script.type = 'text/javascript'; | 154 script.type = 'text/javascript'; |
| 157 | 155 |
| 158 // TODO: Make this logic more like makeNodeReference_ inside api.js | 156 // TODO: Make this logic more like makeNodeReference_ inside api.js |
| 159 // (line 126) so we can use an attribute instead of a classname | 157 // (line 126) so we can use an attribute instead of a classname |
| 160 if (iframe.hasAttribute('id') && | 158 if (iframe.hasAttribute('id') && |
| 161 document.getElementById(iframe.id) == iframe) { | 159 document.getElementById(iframe.id) == iframe) { |
| 162 // Ideally, try to send it based on the iframe's existing id. | 160 // Ideally, try to send it based on the iframe's existing id. |
| 163 script.innerHTML = | 161 script.innerHTML = 'document.getElementById(decodeURI(\'' + |
| 164 'document.getElementById(decodeURI(\'' + | |
| 165 encodeURI(iframe.id) + '\')).contentWindow.postMessage(decodeURI(\'' + | 162 encodeURI(iframe.id) + '\')).contentWindow.postMessage(decodeURI(\'' + |
| 166 encodeURI(encodedMessage) + '\'), \'*\');'; | 163 encodeURI(encodedMessage) + '\'), \'*\');'; |
| 167 } else { | 164 } else { |
| 168 // If not, add a style name and send it based on that. | 165 // If not, add a style name and send it based on that. |
| 169 var styleName = 'cvox_iframe' + message['id']; | 166 var styleName = 'cvox_iframe' + message['id']; |
| 170 if (iframe.className === '') { | 167 if (iframe.className === '') { |
| 171 iframe.className = styleName; | 168 iframe.className = styleName; |
| 172 } else if (iframe.className.indexOf(styleName) == -1) { | 169 } else if (iframe.className.indexOf(styleName) == -1) { |
| 173 iframe.className += ' ' + styleName; | 170 iframe.className += ' ' + styleName; |
| 174 } | 171 } |
| 175 | 172 |
| 176 script.innerHTML = | 173 script.innerHTML = 'document.getElementsByClassName(decodeURI(\'' + |
| 177 'document.getElementsByClassName(decodeURI(\'' + | |
| 178 encodeURI(styleName) + | 174 encodeURI(styleName) + |
| 179 '\'))[0].contentWindow.postMessage(decodeURI(\'' + | 175 '\'))[0].contentWindow.postMessage(decodeURI(\'' + |
| 180 encodeURI(encodedMessage) + '\'), \'*\');'; | 176 encodeURI(encodedMessage) + '\'), \'*\');'; |
| 181 } | 177 } |
| 182 | 178 |
| 183 // Remove the script so we don't leave any clutter. | 179 // Remove the script so we don't leave any clutter. |
| 184 document.head.appendChild(script); | 180 document.head.appendChild(script); |
| 185 window.setTimeout(function() { | 181 window.setTimeout(function() { |
| 186 document.head.removeChild(script); | 182 document.head.removeChild(script); |
| 187 }, 1000); | 183 }, 1000); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 201 if (window.parent) { | 197 if (window.parent) { |
| 202 cvox.Interframe.sendMessageToWindow(message, window.parent); | 198 cvox.Interframe.sendMessageToWindow(message, window.parent); |
| 203 return; | 199 return; |
| 204 } | 200 } |
| 205 | 201 |
| 206 // A content script can't access window.parent, but the page can, so | 202 // A content script can't access window.parent, but the page can, so |
| 207 // use window.location.href to execute a simple line of javascript in | 203 // use window.location.href to execute a simple line of javascript in |
| 208 // the page context. | 204 // the page context. |
| 209 var encodedMessage = cvox.Interframe.IF_MSG_PREFIX + | 205 var encodedMessage = cvox.Interframe.IF_MSG_PREFIX + |
| 210 cvox.ChromeVoxJSON.stringify(message, null, null); | 206 cvox.ChromeVoxJSON.stringify(message, null, null); |
| 211 window.location.href = | 207 window.location.href = 'javascript:window.parent.postMessage(\'' + |
| 212 'javascript:window.parent.postMessage(\'' + | |
| 213 encodeURI(encodedMessage) + '\', \'*\');'; | 208 encodeURI(encodedMessage) + '\', \'*\');'; |
| 214 }; | 209 }; |
| 215 | 210 |
| 216 /** | 211 /** |
| 217 * Send the given ID to a child iframe. | 212 * Send the given ID to a child iframe. |
| 218 * @param {number|string} id The ID you want to receive in replies from | 213 * @param {number|string} id The ID you want to receive in replies from |
| 219 * this iframe. | 214 * this iframe. |
| 220 * @param {HTMLIFrameElement} iframe The iframe to assign. | 215 * @param {HTMLIFrameElement} iframe The iframe to assign. |
| 221 * @param {function()=} opt_callback Called when a ack msg arrives from the | 216 * @param {function()=} opt_callback Called when a ack msg arrives from the |
| 222 *frame. | 217 *frame. |
| 223 */ | 218 */ |
| 224 cvox.Interframe.sendIdToIFrame = function(id, iframe, opt_callback) { | 219 cvox.Interframe.sendIdToIFrame = function(id, iframe, opt_callback) { |
| 225 if (opt_callback) { | 220 if (opt_callback) { |
| 226 cvox.Interframe.idToCallback_[id] = opt_callback; | 221 cvox.Interframe.idToCallback_[id] = opt_callback; |
| 227 } | 222 } |
| 228 var message = {'command': cvox.Interframe.SET_ID, 'id': id}; | 223 var message = {'command': cvox.Interframe.SET_ID, 'id': id}; |
| 229 cvox.Interframe.sendMessageToIFrame(message, iframe); | 224 cvox.Interframe.sendMessageToIFrame(message, iframe); |
| 230 }; | 225 }; |
| 231 | 226 |
| 232 /** | 227 /** |
| 233 * Returns true if inside iframe | 228 * Returns true if inside iframe |
| 234 * @return {boolean} true if inside iframe. | 229 * @return {boolean} true if inside iframe. |
| 235 */ | 230 */ |
| 236 cvox.Interframe.isIframe = function() { | 231 cvox.Interframe.isIframe = function() { |
| 237 return (window != window.parent); | 232 return (window != window.parent); |
| 238 }; | 233 }; |
| 239 | 234 |
| 240 cvox.Interframe.init(); | 235 cvox.Interframe.init(); |
| OLD | NEW |