iframe with RPC "installed"
by David Iglesias
August 31, 2019
HTML
<h1>
iframed but you can ask me things!
</h1>
<p>
I'm under control by:
<ul>
<li id="handler">Nobody!</li>
</ul>
</p>
<label>
Secret value:<br />
<input type="text" id="secret" placeholder="Type a secret value here!" />
</label>
CSS
label {
display: flex;
flex-direction: column;
}
input {
flex: 1;
font-size: 16px;
padding: 6px;
}
JavaScript
(function() {
const handler = document.getElementById('handler');
const secret = document.getElementById('secret');
let handlerId;
const sendResponse = (e, request, data) => {
e.source.postMessage({
secretId: request.secretId,
requestId: request.requestId,
...data,
}, "*");
}
const handleMessage = (e) => {
console.debug('Received message inside iframe...', e);
const data = e.data;
if (handlerId && data.type === "hi") {
// Already authenticated, don't be too kind...
sendResponse(e, data, {
error: 'You only need to say hi once!',
});
} else if (handlerId && data.secretId === handlerId) {
// Known event types...
switch (data.type) {
case 'secret':
sendResponse(e, data, {
secret: secret.value,
});
break;
default:
sendResponse(e, data, {
error: `Don't know how to handle [${data.type}]`,
});
}
} else if (!handlerId && data.type === "hi") {
// Handshaking!
handlerId = e.data.secretId;
handler.innerHTML = 'iframe ' + handlerId;
sendResponse(e, data, {
type: 'ack-hi',
});
} else {
sendResponse(e, data, {
error: 'Ignoring message, be more polite!',
});
}
}
window.addEventListener('message', handleMessage);
}());