Failed to execute 'postMessage' on 'DOMWindow': The target origin provided does not match the recipient window's origin

Viewed 25

I'm working inside a Nuxt JS 2 project and have a global injected function called createIcicleIframeBridge and purgeIcicleHashBetweenDomains. These functions are part of a plugin, and are called from within the mounted hook of a page.

When I call the purge function, it complains and says:

Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://icicle.ext') does not match the recipient window's origin ('http://127.0.0.1:8001')

If I wrap the postMessage in a timeout of a few seconds, then it works as intended and the error goes. I've wrote another global function that'll keep checking if the element exists before attempting to post a message to the iframe, which works in terms of delaying and continuously checking for X seconds, but when combined with my purge check, the javascript still seems to think the iFrame doesn't exist.

I don't want to rely on a setTimeout with a single defined value as this will cause reliability issues.

My plugin file:

/*
** Post Icicle bridge data
*/

function postIcicleBridgeData (app, data, url = 'https://icicle.ext') {
  app.$waitForGlobalElement('[data-icicle-hash-bridge]', () => {
    const bridge = document.querySelector('[data-icicle-hash-bridge]').contentWindow
    if (bridge) bridge.postMessage(data, url)
  })
}

export default function ({ app, route, redirect, context }, inject) {

  /*
  ** Create a bridge to Icicle for cross-domain
  */
  inject('createIcicleIframeBridge', (url = 'https://icicle.ext') => {
    setTimeout(() => {
      const iframeBridge = document.createElement('iframe')
      iframeBridge.src = `${url}?v=${Math.round(new Date().getTime() / 1000)}`
      iframeBridge.dataset.icicleHashBridge = true
      iframeBridge.style.display = 'none'
      document.getElementsByTagName('BODY')[0].appendChild(iframeBridge)
    }, 3 * 1000)
  })

  /*
  ** Clear global hash
  */
  inject('purgeIcicleHashBetweenDomains', () => {
    postIcicleBridgeData(app, 'purgeHash')
  })

  /*
  ** Wait for global element to become available
  */
  inject('waitForGlobalElement', (key, callback, delay = 10) => {
    if (document.querySelector(key)) {
      callback()
    } else {
      setTimeout(() => {
        app.$waitForGlobalElement(key, callback)
      }, delay)
    }
  })

}

Then called from within a page:

mounted () {
  this.$createIcicleIframeBridge()

  // clear Icicle hash in case customer doesn't apply
  this.$purgeIcicleHashBetweenDomains()
}

What am I missing here? What do I need to change so that I can ensure whenever my purge function runs the iFrame is always there.

0 Answers
Related