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 |
(...skipping 23 matching lines...) Expand all Loading... |
34 | 34 |
35 /** | 35 /** |
36 * The message used to set the ID of a child frame so that it can send replies | 36 * The message used to set the ID of a child frame so that it can send replies |
37 * to its parent frame. | 37 * to its parent frame. |
38 * @type {string} | 38 * @type {string} |
39 * @const | 39 * @const |
40 */ | 40 */ |
41 cvox.Interframe.SET_ID = 'cvox.INTERFRAME_SET_ID'; | 41 cvox.Interframe.SET_ID = 'cvox.INTERFRAME_SET_ID'; |
42 | 42 |
43 /** | 43 /** |
| 44 * The message used by a child frame to acknowledge an id was set (sent to its |
| 45 * parent frame. |
| 46 * @type {string} |
| 47 * @const |
| 48 */ |
| 49 cvox.Interframe.ACK_SET_ID = 'cvox.INTERFRAME_ACK_SET_ID'; |
| 50 |
| 51 /** |
44 * The ID of this window (relative to its parent farme). | 52 * The ID of this window (relative to its parent farme). |
45 * @type {number|string|undefined} | 53 * @type {number|string|undefined} |
46 */ | 54 */ |
47 cvox.Interframe.id; | 55 cvox.Interframe.id; |
48 | 56 |
49 /** | 57 /** |
50 * Array of functions that have been registered as listeners to interframe | 58 * Array of functions that have been registered as listeners to interframe |
51 * messages send to this window. | 59 * messages send to this window. |
52 * @type {Array.<function(Object)>} | 60 * @type {Array.<function(Object)>} |
53 */ | 61 */ |
54 cvox.Interframe.listeners = []; | 62 cvox.Interframe.listeners = []; |
55 | 63 |
56 /** | 64 /** |
| 65 * Maps an id to a function which gets called when a frame first sends an ack |
| 66 * for a set id msg. |
| 67 @dict {!Object.<number|string, function()>} |
| 68 * @private |
| 69 */ |
| 70 cvox.Interframe.idToCallback_ = {}; |
| 71 |
| 72 /** |
57 * Flag for unit testing. When false, skips over iframe.contentWindow check | 73 * Flag for unit testing. When false, skips over iframe.contentWindow check |
58 * in sendMessageToIframe. This is needed because in the wild, ChromeVox may | 74 * in sendMessageToIframe. This is needed because in the wild, ChromeVox may |
59 * not have access to iframe.contentWindow due to the same-origin security | 75 * not have access to iframe.contentWindow due to the same-origin security |
60 * policy. There is no reason to set this outside of a test. | 76 * policy. There is no reason to set this outside of a test. |
61 * @type {boolean} | 77 * @type {boolean} |
62 */ | 78 */ |
63 cvox.Interframe.allowAccessToIframeContentWindow = true; | 79 cvox.Interframe.allowAccessToIframeContentWindow = true; |
64 | 80 |
65 /** | 81 /** |
66 * Initializes the cvox.Interframe module. (This is called automatically.) | 82 * Initializes the cvox.Interframe module. (This is called automatically.) |
67 */ | 83 */ |
68 cvox.Interframe.init = function() { | 84 cvox.Interframe.init = function() { |
69 cvox.Interframe.messageListener = function(event) { | 85 cvox.Interframe.messageListener = function(event) { |
70 if (typeof event.data === 'string' && | 86 if (typeof event.data === 'string' && |
71 event.data.indexOf(cvox.Interframe.IF_MSG_PREFIX) == 0) { | 87 event.data.indexOf(cvox.Interframe.IF_MSG_PREFIX) == 0) { |
72 var suffix = event.data.substr(cvox.Interframe.IF_MSG_PREFIX.length); | 88 var suffix = event.data.substr(cvox.Interframe.IF_MSG_PREFIX.length); |
73 var message = /** @type {Object} */ ( | 89 var message = /** @type {Object} */ ( |
74 cvox.ChromeVoxJSON.parse(suffix)); | 90 cvox.ChromeVoxJSON.parse(suffix)); |
75 if (message['command'] == cvox.Interframe.SET_ID) { | 91 if (message['command'] == cvox.Interframe.SET_ID) { |
76 cvox.Interframe.id = message['id']; | 92 cvox.Interframe.id = message['id']; |
| 93 message['command'] = cvox.Interframe.ACK_SET_ID; |
| 94 cvox.Interframe.sendMessageToParentWindow(message); |
| 95 } else if (message['command'] == cvox.Interframe.ACK_SET_ID) { |
| 96 cvox.Interframe.id = message['id']; |
| 97 var callback = cvox.Interframe.idToCallback_[cvox.Interframe.id]; |
| 98 callback(); |
77 } | 99 } |
78 for (var i = 0, listener; listener = cvox.Interframe.listeners[i]; i++) { | 100 for (var i = 0, listener; listener = cvox.Interframe.listeners[i]; i++) { |
79 listener(message); | 101 listener(message); |
80 } | 102 } |
81 } | 103 } |
82 return false; | 104 return false; |
83 }; | 105 }; |
84 window.addEventListener('message', cvox.Interframe.messageListener, true); | 106 window.addEventListener('message', cvox.Interframe.messageListener, true); |
85 }; | 107 }; |
86 | 108 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 window.location.href = | 211 window.location.href = |
190 'javascript:window.parent.postMessage(\'' + | 212 'javascript:window.parent.postMessage(\'' + |
191 encodeURI(encodedMessage) + '\', \'*\');'; | 213 encodeURI(encodedMessage) + '\', \'*\');'; |
192 }; | 214 }; |
193 | 215 |
194 /** | 216 /** |
195 * Send the given ID to a child iframe. | 217 * Send the given ID to a child iframe. |
196 * @param {number|string} id The ID you want to receive in replies from | 218 * @param {number|string} id The ID you want to receive in replies from |
197 * this iframe. | 219 * this iframe. |
198 * @param {HTMLIFrameElement} iframe The iframe to assign. | 220 * @param {HTMLIFrameElement} iframe The iframe to assign. |
| 221 * @param {function()=} opt_callback Called when a ack msg arrives from the |
| 222 *frame. |
199 */ | 223 */ |
200 cvox.Interframe.sendIdToIFrame = function(id, iframe) { | 224 cvox.Interframe.sendIdToIFrame = function(id, iframe, opt_callback) { |
| 225 if (opt_callback) { |
| 226 cvox.Interframe.idToCallback_[id] = opt_callback; |
| 227 } |
201 var message = {'command': cvox.Interframe.SET_ID, 'id': id}; | 228 var message = {'command': cvox.Interframe.SET_ID, 'id': id}; |
202 cvox.Interframe.sendMessageToIFrame(message, iframe); | 229 cvox.Interframe.sendMessageToIFrame(message, iframe); |
203 }; | 230 }; |
204 | 231 |
205 /** | 232 /** |
206 * Returns true if inside iframe | 233 * Returns true if inside iframe |
207 * @return {boolean} true if inside iframe. | 234 * @return {boolean} true if inside iframe. |
208 */ | 235 */ |
209 cvox.Interframe.isIframe = function() { | 236 cvox.Interframe.isIframe = function() { |
210 return (window != window.parent); | 237 return (window != window.parent); |
211 }; | 238 }; |
212 | 239 |
213 cvox.Interframe.init(); | 240 cvox.Interframe.init(); |
OLD | NEW |