Making JSLint AIR: Part 2 - Porting to AIR Beta 2

Now that JSLint AIR Edition is available as an AIR Beta 2 application, I want to share my experiences working with AIR for HTML/Javascript and the process of migrating the app from Beta 1 to Beta 2.

In terms of the functionality provided by AIR, my Beta 1 version allowed you to open and save a file, exit the application and open a default browser window to the original JSLint documentation page. I had originally hoped to include drag and drop of .js files and the ability to open Javascript files from a file explorer context menu, but the rush was on to submit JSLint AIR to the developer derby, so I was forced to trim features. The latter feature is available in the Beta 2 version and the former is still on the roadmap.

A New Security Model

With the release of Adobe AIR Beta 2, there is a new security model for HTML/Javascsript applications. This model was introduced to mitigate potential abuse of the AIR API by malicious persons by disabling eval() among other changes. Rather than rehash some specifics, I suggest reading the HTML Security FAQ. The end result of the of the new security model is that it is now incumbent upon HTML/Javascript developers to expose only the specific AIR functionality required in their application by creating a bridge between the application sandbox (where AIR API resides) and the child sandbox (where the UI resides). Here is a brief description of how the security model works and how methods are exposed between them.

In the Beta1 version of JSLint, I had a single HTML file with script tags importing the Ext JS library, my application mediator and components, the JSLint engine, and AIRAliases.js. In the Beta 2 version, I now have two html files, one named root.html and another named ui.html. The names of the files are irrelevant, what matters is that AIRAliases.js is now referenced in root.html and ui.html is embedded as an iframe.

<html>
<head>
<title>JSLint AIR Edition</title>
<script type="text/javascript" src="AIRAliases.js"></script>
</head>

<body style="margin: 0px; padding: 0px;">
<iframe id="UI"
src="ui.html"
sandboxRoot="http://www.fancybread.com/"
documentRoot="app-resource:/"
frameborder="0"
width="100%"
height="100%"
style="margin: 0px; padding: 0px;">

</iframe>
</body>
</html>

This setup allows you to use libraries like Ext JS or jQuery that make use of eval() to run within the child sandbox (ui.html), while keeping the AIR API within the parent sandbox (root.html). Exposing functionality between the two is a matter of creating object literals within each sandbox called 'parentSandboxBridge' and 'childSandboxBridge'. Here's a snippet from my root.html script. There are different ways to implement the parent and child sandbox bridges, I prefer to set the parentSandboxBridge for the UI iframe within window.onload() event in root.html (example below).

window.onload = function ()
{
     var UI = document.getElementById('UI').contentWindow;
      
     UI.parentSandboxBridge = {
         // provide method to exit via shell
         exitApplication : function ()
         {
             air.Shell.shell.exit();
         },
         // open the jslint docs window
         openDocsWindow : function ()
         {
             air.navigateToURL(new air.URLRequest("http://www.jslint.com/lint.html"));
         }
     };
          
     // initialize the app within the child sandbox
     UI.childSandboxBridge.initApp();
}

And in ui.html, I have the following window.onload() event.

window.onload = function() {
  // expose the init function for the application sandbox
  childSandboxBridge = {
      setSource : function (str) {   
        JSLINT_AIR.app.setSource(str);
      },
      setFileName : function (str) {   
        JSLINT_AIR.app.setFileName(str);
      },
      broadcast : function (event) {
        JSLINT_AIR.app.broadcastEvent(event);
      },
      initApp : function () {
        JSLINT_AIR.app.init();
      }
   }
}

Prior to sandboxing the application, I initialized it within the Ext.onReady(), but under the new security model, the window.onload event in ui.html runs prior to that in root.html, so in order to ensure that the AIR API is exposed prior to initializing the applciation, I provide an initApp() method in the childSandboxBridge that is called within the window.onload event in root.html.

To exit the application in the beta 1 version, I called the following method in my menu component.

function exitApp()
{
    air.Shell.shell.exit();
}

As described above, direct calls to 'air' are not possible in the child sandbox under the new security model, so I moved air.Shell.shell.exit() to the application sandbox and exposed it as 'exitApllication'. Now in my menu component, I call parentSandboxBridge.exitApllication() when a user selects the 'File|Exit' menu.

General Impressions

HTML/Javascript developers will clearly have to consider the extra time required to develop under new security model and plan their applications carefully. Fortunately, I put a lot of effort up front to organize my code and encapsulate my AIR API calls, so that exposing them as the 'parentSandoxBridge' required a minimum amount of refactoring (especially given that my app had a limited amount of AIR functionality built in). Since I plan to maintain JSLint AIR as an HTML/Javascript app, I will likely redesign some aspects in a future release as I feel the current iteration is less cohesive than the last.

JSLint AIR Edition now on RIAForge!

Hot on the heels for Adobe AIR Beta 2 release, JSLint AIR Edition makes its Beta 2 debut on RIAForge.

Version 0.5 introduces a few new features and one bug fix:

NEW: Right click on a .js file to open it from the context menu using "Open with ->".

NEW: HTML code is escaped in the listing view.

NEW: The name of the currently open file will appear in the first tab.

FIXED: code in listing view stays aligned with line numbers when lines are longer than the listing view pane.

There is one known issue with this release with regard to the content not resizing when the app is maximized. This is related to porting a Beta 1 app to the new Beta 2 security model for HTML/Javascript AIR applications. I'll write something on my experiences in a (hopefully near) future post.

Making JSLint AIR: Part 1 - Working with Ext

In my introduction to JSLint AIR Edition, I listed the tools and resources used to build the application. In this post, I'll detail my experience with Ext. I chose the Ext library for this project, because it provides components that can be combined to create a complete desktop look and feel and the documentation center has a nice API and plenty of examples and demos for building individual Ext components. This was my first time using Ext for more than a simple form or menu, so combining individual elements to design a complete UI required a bit of forethought and exploration.

[More]

Introducing JSLint AIR Edition: Made with Aptana, Ext JS and Adobe Integrated Runtime

I've been dabbling with Ext JS for a while now in the hopes of integrating it into the various projects I have on the go. While exploring some ways to better construct a Javascript front end by separating out my code into 'components', I discovered JSLint, The Javascript Verifier. One thing lead to another and within a day I had a working Alpha version of JSLint as an AIR application...

[More]

BlogCFC was created by Raymond Camden. This blog is running version 5.9. Contact Blog Owner