The element that provides the run-time environment for HDML is referred to as the user agent.
The fundamental building block of HDML content is the card. The user agent displays and allows the user to interact with cards of information. Logically, a user navigates through a series of HDML cards, reviews the contents of each, enters requested information, makes choices, and moves on to another or returns to a previously visited card.
Cards come in one of four forms:
Display, choice, and entry cards contain text and/or references to images that are displayed to the user. Choice cards allow the user to pick from a list of available options, and entry cards allow the user to enter text.
While it is expected that cards contain short pieces of information, they might contain more information than can be displayed in one screen full. The user agent will provide a mechanism for the user to view the entire contents of the card. An example of this would be a user-interface that allows scrolling through the information.
HDML cards are grouped together into decks. An HDML deck is similar to an HTML page in that it is identified by URL [RFC1738] and is the unit of content requested from a server and cached by the user agent.
Individual cards within a deck are identified by name and can be addressed by URL fragment. For example, the URL of "Card1" in "http://www.foo.com/MyDeck.hdml" is:
http://www.foo.com/MyDeck.hdml#Card1
The first card in a deck has the same URL as the deck itself. It does not need to be named unless other cards within that deck use it as a destination.
A user agent may store HDML decks in a local cache. If it does so, the user agent shall provide a means to flush decks from its cache by URL. HDML decks can specify their time-to-live (TTL) in the user agent's cache.
Decks can also specify default actions for the cards it contains (see "Actions" below).
After completing interactions with a card, a user may select one of the following actions:
ACCEPT | Complete text entry, move forward to the next card, start or complete an activity; this is the primary action for moving forward |
---|---|
PREV | Move back to the previous card |
SOFT1-SOFT8 | Application defined |
HELP | Display a help card to the user |
The actions defined in HDML are abstract and are supported in the user interface in a user agent specific manner. For example, a data-ready mobile phone with two soft keys may map the left soft key to the ACCEPT action, the right soft key to the SOFT1 action, and dedicated keys to the PREV and HELP actions.
Each action, when selected, performs a task. For example, the GO task displays another card (either in the current deck or a different deck), and (in the case of a data-ready mobile phone) the CALL task starts a voice call to a particular phone number.
The mapping of action to task can be specified in the following places (in order of precedence):
If not specified, actions have the following default behavior
ACCEPT | Display the previous card in the history |
PREV | Display the previous card in the history or cancel the current activity if there is no history (see "History-based navigation") |
SOFTx | Do nothing |
HELP | Display a built-in help card |
The next card the user agent will process in an interaction is referred to as a destination. An HDML destination is similar to a web URL with some extended semantics as described in "Destinations".
The HDML navigation and state model is structured around activities. An activity can be thought of as a group of related cards that perform one logical function. These cards may span one or more decks. Navigation among cards within an activity is non-destructive, that is, UI state is preserved if you move back to a previous card and forward again. When you exit an activity, all card-related information is lost.
Activities are managed on the activity stack. Entering an activity pushes it on the stack, and exiting an activity pops it off the stack. In this way, activities are similar to subroutines. An activity is entered using the GOSUB task and is exited using either the RETURN or CANCEL tasks (see "Tasks").
The activity stack is used for:
In each activity, the user agent maintains a history of the cards displayed to the user. As each card is accessed, it is added to the card history. The user agent allows the user to easily navigate back to the previous card in the history.
A card can override the history by defining a PREV action. Note that accessing a card that specifies a PREV action has the effect of invalidating the current activity's history. It is also possible for other actions to navigate to the previous card in the history by invoking the PREV task.
Note that the PREV action and PREV task are separate and distinct concepts. There are situations where an application might want to override the default PREV action, such as during navigation of a long list of cards. If the application lets the user search and display a card in the middle of the lists, it may overload the PREV action so that it always takes you to the previous card in the list regardless of whether it is in the history or not. Conversely, there are situations where an application may want the ACCEPT action to take the user to the previous card in the history. To accomplish this, the ACCEPT action is bound to the PREV task.
Variables are named pieces of information that can be substituted into cards as they are displayed and otherwise processed. Variables are scoped to the current activity.
There are a number of ways to set variables. Choice and entry cards set variables. The KEY option of the card specifies the name of the variable to set. For entry cards, the value to whatever the user has entered, and for choice cards, the choice entries specify the value in their VALUE options. Variables can be set when navigating from one card to another. Variables can also be set when a sub-activity returns.
The values of variables can be substituted into both the displayed text of a deck and certain option values in HDML elements. The substitution of variable values happens at run-time, in the user agent.
Variables can be set when navigating from one card to the next. There are two ways to pass variables. GO and GOSUB tasks use the VARS option to specify the variables to pass. In the example that follows, the ACCEPT action causes the user agent to go to "card2", and in the process, to set the variable "name" to "John".
<ACTION TYPE=ACCEPT TASK=GO DEST="#card2" VARS="name=John">
Similarly, variables can be passed into a sub-activity. In the following example, a new sub-activity is created with the one initial variable, "name", whose value is "Jane". The first card displayed in the sub-activity is the first card in the deck "sub.hdml".
<ACTION TYPE=ACCEPT TASK=GOSUB DEST="sub.hdml" VARS="name=Jane">
A card can make a call to a sub-activity to have it return new values for variables. For example, a sub-activity may allow the user to pick an email address out of an address book and then return it to the calling activity. Using a deck in this way is similar to calling a subroutine in a computer programming language.
A list of values to be returned from an activity is specified in the RETVALS option of the RETURN task. The names of the variables to assign the values are specified in the RECEIVE option of the calling action. For example:
<HDML version=2.0> <DISPLAY> <ACTION TYPE=ACCEPT TASK=GOSUB DEST="#subact" RECEIVE="var1;var2"> var1 = $(var1)<BR> var2 = $(var2) </DISPLAY> <DISPLAY NAME=subact> <ACTION TYPE=ACCEPT TASK=RETURN RETVALS="abc;xyz"> Return abc;xyz </DISPLAY> </HDML>
In the above example, the sub-activity returns two values, "abc", and "xyz". The calling action assigns these values to the variables "var1" and "var2" respectively. Note that the values are assigned based on their position in the retvals list. A calling action can ignore a return value simply by not specifying a variable name for that position. Similarly, if a variable name is specified for a position that has no value, the variable will be cleared, i.e. set to a zero-length string.
HDML provides the following security features.
The existence of variable state in the language and runtime introduces some security issues that do not exist in other markup languages such as HTML. In particular, certain variable state may be considered private by the user. While he or she may be willing to send a credit card number to a secure service, an insecure and nefarious service should not be able to retrieve that number from the user agent by any means.
Also, HDML applications often use variables to consolidate redundant information to parameterize decks. The basic reliability of an application could potentially be compromised by a card or deck being invoked with invalid or malicious variables.
The user agent performs deck level access control when navigating from one card to the next. A deck can be declared as public, which means it can be accessed from any other deck. Also, decks that are not public can specify which decks can access them by URL. This allows an application to protect decks from the attacks. See "The HDML Element" for more details.
Typically, when an HDML application takes action on behalf of the user, it does so as a side-effect of the user agent accessing a URL. For example, requesting a URL from an HTTP server can cause a CGI program to run. This CGI program can do some things, and then return an HDML deck to display the results. Thus, some URLs have side-effects.
If an application wants to protect a URL that has destructive or other side-effects, it should allow the URL to be invoked from certain other URLs, that is, HDML decks that were generated by the application itself.
The HDML user agent should provide the capability to communicate the referring URL to the application. How this is communicated depends on the client-server protocol. In the case of HTTP [RFC2068], the user agent will specify the referring URL in the "Referer" request header.
In some network configurations, it is prohibitively expensive or infeasible to send the referring URL in every request to a server. To accommodate these networks, HDML allows the application to specify whether to send the referring URL in the request or not. This strikes the balance between security for URLs with side effects and network costs.