7. Detailed Design
7.2 Detailed Design of CAS
In Figure 7-2, almost all of the interfaces are iw, i.e. HTTP1.0 Web interface. Because our system is designed for Web application, the iw interface enable us to develop different system components by different programming languages or platforms. Hence, it provides cross-platform communication for system development.
61
Figure 7-2. System components and their interfaces of CAS.
The Page Tailor is designed to be implemented in JavaScript because of the following considerations.
1. JavaScript was designed to add interactivity to HTML pages. This point conforms to the first objective of this thesis, i.e. easy-to-use, since we can embed the configuration tool in a Web page, so that users can configure their settings directly in the browser.
2. By using JavaScript, we can manipulate a Web page through the DOM interface. DOM provides the interface between the Javascript and original Web pages. In other words, we can change the appearance of a Web page to reflect the user’s choice. This one conforms to the second objective, i.e. personalizing Web page visually.
3. JavaScript is one of the most popular scripting languages on the Internet, and works in all major browsers, such as Internet Explorer and Firefox. This one agrees with the third objective, i.e. support for mainstream browsers.
62
The interface between user and Page Tailor is bookmarklet. That is, the ib interface between user and Page Tailor in Figure 7-2. The source code of this bookmarklet is shown in Figure 7-3. When a user clicks that, an element with tag name “script” is created (Line2). After being created, the new element contains no properties. The “src” property (Line 5) is employed to indicate the location of a remote JavaScript file. A created element exists only in the browser’s memory, and not as part of this Web page. In order to let the “script” element take effect, we have to add it to the Web page. For that reason, we find the first occurrence of
“body” element (Line 6) in the Web page, and then append the “script” element as a child of it (Line 7).
Figure 7-3. This is the bookmarklet used to launch Page Tailor
In this manner, we can dynamically load an external JavaScript file on demand to do something with a Web page. It can also work for other types of files such as CSS. JavaScript has been used in many applications. Some open source projects have already incorporated the commonly used functions such as drag-and-drop and visual effects. In Page Tailor, we do not reinvent the wheel but take advantage of the Script.aculo.us JavaScript framework.
63
Although we can dynamically load these JavaScript files, the exact time spent on loading, however, depends on the browsers. In other words, even if we add the “script” elements to a Web page in some order, which is not equivalent to load the first javascript file and then the second one.
To address the above problem, we must postpone the loading of scriptaculous.js until after prototype.js has been loaded. By selecting a unique identifier from the file (prototype.js or scriptaculous.js) and checking periodically whether the identifier has been defined or not, we can indirectly deduce the current state of that file. In other words, an identifier has been defined, which means that the file containing it must have been loaded, too. For example, we choose the identifier named Prototype in prototype.js and Draggable in scriptaculous.js.
After pagetailor.js is loaded, it would create the containment hierarchy of elements that together compose the Page Tailor window, and the entire hierarchy would be appended to the Web page. Figure 7-4 shows the correspondence between each element and their appearance displayed on the browser. The tag name of each element contained in this hierarchy is labeled on the left-hand side of the figure.
The DOM tree and XPath standards are used to store the user preferences. Page tailor extract the XPathes of blocks which users interest in on Web pages, and store these XPathes to the Configuration Manager. The degree of support for XPath over HTML varies in different types and brands of browsers, so we must deal with the conversion between a selected block and its corresponding XPath expression by ourselves in Page Tailor. The XPath expressions contained in the user preferences are restricted to internal use only. Then, we will make a statement on how to generate the XPath expressions of a selected block.
64
Figure 7-4. The containment hierarchy of elements
As shown in Figure 7-5, every selected block corresponds to a subtree of the document. The way to find its XPath expression can be divided into two steps. First, start from the selected block (or node) and walk recursively up the tree to find all of its ancestors. Then, for each node in the path count the number of its siblings that have the same tag name as that of the node. With these two data, we can finally generate the XPath expressions of the selected block.
65
(a) (b)
Figure 7-5. The selected block (a) and its corresponding sub-tree (b)
It is the XMLHttpRequest object that can be used by JavaScript to transfer data to and from a Web server using HTTP. It is supported by almost all popular browsers. For security reason, however, browsers often impose some restrictions (also referred to as the “same origin policy”) on this object.
The “same origin policy” dates from Netscape Navigator 2.0. This policy prevents a document from one origin from getting or setting properties of another document from a different origin. In general, two documents are considered to have the same origin if they are identical in three aspects: protocol, host, and optionally port. Table 7-1 lists some examples of origin comparisons with the URL “http://store.company.com/dir2/other.html”.
66
Table 7-1. Examples of origin comparisons
URL Result Description
http://store.company.com/dir2/other.html Success http://store.company.com/dir/inner/another.html Success
https://store.company.com/secure.html Failure Different protocols http://store.company.com:81/dir/erc.html Failure Different ports http://news.company.com/dir/other.html Failure Different hosts
From the comparisons in the above table, it is not difficult to imagine that in Page Tailor, it is impossible to retrieve data from Configuration Manager using the XMLHttpRequest object, because a Web page surely comes from the Web server that is situated in a different origin from where Configuration Manager might live. Hence, we do not use the XMLHttpRequest of AJAX standard in Page Tailor.
Using the method, we can overcome the restriction imposed by the “same origin policy”. In the Page Tailor bookmarklet, we dynamically create a “script” element, assign some attributes to it, and add this element to the Web page. After the remote file has been loaded, the JavaScript code written in that file would be executed accordingly. Hence, the limitation of
“same origin policy” of communication between the Page Tailor and Configuration Manager can be overcome by the dynamical javascript loading mechanism in HTTP 1.0 standard.
However, the value assigned to its “src” attribute does not point to a remote file. It points to the query service provided by Configuration Manager. Therefore, adding this element to a Web page is equivalent to using the query service. Moreover, since the type attribute of the
“script” element has a value of “text/javascript”, the response of the query service should be in the form of JavaScript, or some runtime errors might occur. As for how to make use of the response of query service, we can see Figure 7-6.
67
01 query(current url, callback);
02
03 function query(current_url, callback_function_name){
04 var req = document.createElement("script");
05 req.type = "text/javascript";
06 req.id = random number
07 req.src = "http://.../.../query_service?url=" + current_url
08 +"&callback=" + callback_function_name
15 Process the response(i.e. service_response)
16 Find and remove the element with the specified value (i.e.
17 element_id) of the ID attribute 18 }
Figure 7-6. How to load the user preferences (pseudo-code)
The pseudo-code is taken from pagetailor.js. When we need the user preferences of a Web page, the function named query would be invoked (Line 01). What the function does is as described in the last paragraph. There are three parameters in the query string: url, callback, and id. When Configuration Manager receives a request, it would extract the values of each parameter. Among them, the value of url is employed to query the database to find the corresponding user preferences about this Web page. The value of callback contains the name (“callback” in this case) of a function to process the response of query service. And id, the last one, is utilized to identify the “script” element that makes this request, since more than one
“script” element could be added to a Web page at the same time.
68
As mentioned before, the response will be interpreted as JavaScript. What Configuration Manager returns is actually a function invocation like the one in Figure 7-7. The function name, “callback”, is identical to the one involved in the query string. Two parameters are passed to this function. The first one contains the user preferences about the URL specified in the query string, the second one is the id specified in the query string as well, which is left intact.
callback(user preferences, id specified in the query string);
Figure 7-7. The response of query service (pseudo-code)
When the response is sent back to the client side, the function named “callback” would be invoked with the user preferences filled by Configuration Manager. Since Page Tailor has obtained the user preferences, the reconstruction of the past could be performed in the body of this function. Finally, it comes to the id’s turn. We can use the id to find the “script” element that was added to the Web page to trigger this series of events and remove it. Here the callback invocation is sent back from Configuration Manager to the Page Tailor through the iw interface again.
The above descriptions illustrate how to load the user preferences without being restricted by the “same origin policy”. Figure 7-8, on the contrary, illustrates how to update the user preferences. It is not surprising that these two operations are very similar. They differ only in two respects. First, one more parameter is involved in the query string, which is the data required to update. Second, the callback function only serves as a scavenger to remove the
“script” element.
69
01 update(current url, user preferences, callback);
02
03 function update(current_url, user_preferences, callback_function_name){
04 var req = document.createElement("script");
05 req.type = "text/javascript";
06 req.id = random number
07 req.src = "http://.../.../update_service?url=" + current_url 08 +"&prefer=" + user_preferences
16 Find and remove the element with the specified value (i.e.
17 element_id) of the ID attribute 18 }
Figure 7-8. How to update the user preferences (pseudo-code)
We adopt Ruby on Rails to implement the Configuration Manager. Controllers are the subprograms in a Rails application that performs tasks. Controller actions are sequences of Ruby code that correspond directly to the tasks this application can be asked to do. When an action is executed, it not only has access to the data from a submitted form but also to the models. In our system, two Web services exported by Configuration Manager are implemented as separate actions. That is, query_service and update_service. These two interfaces enable the Page Tailor to manipulate the data stored in the backend database.
Mobile Proxy in our system is developed from Muffin. We can modify the content of the Web page before it is sent back to the client according the user preferences specified by the user.
70
The interfaces in the filter logic class depend on what kind of filtering we intend to perform.
There are two interfaces designed: RequestFilter and ReplyFilter. The RequestFilter interface is to filter requests before they are sent to a server. On the contrary, the ReplyFilter is to modify replies after a server responds. These two interfaces follow the HTTP 1.0 standard of iw interface.
If a request issued by the client is destined for a URL that has corresponding user preferences stored in our database, Mobile Proxy would start a chain of processing steps. First of all, it would use a HTML parser, NekoHTMLto parse that Web page and produce a corresponding DOM tree (Figure 7-9). After that, an XPath engine, Jaxen is employed to process XPath queries over the DOM tree. Some specific elements would be selected at this time, and a new DOM tree would be created alongside to hold the replicas of these elements (Figure 7-10).
The sequence of the replicas in the new DOM tree would refer to the sequence of the XPath expressions in the user preferences.
Figure 7-9. Produce a corresponding DOM tree
71
Figure 7-10. A new DOM tree (right) would be created to hold the replicas of selected elements in original DOM tree (left)
The result page (i.e. the new DOM tree) has already been constructed now. However, it is not necessarily self-validating because what we have done already is to find, clone and collect the blocks of content directly. To further polish that, an open source utility, JTidy, would be used.
This tool was originally designed to fix mark-up errors and also offers a means to convert existing HTML content into well-formed XML, such as XHTML. After the process of JTidy, a well-formed and validated result page is finally turned up.