-
Notifications
You must be signed in to change notification settings - Fork 791
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add axe.frameMessenger with configurable allowedOrigins (#2880)
* feat(axe.frameMessenger): api to allow custom iframe communication * reset doc * fixes * fix * tests * chore(wip): refactor messageHandler * add allowed origins * rename directory * fix ie11 window.origin * fix build * fix origin * Update test/core/base/audit.js Co-authored-by: Wilco Fiers <[email protected]> * resolve comments * WIP: chanages * chore: fix up couple more minor points * docs(api): add frameMessenger & allowedOrigins * chore(types): add frameMessenger & allowedOrigins * fix(allowedOrigins): consistently use http * chore: resolve comments * docs(API): document use with file:// * chore: minor improvements * docs(API): recommendation not to test on file:// Co-authored-by: Steven Lambert <[email protected]> Co-authored-by: Steven Lambert <[email protected]>
- Loading branch information
1 parent
33428d8
commit b27bab3
Showing
30 changed files
with
16,050 additions
and
2,522 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# Frame Messenger | ||
|
||
Axe frameMessenger can be used to configure how axe-core communicates information between frames. By default, axe-core uses `window.postMessage()`. Since other scripts on the page may also use `window.postMessage`, axe-core's use of it can sometimes disrupt page functionality. This can be avoided by providing `axe.frameMessenger()` a way to communicate to frames that does not use `window.postMessage`. | ||
|
||
Tools like browser extensions and testing environments often have different channels through which information can be communicated. `axe.frameMessenger` must be set up in **every frame** axe-core is included. | ||
|
||
```js | ||
axe.frameMessenger({ | ||
// Called to initialize message handling | ||
open(topicHandler) { | ||
// Start listening for "axe-core" events | ||
const unsubscribe = bridge.subscribe('axe-core', data => { | ||
topicHandler(data); | ||
}); | ||
// Tell axe how to close the connection if it needs to | ||
return unsubscribe; | ||
}, | ||
|
||
// Called when axe needs to send a message to another frame | ||
async post(frameWindow, data, replyHandler) { | ||
// Send a message to another frame for "axe-core" | ||
const replies = bridge.send(frameWindow, 'axe-core', data); | ||
// Async handling replies as they come back | ||
for await (let data of replies) { | ||
replyHandler(data); | ||
} | ||
} | ||
}); | ||
``` | ||
|
||
## axe.frameMessenger({ open }) | ||
|
||
`open` is a function that should setup the communication channel with iframes. It is passed a `topicHandler` function, which must be called when a message is received from another frame. | ||
|
||
The `topicHandler` function takes two arguments: the `data` object and a callback function that is called when the subscribed listener completes. The `data` object is exclusively passed data that can be serialized with `JSON.stringify()`, which depending on the system may need to be used. | ||
|
||
The `open` function can `return` an optional cleanup function, which is called when another frameMessenger is registered. | ||
|
||
## axe.frameMessenger({ post }) | ||
|
||
`post` is a function that dictates how axe-core communicates with frames. It is passed three arguments: `frameWindow`, which is the frames `contentWindow`, the `data` object, and a `replyHandler` that must be called when responses are received. | ||
|
||
**note**: Currently, axe-core will only call `replyHandler` once, so promises can also be used here. This may change in the future, so it is preferable to make it possible for `replyHandler` to be called multiple times. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { respondable } from '../utils'; | ||
|
||
export default function frameMessenger(frameHandler) { | ||
respondable.updateMessenger(frameHandler); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { postMessage } from './frame-messenger/post-message'; | ||
import { messageHandler } from './frame-messenger/message-handler'; | ||
|
||
/** | ||
* Setup default axe frame messenger (make a function so we can | ||
* call it during tests to reset respondable to default state). | ||
* @param {Object} respondable | ||
*/ | ||
export const frameMessenger = { | ||
open(topicHandler) { | ||
if (typeof window.addEventListener !== 'function') { | ||
return; | ||
} | ||
|
||
const handler = function(messageEvent) { | ||
messageHandler(messageEvent, topicHandler); | ||
}; | ||
window.addEventListener('message', handler, false); | ||
|
||
return () => { | ||
window.removeEventListener('message', handler, false); | ||
}; | ||
}, | ||
|
||
post(win, data, replyHandler) { | ||
if (typeof window.addEventListener !== 'function') { | ||
return false; | ||
} | ||
return postMessage(win, data, false, replyHandler); | ||
} | ||
}; | ||
|
||
/** | ||
* Setup default axe frame messenger (make a function so we can | ||
* call it during tests to reset respondable to default state). | ||
* @param {Object} respondable | ||
*/ | ||
export function setDefaultFrameMessenger(respondable) { | ||
respondable.updateMessenger(frameMessenger); | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import assert from '../assert'; | ||
|
||
const channels = {}; | ||
|
||
export function storeReplyHandler( | ||
channelId, | ||
replyHandler, | ||
sendToParent = true | ||
) { | ||
assert( | ||
!channels[channelId], | ||
`A replyHandler already exists for this message channel.` | ||
); | ||
channels[channelId] = { replyHandler, sendToParent }; | ||
} | ||
|
||
export function getReplyHandler(topic) { | ||
return channels[topic]; | ||
} | ||
|
||
export function deleteReplyHandler(channelId) { | ||
delete channels[channelId]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { postMessage } from './post-message'; | ||
|
||
/** | ||
* Helper closure to create a function that may be used to respond to a message | ||
* @private | ||
* @param {Window} win The window from which the message originated | ||
* @param {String} channelId The "unique" ID of the original message | ||
* @return {Function} A function that may be invoked to respond to the message | ||
*/ | ||
export function createResponder(win, channelId, sendToParent = true) { | ||
return function respond(message, keepalive, replyHandler) { | ||
const data = { channelId, message, keepalive }; | ||
postMessage(win, data, sendToParent, replyHandler); | ||
}; | ||
} |
Oops, something went wrong.