From ee97b78f70076afff3b87b2ac01c297183f77ef7 Mon Sep 17 00:00:00 2001 From: Fiona Hasanaj Date: Fri, 12 Sep 2025 09:44:56 -0700 Subject: [PATCH 1/5] DS-4809: Added logging for debugging --- docs/_includes/swirl_chat.html | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/docs/_includes/swirl_chat.html b/docs/_includes/swirl_chat.html index aaf98bf7..7b752122 100644 --- a/docs/_includes/swirl_chat.html +++ b/docs/_includes/swirl_chat.html @@ -29,17 +29,27 @@ iframe.src = `${CHAT_ORIGIN}/galaxy/pre-chat`; iframe.onload = () => { - console.log('posting setLocalStorage message'); - iframe.contentWindow.postMessage({ + console.log('[HOST] iframe onload fired at', performance.now()); + + const msg = { action: 'setLocalStorage', payload: { 'swirl-token': token, 'swirl-chat-status': 'true', 'swirl-rag-rating-status': 'true', - 'csrftoken': csrfToken - } - }, CHAT_ORIGIN); + 'csrftoken': csrfToken, + }, + }; + + console.log('[HOST] posting message at', performance.now(), 'to', CHAT_ORIGIN, msg); + + iframe.contentWindow.postMessage(msg, CHAT_ORIGIN); }; + + window.addEventListener('message', (e) => { + console.log('[HOST] got message from iframe', e.origin, e.data); + }); + } catch (err) { console.error('initSwirlChat error:', err); document.body.insertAdjacentHTML( From 3af14aa14a3fb2652be89750702c9cfbce568d4f Mon Sep 17 00:00:00 2001 From: Fiona Hasanaj Date: Sun, 14 Sep 2025 21:57:44 -0700 Subject: [PATCH 2/5] DS-4809: Added more debug statements --- docs/_includes/swirl_chat.html | 49 +++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/docs/_includes/swirl_chat.html b/docs/_includes/swirl_chat.html index 7b752122..679b2c6f 100644 --- a/docs/_includes/swirl_chat.html +++ b/docs/_includes/swirl_chat.html @@ -9,12 +9,25 @@ {% assign chat_origin = include.chat_origin | default: "https://chat.docs.swirlaiconnect.com" %} From 9b44003f74a7d66017c5f49cb87ff9e019e534fd Mon Sep 17 00:00:00 2001 From: Fiona Hasanaj Date: Mon, 15 Sep 2025 09:23:05 -0700 Subject: [PATCH 3/5] DS-4809: Added retry-ack logic for postMessage --- docs/_includes/swirl_chat.html | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/docs/_includes/swirl_chat.html b/docs/_includes/swirl_chat.html index 679b2c6f..59455a84 100644 --- a/docs/_includes/swirl_chat.html +++ b/docs/_includes/swirl_chat.html @@ -45,7 +45,7 @@ iframe.onload = function () { console.log(LOG_PREFIX, nowTs(), 'iframe onload fired'); - const msg = { + var msg = { action: 'setLocalStorage', payload: { 'swirl-token': token, @@ -55,8 +55,34 @@ } }; - console.log(LOG_PREFIX, nowTs(), 'posting message to', CHAT_ORIGIN, msg); - iframe.contentWindow.postMessage(msg, CHAT_ORIGIN); + var tries = 0; + var done = false; + var MAX_TRIES = 20; + var INTERVAL_MS = 250; + + function stopOnAck(e) { + if (e.origin === CHAT_ORIGIN && e.data && e.data.action === 'setLocalStorage-ack') { + done = true; + window.removeEventListener('message', stopOnAck); + console.log(LOG_PREFIX, nowTs(), 'received setLocalStorage-ack; stopping retries'); + } + } + window.addEventListener('message', stopOnAck); + + (function resend() { + if (done || tries >= MAX_TRIES) { + if (!done) console.warn(LOG_PREFIX, nowTs(), 'no ack; gave up after', tries, 'tries'); + return; + } + tries++; + console.log(LOG_PREFIX, nowTs(), 'posting setLocalStorage (try', tries, ') to', CHAT_ORIGIN, msg); + try { + iframe.contentWindow.postMessage(msg, CHAT_ORIGIN); + } catch (err) { + console.warn(LOG_PREFIX, nowTs(), 'postMessage failed on try', tries, err); + } + setTimeout(resend, INTERVAL_MS); + })(); }; window.addEventListener('message', function (e) { From a513cb8923519eb13d3ee355ab7aa9a32e812c5b Mon Sep 17 00:00:00 2001 From: Fiona Hasanaj Date: Mon, 15 Sep 2025 13:37:06 -0700 Subject: [PATCH 4/5] DS-4809: Add handshake logic to prevent second set of retries on load --- docs/_includes/swirl_chat.html | 36 ++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/docs/_includes/swirl_chat.html b/docs/_includes/swirl_chat.html index 59455a84..34e1bda2 100644 --- a/docs/_includes/swirl_chat.html +++ b/docs/_includes/swirl_chat.html @@ -42,9 +42,25 @@ const iframe = document.getElementById('swirl-chat-iframe'); iframe.src = CHAT_ORIGIN + '/galaxy/pre-chat'; + let handshakeDone = false; + + window.addEventListener('message', function (e) { + console.log(LOG_PREFIX, nowTs(), 'got message from iframe', e.origin, e.data); + if (e.origin === CHAT_ORIGIN && e.data && e.data.action === 'setLocalStorage-ack') { + handshakeDone = true; + iframe.dataset.swirlHandshakeDone = '1'; + console.log(LOG_PREFIX, nowTs(), 'ack observed in logger; handshakeDone=true'); + } + }); + iframe.onload = function () { console.log(LOG_PREFIX, nowTs(), 'iframe onload fired'); + if (handshakeDone || iframe.dataset.swirlHandshakeDone === '1') { + console.log(LOG_PREFIX, nowTs(), 'handshake already complete; ignoring subsequent load'); + return; + } + var msg = { action: 'setLocalStorage', payload: { @@ -63,6 +79,8 @@ function stopOnAck(e) { if (e.origin === CHAT_ORIGIN && e.data && e.data.action === 'setLocalStorage-ack') { done = true; + handshakeDone = true; + iframe.dataset.swirlHandshakeDone = '1'; window.removeEventListener('message', stopOnAck); console.log(LOG_PREFIX, nowTs(), 'received setLocalStorage-ack; stopping retries'); } @@ -70,25 +88,19 @@ window.addEventListener('message', stopOnAck); (function resend() { - if (done || tries >= MAX_TRIES) { - if (!done) console.warn(LOG_PREFIX, nowTs(), 'no ack; gave up after', tries, 'tries'); + if (done || handshakeDone || tries >= MAX_TRIES) { + if (!done && !handshakeDone) { + console.warn(LOG_PREFIX, nowTs(), 'no ack; gave up after', tries, 'tries'); + } return; } tries++; console.log(LOG_PREFIX, nowTs(), 'posting setLocalStorage (try', tries, ') to', CHAT_ORIGIN, msg); - try { - iframe.contentWindow.postMessage(msg, CHAT_ORIGIN); - } catch (err) { - console.warn(LOG_PREFIX, nowTs(), 'postMessage failed on try', tries, err); - } + try { iframe.contentWindow.postMessage(msg, CHAT_ORIGIN); } + catch (err) { console.warn(LOG_PREFIX, nowTs(), 'postMessage failed on try', tries, err); } setTimeout(resend, INTERVAL_MS); })(); }; - - window.addEventListener('message', function (e) { - console.log(LOG_PREFIX, nowTs(), 'got message from iframe', e.origin, e.data); - }); - } catch (err) { console.error(LOG_PREFIX, nowTs(), 'initSwirlChat error:', err); document.body.insertAdjacentHTML( From a533ef629371d52fd4d77eabf341dcfed249b69a Mon Sep 17 00:00:00 2001 From: Fiona Hasanaj Date: Tue, 16 Sep 2025 12:58:01 -0700 Subject: [PATCH 5/5] DS-4809: Modified logs to not show sensitive info + added nonce to handshake --- docs/_includes/swirl_chat.html | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/docs/_includes/swirl_chat.html b/docs/_includes/swirl_chat.html index 34e1bda2..9a7b1f08 100644 --- a/docs/_includes/swirl_chat.html +++ b/docs/_includes/swirl_chat.html @@ -26,6 +26,15 @@ return null; } + function redact(obj) { + try { + const clone = JSON.parse(JSON.stringify(obj)); + if (clone?.payload?.['swirl-token']) clone.payload['swirl-token'] = '[REDACTED]'; + if (clone?.payload?.['csrftoken']) clone.payload['csrftoken'] = '[REDACTED]'; + return clone; + } catch { return '[unserializable]'; } + } + async function initSwirlChat() { console.log(LOG_PREFIX, nowTs(), 'initSwirlChat start'); try { @@ -43,13 +52,18 @@ iframe.src = CHAT_ORIGIN + '/galaxy/pre-chat'; let handshakeDone = false; + let handshakeNonce = String(Date.now()) + '-' + Math.random().toString(36).slice(2); window.addEventListener('message', function (e) { - console.log(LOG_PREFIX, nowTs(), 'got message from iframe', e.origin, e.data); + console.log(LOG_PREFIX, nowTs(), 'got message from iframe', e.origin, redact(e.data)); if (e.origin === CHAT_ORIGIN && e.data && e.data.action === 'setLocalStorage-ack') { + if (e.data.nonce !== handshakeNonce) { + console.warn(LOG_PREFIX, nowTs(), 'ack nonce mismatch; ignoring'); + return; + } handshakeDone = true; iframe.dataset.swirlHandshakeDone = '1'; - console.log(LOG_PREFIX, nowTs(), 'ack observed in logger; handshakeDone=true'); + console.log(LOG_PREFIX, nowTs(), 'ack observed; handshakeDone=true'); } }); @@ -63,6 +77,7 @@ var msg = { action: 'setLocalStorage', + nonce: handshakeNonce, payload: { 'swirl-token': token, 'swirl-chat-status': 'true', @@ -78,6 +93,7 @@ function stopOnAck(e) { if (e.origin === CHAT_ORIGIN && e.data && e.data.action === 'setLocalStorage-ack') { + if (e.data.nonce !== handshakeNonce) return; done = true; handshakeDone = true; iframe.dataset.swirlHandshakeDone = '1'; @@ -95,7 +111,7 @@ return; } tries++; - console.log(LOG_PREFIX, nowTs(), 'posting setLocalStorage (try', tries, ') to', CHAT_ORIGIN, msg); + console.log(LOG_PREFIX, nowTs(), 'posting setLocalStorage (try', tries, ') to', CHAT_ORIGIN, redact(msg)); try { iframe.contentWindow.postMessage(msg, CHAT_ORIGIN); } catch (err) { console.warn(LOG_PREFIX, nowTs(), 'postMessage failed on try', tries, err); } setTimeout(resend, INTERVAL_MS);