Could you please help with the following? domaina.com/parent.html includes an iframe with src=domainb.com/iframe.html. When we click a button on domaina.com/parent.html, we pass a URL to the iframe using postMessage and localStorage. We will have multiple buttons with different URLs. Then, we're redirected to domainb.com/iframe.html. Then, we retrieve the URL from localStorage and we'll be redirected to that URL. The following code works fine in Chrome but not in Firefox and Safari; I'm able to save the URL to localStorage from the iframe, but once I'm redirected to the iframe page, the URL is not in localStorage on domainb.com. Adding query parameters is not an option.
parent.html:
<!DOCTYPE html>
<html>
<head>
<title>Parent Window</title>
</head>
<body>
<iframe id="iframe-id" src="https://domainb.com/iframe.html" width="500" height="200">
</iframe>
<div class="button" role="button" tabindex="0" style="cursor:pointer">Click Me</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
document.querySelector('.button').addEventListener('click', (event) => {
setTimeout(() => {
const iframeDomain = 'https://domainb.com'; // Set the correct iframe domain here
const data = doSomethingToGetData();
const iframe = document.getElementById('iframe-id');
// Send data to the iframe to save
iframe.contentWindow.postMessage({
action: 'save',
key: 'myKey',
value: data
}, iframeDomain);
// Request data from the iframe
iframe.contentWindow.postMessage({
action: 'get',
key: 'myKey'
}, iframeDomain);
window.addEventListener("message", messageHandler, false);
function messageHandler(event) {
console.log(event)
if (event.origin !== iframeDomain) {
return; // Reject messages from unknown origins
}
const { action, key, value } = event.data;
if (action == 'returnData') {
useData(key, value);
}
}
// Function to simulate getting data
function doSomethingToGetData() {
return "https://redirect.com";
}
// Function to handle the returned data from the iframe
function useData(key, value) {
console.log('Received Data Key:', key);
console.log('Received Data Value:', value);
}
location.href = 'https://domainb.com/iframe.html';
}, 2000);
});
});
</script>
</body>
</html>
iframe.html
<!DOCTYPE html>
<html>
<head>
<title>Iframe Window</title>
</head>
<body>
<script>
document.addEventListener('DOMContentLoaded', () => {
const domains = [
"https://domaina.com", // Add parent domain to the whitelist
"https://domainb.com"
];
window.addEventListener("message", messageHandler, false);
// Check if the page is the top-level window (not inside an iframe)
if (window === window.top) {
window.location.href = getDataFromLocalStorage("myKey");
}
function messageHandler(event) {
if (!domains.includes(event.origin))
return;
const { action, key } = event.data;
if (action === 'save') {
const value = event.data.value;
saveDataToLocalStorage(key, value);
} else if (action === 'get') {
const value = getDataFromLocalStorage(key);
event.source.postMessage({
action: 'returnData',
key,
value
}, event.origin);
}
}
// Function to save data to localStorage
function saveDataToLocalStorage(key, value) {
window.localStorage.setItem(key, JSON.stringify(value));
}
// Function to get data from localStorage
function getDataFromLocalStorage(key) {
const value = window.localStorage.getItem(key);
return value ? JSON.parse(value) : null;
}
});
</script>
</body>
</html>
I have the answer to my own question:
on iframe.html added a postMessage with action 'dataSaved' to respond back to the parent that data has been saved:
//existing code
if (action === 'save') {
const value = event.data.value;
saveDataToLocalStorage(key, value);
// Respond back to the parent that data has been saved
event.source.postMessage({
action: 'dataSaved',
key,
value
}, event.origin);
}
//existing code
on parent.html added a listener to navigate to the new URL after receiving the data:
//existing code
if (action == 'returnData') {
useData(key, value);
} else if (action === 'dataSaved') {
// After receiving data, navigate to the new URL
location.href = value;
}
//existing code