Remote Application Development with Mozilla, Part 2
Pages: 1, 2
Communicating with Amazon
The MAB uses Amazon's web services API to search the company's catalogs and retrieve results. Amazon's API can be accessed via either XML over HTTP or SOAP, and Mozilla supports both methods. The MAB's author chose to use XML over HTTP because it was simpler to implement, and he could not find any advantages to using SOAP (more info on SOAP vs. XML over HTTP at Amazon). XML over HTTP passes parameters to the remote procedure via URL parameters in a standard HTTP request, so the MAB first creates a standard HTTP URL containing the search configuration and string:
var qString = targetUrl[connectionType]+'?t='+ASSID+'&dev-t='+DEVT+'&
'+getSearchBy()+'='+escape(query)+'&mode='+getProductLine()+'&
type='+searchType+'&page='+page+'&f='+f;
In additon to the query variable, which contains the
search string entered by the user, the following values make up the URL:
targetUrl[connectionType]- Base URL of Amazon server or proxy.
ASSID- Associate ID: identifies the provider of the application; required for access to Amazon web services.
DEVT- Developer token issued by Amazon to identify the application author; also required.
getSearchBy()- The type of search the user is doing (Title, Keyword, and so on).
getProductLine()- The catalog in which the user is searching (Books, DVDs, and so on).
searchType- Whether or not to include comments in the results; possible values are
lite(without comments) orheavy(with comments). page- Which page of results to retrieve (Amazon returns, at most, ten results at a time).
f- Output format (always "XML" in the MAB).
The MAB then uses Mozilla's XMLHttpRequest object to
connect to the Amazon servers and initiate a search. First it
creates a new XMLHttpRequest object req. If the user is
connecting directly to the Amazon service, the application also requests
permission to connect to the Amazon servers, which would otherwise be
off-limits due to security restrictions (see A Word About Proxies below for more details). Then the MAB initiates a standard HTTP GET request using the req
object and the previously constructed URL. Finally, it adds a load
handler to req that will run when the MAB receives a
response from the server and will process the results.
var req = new XMLHttpRequest();
...
if(connectionType == "direct") {
netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
}
req.open("GET",qString,true);
req.send(null);
...
req.onload = function() {
...
}
Displaying the Results
The Amazon web service responds to a request from the MAB by searching its catalogs and returning a set of matching products as a series of XML records containing fields for product attributes. For example:
<Details url="http://www.amazon.com/exec/obidos/redirect?tag=webservices-...">
<Asin>B00006IZOC</Asin>
<ProductName>Dial-A-Song: 20 Years of</ProductName>
<Catalog>Music</Catalog>
<Artists>
<Artist>They Might Be Giants</Artist>
</Artists>
<ReleaseDate>17 September, 2002</ReleaseDate>
<Manufacturer>Rhino Records</Manufacturer>
<ImageUrlSmall>http://images.amazon.com/images/P/B00006IZOC.01.THUMBZZZ.jpg
</ImageUrlSmall>
<ImageUrlMedium>http://images.amazon.com/images/P/B00006IZOC.01.MZZZZZZZ.jpg
</ImageUrlMedium>
<ImageUrlLarge>http://images.amazon.com/images/P/B00006IZOC.01.LZZZZZZZ.jpg
</ImageUrlLarge>
<ListPrice>$31.98</ListPrice>
<OurPrice>$28.99</OurPrice>
<UsedPrice>$26.83</UsedPrice>
</Details>
Once the Amazon service has finished returning results and closes
the connection, the load handler on the XMLHttpRequest object
takes over and uses Mozilla's DOMParser object to convert the XML string
into a DOM document:
var responseXML = new DOMParser().parseFromString(req.responseText, 'text/xml');
It then passes the document to an AmazonResult object, a custom
object defined by the MAB to store search results and display them to
the user:
//Create new
ObjmyAmaz = new AmazonResult();
...
myAmaz.parseResponse(responseXML);
The AmazonResult object stores the document in a member property and
then calls its createTree method to display the data in the XUL tree:
AmazonResult.prototype.parseResponse = function(responseXML) {
...
this.xmlDoc = responseXML;
...
this.createTree();
...
}
(Note that this procedure is somewhat different when two searches are being merged together.)
createTree iterates over the search results. For
each one, it retrieves the data using the getElementsByTagName
and item DOM methods and creates tree rows using the createElement
DOM method to create treeitem and treerow elements
for each record and treecell elements for each field
value. Then it uses the appendChild DOM method to
append each row to the tree, causing the row to be displayed to the user:
AmazonResult.prototype.createTree = function() {
var nr = this.getNrRecord();
for(var i=0;i<nr;i++) {
var rowID = this.xmlDoc.getElementsByTagName("Details")[i].
getElementsByTagName('Asin').item(0).firstChild.nodeValue;
var item = document.createElement('treeitem');
var row = document.createElement('treerow');
row.setAttribute('id',rowID);
...
var cell_name = document.createElement('treecell');
cell_name.setAttribute('label',this.getDetail(rowID,'ProductName',false));
... [creation of other cells omitted]
row.appendChild(cell_name);
... [appending of other cells omitted]
item.appendChild(row);
guiListTree.appendChild(item);
}
...
}
Note that while the author considered using an in-memory RDF data source and a XUL template to construct the tree, he ultimately chose to use DOM methods because they were more familiar to him given his experience with traditional web development and avoided issues with accessing Mozilla's RDF API from remote applications. The downside to using DOM methods is the loss of features that come bundled with RDF and XUL templates in Mozilla, such as sorting.
Conclusion
The Mozilla Amazon Browser provides a rich interface for searching Amazon with features not found in existing HTML-based interfaces, and it highlights the potential for remote Mozilla-based applications to improve the capabilities and user experience of Internet applications. Mozilla provides XUL, an application-centric layout language with both basic and complex form controls, web services support for communicating and exchanging data with remote applications, cross-platform support, and many other features. It is an excellent framework for building the next generation of remote Web applications.
Thanks to Fabio Serra, the author of the MAB, for his help with the technical details of its implementation.
Brian King is an independent consultant who works with web and open source technologies.
Myk Melez has been working with Mozilla since 1999, when he started using the browser as a DHTML application platform.
A Word About Proxies
By default, the MAB uses a proxy that runs on the same server as the one from which it is loaded, but it can be reconfigured to connect to the Amazon service directly:

Connection Settings
The advantages of using a proxy for a remote application are:
Better security, since web service authentication tokens can be restricted to the proxy server instead of being downloaded to each user's computer (although the MAB doesn't do this).
A better user experience, since the users don't have to deal with the details of getting access to the web services themselves.
Easier deployment, since the application can avoid Mozilla's stringent cross-domain security restrictions, which prevent a remote application from contacting servers other than the one from which it was loaded, unless the application is cryptographically signed. (These restrictions can be bypassed via the hidden browser preference setting
user_pref("signed.applets.codebase_principal_support",true);, but this is only recommended for development work.)
Proxy servers also have drawbacks. In particular, they are slower than direct connections and may have scalability problems. Still, for some applications, particularly those that use a web service that is not freely accessible, are distributed by organizations that have their own level of authentication, or for whom cryptographic signing is prohibitive, a proxy server is the only workable solution.
Note that Mozilla developers are working on a new security model that lets applications bypass cross-domain restrictions when such access is explicitly permitted by the target server. The model relies on web services publishing a simple, machine-readable document that declares which services are available to which client domains. This model should make it much easier for client applications to access web services in the future.
O'Reilly & Associates recently released (September 2002) Creating Applications with Mozilla.
Sample Chapter 2, "Getting Started," is available free online.
You can also look at the Table of Contents, the Index, and the full description of the book.
For more information, or to order the book, click here.
Return to the Mozilla DevCenter.







