Index: main/plugin-core/i18n/messages_en.xml
===================================================================
--- main/plugin-core/i18n/messages_en.xml	(revision 31744)
+++ main/plugin-core/i18n/messages_en.xml	(working copy)
@@ -16,6 +16,11 @@
    -->
 <catalogue xml:lang="en">
 
+    <!-- RIBBON -->
+    <message key="RIBBON_WORKSPACE_ADMIN_SECTION_SYSTEM_LABEL">System</message>
+
 	<!-- ADMINISTRATOR PASSWORD -->
 	<message key="PLUGINS_CORE_ADMINISTRATOR_PASSWORD_LABEL">Password</message>
 	<message key="PLUGINS_CORE_ADMINISTRATOR_PASSWORD_DESCRIPTION">Change password for 'admin' login</message>
@@ -833,12 +844,77 @@
     <message key="PLUGINS_CMS_HELPER_ENTERURL_LABEL">Address</message>
     <message key="PLUGINS_CMS_HELPER_ENTERURL_OK">Ok</message>
     <message key="PLUGINS_CMS_HELPER_ENTERURL_CANCEL">Cancel</message>
-	
-	<!-- +
+    
+    <!--+
+        | MESSAGES TRACKER
+        + -->
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_LABEL">Bus message tracker</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_DESCRIPTION">See bus messages</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_FOOTER">See Help for details</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_CLEAR_LABEL">Clear messages</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_CLEAR_DESCRIPTION">Click here to clear messages from message tracker.</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_CLEAR_DESCRIPTION2">Action inactive as message tracker window is not opened</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_CLEAR_FOOTER">See Help for détails</message>
+    
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_ID">N°</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_CREATIONDATE">Creation date</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_FIREDATE">Fire date</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_TYPE">Type</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_TARGET">Target</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_CALLSTACK">Creator call stack</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_NOTARGET">&amp;lt;no target&amp;gt;</message>
+    
+    <!--+
+        | REQUESTS TRACKER
+        + -->
+    <message key="PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_LABEL">Server request tracker</message>
+    <message key="PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_DESCRIPTION">See messages sent to server</message>
+    <message key="PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_FOOTER">See Help for details</message>
+    <message key="PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_CLEAR_LABEL">Clear requests</message>
+    <message key="PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_CLEAR_DESCRIPTION">Click here to clear messages from message tracker.</message>
+    <message key="PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_CLEAR_DESCRIPTION2">Action inactive as message tracker window is not opened</message>
+    <message key="PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_CLEAR_FOOTER">See Help for détails</message>
+    <message key="PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_MESSAGE">Select request on the left to display details.</message>
+    
+    <message key="REQUESTSTRACKER_TOOL_COL_ID">N°</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_TYPE">Type</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_TYPE_ASYNC">Asynchronous</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_TYPE_SYNC">Synchronous</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_DATE">Date</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_DURATION">Duration</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_SIZE">Size</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_RETURN">Return</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_RETURN_OK">Ok</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_RETURN_CANCELED">Canceld</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_RETURN_FAILURE">Failure</message>
+    
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_ID">N°</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_READABLE_TYPE">Type</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_READABLE_VALUE">Call</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_READABLE_VAL1">Method</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_READABLE_VAL2">Url</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_PLUGIN">Plugin</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_WORKSPACE">Workspace</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_CCROLE">Extension role</message> 
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_CCID">Component id</message> 
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_CCMETHOD">Method</message> 
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_URL">Address</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY">Priority</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY_LONG_REQUEST">Long</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY_SYNCHRONOUS">Synchronous</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY_MAJOR">Major</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY_NORMAL">Normal</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY_MINOR">Minor</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_TYPE">Return</message>
+
+    <message key="REQUESTSTRACKER_TOOL_DISPLAYMESSAGE_URL">Url</message>
+    <message key="REQUESTSTRACKER_TOOL_DISPLAYMESSAGE_PARAMETERS">Parameters</message>
+    <message key="REQUESTSTRACKER_TOOL_DISPLAYMESSAGE_RESPONSE">Response</message>
+    
+    
+    <!-- +
          | Workspace
          + -->
-    <message key="WORKSPACE_AMETYS_MAIN_ERROR_NOJS">This application can't work without javascript</message>
-    <message key="WORKSPACE_AMETYS_SPLASHSCREEN_LOADING">Loading. Please wait ... </message>
     <message key="WORKSPACE_AMETYS_SPLASHSCREEN_APP_AMETYS_VERSION">powered by Ametys </message>
 	
 </catalogue>
Index: main/plugin-core/i18n/messages_fr.xml
===================================================================
--- main/plugin-core/i18n/messages_fr.xml	(revision 31744)
+++ main/plugin-core/i18n/messages_fr.xml	(working copy)
@@ -15,6 +15,11 @@
    limitations under the License.
    -->
 <catalogue xml:lang="fr">
+    
+    <!-- RIBBON -->
+    <message key="RIBBON_WORKSPACE_ADMIN_SECTION_SYSTEM_LABEL">Système</message>
 
     <!-- ADMINISTRATOR PASSWORD -->
     <message key="PLUGINS_CORE_ADMINISTRATOR_PASSWORD_LABEL">Mot de passe</message>

@@ -834,11 +846,76 @@
     <message key="PLUGINS_CMS_HELPER_ENTERURL_OK">Ok</message>
     <message key="PLUGINS_CMS_HELPER_ENTERURL_CANCEL">Annuler</message>
     
+    
+   <!--+
+       | MESSAGES TRACKER
+       + -->
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_LABEL">Suivi des messages du bus</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_DESCRIPTION">Voir les messages du bus</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_FOOTER">Voir l'aide pour plus de détails</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_CLEAR_LABEL">Effacer les messages affichés</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_CLEAR_DESCRIPTION">Cliquez sur ce bouton pour effacer les messages du bus actuellement visible dans la vue de suivi.</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_CLEAR_DESCRIPTION2">Ce bouton est désactivé car la fenêtre de suivi des messages du bus n'est actuellement pas ouverte</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_CLEAR_FOOTER">Voir l'aide pour plus de détails</message>
+    
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_ID">N°</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_CREATIONDATE">Date de creation</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_FIREDATE">Date d'envoi</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_TYPE">Type</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_TARGET">Cible</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_CALLSTACK">Pile d'appel de création</message>
+    <message key="PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_NOTARGET">&amp;lt;pas de cible&amp;gt;</message>
+    
+    <!--+
+        | REQUESTS TRACKER
+        + -->
+    <message key="PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_LABEL">Suivi des requêtes serveur</message>
+    <message key="PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_DESCRIPTION">Voir les messages envoyés au serveur</message>
+    <message key="PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_FOOTER">Voir l'aide pour plus de détails</message>
+    <message key="PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_CLEAR_LABEL">Effacer les requêtes affichées</message>
+    <message key="PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_CLEAR_DESCRIPTION">Cliquez sur ce bouton pour effacer les messages de requêtes serveur actuellement visible dans la vue de suivi.</message>
+    <message key="PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_CLEAR_DESCRIPTION2">Ce bouton est désactivé car la fenêtre de suivi des requêtes du bus n'est actuellement pas ouverte</message>
+    <message key="PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_CLEAR_FOOTER">Voir l'aide pour plus de détails</message>
+    <message key="PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_MESSAGE">Selectionnez une requête dans la partie gauche pour afficher son détail.</message>
+    
+    <message key="REQUESTSTRACKER_TOOL_COL_ID">N°</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_TYPE">Type</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_TYPE_ASYNC">Asynchrone</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_TYPE_SYNC">Synchrone</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_DATE">Date</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_DURATION">Durée</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_SIZE">Taille</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_RETURN">Retour</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_RETURN_OK">Ok</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_RETURN_CANCELED">Annulé</message>
+    <message key="REQUESTSTRACKER_TOOL_COL_RETURN_FAILURE">Echec</message>
+    
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_ID">N°</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_READABLE_TYPE">Type</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_READABLE_VALUE">Appel</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_READABLE_VAL1">Méthode</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_READABLE_VAL2">Url</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_WORKSPACE">Workspace</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_PLUGIN">Plugin</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_URL">Adresse</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_CCROLE">Rôle extension</message> 
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_CCID">Id composant</message> 
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_CCMETHOD">Méthode</message> 
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY">Priorité</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY_LONG_REQUEST">Longue</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY_SYNCHRONOUS">Synchone</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY_MAJOR">Majeure</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY_NORMAL">Normale</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY_MINOR">Mineure</message>
+    <message key="REQUESTSTRACKER_TOOL_MESSAGE_COL_TYPE">Retour</message>
+
+    <message key="REQUESTSTRACKER_TOOL_DISPLAYMESSAGE_URL">Url</message>
+    <message key="REQUESTSTRACKER_TOOL_DISPLAYMESSAGE_PARAMETERS">Paramètres</message>
+    <message key="REQUESTSTRACKER_TOOL_DISPLAYMESSAGE_RESPONSE">Réponse</message>
+
     <!-- +
          | Workspace
          + -->
-    <message key="WORKSPACE_AMETYS_MAIN_ERROR_NOJS">Cette application ne peut pas fonctionner en l'absence de javascript</message>
-    <message key="WORKSPACE_AMETYS_SPLASHSCREEN_LOADING">Chargement en cours. Veuillez patienter ... </message>
     <message key="WORKSPACE_AMETYS_SPLASHSCREEN_APP_AMETYS_VERSION">motorisé par Ametys </message>
          
 </catalogue>
Index: main/plugin-core/plugin.xml
===================================================================
--- main/plugin-core/plugin.xml	(revision 31744)
+++ main/plugin-core/plugin.xml	(working copy)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-   Copyright 2014 Anyware Services
+   Copyright 2015 Anyware Services
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
                 		 
@@ -1307,174 +1302,519 @@
+    <!-- +  
+         |  MESSAGES TRACKER    
+         + -->     
+    <feature name="userinterface.messages-tracker">
+        <extensions>
+            <extension id="org.ametys.runtime.userinterface.MessageTrackerControlMenu"
+                       point="org.ametys.runtime.ribbon.RibbonControlsManager"
+                       class="org.ametys.runtime.ui.SimpleMenu">
+                <class name="Ametys.ribbon.element.ui.button.OpenToolButtonController"/>
+                <menu-items>
+                    <item ref="org.ametys.runtime.userinterface.MessageTrackerControl" primaryItem="true"/>
+                    <item ref="org.ametys.runtime.userinterface.MessageTrackerControl.clear"/>
+                </menu-items>
+                <!-- right context-prefix="/contributor">CMS_Rights_MessageTracker</right> FIXME -->
+            </extension>
+            <extension id="org.ametys.runtime.userinterface.MessageTrackerControl"
+                       point="org.ametys.runtime.ribbon.RibbonControlsManager"
+                       class="org.ametys.runtime.ui.StaticClientSideElement">
+                <class name="Ametys.ribbon.element.ui.button.OpenToolButtonController">
+                    <opentool-role>uitool-messagestracker</opentool-role>
+                    
+                    <label i18n="true">PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_LABEL</label>
+                    <description i18n="true">PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_DESCRIPTION</description>
+                    <help>org.ametys.runtime.messagetracker</help>
+                    
+                    <icon-small file="true">img/messages/messages_16.png</icon-small>
+                    <icon-medium file="true">img/messages/messages_32.png</icon-medium>
+                    <icon-large file="true">img/messages/messages_48.png</icon-large>
+                </class>   
+                <!-- right context-prefix="/contributor">CMS_Rights_MessageTracker</right> FIXME -->                  
+            </extension>
+            <extension id="org.ametys.runtime.userinterface.MessageTrackerControl.clear"
+                       point="org.ametys.runtime.ribbon.RibbonControlsManager"
+                       class="org.ametys.runtime.ui.StaticClientSideElement">
+                <class name="Ametys.ribbon.element.ui.ButtonController">
+                    <action>Ametys.plugins.core.system.messagetracker.MessageTrackerTool.removeAll</action>
+
+                    <tool-role>uitool-messagestracker</tool-role>
+                    <tool-enable-on-status>active</tool-enable-on-status>
+                    <tool-description-inactive i18n="true">PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_CLEAR_DESCRIPTION2</tool-description-inactive>
+
+                    <label i18n="true">PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_CLEAR_LABEL</label>
+                    <description i18n="true">PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_CLEAR_DESCRIPTION</description>
+                    <icon-small file="true">img/messages/delete_16.gif</icon-small>
+                    <icon-medium file="true">img/messages/delete_16.gif</icon-medium>
+                    <icon-large file="true">img/messages/delete_16.gif</icon-large>
+                </class>                       
+                <scripts>
+                    <file>js/Ametys/plugins/core/system/messagetracker/MessageTrackerTool.js</file>
+                    <file>js/Ametys/plugins/core/system/messagetracker/MessageTrackerTool/MessageEntry.js</file>
+                </scripts>
+                <!-- right context-prefix="/contributor">CMS_Rights_MessageTracker</right> FIXME -->
+            </extension>
+            <extension id="org.ametys.runtime.userinterface.MessageTrackerFactory"
+                       point="org.ametys.runtime.ui.UIToolsFactoriesManager"
+                       class="org.ametys.runtime.ui.StaticClientSideElement">
+                <class name="Ametys.tool.factory.UniqueToolFactory">
+                    <role>uitool-messagestracker</role>
+                    <toolClass>Ametys.plugins.core.system.messagetracker.MessageTrackerTool</toolClass>
+                    
+                    <title i18n="true">PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_LABEL</title>
+                    <description i18n="true">PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_DESCRIPTION</description>
+                    <help>org.ametys.runtime.messagetracker</help>
+                    <icon-small file="true">img/messages/messages_16.png</icon-small>
+                    <icon-medium file="true">img/messages/messages_32.png</icon-medium>
+                    <icon-large file="true">img/messages/messages_48.png</icon-large>
+                    
+                    <default-location>b</default-location>
+                </class>
+                <scripts>
+                    <file>js/Ametys/plugins/core/system/messagetracker/MessageTrackerTool.js</file>
+                    <file>js/Ametys/plugins/core/system/messagetracker/MessageTrackerTool/MessageEntry.js</file>
+                </scripts>
+                <css>
+                    <file>css/messagetracker.css</file>
+                </css>
+            </extension>
+        </extensions>
+    </feature>
+    
+    <!-- +  
+         |  REQUESTS TRACKER    
+         + -->     
+    <feature name="userinterface.requests-tracker">
+        <extensions>
+            <extension id="org.ametys.runtime.userinterface.RequestTrackerControlMenu"
+                       point="org.ametys.runtime.ribbon.RibbonControlsManager"
+                       class="org.ametys.runtime.ui.SimpleMenu">
+                <class name="Ametys.ribbon.element.ui.button.OpenToolButtonController"/>
+                <menu-items>
+                    <item ref="org.ametys.runtime.userinterface.RequestTrackerControl" primaryItem="true"/>
+                    <item ref="org.ametys.runtime.userinterface.RequestTrackerControl.clear"/>
+                </menu-items>
+                <!-- right context-prefix="/contributor">CMS_Rights_MessageTracker</right> FIXME -->
+            </extension>
+            <extension id="org.ametys.runtime.userinterface.RequestTrackerControl"
+                       point="org.ametys.runtime.ribbon.RibbonControlsManager"
+                       class="org.ametys.runtime.ui.StaticClientSideElement">
+                <class name="Ametys.ribbon.element.ui.button.OpenToolButtonController">
+                    <opentool-role>uitool-requeststracker</opentool-role>
+                    
+                    <label i18n="true">PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_LABEL</label>
+                    <default-description i18n="true">PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_DESCRIPTION</default-description>
+                    <help>org.ametys.runtime.requesttracker</help>
+                    
+                    <icon-small file="true">img/requests/requests_16.png</icon-small>
+                    <icon-medium file="true">img/requests/requests_32.png</icon-medium>
+                    <icon-large file="true">img/requests/requests_48.png</icon-large>
+                </class> 
+                <!-- right context-prefix="/contributor">CMS_Rights_MessageTracker</right> FIXME -->                   
+            </extension>
+            <extension id="org.ametys.runtime.userinterface.RequestTrackerControl.clear"
+                       point="org.ametys.runtime.ribbon.RibbonControlsManager"
+                       class="org.ametys.runtime.ui.StaticClientSideElement">
+                <class name="Ametys.ribbon.element.ui.ButtonController">
+                    <action>Ametys.plugins.core.system.requesttracker.RequestTrackerTool.removeAll</action>
+                    
+                    <tool-role>uitool-requeststracker</tool-role>
+                    <tool-enable-on-status>active</tool-enable-on-status>
+                    <tool-description-inactive i18n="true">PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_CLEAR_DESCRIPTION2</tool-description-inactive>
+                    
+                    <label i18n="true">PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_CLEAR_LABEL</label>
+                    <description i18n="true">PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_CLEAR_DESCRIPTION</description>
+                    <description-footer i18n="true">PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_CLEAR_FOOTER</description-footer>
+                    <icon-small file="true">img/requests/delete_16.gif</icon-small>
+                    <icon-medium file="true">img/requests/delete_16.gif</icon-medium>
+                    <icon-large file="true">img/requests/delete_16.gif</icon-large>
+                </class>
+                <scripts>
+                    <file>js/Ametys/plugins/core/system/requesttracker/RequestTrackerTool.js</file>
+                    <file>js/Ametys/plugins/core/system/requesttracker/RequestTrackerTool/RequestEntry.js</file>
+                    <file>js/Ametys/plugins/core/system/requesttracker/RequestTrackerTool/MessageEntry.js</file>
+                </scripts>
+                <!-- right context-prefix="/contributor">CMS_Rights_MessageTracker</right> FIXME -->
+            </extension>
+            <extension id="org.ametys.runtime.userinterface.RequestTrackerFactory"
+                       point="org.ametys.runtime.ui.UIToolsFactoriesManager"
+                       class="org.ametys.runtime.ui.StaticClientSideElement">
+                <class name="Ametys.tool.factory.UniqueToolFactory">
+                    <role>uitool-requeststracker</role>
+                    <toolClass>Ametys.plugins.core.system.requesttracker.RequestTrackerTool</toolClass>
+                    
+                    <title i18n="true">PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_LABEL</title>
+                    <description i18n="true">PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_DESCRIPTION</description>
+                    <help>org.ametys.runtime.requesttracker</help>
+                    <icon-small file="true">img/requests/requests_16.png</icon-small>
+                    <icon-medium file="true">img/requests/requests_32.png</icon-medium>
+                    <icon-large file="true">img/requests/requests_48.png</icon-large>
+                    
+                    <default-location>b</default-location>
+                </class>               
+                <scripts>
+                    <file>js/Ametys/plugins/core/system/requesttracker/RequestTrackerTool.js</file>
+                    <file>js/Ametys/plugins/core/system/requesttracker/RequestTrackerTool/RequestEntry.js</file>
+                    <file>js/Ametys/plugins/core/system/requesttracker/RequestTrackerTool/MessageEntry.js</file>
+                </scripts>
+                <css>
+                    <file>css/requesttracker.css</file>
+                </css>
+            </extension>
+        </extensions>
+    </feature>
+    
     <!-- +
     	 |  VERSIONS
          + -->    
Index: main/plugin-core/resources/js/Ametys/plugins/core/system/messagetracker/MessageTrackerTool.i18n.js
===================================================================
--- main/plugin-core/resources/js/Ametys/plugins/core/system/messagetracker/MessageTrackerTool.i18n.js	(revision 0)
+++ main/plugin-core/resources/js/Ametys/plugins/core/system/messagetracker/MessageTrackerTool.i18n.js	(revision 0)
@@ -0,0 +1,204 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * This tool does display the message running on the message bus.
+ * @private
+ */
+Ext.define("Ametys.plugins.core.system.messagetracker.MessageTrackerTool",
+	{
+		extend: "Ametys.tool.Tool",
+		
+		statics: {
+			/**
+			 * This action find the unique instance of the message tracker tool, and removes all the entries
+			 */
+			removeAll: function()
+			{
+				var tool = Ametys.tool.ToolsManager.getTool("uitool-messagestracker");
+				if (tool != null)
+				{
+					tool.store.removeAll();
+				}
+				else
+				{
+					this.getLogger().error("Cannot remove entries from unexisting tool 'uitool-messsagestracker'")
+				}
+			}
+		},
+		
+		/**
+		 * @property {Ext.data.ArrayStore} store The store with the messages received
+		 * @private
+		 */
+		
+		/**
+		 * @property {Ext.grid.Panel} grid The grid panel displaying the messages
+		 * @private
+		 */
+		
+		constructor: function(config)
+		{
+			this.callParent(arguments);
+			
+			Ametys.message.MessageBus.on('*', this.onMessage, this);
+		},
+		
+		createPanel: function()
+		{
+			this.store = Ext.create("Ext.data.ArrayStore",{
+				autoDestroy: true,
+				autoSync: true,
+				proxy: { type: 'memory' },				
+				sorters: [{property: 'fireDate', direction:'DESC'}],
+				model: "Ametys.plugins.core.system.messagetracker.MessageTrackerTool.MessageEntry"
+		    });
+			
+			this.grid = Ext.create("Ext.grid.Panel", { 
+				stateful: true,
+				stateId: this.self.getName() + "$grid",
+				store: this.store,
+				autoScroll: true,
+			    columns: [
+			    	{stateId: 'grid-id', header: "<i18n:text i18n:key='PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_ID'/>", width: 40, sortable: true, dataIndex: 'id', hideable: false},
+			        {stateId: 'grid-creationdate', header: "<i18n:text i18n:key='PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_CREATIONDATE'/>", width: 120, sortable: true, renderer: Ext.util.Format.dateRenderer(Ext.Date.patterns.ShortDateTime), dataIndex: 'creationDate'},
+			        {stateId: 'grid-firedate', header: "<i18n:text i18n:key='PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_FIREDATE'/>", width: 120, sortable: true, renderer: Ext.util.Format.dateRenderer(Ext.Date.patterns.ShortDateTime), dataIndex: 'fireDate'},
+			        {stateId: 'grid-type', header: "<i18n:text i18n:key='PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_TYPE'/>", width: 200, sortable: true, dataIndex: 'type'},
+			        {stateId: 'grid-target', header: "<i18n:text i18n:key='PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_TARGET'/>", flex: 1, sortable: true, dataIndex: 'target'},
+			        {stateId: 'grid-callstack', header: "<i18n:text i18n:key='PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_COL_CALLSTACK'/>", flex: 0.5, sortable: true, hidden: true, dataIndex: 'callstack'}
+			    ]
+			});
+
+			return this.grid;
+		},
+
+		getMBSelectionInteraction: function() 
+		{
+		    return Ametys.tool.Tool.MB_TYPE_NOSELECTION;
+		},
+		
+		/**
+		 * The listener on all bus messages
+		 * @param {Ametys.message.Message} message The message received
+		 * @private
+		 */
+		onMessage: function(message)
+		{
+			var store = this.store;
+			try
+			{
+				var parametersAsString = Ext.JSON.prettyEncode(message.getParameters());
+				
+				var record = Ext.create("Ametys.plugins.core.system.messagetracker.MessageTrackerTool.MessageEntry", {
+					id: message.getNumber(),
+					creationDate: message.getCreationDate(),
+					fireDate: new Date(),
+					type: "<span style='font-weight: bold'>" + message.getType() + "</span>" + (parametersAsString ? ("<br/>" + parametersAsString) : ''),
+					target: this._targetsToString(message.getTargets()),
+					callstack: "<div class='callstack'>" + this._stackToString(message.getCallStack()) + "</div>"
+				});
+				store.addSorted(record);
+				// Scroll to the top of the panel
+				this.grid.getView().getEl().scrollTo('Top', 0, false);
+			}
+			catch (e)
+			{
+				this.getLogger().error({
+					message: "Cannot create the message entry",
+					details: e
+				});
+			};
+		},
+		
+		/**
+		 * Converts a stack as string as a readable html string
+		 * @param {String} stack The stack to convert. Cannot be null.
+		 * @private
+		 */
+		_stackToString: function(stack)
+		{
+			var stack2 = stack.replace(/\r?\n/g, "<br/>");
+			
+			var linesToRemove = 5; // remove useless stack due to extjs creation process
+			if (stack2.substring(0,5) == "Error")
+			{
+				linesToRemove++;
+			}
+			
+			for (var i = 0; i < linesToRemove; i ++)
+			{
+				stack2 = stack2.substring(stack2.indexOf("<br/>") + 5);
+			}
+			
+			var stack3 = "";
+		    Ext.each(stack2.split('<br/>'), function(node, index) 
+			    	{
+		    			// Firefox
+		    			node = node.replace(/^([^@]*)@(.*):([0-9])*$/, "<span class='method'>$1</span>@<a class='filename' href='$2' target='_blank'>$2</a>:<span class='line'>$3</span>");
+		    	
+		    			// IE - Chrome
+		    			node = node.replace(/^.*at (.*) \((.*):([0-9]*):([0-9]*)\).*$/, "at <span class='method'>$1</span> (<a class='filename' href='$2' target='_blank'>$2</a>:<span class='line'>$3</span>:<span class='line'>$4</span>)");
+		    			
+		    			stack3 += node + "<br/>"
+			    	}
+		    );
+		    return stack3.substring(0, stack3.length - 5); // remove last <br/>
+		},
+		
+		/**
+		 * Converts '@link Ametys.message.MessageTarget} to a readable string
+		 * @param {Ametys.message.MessageTarget[]} targets The message parameters to convert
+		 * @param {Number} [offset = 0] The offset to indent the text
+		 * @private
+		 */
+		_targetsToString: function (targets, offset)
+		{
+			offset = offset || 0;
+			
+			var s = "";
+			for (var i = 0; i < targets.length; i++)
+			{
+				var target = targets[i];
+				
+				if (offset != 0 && i != 0)
+				{
+					s += "<br/>";
+				}
+				
+				for (var j = 0; j < offset; j++)
+				{
+					s += "&#160;&#160;&#160;&#160;";
+				}
+				
+				s += "<span style='font-weight: bold'>" + target.getType() + "</span><br/>"
+				s += Ext.JSON.prettyEncode(target.getParameters(), offset);
+				
+				if (target.getSubtargets().length > 0)
+				{
+					s += "<br/>";
+				}
+				s += this._targetsToString(target.getSubtargets(), offset + 1);
+			}
+			
+			if (targets.length == 0 && offset == 0)
+			{
+				s = "<span style='color: #7f7f7f; font-style: italic;'><i18n:text i18n:key='PLUGINS_CORE_TOOLS_MESSAGES_TRACKER_TOOL_NOTARGET'/></span>";
+			}
+			
+			return s;
+		}
+	}
+);
Index: main/plugin-core/resources/js/Ametys/plugins/core/system/messagetracker/MessageTrackerTool/MessageEntry.js
===================================================================
--- main/plugin-core/resources/js/Ametys/plugins/core/system/messagetracker/MessageTrackerTool/MessageEntry.js	(revision 0)
+++ main/plugin-core/resources/js/Ametys/plugins/core/system/messagetracker/MessageTrackerTool/MessageEntry.js	(revision 0)
@@ -0,0 +1,32 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * This class is the model for entries in the grid of the message tracker tool
+ * @private
+ */
+Ext.define("Ametys.plugins.core.system.messagetracker.MessageTrackerTool.MessageEntry", {
+	extend: 'Ext.data.Model',
+	
+    fields: [
+             {name: 'id'},
+             {name: 'creationDate', type: 'date', dateFormat: 'Y-m-d'},
+             {name: 'fireDate', type: 'date', dateFormat: 'Y-m-d'},
+             {name: 'type'},
+             {name: 'target'},
+             {name: 'callstack'}
+    ]
+});
\ No newline at end of file
Index: main/plugin-core/resources/js/Ametys/plugins/core/system/requesttracker/RequestTrackerTool.i18n.js
===================================================================
--- main/plugin-core/resources/js/Ametys/plugins/core/system/requesttracker/RequestTrackerTool.i18n.js	(revision 0)
+++ main/plugin-core/resources/js/Ametys/plugins/core/system/requesttracker/RequestTrackerTool.i18n.js	(revision 0)
@@ -0,0 +1,600 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * This tool does display the message running on the message bus.
+ * @private
+ */
+Ext.define("Ametys.plugins.core.system.requesttracker.RequestTrackerTool",
+	{
+		extend: "Ametys.tool.Tool",
+		
+		statics: {
+			/**
+			 * This action find the unique instance of the message tracker tool, and removes all the entries
+			 */
+			removeAll: function()
+			{
+				var tool = Ametys.tool.ToolsManager.getTool("uitool-requeststracker");
+				if (tool != null)
+				{
+					tool.store.removeAll();
+				}
+				else
+				{
+					this.getLogger().error("Cannot remove entries from unexisting tool 'uitool-requeststracker'");
+				}
+			}
+		},
+		
+		/**
+		 * @property {Number} _currentId The current identifier. Each request displayed will show an identifier
+		 * @private
+		 */
+		
+		/**
+		 * @property {Ext.data.ArrayStore} store The store with the requests sent
+		 * @private
+		 */
+		
+		/**
+		 * @property {Ext.grid.Panel} grid The grid panel displaying the requests
+		 * @private
+		 */
+		
+		constructor: function()
+		{
+			this.callParent(arguments);
+			this._currentId = 1;
+			
+			Ametys.data.ServerComm._observer = this;
+		},
+		
+		createPanel: function()
+		{
+			this.store = Ext.create("Ext.data.ArrayStore",{
+				sorters: [{property: 'id', direction:'DESC'}],
+				model: "Ametys.plugins.core.system.requesttracker.RequestTrackerTool.RequestEntry",
+				autoDestroy: true,
+				autoSync: true,
+				proxy: { type: 'memory' }
+		    });
+			
+			this.grid = Ext.create("Ext.grid.Panel", { 
+				region: 'center',
+				stateful: true,
+				stateId: this.self.getName() + "$grid",
+				store: this.store,
+				autoScroll: true,
+			    columns: [
+			        {stateId: 'grid-id', header: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_COL_ID'/>", width: 40, sortable: true, dataIndex: 'id', hideable: false},
+			        {stateId: 'grid-type', header: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_COL_TYPE'/>", width: 70, sortable: true, dataIndex: 'type'},
+			        {stateId: 'grid-date', header: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_COL_DATE'/>", width: 130, sortable: true, renderer: Ext.util.Format.dateRenderer(Ext.Date.patterns.ShortDateTime), dataIndex: 'date'},
+			        {stateId: 'grid-duration', header: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_COL_DURATION'/>", width: 50, sortable: true, dataIndex: 'duration'},
+			        {stateId: 'grid-size', header: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_COL_SIZE'/>", width: 60, sortable: true, dataIndex: 'size'},
+			        {stateId: 'grid-return', header: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_COL_RETURN'/>", width: 50, sortable: true, dataIndex: 'return'}
+			    ],
+			    
+			    listeners: {'selectionchange': Ext.bind(this._onSelectRequest, this)}
+			});
+
+			
+			this.msgStore = Ext.create("Ext.data.ArrayStore",{
+				sorters: [{property: 'id', direction:'DESC'}],
+				model: "Ametys.plugins.core.system.requesttracker.RequestTrackerTool.MessageEntry",
+				autoDestroy: true,
+				autoSync: true,
+				proxy: { type: 'memory' }
+		    });
+			
+			this.msgGrid = Ext.create("Ext.grid.Panel", { 
+				region: 'south',
+				height: 120,
+				stateful: true,
+				stateId: this.self.getName() + "$msggrid",
+				split: true,
+				store: this.msgStore,
+				autoScroll: true,
+			    columns: [
+			        {stateId: 'msgrid-id', header: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_ID'/>", width: 40, sortable: true, dataIndex: 'id', hideable: false},
+			        {stateId: 'msgrid-readabletype', header: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_READABLE_TYPE'/>", width: 70, sortable: true, dataIndex: 'readableCallType', renderer: Ext.bind(this._renderCallType, this)},
+			        {stateId: 'msgrid-readablevalue', header: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_READABLE_VALUE'/>", width: 250, sortable: true, dataIndex: 'readableCallValue'},
+			        {stateId: 'msgrid-plugin', header: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_PLUGIN'/>", width: 70, sortable: true, hidden: true, dataIndex: 'plugin'},
+			        {stateId: 'msgrid-workspace', header: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_WORKSPACE'/>", width: 70, sortable: true, hidden: true, dataIndex: 'workspace'},
+			        {stateId: 'msgrid-url', header: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_URL'/>", width: 180, sortable: true, hidden: true, dataIndex: 'url'},
+			        {stateId: 'msgrid-ccrole', header: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_CCROLE'/>", width: 180, sortable: true, hidden: true, dataIndex: 'clientCallRole'},
+			        {stateId: 'msgrid-ccid', header: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_CCID'/>", width: 180, sortable: true, hidden: true, dataIndex: 'clientCallId'},
+			        {stateId: 'msgrid-ccmethod', header: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_CCMETHOD'/>", width: 180, sortable: true, hidden: true, dataIndex: 'clientCallMethod'},
+			        {stateId: 'msgrid-priority', header: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY'/>", width: 60, sortable: true, dataIndex: 'priority'},
+			        {stateId: 'msgrid-type', header: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_TYPE'/>", width: 50, sortable: true, dataIndex: 'type'}
+			    ],
+			    
+			    listeners: {'selectionchange': Ext.bind(this._onSelectMessage, this) }
+			});
+			
+			this.leftPanel = Ext.create("Ext.Panel", {
+				region: 'west',
+				layout: 'border',
+				stateful: true,
+				stateId: this.self.getName() + "$leftPanel",
+				split: true,
+				width: 500,
+				items: [ this.grid, this.msgGrid ]
+			});
+			
+			this.rightPanel = Ext.create("Ext.Panel", {
+				region: 'center',
+				layout: 'fit',
+				autoScroll: true,
+				cls: 'message-details',
+				defaultHtml: "<i18n:text i18n:key='PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_MESSAGE'/>",
+				html: "<i18n:text i18n:key='PLUGINS_CORE_TOOLS_REQUESTS_TRACKER_MESSAGE'/>"
+			});
+			
+			this._messageTpl = new Ext.Template(
+					"<b><i18n:text i18n:key='REQUESTSTRACKER_TOOL_DISPLAYMESSAGE_URL'/></b> : ",
+					"{url}<br/><br/>",
+					"<b><i18n:text i18n:key='REQUESTSTRACKER_TOOL_DISPLAYMESSAGE_PARAMETERS'/></b> : ",
+					"<code class='resquest-tracker'>{parameters}</code><br/>",
+					"<b><i18n:text i18n:key='REQUESTSTRACKER_TOOL_DISPLAYMESSAGE_RESPONSE'/></b> : ",
+					"<code class='resquest-tracker'>{response}</code>"
+			);
+			return Ext.create("Ext.Panel", {
+				layout: 'border',
+				stateful: true,
+				stateId: this.self.getName() + "$mainPanel",
+				items: [ this.leftPanel, this.rightPanel ]
+			});
+		},
+		
+		/**
+		 * @private
+		 * The renderer for the call column
+	     * @param {Object} value The data value for the current cell
+	     * @param {Object} metaData A collection of metadata about the current cell; can be used or modified by the renderer. Recognized properties are: tdCls, tdAttr, and style.
+	     * @param {Ext.data.Model} record The record for the current row
+	     * @param {Number} rowIndex The index of the current row
+	     * @param {Number} colIndex The index of the current column
+	     * @param {Ext.data.Store} store The data store
+	     * @param {Ext.view.View} view The current view
+	     * @return {String} The HTML string to be rendered.
+	     */
+		_renderCallType: function(value, metaData, record, rowIndex, colIndex, store, view)
+		{
+			if (record.get('readableCallType'))
+			{
+				return "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_READABLE_VAL1'/>";
+			}
+			else
+			{
+				return "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_READABLE_VAL2'/>";
+			}
+		},
+		
+		getMBSelectionInteraction: function() 
+		{
+		    return Ametys.tool.Tool.MB_TYPE_NOSELECTION;
+		},
+		
+		/**
+		 * Listener on the main grid panel, when selecting a record
+		 * @param {Ext.selection.RowModel} selModel The selection mode
+		 * @param {Ext.data.Model[]} records The record selected
+		 * @param {Object} eOpts The options object passed to Ext.util.Observable.addListener.
+		 * @private
+		 */
+		_onSelectRequest: function (selModel, records, eOpts)
+		{
+			this.msgStore.removeAll();
+			
+			function getClientCallInfo(message)
+			{
+				if (message && message.url == "client-call" && message.plugin == "core")
+				{
+					return {
+						role: message.parameters ? message.parameters.role : null,
+						id: message.parameters ? message.parameters.id : null,
+						method: message.parameters ? message.parameters.methodName : null
+					}
+				}
+				else
+				{
+					return {
+						role: null,
+						id: null
+					}
+				}
+			}
+			
+			var messages = records.length > 0 ? records[0].get("messages") : [];
+			var response = records.length > 0 ? records[0].get("response") : null;
+			for (var i = 0; i < messages.length; i++)
+			{
+				var message = messages[i];
+				var clientCallInfo = getClientCallInfo(message);
+				if (message.priority != null)
+				{
+					var priority = "";
+					switch (message.priority)
+					{
+						case Ametys.data.ServerComm.PRIORITY_MAJOR: priority = "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY_MAJOR'/>"; break;
+						case Ametys.data.ServerComm.PRIORITY_NORMAL: priority = "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY_NORMAL'/>"; break;
+						case Ametys.data.ServerComm.PRIORITY_MINOR: priority = "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY_MINOR'/>"; break;
+						case Ametys.data.ServerComm.PRIORITY_SYNCHRONOUS: priority = "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY_SYNCHRONOUS'/>"; break;
+						case Ametys.data.ServerComm.PRIORITY_LONG_REQUEST: priority = "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY_LONG_REQUEST'/>"; break;
+						default: priority = message.priority;
+					}
+					
+					var r = Ext.create("Ametys.plugins.core.system.requesttracker.RequestTrackerTool.MessageEntry", {
+						id: i,
+						plugin: message.plugin,
+						workspace: message.workspace,
+						url: this._removeGetParameters(message.url),
+						priority: priority,
+						type: message.responseType,
+						clientCallRole: clientCallInfo.role,
+						clientCallId: clientCallInfo.id,
+						clientCallMethod: clientCallInfo.method,
+						message: message,
+						response: response
+					});
+					this.msgStore.addSorted(r);
+				}
+				else
+				{
+					var r = Ext.create("Ametys.plugins.core.system.requesttracker.RequestTrackerTool.MessageEntry", {
+						id: 0,
+						plugin: message.plugin,
+						workspace: message.workspace,
+						url: this._removeGetParameters(message.url),
+						priority: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_MESSAGE_COL_PRIORITY_SYNCHRONOUS'/>",
+						type: message.responseType,
+						clientCallRole: clientCallInfo.role,
+						clientCallId: clientCallInfo.id,
+						clientCallMethod: clientCallInfo.method,
+						message: message,
+						response: response
+					});
+					this.msgStore.addSorted(r);
+				}
+			}
+		},
+		
+		/**
+		 * Listener on the south grid panel (details in a request), when selecting a record
+		 * @param {Ext.selection.RowModel} selModel The selection mode
+		 * @param {Ext.data.Model} records The record selected
+		 * @param {Object} eOpts The options object passed to Ext.util.Observable.addListener.
+		 * @private
+		 */
+		_onSelectMessage: function (selModel, records, eOpts)
+		{
+			if (records.length > 0)
+			{
+				var record = records[0];
+				var id = record.getId();
+				var message = record.get("message");
+				var response = record.get("response");
+				
+				var parametersAsString = Ext.JSON.prettyEncode(message.parameters);
+				var responseAsString = this._responseToString(response, id); 
+				this.rightPanel.body.update(this._messageTpl.applyTemplate({url: message.url, parameters: parametersAsString, response: responseAsString}));
+			}
+			else
+			{
+				this.rightPanel.body.update(this.rightPanel.defaultHtml);
+			}
+		},
+		
+		/**
+		 * Display a part of the response as a readable string
+		 * @param {Object} response The XMLHTTPResponse
+		 * @param {String} id The id of the part of the response to extract and display
+		 * @private
+		 */
+		_responseToString: function(response, id)
+		{
+			if (response == null)
+			{
+				return "null";
+			}
+			else
+			{
+				function xmlstringToHTML(xmlstring)
+				{
+					function escape(htmlstring)
+					{
+						return htmlstring.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/\r\n/g, '<br/>').replace(/&amp;#160;/g, '&#160;');
+					}
+					function escapeOpening(tagstring)
+					{
+						return "<span class='tag'>" + tagstring.replace(/( [^=]+)(=)(\"[^"]*\")/g, "<span class='attr-name'>$1</span><span class='attr-eq'>$2</span><span class='attr-value'>$3</span>") + "</span>";
+					}
+					function escapeText(textstring, pad)
+					{
+						var json = Ext.JSON.decode(textstring, true)
+						if (json != null)
+						{
+							var ppad = parseInt(pad/ 2) + 1;
+							textstring = Ext.JSON.prettyEncode(json, ppad);
+							if (textstring.indexOf("<br/>") != -1)
+							{
+								var padding = "";
+						        for (var i = 0; i < ppad; i++) 
+						        {
+						            padding += '&#160;&#160;&#160;&#160;';
+						        }
+								textstring = "<br/>" + padding + textstring + "<br/>";
+							}
+						}
+						
+						return "<span class='text'>" + textstring + "</span>";
+					}
+					function escapeClosing(tagstring)
+					{
+						return "<span class='tag'>" + tagstring + "</span>";
+					}
+					
+				    var formatted = '';
+				    xml = xmlstring.replace(/(>)(<)(\/*)/g, '$1\r\n$2$3');
+				    var pad = 0;
+				    Ext.each(xml.split('\r\n'), function(node, index) 
+				    	{
+					        var indent = 0;
+					        if (node.match( /.+<\/\w[^>]*>$/ )) 
+					        {
+					        	// full tag <test>foo</test>
+					        	node = escape(node);
+					        	
+					        	var i = node.indexOf('>');
+					        	var j = node.indexOf('&lt;', i+1);
+					        	node = escapeOpening(node.substring(0, i+1)) 
+					        			+ escapeText(node.substring(i+1, j), pad) 
+					        			+ escapeClosing(node.substring(j));
+					            indent = 0;
+					        } 
+					        else if (node.match( /^<\/\w/ )) 
+					        {
+					        	// just a closing tag </test>
+					        	node = escape(node);
+					        	node = escapeClosing(node);
+					            if (pad != 0) 
+					            {
+					                pad -= 1;
+					            }
+					        } 
+					        else if (node.match( /^<\w[^>]*[^\/]>.*$/ )) 
+					        {
+					        	// just an opening tag <test attr="1">
+					        	node = escape(node);
+					        	node = escapeOpening(node);
+					            indent = 1;
+					        } 
+					        else 
+					        {
+					        	// autoclosing tags <test/>
+					        	node = escape(node);
+					        	node = escapeOpening(node);
+					            indent = 0;
+					        }
+					 
+					        var padding = '';
+					        for (var i = 0; i < pad; i++) 
+					        {
+					            padding += '&#160;&#160;';
+					        }
+					 
+					        formatted += padding + node + '<br/>';
+					        pad += indent;
+				    	}
+				    );
+				 
+				    return formatted;
+				}
+				
+				var node = Ext.dom.Query.selectNode("/responses/response[@id='" + id + "']", response.responseXML);
+				if (node.outerHTML)
+				{
+					return xmlstringToHTML(node.outerHTML);
+				}
+				else
+				{
+					try 
+					{
+						// Gecko- and Webkit-based browsers (Firefox, Chrome), Opera.
+						return xmlstringToHTML((new XMLSerializer()).serializeToString(node));
+					}
+					catch (e) 
+					{
+						try 
+						{
+							// Internet Explorer.
+							return xmlstringToHTML(xmlNode.xml);
+						}
+						catch (e) {  
+							//Other browsers without XML Serializer
+							return "..."
+						}
+					}
+				}
+			}
+		},
+		
+		
+		/**
+		 * Remove the GET request parameters from the url
+		 * @param url The url 
+		 * @returns The request url without the GET paramters
+		 * @private
+		 */
+		_removeGetParameters: function (url)
+		{
+			var i = url.indexOf("?");
+			if (i == -1) return url;
+			else return url.substring(0, i);
+		},
+		
+		/**
+		 * Observer of the Ametys.data.ServerComm for sent request
+		 * @param {Object} sendOptions The options used in Ametys.data.ServerComm#_sendMessages 
+		 */
+		onRequestDeparture: function (sendOptions)
+		{
+			var store = this.store;
+			try
+			{
+				var id = this._currentId++;
+				
+				var record = Ext.create("Ametys.plugins.core.system.requesttracker.RequestTrackerTool.RequestEntry", {
+					id: id,
+					type: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_COL_TYPE_ASYNC'/>",
+					date: new Date(),
+					duration: "...",
+					"return": "...",
+					size: sendOptions.messages.length,
+					messages: sendOptions.messages,
+					response: null
+				});
+				store.addSorted(record);
+				// Scroll to the top of the panel
+				this.grid.getView().getEl().scrollTo('Top', 0, false);
+				
+				sendOptions.observerId = id;
+			}
+			catch (e)
+			{
+				this.getLogger().error({
+					message: "Cannot create the request entry",
+					details: e
+				})
+			};
+		},
+		
+		/**
+		 * Observer of the Ametys.data.ServerComm for request back
+		 * @param {Object} sendOptions The options used in Ametys.data.ServerComm#_sendMessages 
+		 * @param {Number} responseType 0 for success, 1 for canceled and 2 for failure
+		 * @param {Object} [response] The XMLHTTPResponse when available
+		 */
+		onRequestArrival: function (sendOptions, responseType, response)
+		{
+			var store = this.store;
+			try
+			{
+				var record = this.store.query("id", sendOptions.observerId).getAt(0);
+				record.set("duration", (new Date().getTime() - record.get("date").getTime()) / 1000.0);
+				record.set("response", response);
+				switch (responseType)
+				{
+					case 0:
+						record.set("return", "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_COL_RETURN_OK'/>"); 
+						break;
+					case 1:
+						record.set("return", "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_COL_RETURN_CANCELED'/>");
+						break;
+					case 2:
+						record.set("return", "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_COL_RETURN_FAILURE'/>");
+						break;
+				}
+				record.commit();
+			}
+			catch (e)
+			{
+				this.getLogger().error({
+					message: "Cannot update the request entry",
+					details: e
+				})
+			};
+		},
+
+		/**
+		 * Observer of the Ametys.data.ServerComm for sent synchronous request
+		 * @param {Object} message The message sent. Argument of Ametys.data.ServerComm#_sendSynchronousMessage
+		 */
+		onSyncRequestDeparture: function (message)
+		{
+			var store = this.store;
+			try
+			{
+				var id = this._currentId++;
+				
+				window.setTimeout(function() {
+					var record = Ext.create("Ametys.plugins.core.system.requesttracker.RequestTrackerTool.RequestEntry", {
+						id: id,
+						type: "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_COL_TYPE_SYNC'/>",
+						date: new Date(),
+						duration: "...",
+						"return": "...",
+						size: 1,
+						messages: [message]
+					});
+					store.addSorted(record);
+					
+				}, 1);
+				message.observerId = id;
+			}
+			catch (e)
+			{
+				this.getLogger().error({
+					message: "Cannot create the request entry",
+					details: e
+				})
+			};
+		},
+		
+		/**
+		 * Observer of the Ametys.data.ServerComm back from a synchronous request
+		 * @param {Object} message The message sent. Argument of Ametys.data.ServerComm#_sendSynchronousMessage
+		 * @param {Number} responseType 0 for success and 2 for failure
+		 * @param {Object} [response] The XMLHTTPResponse when available
+		 */
+		onSyncRequestArrival: function (message, responseType, response)
+		{
+			var store = this.store;
+			try
+			{
+				window.setTimeout(function() {
+					var record = store.query("id", message.observerId).getAt(0);
+					record.set("duration", (new Date().getTime() - record.get("date").getTime()) / 1000.0);
+					record.set("response", response);
+					switch (responseType)
+					{
+						case 0:
+							record.set("return", "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_COL_RETURN_OK'/>"); 
+							break;
+						case 2:
+							record.set("return", "<i18n:text i18n:key='REQUESTSTRACKER_TOOL_COL_RETURN_FAILURE'/>");
+							break;
+					}
+					record.commit();
+				}, 1);
+			}
+			catch (e)
+			{
+				this.getLogger().error({
+					message: "Cannot update the request entry",
+					details: e
+				})
+			};
+		},
+		
+		onClose: function ()
+		{
+			this.callParent(arguments);
+			Ametys.data.ServerComm._observer = {};
+		}
+	}
+);
Index: main/plugin-core/resources/js/Ametys/plugins/core/system/requesttracker/RequestTrackerTool/MessageEntry.js
===================================================================
--- main/plugin-core/resources/js/Ametys/plugins/core/system/requesttracker/RequestTrackerTool/MessageEntry.js	(revision 0)
+++ main/plugin-core/resources/js/Ametys/plugins/core/system/requesttracker/RequestTrackerTool/MessageEntry.js	(revision 0)
@@ -0,0 +1,62 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * This class is the model for entries in the sub grid of the request tracker tool
+ * @private
+ */
+Ext.define("Ametys.plugins.core.system.requesttracker.RequestTrackerTool.MessageEntry", {
+	extend: 'Ext.data.Model',
+	
+    fields: [
+        {name: 'id'},
+        {
+        	name: 'readableCallType', //True if the value to display is 'REQUESTSTRACKER_TOOL_MESSAGE_COL_READABLE_VAL1', 
+        								//false if 'REQUESTSTRACKER_TOOL_MESSAGE_COL_READABLE_VAL2'
+        	
+        	calculate: function(data) 
+        	{
+        		return (data.url == "client-call" && data.plugin == "core");
+        	}
+        },
+        {
+        	name: 'readableCallValue',
+        	
+        	calculate: function(data) 
+        	{
+	        	if (data.url == "client-call" && data.plugin == "core")
+				{
+					return data.message.parameters.id + " # " + data.message.parameters.methodName;
+				}
+				else
+				{
+					return (data.workspace ? ("_" + data.workspace) : ('plugins/' + data.plugin)) + "/" + data.url;
+				}
+        	}
+        },
+        {name: 'plugin'},
+        {name: 'workspace'},
+        {name: 'url'},
+        {name: 'clientCallRole'},
+        {name: 'clientCallId'},
+        {name: 'clientCallMethod'},
+        {name: 'url'},
+        {name: 'priority'},
+        {name: 'type'},
+        {name: 'message'},
+        {name: 'response'}
+    ]
+});
\ No newline at end of file
Index: main/plugin-core/resources/js/Ametys/plugins/core/system/requesttracker/RequestTrackerTool/RequestEntry.js
===================================================================
--- main/plugin-core/resources/js/Ametys/plugins/core/system/requesttracker/RequestTrackerTool/RequestEntry.js	(revision 0)
+++ main/plugin-core/resources/js/Ametys/plugins/core/system/requesttracker/RequestTrackerTool/RequestEntry.js	(revision 0)
@@ -0,0 +1,34 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * This class is the model for entries in the grid of the request tracker tool
+ * @private
+ */
+Ext.define("Ametys.plugins.core.system.requesttracker.RequestTrackerTool.RequestEntry", {
+	extend: 'Ext.data.Model',
+	
+    fields: [
+		{name: 'id'},
+		{name: 'type'},
+		{name: 'date', type: 'date', dateFormat: 'Y-m-d'},
+		{name: 'duration'},
+		{name: 'return'},
+		{name: 'size'},
+		{name: 'messages'},
+		{name: 'response'}
+    ]
+});
Index: main/plugin-core/resources/css/messagetracker.css
===================================================================
--- main/plugin-core/resources/css/messagetracker.css   (revision 0)
+++ main/plugin-core/resources/css/messagetracker.css   (revision 0)
@@ -0,0 +1,30 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+ 
+.callstack .filename {
+   color: #2a00ff;
+   text-decoration: none;
+}
+.callstack .filename:hover {
+    text-decoration: underline;
+}
+.callstack .line {
+   color: #9500ab;
+    font-style: italic;
+}
+.callstack .method {
+    color: #3f7f7f;
+}
Index: main/plugin-core/resources/css/requesttracker.css
===================================================================
--- main/plugin-core/resources/css/requesttracker.css   (revision 0)
+++ main/plugin-core/resources/css/requesttracker.css   (revision 0)
@@ -0,0 +1,49 @@
+/*
+ *  Copyright 2015 Anyware Services
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+.message-details .x-panel-body {
+   padding: 5px;
+   font-family:Arial;
+   font-size:11px;
+   padding: 10px;
+   background-color: #FFF !important;
+}
+
+.message-details .x-panel-body div {
+   padding: 0 0 0 10px;
+}
+
+code.resquest-tracker {
+   color: #000000;
+   white-space: nowrap;
+   display: block;
+}
+code.resquest-tracker .tag {
+    color: #3f7f7f;
+}
+code.resquest-tracker .text {
+    color: #000000;
+}
+code.resquest-tracker .attr-name {
+   color: #9500ab;
+}
+code.resquest-tracker .attr-eq {
+    color: #000000;
+}
+code.resquest-tracker .attr-value {
+    color: #2a00ff;
+    font-style: italic;
+}
