Skip to content
This repository has been archived by the owner on Nov 18, 2021. It is now read-only.

Random development notes

bard edited this page Sep 13, 2010 · 3 revisions

This page contains notes about developing applications on xmpp4moz,
the code base itself, etc. not ordered by any particular criteria. As
clusters of notes form around subjects, they will be refactored into
separate pages.


xmpp4moz is designed around the idea of ‘’late binding of structure to
data_. You won’t see any ’’Contact’’, ’’Message’’, ’’Conference_
class that interpret1 the underlying XMPP traffic for you.

Instead, XMPP is considered to be semantically rich enough to deal
with it directly, and means are provided to do it in a comfortable
way.

1 Interpret’’, not ’’abstract, because it would simply
substitute a meaning (even a narrower one) for another, instead of
surfacing any latent meaning.


When you perform a network action that should also cause something to
be displayed locally (e.g. sending a message to a contact, which
should also be displayed in a conversation pane), don’t perform the
network action and then update the interface manually; instead have a
listener on outgoing traffic that will update the interface. This
way, it will be updated even when a message is sent from an extension
other than yours.


How to check what chat rooms are currently open?

Iterate over XMPP.cache.presenceOut, searching for <presence>
stanzas with an <x xmlns="http://jabber.org/protocol/muc"/> payload.

(But note that presenceOut will be deprecated and cache entries will
be selected through the same API through which events are picked out
of a channel.)


A contact is univocally identified by a {account, address} tuple.
Account is in the form @user@server/resource@ and is configured via
Menu Jabber → Accounts → Configure. Address is in the form
@contact@server@.


An conversation is a subclass (in concept, not in code) of an
interaction (specifically, a verbal interaction). There is (will be)
no first-class concept of “conversation” in the code. However,
interactions, even non-verbal ones, are referred to as “conversations”
in the user interface for familiarity.


An interaction is (will be) univocally identified by an {account, address, url} tuple.


SamePlace and other extensions follow a simple arrangement for
functions:

- GUI actions - GUI reactions - Network actions - Network reactions - Utilities - GUI utilities - Network utilities

Action names are <active verb><object> (e.g. createConversation),
reactions are <passive verb><object> (e.g. receivedMessage).

Actions and reaction rely on the environment (e.g. refer to specific
elements of the interface), utilities only rely on their arguments and
can thus reused in other contexts easily.


The XMPP object is the main entry point to xmpp4moz functionality from
JavaScript. It is completely stateless, so it can be used from
multiple places without need of synchronization. It provides
higher-level functionality over the XPCOM nsIXMPPSession and
nsIXMPPService components.


Hybrid applications, just like web applications, have a limited
worldview. They cannot reach outside the content panel they live in.
This is true also for non-remote applications like the chat
application in SamePlace: it follows the same rules.

Some things a hybrid application can know about: what your JID is;
what your presence is; what your contact’s JID is; what his or her
presence is. These information are sent when a content panel is
“enabled” to work with a certain contact.

Some things a hybrid application cannot know about: what your other
contacts are; your account information.


We want to build a communication layer, and programs that want to use
this communication layer should be able to hop on it at any time and
look at a state of things that is consistent. XMPP mechanisms alone
are not enough and there is some gap to bridge.

Example: platform establishes an XMPP session. Server sends platform
presence information about user’s contacts. Later, user starts a chat
client. How does the chat client know what contacts to display as
“online”? Still later, user establishes a second XMPP sessionn
through another account and kills the first one. How does the client
know that contacts from the first session are no longer available?

The first question is answered by keeping an intelligent cache of
events. Say that, upon connection, the “foo” and “bar” contacts are
both online, and the server sends the following:


&lt;presence from="foo@server.org/Firefox"/&gt;
&lt;presence from="bar@server.org/Firefox"/&gt;

The XMPP communication layer will cache those stanzas. Later, “bar”
goes away and the server sends:


&lt;presence from="bar@server.org/Firefox"&gt;
&lt;show&gt;away&lt;/show&gt;
&lt;/presence&gt;

The cache receives the event, sees it nullifies a previous event, and
replaces the previous with the new one. So the cache content becomes:


&lt;presence from="foo@server.org/Firefox"/&gt;
&lt;presence from="bar@server.org/Firefox"&gt;
&lt;show&gt;away&lt;/show&gt;
&lt;/presence&gt;

In other words, the cache keeps the bare minimun needed to reproduce a
certain state of things later.

When the chat client is started, it queries the cache and finds that
information and can synchronize to it. Since state is collected as a
series of state-building events, the client can reconstruct state
using the same routines it uses to handle real events.

The second question (“How does the client know that contacts from the
first session are no longer available?”) is instead answered by the
“service”.

When an XMPP client quits a session, the server does not signal it
that contacts become unavailable. It is the client’s job to give the
user visual cues that those contacts are no longer reachable.
Usually, it does it through ad-hoc code that affects the in-memory
structure that represents the contact list.

However, since xmpp4moz is a layer and not a client, we don’t have the
luxury of knowing how “contact unavailability” will be represented to
the end user. Moveover, quitting a session is not the end of
communication: more sessions might be connected.

The easiest thing to do would be for each program using the
communication layer to handle a closed session on its own, updating
its own structures with ad-hoc code. However this means adding
complexity to the programs.

Instead, just like the XMPP protocol wants to move complexity to the
server, we want to move complexity to the communication layer.

So, when a session quits, we simply synthesize unavailable presences
for contacts that were previously online. From the perspective of the
program that uses the communication layer, it’s just as if all those
contacts had disconnected simultaneously.


This is the policy applied to presence information with respect to
their interaction with the cache. “Contact” here is identified by a
full JID, so @foo@server.org/Res1@ and @foo@server.org/Res2@ are
not the same thing.

From To Type Handling
contact user available if presence from same contact in cache, replace, else add
contact user unavailable if presence from same contact in cache, replace, else ignore
room occupant user available if presence from same occupant in cache, replace, else add
room occupant user unavailable if presence from same occupant in cache, remove, else ignore

This is the policy applied to presence information with respect to
stanza synthesis.

From Event To Type Handling
user presence room unavailable synthesize unavailable presences for all room occupants
user stream close synthesize unavailable presences for all contacts