0

I have 2 iframe on my webpage. iframe S has the same origin as the web page, iframe D has a different one:

<iframe src="https://mdn-samples.mozilla.org/snippets/html/iframe-simple-contents.html" title="iframe example 1" width="400" height="300">
  <p>Your browser does not support iframes.</p>
</iframe>

I need to addEventListener only onto the iframes that have the same origin. This is what I do:

for (let i = 0; i < frames.length; i++) {
    const iframe = window.frames[I]
    console.log(iframe)        
    if (iframe.document.domain === window.document.domain) {
        iframe.addEventListener('message', event => {
            console.log(event.data)
        }, false)
    }
}

But this gives an error, when I try to read iframe.document of iframe D.

Uncaught DOMException: Blocked a frame with origin "http://localhost:8080" from accessing a cross-origin frame.

Because, unlike iframe S, iframe D gives me this object, when I try console.log(iframe) from the 2 snippet of code above:

enter image description here

And as you can see, there is no document property.

Eduard
  • 8,437
  • 10
  • 42
  • 64
  • Possible duplicate of [SecurityError: Blocked a frame with origin from accessing a cross-origin frame](https://stackoverflow.com/questions/25098021/securityerror-blocked-a-frame-with-origin-from-accessing-a-cross-origin-frame) – Osvaldo Maria Mar 07 '18 at 10:13

2 Answers2

1

Simply select all iframes using querySelectorAll, then construct a new URL using their src attribute and check if it matches your own hostname.

document.querySelectorAll('iframe').forEach(frame => {
  const url = new URL(frame.src)

  if (url.hostname === window.location.hostname) {
    frame.addEventListener('message', event => {
        console.log(event.data)
    }, false)
  }
})
<iframe src="https://stackoverflow.com"></iframe>
<iframe src="https://stackoverflow.com"></iframe>
<iframe src="https://stackoverflow.com"></iframe>
<iframe src="https://stackoverflow.com"></iframe>
<iframe src="https://stackoverflow.com"></iframe>
<iframe src="https://google.com"></iframe>

Note that new URL won't work in IE browsers. You'd have to manually split your URL parts to do the hostname equality check.

nicholaswmin
  • 21,686
  • 15
  • 91
  • 167
-1

Wrapping an entire if-statement with with try - catch block rids of the error, but not sure if that's the best way to tackle this problem.

for (let i = 0; i < frames.length; i++) {
    const iframe = window.frames[I]
    console.log(iframe)
    try {        
        if (iframe.document.domain === window.document.domain) {
            iframe.addEventListener('message', event => {
                console.log(event.data)
            }, false)
        }
    }
    catch(error) {
    }
}
Eduard
  • 8,437
  • 10
  • 42
  • 64