Question

I'm integrating a third party photo upload service with my app. So I'm loading it in my page via iframe.

When the upload service is done with uploading my photo it can either trigger certain event to my parent page i.e :

parent.$('body').trigger('photoUpload.complete');

or it triggers a function in the parent page i.e :

window.parent.reloadParentPage();

In any case I get this warning in my chrome console :

Uncaught SecurityError: Blocked a frame with origin "https://photoupload.com" from accessing a frame with origin "https://website.com".

I realize this is a security issue as described here :

http://www.w3.org/TR/2008/WD-access-control-20080912/

So I wanted to enable the origin https://photoupload.com to access my site. I did this in my controller :

after_filter :set_access_control_headers

Then the method :

def set_access_control_headers 
  headers['Access-Control-Allow-Origin'] = "https://photoupload.com" 
  headers['Access-Control-Request-Method'] = '*' 
end

Please not that https://photoupload.com is the photo upload service and https://website.com is my website. (Imaginary names for example sake), but they are both hosted on heroku.

How do I make this work?

Saw similar questions that people had success with this :

Triggering a jQuery event from iframe

Update

Maybe a better question would be, in which app should I set the headers? I was assuming in my app?

Update II

Is there a better way to do this? Send action/event/something from iframe to the parent page, so the parent page can react in some way

Was it helpful?

Solution

As long as you don't have to support IE6 or IE7, the preferred way to send cross-domain messages between an iframe and its parent is to use window.postMessage(...).

Since you have the ability to modify the upload service, you should have it invoke something like this:

window.parent.postMessage('photoUpload.complete', 'https://website.com');

(the second parameter can be set to '*' to allow the iframe to send messages regardless of the containing page's domain, but that's correspondingly less secure - may not be relevant in your case though as no actual data is being sent).

and your site would use something like

if (!window.addEventListener) {
    // IE8 support (could also use an addEventListener shim)
    window.attachEvent('onmessage', handleMessage);
} else {
    window.addEventListener('message', handleMessage, false);
}

function handleMessage(event) {
  // check where the message is coming from - may be overkill in your case
  if (event.origin==='https://photoupload.org') {
    // check event type - again probably not required
    if (event.data==='photoUpload.complete') {
      // do your thing
    }
  }
}

And if you want to send messages back from the outer page to the iframe, it's basically the same setup but you send with:

iframe.contentWindow.postMessage(...)

If IE7 or IE6 support is required, postMessage() is not supported but you could use something like http://easyxdm.net/wp/

OTHER TIPS

I guess this line should work as well

window.parent.$(window.parent.document).trigger('photoUpload.complete');

Explanation: In your code parent.$('body').trigger('photoUpload.complete'); 'body' is referring to iframe body and not the parent window body.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top