Programmation entre contenus de différents domaines

Adobe AIR 1.0 et les versions ultérieures

Les applications AIR disposent de privilèges spéciaux lorsqu’elles sont installées. Il est essentiel que les mêmes privilèges ne soient pas dévoilés à un autre contenu, y compris les fichiers distants et les fichiers locaux qui ne font pas partie de l’application.

A propos du pont de sandbox AIR

Généralement, le contenu d’un autre domaine ne peut pas appeler de scripts d’autres domaines. Pour protéger les applications AIR d’une divulgation accidentelle d’informations ou de contrôles privilégiés, les restrictions suivantes sont placées dans le contenu du sandbox de sécurité de l'application (contenu installé avec l’application) :

  • Le code dans le sandbox de sécurité de l’application ne peut pas autoriser l’accès aux autres sandbox par un appel à la méthode Security.allowDomain() . L’appel à cette méthode depuis le sandbox de sécurité de l’application renvoie une erreur.

  • Il est impossible d’importer un contenu hors application dans un sandbox de l’application en paramétrant la propriété LoaderContext.securityDomain ou LoaderContext.applicationDomain .

Il subsiste encore des situations où l’application AIR principale demande un contenu à partir du domaine distant pour avoir un accès contrôlé à des scripts de celle-ci, ou vice-versa. Pour ce faire, le moteur d’exécution fournit un mécanisme de pont de sandbox qui sert de passerelle entre deux sandbox. Un pont de sandbox peut fournir une interaction explicite entre sandbox de sécurité distant et d’application.

Le pont de sandbox présente deux objets auxquels les scripts chargés et en cours de chargement peuvent tous deux accéder :

  • L’objet parentSandboxBridge permet au contenu en cours de chargement de présenter des propriétés et des fonctions à des scripts du contenu chargé.

  • L’objet childSandboxBridge permet au contenu chargé de présenter des propriétés et des fonctions à des scripts dans le contenu en cours de chargement.

Ce sont les valeurs et non les références qui sont transmises par le pont de sandbox. Toutes les données sont sérialisées. Ce qui signifie que les objets présentés par l’un des côtés du pont ne peuvent pas être définis par l’autre et qu’aucun des objets présentés n’est typé. De plus, vous ne pouvez présenter que des objets et des fonctions simples (pas complexes).

Si le contenu enfant tente de définir une propriété de l’objetparentSandboxBridge, le moteur d’exécution renvoie une exception SecurityError. De même, si le contenu parent tente de définir une propriété de l’objetchildSandboxBridge, le moteur d’exécution renvoie une exception SecurityError.

Exemple de pont de sandbox (SWF)

Supposez qu’une application de disquaire AIR souhaite autoriser des fichiers distants à diffuser le prix des albums, mais qu’il ne souhaite pas que le fichier SWF distant dévoile s’il s’agit d’un prix de vente. Pour ce faire, une classe StoreAPI fournit une méthode d’acquisition de prix tout en masquant le prix de vente. Une occurrence de cette classe StoreAPI est alors affectée à la propriété parentSandboxBridge de l’objet LoaderInfo dont l’objet Loader charge le fichier SWF distant.

Voici le code pour le disquaire AIR :

<?xml version="1.0" encoding="utf-8"?> 
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" title="Music Store" creationComplete="initApp()"> 
    <mx:Script> 
        import flash.display.Loader; 
        import flash.net.URLRequest; 
     
        private var child:Loader; 
        private var isSale:Boolean = false; 
         
        private function initApp():void { 
            var request:URLRequest =  
                    new URLRequest("http://[www.yourdomain.com]/PriceQuoter.swf") 
 
            child = new Loader(); 
            child.contentLoaderInfo.parentSandboxBridge = new StoreAPI(this); 
            child.load(request); 
            container.addChild(child); 
        } 
        public function getRegularAlbumPrice():String { 
            return "$11.99"; 
        } 
        public function getSaleAlbumPrice():String { 
            return "$9.99"; 
        } 
        public function getAlbumPrice():String { 
            if(isSale) { 
                return getSaleAlbumPrice(); 
            } 
            else { 
                return getRegularAlbumPrice();     
            } 
        } 
    </mx:Script> 
    <mx:UIComponent id="container" /> 
</mx:WindowedApplication> 

L’objet StoreAPI appelle l’application principale pour récupérer le prix courant de l’album mais renvoie « Non disponible » lorsque la méthode getSaleAlbumPrice() est appelée. Le code ci-dessous définit la classe StoreAPI :

public class StoreAPI 
{ 
    private static var musicStore:Object; 
     
    public function StoreAPI(musicStore:Object) 
    { 
        this.musicStore = musicStore; 
    } 
 
    public function getRegularAlbumPrice():String { 
        return musicStore.getRegularAlbumPrice(); 
    } 
     
    public function getSaleAlbumPrice():String { 
        return "Not available"; 
    } 
     
    public function getAlbumPrice():String { 
        return musicStore.getRegularAlbumPrice();     
    } 
}

Le code suivant représente un exemple d’un fichier SWF PriceQuoter qui rend compte du prix du disquaire mais pas de celui de la vente.

package 
{ 
    import flash.display.Sprite; 
    import flash.system.Security; 
    import flash.text.*; 
     
    public class PriceQuoter extends Sprite 
    { 
        private var storeRequester:Object; 
         
        public function PriceQuoter() { 
            trace("Initializing child SWF"); 
            trace("Child sandbox: " + Security.sandboxType); 
            storeRequester = loaderInfo.parentSandboxBridge; 
             
            var tf:TextField = new TextField(); 
            tf.autoSize = TextFieldAutoSize.LEFT; 
            addChild(tf); 
             
            tf.appendText("Store price of album is: " + storeRequester.getAlbumPrice()); 
            tf.appendText("\n"); 
            tf.appendText("Sale price of album is: " + storeRequester.getSaleAlbumPrice()); 
        } 
    } 
}

Exemple de pont de sandbox (HTML)

Dans un contenu HTML, les propriétés parentSandboxBridge et childSandboxBridge sont ajoutées à l’objet Window de JavaScript d’un document enfant. Pour un exemple sur la façon de configurer des fonctions de pont dans un contenu HTML, voir la section Configuration d’une interface de pont de sandbox .

Limitation de l’exposition de l’interface de programmation

Lorsque vous présentez des ponts de sandbox, il est important de présenter des interfaces de programmation de haut niveau qui limitent le degré d’exposition à des abus. Nous vous rappelons que le contenu qui appelle votre implémentation de pont peut être en danger (par exemple, par une injection de code). Ainsi, par exemple, la présentation de la méthode readFile(path:String) (qui lit le contenu d’un fichier arbitraire) par un pont est exposé à un risque. Il serait préférable de présenter une interface de programmation readApplicationSetting() qui ne suit pas un chemin mais qui lit un fichier spécifique. L’approche plus sémantique limite les dommages qu’une application peut causer dès qu’une de ses parties est affectée.