Avg. Rating 3.0

Problem

You may want to run content, exchange data, and use functionality from the application sandbox and a non-application sandbox at the same time. You may even want to do these from between different non- application sandboxes.

Solution

Use the provided bridging interface to expose variables or methods between the sandboxes. For communication between non-application sandboxes use the application sandbox as a proxy between them.

Detailed explanation

Case 1 : Access application sandbox from non- application content

The application sandbox can setup a bridge interface inside the non-application box called parentSandboxBridge which can be accessed by the non-application sandbox code:

var parentBridge = {
    sayHello = function (msg) {
        alert("Hello from the application sandbox! "+msg);
};

function setupBridge(){
    document.getElementById("sandbox").contentWindow.parentSandboxBridge = parentBridge;
}

The HTML to include non-application sandbox content:

<iframe id="sandbox" src="http://www.site_abc.com/sandbox.html" 
     documentRoot="app:/"
     sandboxRoot="http://www.site_abc.com/" 
     ondominitialize="setupBridge ()">
</iframe>

In this way the non-application sandbox code (in sandbox.html) can invoke the method sayHello from the application sandbox:

window.parentSandboxBridge.sayHello("and from non-app sandbox");

Case 2: Communicate between different non-application sandboxes

The non-application code can access the parent via the parentSandboxBridge and can expose data and methods via childSandboxBridge. One would immediately suppose that in this case it is possible to expose directly the childSandboxBridge of non-app Sandbox 1 to non-app Sandbox 2 (using the application sandbox's parentSandboxBridge ), but this setup does not work (for security reasons). The access to the bridges is very restricted--from outside the sandbox they are defined, they are read-only; and if you try to read an exposed method's body in order to peak at the non-exposed objects it might use you will find out "alert(childSandboxBridge.exposedMethod)" will give you an empty function.

To exchange data between non-app sandboxes you should set up a bridge proxy in the application sandbox code. Follows an example of application which loads two different websites: One that has a database with clients, and another where the user wants to copy some of those clients (of course the two sites must implement the appropriate code, as described below for this setup to work).

The parent code (running on AIR) :

<html>
<head>
<script type="text/javascript">

    var bridgeProxy = {
        
        //I chose the fancy 'broadcast' name, you can use one you fancy the most
        broadcast: function (method, args, sandbox) {
            //method that just forwards a method call to a sandbox 
            document.getElementById(sandbox).contentWindow.childSandboxBridge.callMethod(method, args)

    }

    //setup each sandbox's parent bridge
    function setupBridge(sandbox){
        sandbox.contentWindow.parentSandboxBridge = bridgeProxy;
    }

</script>
</head>
<body>

<!-- that's the first non-app sandbox www.abc.com -->
<iframe id="site_abc" src="http://www.abc.com/site_abc.html" documentRoot="app:/" sandboxRoot="http://www.abc.com/" ondominitialize="setupBridge(this)"></iframe>

<!-- that's the second non-app sandbox www.xyz.com -->
<iframe id="site_xyz" src="http://www.xyz.com/site_xyz.html" documentRoot="app:/" sandboxRoot="http://www.xyz.com/" ondominitialize="setupBridge(this)"></iframe> 

</body>
</html>

Note that each iframe calls the setupBridge function, to create the parentSandboxBridge in its window object.

The code of the view customer page on the website ABC (you first non-app sandbox):

<html>
<head>
<script type="text/javascript">
    function copyInfo() {
       // call the parent bridge with arguments : method name, data, iframe id
       window.parentSandboxBridge.broadcast('copyInfo',
       {
           firstName: document.getElementById('firstName').value,
           lastName : document.getElementById('lastName').value,
           street : document.getElementById('street').value,
           city : document.getElementById('city').value
       },
      'site_xyz');
    }

</script>
</head>
<body>

<b>Web site ABC</b><br />
View Client information:<br /><br />

First name: <input type="text" id="firstName" value="Ford" /> <br />
Last name: <input type="text" id="lastName" value="Prefect" /> <br />
Street: <input type="text" id="street" value="42, East side drive" /> <br />
City: <input type="text" id="city" value="Manchester" /> <br />

<input type="button" value="Copy information" onClick="copyInfo()" />

</body>
</html>

When the user clicks the "Copy information" button, the form information is gathered and sent to the parent bridge proxy, and the data is "addressed" to sandbox with id site_xyz.

Let's see the code in the other website, which has to receive the customer information:

<html>
<head>

<script type="text/javascript">
    //rearrange the customer information, as expected on xyz.com's customer form
    function copyInfo (args) {
        document.getElementById('name').value = args.firstName +" "+ args.lastName;
        document.getElementById('address').value = args.street +", "+ args.city;
    }

   //setup the non-application's bridge, which only proxies window's methods
   var childBridge = {

        // invokes the required method - warning that's not such a great practice
        callMethod : function(name, args) {
            if (window[name]) window[name](args);
            else alert("No "+name+" defined!");
        }
   }

   window.childSandboxBridge = childBridge;

</script>
</head>
<body>
<b>Web site XYZ</b><br />
Create new customer:<br /><br />

Name: <input type="text" id="name" value="" /> <br />
Address: <input type="text" id="address" value="" /> <br />

<input type="button" value="Create customer" onClick="alert('New customer created!')" />

</body>
</html>

The bridge interface of site_xyz just calls the required method and passes the data--in this case the method copyInfo, which reformats the customer data and fills it in the form. The user now has to just click "Create customer" and you're done.

Note that I just wanted to show how far you can go by exposing the window's methods via the bridge. In most cases it would have been better to encapsulate the exposed methods in the bridge object.

sandbox_test.zip
[The sample from the post ]

+
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.

Report abuse

Related recipes