A la demande de mon camarade Benjamin, qui faisait à juste titre remarquer que nous utilisons quotidiennement une application web lourde au niveau client nommée Zimbra, je me suis dit que j’allais en effet étudier celle-ci pour comprendre son fonctionnement.

Qu’est ce que Zimbra ?

C’est un groupware qui permet de gérer collaborativement les mails mais aussi les agendas et les documents. Disponible en libre ou en payant, Zimbra est un logiciel de webmail haut-de-gamme pour les utilisateurs ayant besoin de fonctionnalités évoluées. Autrement dit, c’est googleApps sans Google ;)

Autopsie d’une page d’accueil

Pour se convaincre de l’utilisation intensive de Javascript par Zimbra, il suffit de le lancer en bloquant ce dernier, on obtient une page d’erreur renvoyant éventuellement vers la version “safe” de l’application (accessible sur https://domain.tld/zimbra/h), qui échange classiquement du HTML avec du JS limité aux interactions, représentant tout de même plus de 300Ko de JS compressé… pas mal pour une version capable de tourner sans javascript.

De fait, la page de login de l’application laisse le choix de la version du client qu’on souhaite utiliser avec un menu proposant le client (je cite) :

  • Évolué (Ajax) /public/launchZCS.jsp
  • Standard HTML /h/search
  • Mobile  /m/mainx

Dès que JS est activé et la version “évoluée” choisie, on voit dans les chargements de Firebug d’abord une page de 25Ko qui contient

– La déclaration de la licence Zimbra Collaboration Suite Web Client
– Un head minimaliste, avec title, favicon, redirection noscript et un début de bootstrap de l’application client, avec des paramètres comme

...	window.appDevMode     = false; window.isNotifyDebugOn     = false;...

- De nouveau la licence (Wut?)
– Une balise script chargeant un fichier …/I18nMsg,AjxMsg,ZMsg,ZmMsg,AjxKeys,ZmKeys,ZdMsg,AjxTemplateMsg.js.zgz?… (zgz = js gunzippé)
– Des commentaires attestant de la reconnaissance du navigateur afin d’en définir les capacités de toute évidence.

Aparté : du coup j’ai voulu regarder sur le Firefox de Safari ce que ça donne. Quatre choses :
1. le Client Zimbra  version mobile est bien lancé automatiquement, on voit dans son code qu’il est pensé pour iPhone (accessible sur https://domain.tld/zimbra/m).
2. Pour voir la source d’une page dans FF, saisir “view-source:http://url.tld” dans la barre d’url
3. Cette version mobile est encore moins interactive, quasi aucun javascript
4. Quand je demande à voir la  version “ordinateur” de la page, je suis de toute façon ramené à la version “sûre”.

– Ensuite 140 lignes de balises HTML vides de tout contenu, destinées à composer le squelette de base
– Un modal Splash qui est masqué lorsque la page est chargée
– Enfin plus de 1700 lignes de Javascript destinées à paramétrer l’application avec au milieu deux nouveaux appels de <script>.
Note : A quoi voit-on que la version de test date un peu ?  Au fait que la dernière version de Firefox référencée est la 3.6… alors qu’on en est à la 17.0 depuis la semaine dernière :)

Pour formaliser un peu tout ça voilà ce que dit la doc sur l’ordre de chargement :

1) remote style: app & skin CSS
2) inline script: global constants such as appContextPath, etc
3) remote script: message & key binding resources
4) inline HTML: skin HTML (from /skins/{skin}/manifest.xml)
5) inline script: /js/Boot_all.js
6) inline script: timezone data
7) remote script: /js/Startup1_1_all.js
8) remote script: /js/Startup1_2_all.js
9) inline script: skin JS (from /skins/{skin}/manifest.xml) **
10) inline script: onload code to launch the app

Où l’on entre dans le vif du sujet

Au chargement de la version AJAX, c’est plus de 450Ko de JS compressé (mais pas minifié) qui sont téléchargés en 3 fichiers de 5 000,  23 000 et 30 000lignes. Soit, avec le “bootloader” inline, environ 60 000 lignes de code.

Le fait que le code ne soit pas minifié simplifie sa lecture… mais pas la compréhension de sa structure. Les lignes de déclarations atomisées s’enchaînent. Ainsi le premier fichier de 5K lignes définit chaque propriété de traductions ligne par ligne :

...
a.errorNoPhone="You need to enter a phone number to forward from.";
a.errorNoSuchConv="No such conversation exists.";
...

La même méthode se répète ensuite pour les propriétés des objets : toutes les déclarations sont individualisées. Je présume que ceci permet de rendre le code plus robuste et modulable [à coup de IF( IE && IE.VERSION <8 THEN INCLUDE(“lib.part.method.xxx”) dans le pipe vers le stream gunzippé]. Ce qui est clair c’est qu’une gestion “propre” du namespace dans le DOM n’est pas à l’ordre du jour : tous les objets se retrouvent à la racine.

A ce stade on observe que plusieurs pseudo-namespaces principaux co-existent : Ajx, Dwt, Email, YM, Zm.

Pour comprendre le namespace Zm, il faut se référer à la documentation  qui indique qu’il désigne le Zimbra Mail, soit la partie réservée au client tandis qu’existent aussi les namespaces Z et Za dont le premier contient des objets partagés entre le code du frontend client et celui du frontend d’admin; tandis que le second est réservé à la partie Admin.

Ajx est la partie chargée des échanges, manipulations et validations Ajax, elle contient une quarantaine d’objets. Certains sont assez réjouissants comme AjxSHA1 qui contient 7 méthodes cryptographiques publiques, d’autres sont très simples. Ils conservent une bonne partie de leur propriétés dans leur espace interne avec des déclarations “privées”, ce qui les rend difficile à inspecter, c’est d’ailleurs le cas avec tous les objets du client Zimbra. Néanmoins une fois le code source téléchargé on peut en savoir un peu plus concernant les entrailles de la bête.

Dwt” (DHTML widget toolkit) Dwt représente une soixantaine d’objets chargés de générer les éléments HTML. C’est évidemment un élément central d’une application qui génère ses propres éléments de DOM. Pour la partie administration il implémente le protocole XForms, néanmoins pour le moment on s’intéressera au client Web, l’administration attendra ;).

Note : Comme il était difficile de se rendre compte du fonctionnement des différentes parties, à ce point là je me suis servi du code source et des documents pour développeurs. De fait la rédaction de cet article rend mal compte de la progression de la recherche car il m’est arrivé de revenir en arrière pour ajouter des précisions ou corriger des incompréhensions.

Vu du ciel

Voici ce que dit la documentation concernant l’organisation générale des sources AJAX générales ://depot/{branch}/ZimbraWebClient/WebRoot/js/ajax/

boot/ – bootstrap code (e.g. loading source, callbacks, etc)
dwt/ – DWT framework (widgets/, etc)
package/ – package manifests for combining files
util/ – utility code (e.g. text formatting, etc)

Et voici l’organisation générale des sources pour le client Avancé :

//depot/{branch}/ZimbraWebClient/WebRoot/js/zimbraMail/

abook/ – Address Book app
briefcase/ – Briefcase app
calendar/ – Calendar app
core/ – core advanced client functionality
im/ – Instant Messaging app
mail/ – Mail app
mixed/ – Mixed view ***
notebook/ – Notebook app
package/ – package manifests for combining files
portal/ – Portal (or Home page) app
prefs/ – Preferences app
share/ – common code shared among apps
tasks/ – Tasks app

Il est intéressant de noter que le client avancé fonctionne selon un modèle MVC, ainsi par exemple voici la structure de l’application mail et de ses objets situés dans :

//depot/{branch}/ZimbraWebClient/WebRoot/js/zimbraMail/mail/

ZmMailApp.js

controller/
ZmMailListController.js

model/
ZmMailMsg.js

view/
ZmMailListView.js
ZmMailMsgView.js

Très clairement à ce point là de la recherche, il apparaît que discuter et documenter les classes, leurs usages et leurs interactions nécessiterait bien plus qu’une entrée de blog tant l’étendue du travail est vaste. De plus, je n’ai pas réussi à sortir une documentation propre pour les 700+ classes disponibles, Doxygen ne marche pas sur le JS et YUIDoc produit une erreur de RAM (merci Node) et un contenu inutilisable. Pour une bonne raison : les déclarations atomisées ne permettent pas facilement de construire une vue centralisée comme le permettrait une construction de classe “typique” avec un environnement déclaratif fermé et unique. Ne pas pouvoir extraire automatiquement une documentation du code, c’est un frein terrible quand on veut créer un framework. C’est un souci majeur pour javascript auquel il faut penser.94

Pour le moment, je m’en tiendrai donc à observer que l’application Zimbra Web Client présente une structure “moderne” en MVC et une librairie très étendue. Connue sous le nom de Kabuki, cette librairie a voulu devenir un projet Apache (voir le projet en PDF qui contient une documentation succinte des classes) puis a fait marche arrière suite à des discussions au sein de l’OpenAjax Alliance qui comprenait Dojo, IBM, SAP, Zend et Zimbra. Ce qui expliquerait le support prioritaire de DOJO dans ZendFramework au départ. De fait maintenant le projet OAA est mort et Kabuki ne semble pas plus vaillant. En revanche le dernier projet de l’OAA  nommé Maqetta est intéressant puisqu’il permet de développer des sites en ligne en HTML5 via un code opensource BSD. Les autres projets  sont le OpenAjaxHub à télécharger ici qui sert à dispatcher entre librairies sur une page web et OpenAjax Metadata qui définit une norme xml pour décrire notamment les widgets et les API.

 

Côté serveur

Revenons à notre application pour nous interroger sur ce qui tourne côté serveur et les échanges entre client et serveur.

L’application chargée des échanges est Jetty, un choix expliqué par son implémentation du protocole Comet (datant de 2006) qui maintient sur une durée indéterminée deux sessions entre le serveur et l’utilisateur pour pousser / tirer des informations entre chacun. Ce qui est assez proche de ce que nous utilisons pour la vidéo.

Cette technique permet notamment des échanges sans requête de la part de l’utilisateur, la connection restant ouverte en permanence. De fait, si Zimbra utilise intensivement Nginx comme reverse proxy pour toutes sortes de protocole de messagerie, ce n’est pas le cas pour le web sur notre installation.

Conclusion

Zimbra est une solution côté client vraiment intéressante mais il semble que les bonnes idées qui la soutiennent

 

 

Categories: javascript

Comments are closed.