Cisco AJAX XMPP Library v2012.02 Release Notes
The latest release of the Cisco Ajax XMPP Library offers many new features. The most significant new features included with the library include:
Abstract core browser properties
The browser properties CAXL relies on most have been abstracted into a new namespace: jabberwerx.system. This allows future editions of the library to support non-browser environments.
No changes to user code are necessary, and the complete set of abstractions is still subject to change.
Supported Platform Updates
CAXL now supports the latest versions of Chrome, Internet Explorer, Firefox, and Safari.
This release includes support for Internet Explorer 9, both Quirks and Standards Mode. When used in IE9 Standards Mode, this API ensures the correct MSXML DOM is used, and all interactions with XMLHttpRequest or XDomainRequest are correct for this and Internet Explorer 8.
Support for IE9 means that support for versions older than 8 are no longer confirmed. While many things are expected to function correctly, testing is no longer performed on IE7.
Protocol Compliance Improvements
A number of changes were made to improve compliance with existing standards from the IETF, W3C, and XSF. The compliance documentation within CAXL has been updated to detail the level of support, including any differences or gaps.
Documentation Improvements
The documentation and examples have gone through a review, with adjustments made to improve usability and correctness. The documentation index was reorganized to emphasize the developer guide and the most useful examples. All HTML examples now include a !DOCTYPE which hints to the browser to use the most standards-compliant mode it understands. All files now have indications on what consumers may do with them.
Privacy List Enhancements
The jabberwerx.PrivacyList now provides the ability for the user to specify which stanza kinds are blocked for a given JID, or to block all communications. This is done by specifying the list of stanza kinds to block:
var blocked = [ jabberwerx.PrivacyList.PRESENCE_OUT,
jabberwerx.PrivacyList.MESSAGE,
jabberwerx.PrivacyList.IQ];
privacyList.blockJid("blocked@example.com", blocked);
privacyList.update();
If no kinds are given, all communications for the JID are blocked. Unblocking a JID is not selective; unblocking a JID will allow all communications for that JID. To change the list of block stanza kinds, simply call blockJid() with the new list.
To retrieve the list of blocked stanza kinds for a given JID, call getBlockedStanzas(jid). If the JID is not blocked, an empty list is returned. If all communications are blocked, the special jabberwerx.PrivacyList.ALL pseudo-kind is returned.
RosterController.fetch is now Deprecated
The method RosterController.fetch() is now deprecated, and may be removed in a future version. Instead, API users should create the RosterController before logging in a user; the roster will automatically be fetched once the user is logged in.
Client sends all pending outbound Stanzas while Disconnecting
The jabberwerx.Client will now attempt to send all outbound Stanzas as part of calling disconnect(). This allows API users to perform certain cleanup operations, such as sending unavailable presence or unsubscribing from PubSub nodes, as part of their shutdown logic.
This logic makes a best effort to send, and is only done as part of a user-driven disonnect(). Due to the asynchronous nature of the protocol and browser platforms, it is not possible to guarantee these stanzas have actually be sent before completing the disconnect.
PubSub Enhancements
The API documentation for PubSubController and PubSubNode has been greatly improved, thanks to the insightful feedback of community members.
Also, the callback for PubSubNode.publish() now returns the id of the newly-published item. This is especially useful if applications rely on the PubSub service to automatically generate id's for published items. For example:
var publishCB = function(err, id) {
// if successful, err is undefined, and id is the actual item id
// if failed, err is the DOM \<error/> node describing the failure, and id is undefined
if (id) {
alert("published item id is " + id);
}
};
// publishCB is called when publish completes
psnode.publish(null, payload, publishCB);
This change is backwards-compatible with previous releases; applications that supply a callback do not need to be updated.
Added the ability for PubSubNode to subscribe using the full JID. This changes the behavior from using the bare JID to the full JID for the currently logged-in user.
Example Implementation of (non-SSO) WEBEX-TOKEN Authentication
This release includes an example for authenticating to cloud-based Connect services using WEBEX-TOKEN, in non-SSO deployments. This is useful for those that need to integrate IM with existing WebEx services.
jabberwerx.NodeBuilder Optimizations
The jabberwerx.NodeBuilder implementation changed how elements are created, resulting in a 5x to 10x performance boost. No changes to its API were necessary, so all existing tests and examples function the same.
Caching jabberwerx.JID Instances
Instances of jabberwerx.JID are cached, which helps reduce the amount of time spent creating and preparing JIDs. The cache is global, and a "best effort" is made within the library to ensure a cached JID is used before creating a new one.
To make best use of the cache, users should call jabberwerx.asJID instead of the JID constructor. There is also a method for clearing the JID cache, although most implementation should not need to do this. This method does not destroy all JID instances; it only removes those instances from the internal cache.
Reduce Distinct "batchUpdateStarted"/"batchUpdateEnded" Events
The number of "batchUpdateStarted" and "batchUpdateEnded" events during login were reduced to a single occurrence of each. This helps client implementations better process large changes to the jabberwerx.Client's entitySet by allowing implementations to make more assumptions.
Improve jabberwerx.RosterController/RosterView Scalability
The scalability of the jabberwerx.RosterController was improved by limiting the number of
There is also a new event, "rosterFetched", to indicate when the jabberwerx.RosterController has completed processing the initial roster fetch:
var rosterCtrl = client.controllers.roster;
rosterCtrl.event("rosterFetched").bind(function(evt) {
// no special event data
// walk client.entitySet to process...
});
The performance of the RosterView has improved significantly; more than 5 times faster in Firefox 3.6, with similar improvements in others. The RosterView now monitors "entityBatchStarted" and entityBatchEnded" events; updates are disabled on a "entityBatchStarted" event, and re-enabled on a "entityBatchEnded" event. In addition, the "entityBatchEnded" event now includes data on what entities were added/removed/updated. See the events documentation for more information.
Client.sendIq Reports "<remote-server-timeout/>" Instead of null for Timed Out Requests
The jabberwerx.Client.sendIq method will no longer pass null to the result callback. Instead, an error
client.sendIq("get", "no-exist.example.com", "<query xmlns='jabber:iq:version'/>", function(iq) {
iq = jabberwerx.Stanza.createWithNode(iq);
if (iq.getType() != "error") {
// ...
}
});
and "no-exist.example.com" is not a running service or component, then the callback will eventually be called with a value for "iq" similar to the following:
<iq type='error' id='example1' to='no-exist.example.com'>
<query xmlns='jabber:iq:version'/>
<error type='wait'>
<remote-server-timeout xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
This change helps provide a common error handling flow, and allows
jabberwerx.Client Yields to the Browser While Processing Received Stanzas
jabberwerx.Client now limits the number of stanzas it processes at one time before yielding control back to the browser. The yields are done by calling window.setTimeout() after processing a fixed number of stanzas. This allows the browser to stay more responsive while processing large (100+) number of incoming stanzas. The order the stanzas are received is maintained.
Optimize Entity Cleanup on Logout
All Controllers of a client are responsible for cleaning up their entities on logout (if appropriate). Previously, this meant each controller required a "clientStatusChanged" event callback, then walked the array of cached entities, calling client.entitySet.unregister() for each. This results in at least two complete iterations of the entitySet (once to create an array of entities, another to determine which entities need to be unregistered).
Now, Controllers implement a method, "cleanupEntity(entity)". After the jabberwerx.Client is disconnected, it walks all the entities in its entitySet, calling "cleanupEntity()" on that entity's controller. This drastically reduces the number of tight loops during login, particularly if jabberwerx.RosterController and jabberwerx.QuickContactController are both in use.
The previous form of cleanup is still possible, so existing Controller implementations outside of this library should still function the same. However, this gives implementations a better alternative to migrate to.
Controller Lifecycle via Rendezvous Pattern
jabberwerx.Client now allows interested controllers to influence when the "clientStatusChanged" event for the connected status to be triggered. This allows, for example, the RosterController to finish processing the initial roster before the connected status change, making it ready for the "presence flood" that happes upon login.
Any controller can be interested in influencing startup. A controller mixes in the jabberwerx.Rendezvousable interface, and overrides the "startRendezvous(ctx)" method to start performing their login logic. When the logic is complete, the controller calls "finishRendezvous()". The client waits until all Rendezvousable controllers are finished before triggering the "clientStatusChanged" event for connected.
Support for "see-other-uri" BOSH Error (Load Balancing-Related)
CAXL now supports the "see-other-uri" BOSH error condition from XEP-0124. This feature can be useful for distributing load of BOSH CMs, or to allow a BOSH CM to provide a URL-based session identifier.
When CAXL receives this error from a BOSH CM, it will then re-attempt the BOSH request against the new URL. The following criteria MUST be met, or CAXL will report a "policy-violation" error to the user:
- If the original BOSH request was to an "https" URL, the "see-other-uri" address is accepted as-is
- If the original BOSH request was to an "http" URL, then:
- The protocol ("http") of the "see-other-uri" request MUST be to a "http" URL
- The port of the "see-other-uri" request MUST match the original BOSH request
- The domain of the "see-other-uri" MUST match the original BOSH request, or be a sub-domain (e.g. "example.com" and "cm1.example.com" is valid for "example.com", but not "sample.com" or "ample.com")
NOTE: For IE8, all BOSH requests (original or "see-other-uri") MUST have the same protocol as the page origin. If the page was loaded from "http", all BOSH requests MUST go to "http" URLs; if the page was loaded from "https", all BOSH requests MUST to go "https" URLS. This is a restriction Microsoft has placed into their support for CORS, and cannot be bypassed.
Eventing Queue
Events in CAXL are now queued per source. If a callback triggers a new event on a given source (e.g. the client's EntitySet), it is deferred until all of the current event's callbacks are processed. Also, event callbacks may return a Boolean value, which trigger will propagate via a callback argument:
var resultCB = function(result) {
// result is true if at least one callback returned true; false otherwise
};
Performance Improvements to Persistence
The persistence layer's performance has improved significantly; 10 times faster in Firefox 3.5, and noticeably faster in others. Data is now stored as a single value within the browser's storage mechanisms instead of hundreds of small values, which has led to the massive improvement.
When upgrading, this newer version will load the previous version's data, and convert to the new format when saved.