Contournement des erreurs JavaScript liées à la sécurité

Adobe AIR 1.0 et les versions ultérieures

Si vous appelez du code interdit d’exécution dans un sandbox en raison de ces restrictions liées à la sécurité, le moteur d’exécution distribue une erreur JavaScript : « Violation des règles de sécurité dans le sandbox de sécurité de l’application par le moteur d’exécution d’Adobe AIR sur du code JavaScript ». Pour éviter cette erreur, suivez les règles de codage suivantes.

Causes des erreurs JavaScript liées à la sécurité

Le code qui s’exécute dans le sandbox de l’application ne peut pas exécuter des opérations qui impliquent l’évaluation et l’exécution de chaînes dès le moment où l’événement load est lancé et que les gestionnaires d’événement load ne sont plus actifs. Les tentatives d’utilisation des types suivants d’instructions JavaScript, qui évaluent et exécutent des chaînes potentiellement non protégées, génèrent des erreurs JavaScript.

Mappage du contenu de l’application dans un sandbox différent

Le plus souvent, vous pouvez réécrire ou restructurer une application pour éviter des erreurs JavaScript liées à la sécurité. Toutefois, lorsque la réécriture ou la restructuration s’avèrent impossibles, vous pouvez charger le contenu de l’application dans un sandbox différent à l’aide de la technique décrite à la section Chargement du contenu de l’application dans un sandbox hors application. Si ce contenu doit également accéder aux interfaces de programmation d’AIR, vous pouvez créer un pont de sandbox, tel que décrit à la section Configuration d’une interface de pont de sandbox.

eval(), fonction

Dans le sandbox de l’application, la fonction eval() ne peut être utilisée qu’avant l’exécution de l’événement load de page ou qu’en cours d’exécution d’un gestionnaire d’événement load. Après le chargement de la page, les appels à eval() n’exécuteront pas de code. Toutefois, dans les situations suivantes, il vous est possible de réécrire le code pour éviter d’utiliser eval().

Affectation des propriétés à un objet

Au lieu d’analyser une chaîne pour construire l’accesseur propriété :

eval("obj." + propName + " = " + val);

accédez aux propriétés par une notation crochets :

obj[propName] = val;

Création d’une fonction avec des variables disponibles dans le contexte

Remplacez les instructions telles que les suivantes :

function compile(var1, var2){ 
    eval("var fn = function(){ this."+var1+"(var2) }"); 
    return fn; 
}

par :

function compile(var1, var2){ 
    var self = this; 
    return function(){ self[var1](var2) }; 
}

Création d’un objet à l’aide du nom de la classe comme paramètre de chaîne

Considérez une classe de JavaScript hypothétique définie de la manière suivante :

var CustomClass =  
    { 
        Utils: 
        { 
            Parser: function(){ alert('constructor') } 
        }, 
        Data:  
        { 
         
        } 
    }; 
var constructorClassName = "CustomClass.Utils.Parser";

La façon la plus simple de créer une occurrence consisterait à utiliser eval() :

var myObj; 
eval('myObj=new ' + constructorClassName +'()')

Toutefois, vous pouvez éviter l’appel à eval() en analysant chaque composant du nom de la classe et en construisant le nouvel objet à l’aide de la notation crochets :

function getter(str) 
{ 
    var obj = window; 
    var names = str.split('.'); 
    for(var i=0;i<names.length;i++){ 
        if(typeof obj[names[i]]=='undefined'){ 
            var undefstring = names[0]; 
            for(var j=1;j<=i;j++) 
                undefstring+="."+names[j]; 
            throw new Error(undefstring+" is undefined"); 
        } 
        obj = obj[names[i]]; 
    } 
    return obj; 
}

Pour créer l’occurrence, utilisez :

try{ 
    var Parser = getter(constructorClassName); 
    var a = new Parser(); 
    }catch(e){ 
        alert(e); 
}

setTimeout() et setInterval()

Remplacez la chaîne passée en tant que fonction gestionnaire avec une référence de fonction ou un objet de fonction. Par exemple, remplacez une instruction telle que :

setTimeout("alert('Timeout')", 100);

par :

setTimeout(function(){alert('Timeout')}, 100); 

Ou bien, lorsque la fonction demande que l’objet this soit paramétré par l’appelant, remplacez une instruction telle que :

this.appTimer = setInterval("obj.customFunction();", 100);

par ce qui suit :

var _self = this; 
this.appTimer = setInterval(function(){obj.customFunction.apply(_self);}, 100);

Constructeur Function

Les appels à new Function(param, body) peuvent être remplacés par une déclaration de fonction inline ou utilisés seulement avant que l’événement load de la page n’ait été traité.

javascript: URL

Le code défini dans un lien à l’aide du modèle javascript: URL est ignoré dans le sandbox de l’application. Aucune erreur JavaScript risquée n’est générée. Vous pouvez remplacer des liens à l’aide d’URL JavaScript: telles que :

<a href="javascript:code()">Click Me</a>

par :

<a href="#" onclick="code()">Click Me</a>

Rappels d’événements affectés par les attributs onevent dans les instructions innerHTML et outerHTML

Lorsque vous utilisez innerHTML ou outerHTML pour ajouter des éléments au DOM d’un document, tous les rappels d’événements affectés au sein de l’instruction, tels que onclick ou onmouseover sont ignorés. Aucun message d’erreur sur la sécurité n’est généré. A la place, vous pouvez affecter un attribut id aux nouveaux éléments et paramétrer les fonctions de rappel de gestionnaires d’événement à l’aide de la méthode addEventListener().

Par exemple, étant donné un élément-cible dans un document tel que :

<div id="container"></div>

Remplacez les instructions telles que :

document.getElementById('container').innerHTML =  
    '<a href="#" onclick="code()">Click Me.</a>';

par :

document.getElementById('container').innerHTML = '<a href="#" id="smith">Click Me.</a>'; 
document.getElementById('smith').addEventListener("click", function() { code(); });

Chargement de fichiers JavaScript à partir d’emplacements hors du répertoire d’installation de l’application

Le chargement de fichiers de script à partir d’emplacements hors du sandbox de l’application n’est pas autorisé. Aucun message d’erreur sur la sécurité n’est généré. Tous les fichiers de script qui s’exécutent dans le sandbox de l’application doivent être installés dans le répertoire de l’application. Pour utiliser des scripts externes dans une page, il vous faut mapper la page dans un sandbox distinct. Voir la section Chargement du contenu de l’application dans un sandbox hors application.

document.write() et document.writeln()

Les appels à document.write() ou document.writeln() sont ignorés après le traitement de l’événement load de la page. Aucun message d’erreur sur la sécurité n’est généré. Vous pouvez également charger un nouveau fichier ou remplacer le corps du document à l’aide des techniques de manipulation du DOM :

XMLHttpRequests synchrones lancées avant l’événement load ou au cours de l’exécution d’un gestionnaire d’événement load

Les XMLHttpRequests synchrones lancées avant l’événement load de la page ou au cours du traitement d’un événement load ne renvoient pas de contenu. Les XMLHttpRequests asynchrones peuvent être lancées, mais elles ne renvoient rien avant la fin de l’événementload. Après le traitement de l’événement load, les XMLHttpRequests synchrones se comportent normalement.

Eléments de script créés dynamiquement

Les éléments de script créés dynamiquement, tels ceux créés avec les méthodes innerHTML ou document.createElement() sont ignorés.