Sunday, September 21, 2008

Ubiquitizing Jenn for Flight Information

Last month, Aza Raskin introduced Ubiquity on Mozilla Labs. As stated in Aza’s post, the overall goals of Ubiquity are to explore how best to:

  • Empower users to control the web browser with language-based instructions. (With search, users type what they want to find. With Ubiquity, they type what they want to do.)
  • Enable on-demand, user-generated mashups with existing open Web APIs. (In other words, allowing everyone–not just Web developers–to remix the Web so it fits their needs, no matter what page they are on, or what they are doing.)
  • Use Trust networks and social constructs to balance security with ease of extensibility.
  • Extend the browser functionality easily.

Aza included the following screenshot as an example of what could be done in an effort to inspire people to begin creating commands for Ubiquity.

This got me thinking. on February 7th, 2008, Alaska Airlines introduced Jenn, a virtual assistant that guides and assists website visitors.

One of the more interesting features of Jenn is the ability to ask her to find flights based on command line input.

Ask her to search for flights from “Seattle to Cancun leaving April 2, 2009 return April 15”, and she’ll redirect you to a webpage listing itineraries for flying to Cancun next Spring.

So, inspired by Aza’s post and some parsing help from Jenn, I set out to create my first Ubiquity command.

Deconstructing Jenn

My first task was to figure out how Jenn worked her magic. To do this, I enlisted the help of Fiddler to capture my conversation with Jenn during a recent session on alaskaair.com.

Fiddler was able to track a post to a web service hosted on activeagent.alaskaair.com.

image

Great, I’ll simply ask for the WSDL and utilize that to submit my call from Ubiquity to Jenn. Unfortunately querying for the WSDL only resulted in an error page. To get what I need, I’ll have to dig further into the session.

The first part confirms that the AgentProxy.asmx is indeed where we want to be posting our query. Furthermore, we can see that the soapaction header gives us the method that we want to call, GetResponse.

image

Looking further down the post information, we see the actual payload that we want to send. There, buried in the Input argument we can see  our query about flying to Cancun.

image

Now, let’s take a look at the response. Aha, buried in the return response, we can see the value for the NavUrl. This must be how Jenn knows how to display the page with the correct information.

image

We should be able to call the SOAP method, passing in the flight query and then extract the URL from the response, and open a new window displaying the results.

Teaching Ubiquity About SOAP

So, after reading through a very simple tutorial about creating Ubiquity commands, I set out to create my own.

jQuery is integrated in with Ubiquity. My first inclination was to utilize the SOAP plugin for jQuery. jQuery is a JavaScript library that simplifies HTML document interaction, event handling and AJAX. The SOAP plugin for jQuery, simplifies the interfacing of SOAP calls.

Since the SOAP plugin is not integrated with jQuery, I need to use the CmdUtils.injectJavaScript() method to load the external script. Davanum Srinivas created a very succinct example for loading and using external JavaScript in Ubiquity.

Unfortunately, it doesn’t work with the jQuery SOAP plugin.

Rethinking SOAP

Clearly we’re going to have to use a different tactic. We’ll use the jQuery’s ajax method and brute force a SOAP call. Thanks again for Davanum Srinivas excellent example. To do this, I’ll work up the payload manually. The figure below builds up the SOAP request. The highlighted portion below displays how the command text entered in Ubiquity gets added to the request.

image

The jQuery.ajax() method allows us to make a HTTP POST call. Before sending the payload request above, we will go ahead and set the soapaction header variable equal to the soapaction we discovered with the Fiddler tool.

image

Finally, upon a successful call we’ll use the jQuery.find() method to get the URL that will display the list of flights that satisfy our query. Please note, that since the GetResponseResult contains many <Name/><Value/> pairs, jQuery returns an array. In this case we are asking for the first <Value/> since that contains the destination URL in a successful call.

fly-alaskaair

Putting it all together, we get the following Ubiquity display. You simply enter in your search command for the flight you want to take and then return. A new browser window will be opened displaying the result of your query.

image

The first time you execute the query it may take a couple of seconds. Soon you will be rewarded with the following display.

image 

To use the “fly-alaskaair” command, you simply need to add it to your set of Ubiquity commands. You should see a bar across the top of this web entry prompting you to subscribe to the command. Once you subscribe, you’ll be able to search away.

What’s Next

I still haven’t achieved Aza’s vision, but perhaps with a little more effort I can get there. It would be nice if Jenn provided a RESTful interface, and rather than return a URL, simply returned some parsed information like, origin, destination, dates, etc. This way, I could use her as a “human” parser.

In addition, it would be nice if the alaskaair.com website also allowed me to call some RESTful web services. I could bring back the data using jQuery, mash it up with Google Maps and display a better preview.

I’ll see what I can do with what I have to work with now. If you would like to see some enhancements, just let me know.

You can fine other commands to subscribe to on the Herd.