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 |