Sunday, 15 November 2009

Overcoming cross domain issues between frames

In an application that I am building at the moment, I had need to “mash-up” content from different sources into a SharePoint site. This SharePoint site would;

  1. Use an iframe to pull in a list of content from another server
  2. Launch a modal dialog (AJAX style) overlaid on top of the SharePoint portal with an iframed form to action against the data
  3. Display validation errors from that form as another modal dialog (owned by the parent SharePoint page so as not to be size limited to the owning dialog).

A picture says a thousand words;

 image

In this case, we’d want the SharePoint host page to offer two methods

  • launchTool(url) – which will launch the given URL in an iframe within a modal jquery overlay (using boxy in my instance).
  • displayValidation(message) – which will be called by the form iframe to display the validation messages if the form can’t be submitted

And this is where we have a problem. If everything was on the same server, it would all be quite happy with this scenario and all the components would play together nicely but in this instance the content is spread across different servers. In this case, we’re not allowed to build this level of interaction using JavaScript as the content doesn’t fulfil the “same origin policy” – which means content from different domains can’t interrogate each others DOM nor invoke methods etc against each other.

image

Working around this isn’t just as simple as putting the sites into a different zone in the browser etc, we have to do something a little more innovative. If you are in total control of your infrastructure you can set all of the content servers to have a fully qualified domain name – eg: sp.mysite.com and forms.mysite.com and then use the document.domain property in JavaScript to set the domain to the higher level domain ie: mysite.com (document.domain = “mysite.com”) – but this does cause problems in my scenario where the SSRS report viewer web part in sharepoint doesn’t work (it does some funky stuff under the covers with iframes which fails miserably when we set document.domain in the host pages).

So, what can we do?

Well, the content from formserver can’t call anything within the sharepoint page and vice versa, but the formserver content could somehow create an iframe of it’s own with a special url on the sharepoint site that then calls the javascript we’re looking for in the sharepoint page. Clear as mud? No? here’s another diagram.

image

So, the list iframe doesn’t go back up the window stack to ask it’s parent to do something (which it has no rights to), it instead goes down – creating it’s own iframe and navigating it to a known page on the host and passes information to the page using a # bookmark. This known page then uses javascript on it’s page load event to determine what to do with the data passed in. If this indicates it should launch a modal dialog for a given URL, it passes the request to the overall parent, which, because it’s on the same domain, can be accessed.

It’s important to note the # part of the URL – by doing this, the cross domain receiver page can be fully cached in the browser, meaning there should be no lag between making the request down the stack to the parent actually processing that request.

I’ve wrapped the above into an API and built a sample that does the above, but also supports bi-directional message passing – so our host page has a list from another domain, it asks the host to display a form from yet another domain and this form requires confirmation, so it asks the host to display a message with options – the result of this message is then passed back down to the form.

Get the source code here: http://xdsframes.codeplex.com

(This isn’t a finished API in any way, just a starting off point for solving your own cross domain issues.)

5 comments:

  1. Hi Tony,

    I am having an issue integrating SAP with MOSS. We have a SAP page that pulls in MOSS content via and iView (which is basically an iFrame)

    The issue in question is in regards to the Editing Tool Bar that pops up when you click on a rich html field whist in Edit Mode. The edit window will not pop up and we get a javascript "Access Denied" error.

    When I got to the MOSS Portal and check document.domain, i get "machine-name.labs.co.uk" and when I go to the SAP portal and check domain I get "labs.co.uk", so i can see from here that i have a different domain.

    The error can be easily replicated if you create a basic html page with an iframe and set the SRC to be a MOSS publishing page. The when you switch to Edit Mode and click on a control the error will be shown.

    I think that this is something to do with domain getting mixed up, but i am not sure how to fix it. I tried putting a test iframe page in the layouts folder and then browsed to it via http://mymosssite/_layouts/iframe.html and it works ok.

    Any ideas on where to set the domain?

    ReplyDelete
  2. Hi Sa,

    From what I can tell (and I'm not familiar with sap) you need to set document.domain = "labs.co.uk" in your master page in MOSS so that all the items of content fulfil the same origin policy.

    You could probably try this out by adding a content editor web part and manually adding the javascript.

    Hope this helps,
    Tony

    ReplyDelete
  3. Hi Tony,

    I'm Atul, need solution for one major problem. As I am ruining out of the ideas for the problem we are facing so added question here.

    We use DOJO Framework

    About Problem

    We have created different kind of Widgets (Overlay, Full page mode these are dojo dialogues) for my project. And I need to expose Overlay widget. It is JSP page which is having a 3-4 dialogs, Global Variables, a lot of Images, Google map for which data is populated from 4-5 AJAX calls. This widget should be open in Client domain and client container (i.e in Another JVM/Sites) and we have to fetch the data from our Database. So it's a cross domain communication.

    We need to provide sort of JavaScript code/HTML/JSP which can include in
    Client application and he/she will able to access our overlay widget (dojo dialogue which is is getting loaded from our database data.)

    Technical Challenge
    For Cross domain communication, In DOJO we use dojo.io.Iframe , so it goes
    directly to the other domain and populate on client end. We are able to
    fetch the data from the domain but couldn't able to populate the data in
    our iframe, In iframe we are fetching data in terms of HTMLDocument object
    but getting some "Permission denied" exception. For the error please refer
    the attached screenshot.

    Please help me to find out the best way to proceed.

    Tested Scenario: -

    1) Created a Web Project on local, created a JSP which include the CSS and
    DOJO required libraries from my E1 server path.

    Firing a Ajax call which is having my app server path (right now it is
    hardcoded):

    We are able to hit the application server and in firebug all the JavaScript logs are
    displaying, but getting permission denied exception in HTMLDcoument object.

    2) Referred jsp is CustomOverlayWidget_new.jsp

    in this, I am calling my website path, and able to populate the result, but on the fly couldn't able fire a JavaScript method.

    ReplyDelete
  4. Hi Atul,

    Not sure I'm following along and I'm nit familiar with dojo or jsp. That aside, if you're having cross domain issues in the browser its unlikely relevant.

    From what I can read here it sounds like your getting permission denied issues when you try to manipulate a HTML document loaded from a source that isn't in the same origin as the host? If this is the case there is no way to solve this on the client if you don't have control of both sides.

    If you have control of the target system as well, you can use the technique above to go down the frames and achieve what you need to do, but otherwise you will need to consider a proxy or URL rewrites to make the browser think its data is coming from the same source etc.

    This is all very vague, but I hope it helps in some way. If not and you can distill your issue down to as little HTML and JavaScript as possible, i would be happy to take a look at it for you.

    Regards,
    Tony

    ReplyDelete
  5. the codeplex download isn't working anymore, can someone repost the source?

    ReplyDelete