Skip to content

Commit

Permalink
[TEST] Cross-domain message posting
Browse files Browse the repository at this point in the history
  • Loading branch information
vpodk committed Dec 19, 2024
1 parent f220c10 commit 2a6c8c7
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 2 deletions.
4 changes: 2 additions & 2 deletions about/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" itemscope
itemtype="http://schema.org/AboutPage" lang="en">
<head>
<meta itemprop="dateModified" content="2021-03-22">
<meta itemprop="dateModified" content="2024-12-18">
<meta itemprop="datePublished" content="2019-09-14">
<meta charset="utf-8">

Expand Down Expand Up @@ -240,7 +240,7 @@ <h3>Status</h3>
<li><b>7</b> supported web analytics software;</li>
<li><b>1</b> plugin for CMS (<a href="../integration/wordpress/">WordPress</a>);</li>
<li><b>6K+</b> followers on <a href="https://www.facebook.com/KomitoAnalytics/" rel="nofollow">Facebook</a>;</li>
<li><b>MVP</b> of Komito Analytics <a href="../dashboard/">Dashboard</a>.</li>
<!--li><b>MVP</b> of Komito Analytics <a href="../dashboard/">Dashboard</a>.</li-->
</ul>
<div>&nbsp;</div>
<ul>
Expand Down
103 changes: 103 additions & 0 deletions demo/iframe.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="robots" content="noindex,follow" />
<meta charset="utf-8" />
<!--
An iframe analytics handler hosted on a shared domain:
e.g. https://shared-domain.com/iframe.html?origin=https://example.com
-->
<script>
(() => {
if (self !== parent) {
const VISITOR_KEY = "_vstr";

const actions = {
HANDSHAKE_ACTION: "handshake",
GET_VISITOR_ACTION: "getVisitor",
INCREMENT_VIEWS_ACTION: "incrementViews",
BLA_BLA_BLA_ACTION: "bla",
FOO_ACTION: "bar",
};

const getCookie = (/** @type {string} */ name) => {
const pair = document.cookie
.split("; ")
.find((cookie) => cookie.startsWith(name + "="));

const cookie = (pair || "").split("=")[1];
if (cookie) {
try {
return JSON.parse(atob(decodeURIComponent(cookie)));
} catch (ex) {
console.error("[IFRAME] Coult not parse cookie:", cookie, ex);
}
}
return null;
};

const setCookie = (
/** @type {string} */ name,
/** @type {Object} */ value
) => {
const encoded = encodeURIComponent(btoa(JSON.stringify(value)));
const cookie = [
`${encodeURIComponent(name)}=${encoded}`,
`expires=${new Date(Date.now() + 86400e3 * 365).toUTCString()}`,
`domain=${document.domain}`,
"path=/; samesite=none; secure",
].join("; ");
document.cookie = cookie;
console.debug("[IFRAME] setCookie:", document.cookie);
};

const getVisitor = () => {
let visitor = getCookie(VISITOR_KEY);
if (!visitor) {
visitor = {
id: window.crypto.getRandomValues(new Uint32Array(1))[0],
views: 0,
};
setCookie(VISITOR_KEY, visitor);
}
return visitor;
};

window.addEventListener("load", (event) => {
console.log("[IFRAME] load:event:", event);
const url = new URL(document.referrer || location.href);
const origin = document.referrer
? url.origin
: url.searchParams.get("origin");
if (origin) {
const action = actions.HANDSHAKE_ACTION;
const source = window.parent;
const visitor = getVisitor();
source.postMessage({ visitor, action, actions }, origin);
}
});

window.addEventListener("message", (event) => {
console.log("[IFRAME] message:event:", event);
if (event.data) {
const action = event.data.action;
const origin = event.origin;
const source = event.source;
const visitor = getVisitor();
if (
action === actions.HANDSHAKE_ACTION ||
action === actions.GET_VISITOR_ACTION
) {
source.postMessage({ visitor, action, actions }, origin);
} else if (action === actions.INCREMENT_VIEWS_ACTION) {
visitor.views += 1;
setCookie(VISITOR_KEY, visitor);
source.postMessage({ visitor, action, actions }, origin);
}
}
});
}
})();
</script>
</head>
</html>
70 changes: 70 additions & 0 deletions demo/iframe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copy of https://komito.net/demo/iframe.js

(() => {
const IFRAME_DOMAIN = "komito.net";
const IFRAME_ORIGIN = `https://${IFRAME_DOMAIN}`;
const IFRAME_SOURCE = `${IFRAME_ORIGIN}/demo/iframe.html`;
const RANDOM_NUMBER = (+new Date()).toString(36).slice(-5);
const IFRAME_ID = `iframe-${RANDOM_NUMBER}`;

const updateCSP = () => {
let meta =
document.querySelector('meta[http-equiv="Content-Security-Policy"]') ||
document.querySelector('meta[http-equiv="content-security-policy"]');

if (!meta) {
meta = document.head.appendChild(document.createElement("meta"));
meta.setAttribute("http-equiv", "content-security-policy");
}

let content = meta.getAttribute("content") || "";
// TODO: update the "frame-src" policy directive if exisits:
content = `frame-src 'self' ${IFRAME_ORIGIN}; ${content}`;
meta.setAttribute("content", content);
};

const initIframe = () => {
// updateCSP();
const body = document.body || document.documentElement;
const iframe = body.appendChild(document.createElement("iframe"));
iframe.style.position = "absolute";
iframe.style.width = "9px";
iframe.style.height = "9px";
iframe.style.top = "-9px";
iframe.style.left = "-9px";
iframe.style.border = 0;
iframe.sandbox = "allow-scripts allow-same-origin";
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/csp
// iframe.csp = `frame-src 'self' ${IFRAME_ORIGIN}`;
iframe.id = IFRAME_ID;
iframe.src = `${IFRAME_SOURCE}?origin=${location.origin}&nc=${IFRAME_ID}`;
return iframe;
};

window.addEventListener("load", (event) => {
console.log("[PARENT] load:event:", event);
initIframe();
});

window.addEventListener("message", (event) => {
console.log("[PARENT] message:event:", event);

const actions = event.data && event.data.actions;
const origin = event.origin;
if (actions && origin === IFRAME_ORIGIN) {
const iframe = document.getElementById(IFRAME_ID) || initIframe();
const action = event.data && event.data.action;
if (action === actions.HANDSHAKE_ACTION) {
console.log("[PARENT] HANDSHAKE_ACTION");
iframe.contentWindow.postMessage(
{ action: actions.INCREMENT_VIEWS_ACTION },
IFRAME_ORIGIN
);
} else if (action === actions.INCREMENT_VIEWS_ACTION) {
console.log("[PARENT] INCREMENT_VIEWS_ACTION");
} else {
console.error("[PARENT] Unknowon action:", action);
}
}
});
})();

0 comments on commit 2a6c8c7

Please sign in to comment.