Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cant access JS function in Cross Domain Environment

In order to solve Cross Domain security woes of JavaScript, I am implementing the following method

On Domain [ abc.com ]

On domain abc.com I have a page called main_page.html. Its code is as follows -

<script>
function SendMsg(id)
{
   frames["invisible_iframe"].location = "http://xyz.com/invisible_iframe.html#"+id;
}
</script>
<body>
  <input type="button" id="Test" value="Call iFrame" onclick="SendMsg(this.id);">
  <iframe src="ttp://xyz.com/visible_iframe.html" name="visible_iframe" height="250" width="500"></iframe>
  <iframe name="invisible_iframe" height="0" width="0" style="display:none;"></iframe>
</body>

On Domain [ xyz.com ]

On domain xyz.com I have a page called visible_iframe.html. Its code is as follows -

<script>
function Hi()
{
   alert("Hi there!");
}
</script>
<body>
  <h1>Visible iFrame on xyz.com
  <iframe name="d2_invisible_iframe" id="d2_invisible_iframe" class="iFrame" src="http://xyz.com/invisible_iframe.html" height="310" width="520"></iframe>
</body>

Now I want to access the function Hi() from invisible_iframe.html (which is on the same domain)

The code of invisible_iframe.html is as follows

<script>
var sActionText = "";
function CheckForMessages()
{
   if(location.hash != sActionText)
   {
     sActionText = location.hash;
     var sAction = "";
     var oSplitActionText = sActionText.split("#");
     sAction = oSplitActionText[1];
     if (sAction == "Test")
     {
        parent.Hi();
     }
   }
}

setInterval(CheckForMessages, 200); 
</script>
<body>
  <h1>Invisible iFrame on xyz.com</h1>
</body>

I am using hidden iFrame in visible_iframe.html because I don't want the URL of visible_iframe.html to change.

Now I expect when the button on main_page.html is clicked, I'd get alert message. But that doesn't happen. In firefox it says - Permission denied to access property 'Hi'

The strange thing is when I put parent.Hi(); outside CheckForMessages() function, the Hi() function can be accessed and alert box is shown.

What should I do to resolve this ?

like image 987
skos Avatar asked Jun 07 '12 08:06

skos


2 Answers

Why not using easyXDM? This library should make your life really easy and help to avoid the security limitations when dealling with cross domain issues. Specially if you have control over the two domains.

easyXDM is a Javascript library that enables you as a developer to easily work around the limitation set in place by the Same Origin Policy, in turn making it easy to communicate and expose javascript API’s across domain boundaries.

[This is one of the best and easy to use APIs] available for Cross Domain Communication between web applications. easyXDM is easy to use, light weight, flexible, writing good quality code etc. I strongly think if you are going to continue with cross domain scenario, then you should adapt a robust cross domain apis such as easyXDM.

[easyXDM vs PostMessage Transport?] easyXDM will use the PostMessageTransport method if this feature is enabled by the browser such as (IE8+, Opera 9+, Firefox 3+, Safari 4+,Chrome 2+) on the other side it will use different transport methods for the un supported browsers such as (Firefox 1-2 - using the FrameElementTransport) other transport methods will be used as needed such as FlashTransport, NameTransport, and HashTransport).

This clearly makes easyXDM superior in terms on browser support specially the old browsers.


To demonstrate cross-domain access using easyXDM (Domain1 [abc.com] calls a method on a remote domain [xyz.com]):


*On Domain [ abc.com ] - main domain*

    <script type="text/javascript">
        /**
         * Request the use of the JSON object
         */
        easyXDM.DomHelper.requiresJSON("../json2.js");
    </script>
    <script type="text/javascript">
        var remote;
        window.onload = function(){
            /**
             * When the window is finished loading start setting up the interface
             */
            remote = new easyXDM.Interface(/** The channel configuration */{
                /**
                 * Register the url to hash.html, this must be an absolute path
                 * or a path relative to the root.
                 * @field
                 */
                local: "/hash.html",
                /**
                 * Register the url to the remote interface
                 * @field
                 */
                remote: "http://YOUR.OTHER.DOMAIN/YOUR_APPLICATION/YourRemoteApplication.html",
                /**
                 * Register the DOMElement that the generated IFrame should be inserted into
                 */
                container: document.getElementById("embedded")
            }, /** The interface configuration */ {
                remote: {
                    remoteApplicationMethod: {},
                    noOp: {
                        isVoid: true
                    }
                },
                local: {
                    alertMessage: {
                        method: function(msg){
                            alert(msg);
                        },
                        isVoid: true
                    }
                }
            },/**The onReady handler*/ function(){
                /**
                 * Call a method on the other side
                 */
                remote.noOp();
            });
        }

        function callRemoteApplicationMethod(Value1, Value2){
            remote.remoteApplicationMethod(Value1, Value2, function(result){
                alert("Results from remote application" + result);
            });
        }


    </script>

In the body

<input type="button" onclick="callRemoteApplicationMethod(3,5)" value="call remoteApplicationMethod on remote domain"/>

Now on your remote domain side you need to define your remote client as follows

*On Domain [ xyz.com ] - Remote domain*

This should go into the page YOUR_APPLICATION/YourRemoteApplication.html

    <script type="text/javascript">
        /**
         * Request the use of the JSON object
         */
        easyXDM.DomHelper.requiresJSON("../json2.js");
    </script>
    <script type="text/javascript">
        var channel, remote;
        /**
         * When the window is finished loading start setting up the channel
         */
        window.onload = function(){

            /**
             * When the channel is ready we create the interface
             */
            remote = new easyXDM.Interface(/** The channel configuration*/{}, /** The configuration */ {
                remote: {
                    alertMessage: {
                        isVoid: true
                    }
                },
                local: {
                    remoteApplicationMethod: {
                        method: doSomething(value1, value2){
                        // do somethigs with values

                        return "i'm return value from remote domain";
                        }
                    },
                    noOp: {
                        isVoid: true,
                        method: function(){
                            alert("Method not returning any data");
                        }
                    }
                }
            });
        }
    </script>
like image 144
Future2020 Avatar answered Nov 03 '22 12:11

Future2020


I suppose there is no need to suport old browsers, right? You can use window.postMessage in modern browsers to support cross-origin communication.

like image 3
Hippasus Avatar answered Nov 03 '22 13:11

Hippasus