Forums : Xul, Xbl, JS...

Aller à la discussion :  Plus récente Plus ancienne

# XBL - bug binding asynchrone

Envoyé par : alexp

Date : 11/04/2006 19:52

Bonjour à tous,

J'ai passé pas mal de temps sur la fonction document.loadBindingDocument( <url du xbl> ), qui permet -normalement- de charger de manière synchrone le contenu d'un fichier XBL. Son comportement assez aléatoire m'a poussé à venir expliquer en détail les cas particuliers (bug?). Prenons l'exemple d'un XBL trivial qui possède juste une fonction test(), il est assez naturel de faire la chose suivante :

document.loadBindingDocument("monfichierxbl.xml");
var obj=document.createElement("monxbltrivial");
obj.test(); // erreur ici

Mais voilà ... ceci ne marche pas ! Heureusement, il existe une solution simple et logique : ajouter cet objet au document XUL :

document.loadBindingDocument("monfichierxbl.xml");
var obj=document.createElement("monxbltrivial");
document.documentElement.appendChild(obj);
obj.test();

Ceci marche MAIS seulement dans un certain cas, cette fois ci bien bizarre : il ne faut pas qu'il y ait de ressource feuille de style dans l'objet XBL !!! (c'est à dire <resources><stylesheet src="test.css" /></resources> )

Pour identifier ce comportement, j'ai réalisé les tests suivants :

function test(i) {
if (withcss.test)
	withcss.test(i);
if (withoutcss.test)
	withoutcss.test(i);
}
document.loadBindingDocument("test.xml");
withcss=document.createElement("withcss"); // XBL avec resources/stylesheet
withoutcss=document.createElement("withoutcss"); // XBL sans resources/stylesheet
test(1);
document.documentElement.appendChild(withcss);
document.documentElement.appendChild(withoutcss);
test(2); // OK uniquement pour withoutcss
window.setTimeout("test(3)",1000); // OK pour les deux

Donc si quelqu'un a déjà rencontré ce problème : existe-t-il une solution pour charger de manière synchrone ce type d'objet XBL ? Sinon, faut-il déclarer ce comportement comme un bug ?

# Re: XBL - bug binding asynchrone

Envoyé par : hhf

Date : 11/04/2006 23:19

pourquoi, ne declare tu pas le fichier xml dans le document : via une css ou via un style :

<html:style>
  withcss {
   -moz-binding: url('chrome://findfile/content/test.xml#withcss');
  }
  withoutcss {
   -moz-binding: url('chrome://findfile/content/test.xml#withoutcss');
  }
</html:style>

# Re: XBL - bug binding asynchrone

Envoyé par : alexp

Date : 11/04/2006 23:47

Je tourne trop longtemps autour de ce problème et je deviens de moins en moins clair ... Je déclare effectivement le binding par une CSS. Mais lorsque j'utilise un éléments XBL, celui ci n'est pas "bindé" immédiatement et celà me provoque des erreurs dûes à l'inexistances de certaines méthodes sur ces objets. En fait je n'utilise pas document.createElement dans mon application, sauf pour ce test, afin qu'il soit le plus simple possible.

Pour clarifier tout ça, voici l'ensemble des fichiers de mon test : index.xul :

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet href="index.css" type="text/css"?>
<window onload="init()" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" >
  <script type="application/x-javascript" src="script.js"/>
  <textbox multiline="true" rows="10" />
</window>

index.css :

withcss {
  -moz-binding:url("test.xml#withcss");
}
withoutcss {
  -moz-binding:url("test.xml#withoutcss");
}

test.xml :

<?xml version="1.0" encoding="ISO-8859-1"?>
<bindings xmlns="http://www.mozilla.org/xbl">
<binding id="withcss">
 <resources><stylesheet src="test.css" /></resources>
 <implementation>
  <method name="test"><parameter name="i" />
  <body>document.getElementsByTagName("textbox")[0].value+="withcss ok : "+i+"\n";</body>
  </method>
 </implementation>
</binding>
<binding id="withoutcss">
 <implementation>
  <method name="test"><parameter name="i" />
  <body>document.getElementsByTagName("textbox")[0].value+="withoutcss  ok : "+i+"\n";</body>
  </method>
 </implementation>
</binding>
</bindings>

script.js :

var withcss;
var withouscss;
function test(i) {
if (withcss.test)
	withcss.test(i);
if (withoutcss.test)
	withoutcss.test(i);
}
function init() { /* appelé au window:onload */
  document.loadBindingDocument("test.xml");
  withcss=document.createElement("withcss");
  withoutcss=document.createElement("withoutcss");
  test(1);
  document.documentElement.appendChild(withcss);
  document.documentElement.appendChild(withoutcss);
  test(2);
  window.setTimeout("test(3)",1000);
}

test.css : Fichier vide.

résultat affiché :

withoutcss ok : 2
withcss ok : 3
withoutcss ok : 3

Si vous voulez tester ce mini script, je laisse un accès -temporaire- ici

# Re: XBL - bug binding asynchrone

Envoyé par : alexp

Date : 12/04/2006 14:23

Suite à quelques tests complémentaires, il s'avère que ce bug :
chargement asynchrone des xbl AVEC resources/stylesheet avec l'utilisation de loadBindingDocument
n'existe que dans le cas d'une application distante. (ça marche très bien dans le cas d'une application xulrunner)

A tester maintenant, le cas d'une application signée ... il y'a de fortes chances que ça marche! Alors faut-il déclarer ce comportement comme un bug ?

# Re: XBL - bug binding asynchrone

Envoyé par : laurentj

Date : 12/04/2006 18:26

alors, quelques précisions conçernant xbl.

Premièrement, pour qu'un binding s'applique, il faut qu'effectivement l'element concerné soit présent dans le document. En effet, une feuille de style (et donc par conséquence les bindings) s'applique sur un document, pas sur un element crée tout seul avec createElement.

Deuxièmement : il y a nécessairement un temps de latence, entre le moment où tu insere ton élement dans le document, et le moment où le binding est appliqué. En particulier, quand celui-ci est distant : le temps de le télécharger, et ensuite de l'appliquer (j'imagine que si en plus ce binding comporte sa propre feuille de style, cela doit être plus long)... Sachant que tout ceci se fait de manière asynchrone.

Bref, rien n'est instantanné, et c'est pour cela que tenter d'acceder à une methode du xbl juste aprés l'insertion de l'element, cela a de fortes chances d'échouer.

En conclusion : c'est un comportement normal.

En fait, il manque la possibilité d'être informé quand le binding est prêt.. (mais on peut se débrouiller en emettant un event dans le constructeur du binding...)

# Re: XBL - bug binding asynchrone

Envoyé par : alexp

Date : 12/04/2006 19:19

Merci Laurent pour cette réponse détaillée.

Pour moi, ce comportement asynchrone est -normal- dans le cas où on n'utilise pas la fonction loadBindingDocument. Voici tout d'abord ce qu'on peut trouver sur la référence XBL 1.0 :

An author can ensure that all bindings are synchronously attached by calling 
loadBindingDocument to pre-fetch any XBL documents that are required. If the binding 
document is loaded prior to the firing of the load event, then any binding attachments 
that are placed following the load will be synchronous if they come from one of these 
previously loaded binding documents.
[http://www.w3.org/TR/xbl/#binding-documents]

Mais apparament mozilla n'a pas implémenté XBL 1.0 à 100%, car on peut trouver ceci sur le livre de référence mozilla :

Neither addBinding nor removeBinding are implemented at the time of writing. They are 
covered because they are part of the XBL 1.0 specification. When implemented, they offer 
crucial alternatives for attaching and detaching bindings, making XBL a more interactive 
technology.
loadBindingDocument(URL)
XBL documents are loaded only the first time a bound document uses a binding from it. You
 can get around this problem and load the binding documents synchronously by using this method. It returns an XBL document for use within a bound document. If your document is 
large and you need to optimize performance, this method may provide better performance. 
[http://books.mozdev.org/chapters/ch07.html#77047]

En effet, je n'ai pas réussi à faire marcher addBinding (et je ne suis pas le seul). Pourtant en regardant les sources C++ de firefox, on peut voir que addBinding est bel et bien implémenté !?

Donc pour résumé : loadBindingDocument, addBinding ... ça marche vraiment avec une application distante ? Ou ça plante (ou marche à moitié) sans message d'erreur ? (Je dis ça, car le comportement est normal par rapport à XBL1.0 du W3C sous xulRunner)

# Re: XBL - bug binding asynchrone

Envoyé par : alexp

Date : 12/04/2006 20:05

Suite au dernier message, j'ai regardé du côté xulRunner, et il s'avère que addBinding marche à une condition : indiquer les urls sous la forme chrome:/... Après un petit parcours dans les sources de mozilla, je suis tombé sur ça (dans la fonction nsXBLService:LoadBindings appelée par addBinding) :

 // Security check - remote pages can't load local bindings, except from chrome
 nsIURI *docURI = document->GetDocumentURI();
 PRBool isChrome = PR_FALSE;
 rv = docURI->SchemeIs("chrome", &isChrome);
  
 // Not everything with a chrome URI has a system principal.  See bug 160042.
 if (NS_FAILED(rv) || !isChrome) {
   nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
   rv = secMan->
     CheckLoadURIWithPrincipal(document->GetPrincipal(), aURL,
                               nsIScriptSecurityManager::ALLOW_CHROME);
   if (NS_FAILED(rv))
     return rv;
 }

Difficile de savoir exactement ce que celà fait, mais suite au comportement constaté et aux multiples vérifications d'uri dans nsXBLService ... je pense que les fonctions DOM/XBL ne fonctionnent correctement que dans le chrome.

Pour info, ceci marche très bien dans le chrome (xulrunner) :

var objetXBL=document.createElement("box");
document.addBinding(objetXBL,"chrome://bug/content/test.xml#withcss");
objetXBL.test(); 
// pas besoin d'ajouter l'objet à un document, 
// ni de loadBindingDocument, ni d'event, ... rien!

Apparament les chargements sont tous synchrones dans chrome (nsXBLService::LoadBindingDocumentInfo):

// Always load chrome synchronously
     PRBool chrome;
     if (NS_SUCCEEDED(documentURI->SchemeIs("chrome", &chrome)) && chrome)
       aForceSyncLoad = PR_TRUE;

# Re: XBL - bug binding asynchrone

Envoyé par : alexp

Date : 14/04/2006 17:33

Apparament, je ne suis pas le seul à remarquer ce défaut : message d'Alex Fritze sur la newsgroup xbl

Je viens de lui envoyer un message ...

Le post commence à être lourd et peu attirant !
On peut résumer la situation à :
loadBindingDocument ne marche pas lorsqu'il y a une feuille de style dans le XBL (<resources>/<stylesheet>)

Il n'est plus possible de poster des messages dans ce forum.


Copyright © 2003-2013 association xulfr, 2013-2016 Laurent Jouanneau - Informations légales.

Mozilla® est une marque déposée de la fondation Mozilla.
Mozilla.org™, Firefox™, Thunderbird™, Mozilla Suite™ et XUL™ sont des marques de la fondation Mozilla.