Présentation du flux de travail associé au contenu protégé

Flash Player 10.1 et les versions ultérieures, Adobe AIR 2.0 et les versions ultérieures

Important : Flash Player 11.5 et les versions ultérieures intègrent le module Adobe Access ; l’étape de mise à jour (l’appel de SystemUpdater.update(SystemUpdaterType.DRM) ) est donc inutile. Les navigateurs et plates-formes suivants sont concernés :

  • Contrôle ActiveX Flash Player 11.5, pour toutes les plates-formes à l’exception d’Internet Explorer sous Windows 8 sur les processeurs Intel

  • Plug-in Flash Player 11.5, pour tous les navigateurs

  • Adobe AIR (version de bureau et version mobile)

L’étape de mise à jour est toujours requise dans les cas suivants :

  • Internet Explorer sous Windows 8 sur les processeurs Intel

  • Flash Player 11.4 et versions antérieures, à l’exception de Google Chrome 22 et des versions ultérieures (toutes les plates-formes) ou de Google Chrome 21 et des versions ultérieures (Windows)

Remarque : vous pouvez toujours appeler SystemUpdater.update(SystemUpdaterType.DRM) sur un système doté de Flash Player 11.5 ou d’une version ultérieure, mais rien n’est téléchargé.

Le flux de travail de haut niveau suivant indique comment une application peut récupérer et lire du contenu protégé. Il part du principe que l’application est conçue spécifiquement pour lire un contenu protégé par Adobe Access :

  1. Récupérez les métadonnées du contenu.

  2. Exécutez les mises à jour de Flash Player, s’il y a lieu.

  3. Vérifiez si une licence est disponible localement. Si tel est le cas, chargez-la et passez à l’étape 7. Dans le cas contraire, passez à l’étape 4.

  4. Vérifiez si l’authentification est obligatoire. Dans le cas contraire, passez à l’étape 7.

  5. Si l’authentification est obligatoire, demandez les informations d’identification à l’utilisateur et transmettez-les au serveur de licences.

  6. Si l’enregistrement de domaine est requis, joignez le domaine (AIR 3.0 et versions ultérieures).

  7. Lorsque l’authentification aboutit, téléchargez la licence du serveur.

  8. Lisez le contenu.

Si aucune erreur n’est survenue et si l’utilisateur a été autorisé à visionner le contenu, l’objet NetStream distribue un objet DRMStatusEvent. L’application procède alors à la lecture. L’objet DRMStatusEvent mémorise les informations relatives au voucher, qui identifient les régulations et autorisations de l’utilisateur. Il contient par exemple des informations relatives à la disponibilité du contenu hors connexion ou à la date d’expiration de la licence. L’application peut utiliser ces données pour avertir l’utilisateur de l’état de ses régulations. Elle peut par exemple afficher dans une barre d’état le nombre de jours restants pendant lesquels l’utilisateur est autorisé à visionner le contenu.

Si l’utilisateur est autorisé à accéder au contenu hors connexion, le voucher est mis en mémoire cache et le contenu chiffré est téléchargé sur la machine de l’utilisateur. L’utilisateur peut accéder au contenu pendant le nombre de jours défini dans la durée de mise en mémoire cache de la licence. La propriété detail de l’événement contient "DRM.voucherObtained" . L’application décide de l’emplacement local de stockage du contenu pour assurer sa disponibilité hors connexion. Vous pouvez également précharger les vouchers à l’aide de la classe DRMManager.

Remarque : la mise en mémoire cache et le préchargement de vouchers sont pris en charge dans AIR et dans Flash Player. Néanmoins, le téléchargement et le stockage du contenu chiffré sont pris en charge uniquement dans AIR.

C’est l’application elle-même qui est chargée de gérer explicitement les événements d’erreur, notamment lorsque l’utilisateur saisit correctement ses informations d’identification, mais que le voucher qui protège le contenu chiffré limite l’accès au contenu. Un utilisateur authentifié ne peut par exemple pas accéder au contenu s’il ne s’est pas acquitté des droits. Ce cas peut également se produire lorsque deux membres inscrits du même éditeur tentent de partager du contenu que seul l’un d’entre eux a payé. L’application doit informer l’utilisateur de l’erreur et proposer une solution de remplacement. Par exemple, l’application peut donner à l’utilisateur des instructions sur le mode d’inscription et de paiement des droits d’affichage.

Flux de travail détaillé des API

Ce flux de travail illustre de manière plus détaillée le flux de travail associé à un contenu protégé. Il décrit les API impliquées dans la lecture du contenu protégé par Adobe Access.

  1. Par le biais d’un objet URLLoader, chargez les octets du fichier de métadonnées du contenu protégé. Définissez cet objet sur une variable, telle que metadata_bytes .

    Tout contenu contrôlé par Adobe Access contient des métadonnées Adobe Access. Lorsque le contenu est mis en package, ces métadonnées peuvent être enregistrées dans un fichier de métadonnées distinct (.metadata) parallèlement au contenu. Pour plus d’informations, voir la documentation d’Adobe Access.

  2. Créez une occurrence de DRMContentData. Placez ce code dans un bloc try-catch :

    new DRMContentData( metadata_bytes )

    metadata_bytes est l’objet URLLoader obtenu à l’étape 1.

  3. (Flash Player uniquement) Le moteur d’exécution recherche le module Adobe Access. S’il ne le trouve pas, une erreur IllegalOperationError avec le code d’erreur DRMErrorEvent 3344 ou DRMErrorEvent 3343 est renvoyée.

    Pour gérer cette erreur, téléchargez le module Adobe Access à l’aide de l’API SystemUpdater. Une fois ce module téléchargé, l’objet SystemUpdater distribue un événement COMPLETE. Définissez un écouteur d’événement qui retourne à l’étape 2 lors de la distribution de cet événement. Le code suivant illustre ces étapes :

    flash.system.SystemUpdater.addEventListener(Event.COMPLETE, updateCompleteHandler); 
    flash.system.SystemUpdater.update(flash.system.SystemUpdaterType.DRM)
    private function updateCompleteHandler (event:Event):void { 
        /*redo step 2*/ 
        drmContentData = new DRMContentData(metadata_bytes); 
    } 

    Si le lecteur en tant que tel doit être mis à jour, un événement d’état est distribué. Pour plus d’informations sur la gestion de cet événement, voir Ecoute d’un événement de mise à jour .

    Remarque : dans les applications AIR, le programme d’installation AIR gère la mise à jour du module Adobe Access et les mises à jour du moteur d’exécution requises.
  4. Créez des écouteurs qui écoutent les événements DRMStatusEvent et DRMErrorEvent distribués par l’objet DRMManager :

    DRMManager.addEventListener(DRMStatusEvent.DRM_STATUS, onDRMStatus); 
    DRMManager.addEventListener(DRMErrorEvent.DRM_ERROR, onDRMError);

    Dans l’écouteur d’événements DRMStatusEvent, vérifiez que le voucher est valide (valeur autre que null). Dans l’écouteur d’événements DRMErrorEvent, gérez les événements DRMErrorEvents. Voir Utilisation de la classe DRMStatusEvent et Utilisation de la classe DRMErrorEvent .

  5. Chargez le voucher (la licence) requis pour lire le contenu.

    Essayez tout d’abord de charger une licence stockée localement pour lire le contenu :

    DRMManager.loadvoucher(drmContentData, LoadVoucherSetting.LOCAL_ONLY)

    Une fois le chargement terminé, l’objet DRMManager distribue DRMStatusEvent.DRM_Status .

  6. Si l’objet DRMVoucher possède une valeur autre que null, le voucher est valide. Passez à l’étape 13.

  7. Si l’objet DRMVoucher est défini sur null, vérifiez la méthode d’authentification requise par la régulation associée au contenu. Faites appel à la propriété DRMContentData.authenticationMethod .

  8. Si la méthode d’authentification est ANONYMOUS , passez à l’étape 13.

  9. Si la méthode d’authentification est USERNAME_AND_PASSWORD , l’application doit intégrer un mécanisme permettant à l’utilisateur d’entrer des informations d’identification. Transmettez ces informations d’identification au serveur de licences pour authentifier l’utilisateur :

    DRMManager.authenticate(metadata.serverURL, metadata.domain, username, password)

    DRMManager distribue un événement DRMAuthenticationErrorEvent si l’authentification échoue, un événement DRMAuthenticationCompleteEvent si elle aboutit. Associez des écouteurs à ces événements.

  10. Si la méthode d’authentification est UNKNOWN , une méthode d’authentification personnalisée doit être utilisée. Dans ce cas, le fournisseur de contenu a prévu d’exécuter l’authentification hors bande, c’est-à-dire de ne pas utiliser les API ActionScript 3.0. La procédure d’authentification personnalisée doit produire un jeton d’authentification qu’il est possible de transmettre à la méthode DRMManager.setAuthenticationToken() .

  11. Si l’authentification échoue, l’application doit retourner à l’étape 9. Assurez-vous que l’application intègre un mécanisme permettant de gérer et restreindre les échecs successifs d’authentification. Après trois tentatives, vous pouvez, par exemple, afficher un message indiquant à l’utilisateur que l’authentification a échoué et qu’il est impossible de lire le contenu.

  12. Pour utiliser le jeton stocké au lieu d’inviter l’utilisateur à entrer des informations d’identification, définissez-le à l’aide de la méthode DRMManager.setAuthenticationToken() . Téléchargez ensuite la licence à partir du serveur de licences et lisez le contenu (voir étape 8).

  13. (Facultatif) Si l’authentification aboutit, vous pouvez capturer le jeton d’authentification, à savoir un tableau d’octets placé en mémoire cache. Récupérez ce jeton à l’aide de la propriété DRMAuthenticationCompleteEvent.token . Vous pouvez stocker et utiliser le jeton d’authentification pour éviter à l’utilisateur d’avoir à entrer plusieurs fois les informations d’identification associées au contenu. Le serveur de licences détermine la période de validité du jeton d’authentification.

  14. Si l’authentification aboutit, téléchargez la licence du serveur de licences :

    DRMManager.loadvoucher(drmContentData, LoadVoucherSetting.FORCE_REFRESH)

    Une fois le chargement terminé, l’objet DRMManager distribue l’événement DRMStatusEvent.DRM_STATUS. Ecoutez cet événement. Une fois ce dernier distribué, vous pouvez lire le contenu.

  15. Lisez la vidéo en créant un objet NetStream, puis en appelant sa méthode play() :

    stream = new NetStream(connection); 
    stream.addEventListener(DRMStatusEvent.DRM _STATUS, drmStatusHandler); 
    stream.addEventListener(DRMErrorEvent.DRM_ERROR, drmErrorHandler); 
    stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); 
    stream.client = new CustomClient(); 
    video.attachNetStream(stream); 
    stream.play(videoURL); 

Objets DRMContentData et objets session

Lors de la création d’un objet DRMContentData , celui-ci est utilisé en tant qu’objet session qui fait référence au module DRM de Flash Player. Toutes les API DRMManager qui reçoivent cet objet DRMContentData utilisent ce module DRM particulier. Il existe néanmoins deux API DRMManager qui n’utilisent pas l’objet DRMContentData . Voici ces règles :
  1. authenticate()

  2. setAuthenticationToken()

Etant donné qu’il n’existe aucun objet DRMContentData associé, l’invocation de ces API DRMManager fait appel au module DRM le plus récent du disque. Cela peut être problématique si une mise à jour du module DRM se produit au cours du flux de travail du DRM de l’application. Tenez compte du scénario suivant :
  1. L’application crée un objet DRMContentData contentData1 , qui utilise AdobeCP1 comme module DRM.

  2. L’application invoque la méthode DRMManager.authenticate(contentData1.serverURL,...) .

  3. L’application invoque la méthode DRMManager.loadVoucher(contentData1, ...) .

Si une mise à jour du module DRM se produit avant que l’application ne puisse accéder à l’étape 2, la méthode DRMManager.authenticate() finit par effectuer l’authentification à l’aide du module DRM AdobeCP2 . La méthode loadVoucher() de l’étape 3 échoue, car elle utilise toujours le module DRM AdobeCP1 . Il est possible que la mise à jour ait eu lieu suite à l’invocation de la mise à jour du module DRM par une autre application. Vous pouvez éviter ce scénario en invoquant la mise à jour du module DRM au démarrage de l’application.

Evénements DRM

Le moteur d’exécution distribue un grand nombre d’événements lorsqu’une application essaie de lire un contenu protégé :

  • DRMDeviceGroupErrorEvent (AIR uniquement), distribué par DRMManager

  • DRMAuthenticateEvent (AIR uniquement), distribué par NetStream

  • DRMAuthenticationCompleteEvent, distribué par DRMManager

  • DRMAuthenticationErrorEvent, distribué par DRMManager

  • DRMErrorEvent, distribué par NetStream et DRMManager

  • DRMStatusEvent, distribué par NetStream et DRMManager

  • StatusEvent

  • NetStatusEvent (voir Ecoute d’un événement de mise à jour )

Pour prendre en charge un contenu protégé par Adobe Access, associez des écouteurs aux événements DRM.

Préchargement de vouchers pour une lecture hors connexion

Vous pouvez précharger les vouchers (licences) requis pour lire le contenu protégé par Adobe Access. Les vouchers préchargés permettent aux utilisateurs de visionner le contenu même si leur connexion Internet n’est pas active. (Le processus de préchargement à proprement parler requiert une connexion à Internet.) Faites appel à la méthode preloadEmbeddedMetadata() de la classe NetStream et à la classe DRMManager pour précharger les vouchers. Dans AIR 2.0 et les versions ultérieures, vous pouvez précharger directement des vouchers par le biais d’un objet DRMContentData. Il est préférable d’utiliser cette technique, car elle permet de mettre à jour l’objet DRMContentData indépendamment du contenu. (La méthode preloadEmbeddedData() extrait l’objet DRMContentData du contenu.)

Utilisation de l’objet DRMContentData

La procédure ci-dessous décrit le préchargement du voucher associé à un fichier multimédia protégé par le biais d’un objet DRMContentData.

  1. Extrayez les métadonnées binaires associées au contenu mis en package. Si vous utilisez Adobe Access Java Reference Packager, ce fichier de métadonnées est automatiquement généré avec une extension .metadata . Vous pourriez, par exemple, télécharger ces métadonnées à l’aide de la classe URLLoader.

  2. Créez un objet DRMContentData en transmettant les métadonnées à la fonction constructeur :

    var drmData:DRMContentData = new DRMContentData( metadata );
  3. Les autres étapes sont identiques au flux de travail décrit à la section Présentation du flux de travail associé au contenu protégé .

Utilisation de preloadEmbeddedMetadata()

La procédure suivante décrit le préchargement du voucher associé à un fichier multimédia protégé par DRM par le biais de preloadEmbeddedMetadata() :

  1. Téléchargez et stockez le fichier multimédia. (Il est uniquement possible de précharger les métadonnées du module DRM à partir des fichiers enregistrés localement.)

  2. Créez les objets NetConnection et NetStream, en fournissant des implémentations pour les fonctions de rappel onDRMContentData() et onPlayStatus() de l’objet client NetStream.

  3. Créez un objet NetStreamPlayOptions et définissez la propriété stream sur l’URL du fichier multimédia local.

  4. Appelez la méthode NetStream preloadEmbeddedMetadata() , en transmettant l’objet NetStreamPlayOptions identifiant le fichier multimédia à analyser.

  5. Si le fichier multimédia contient des métadonnées DRM, la fonction de rappel onDRMContentData() est invoquée. Les métadonnées sont transmises à cette fonction sous forme d’objet DRMContentData.

  6. Utilisez l’objet DRMContentData pour obtenir le voucher à l’aide de la méthode DRMManager loadVoucher() .

    Si la valeur de la propriété authenticationMethod de l’objet DRMContentData est flash.net.drm.AuthenticationMethod.USERNAME_AND_PASSWORD , authentifiez l’utilisateur sur le serveur de droits multimédias avant de charger le voucher. Les propriétés serverURL et domain de l’objet DRMContentData peuvent être transmis à la méthode DRMManager authenticate() , de même que les informations d’identification de l’utilisateur.

  7. La fonction de rappel onPlayStatus() est invoquée lorsque l’analyse du fichier est terminée. Si la fonction onDRMContentData() n’a pas été appelée, le fichier ne contient pas les métadonnées nécessaires à l’obtention d’un voucher. L’absence de cet appel peut également signifier qu’Adobe Access ne protège pas ce fichier.

L’exemple de code pour AIR suivant illustre le préchargement d’un voucher associé à un fichier multimédia local :

package 
{ 
import flash.display.Sprite; 
import flash.events.DRMAuthenticationCompleteEvent; 
import flash.events.DRMAuthenticationErrorEvent; 
import flash.events.DRMErrorEvent;   
import flash.ev ents.DRMStatusEvent; 
import flash.events.NetStatusEvent; 
import flash.net.NetConnection; 
import flash.net.NetStream; 
import flash.net.NetStreamPlayOptions; 
import flash.net.drm.AuthenticationMethod; 
import flash.net.drm.DRMContentData; 
import flash.net.drm.DRMManager; 
import flash.net.drm.LoadVoucherSetting;   
public class DRMPreloader extends Sprite  
{ 
     private var videoURL:String = "app-storage:/video.flv"; 
    private var userName:String = "user"; 
    private var password:String = "password";  
    private var preloadConnection:NetConnection; 
    private var preloadStream:NetStream; 
    private var drmManager:DRMManager = DRMManager.getDRMManager(); 
    private var drmContentData:DRMContentData; 
    public function DRMPreloader():void { 
        drmManager.addEventListener( 
            DRMAuthenticationCompleteEvent.AUTHENTICATION_COMPLETE, 
            onAuthenticationComplete); 
        drmManager.addEventListener(DRMAuthenticationErrorEvent.AUTHENTICATION_ERROR, 
            onAuthenticationError);             
        drmManager.addEventListener(DRMStatusEvent.DRM_STATUS, onDRMStatus); 
        drmManager.addEventListener(DRMErrorEvent.DRM_ERROR, onDRMError); 
        preloadConnection = new NetConnection(); 
        preloadConnection.addEventListener(NetStatusEvent.NET_STATUS, onConnect); 
        preloadConnection.connect(null);            
    } 
 
    private function onConnect( event:NetStatusEvent ):void 
    { 
        preloadMetadata(); 
    } 
    private function preloadMetadata():void 
    { 
        preloadStream = new NetStream( preloadConnection ); 
        preloadStream.client = this; 
        var options:NetStreamPlayOptions = new NetStreamPlayOptions(); 
        options.streamName = videoURL; 
        preloadStream.preloadEmbeddedData( options );                         
    }     
    public function onDRMContentData( drmMetadata:DRMContentData ):void 
    { 
        drmContentData = drmMetadata; 
        if ( drmMetadata.authenticationMethod == AuthenticationMethod.USERNAME_AND_PASSWORD ) 
        { 
            authenticateUser(); 
        } 
        else 
            { 
                getVoucher(); 
            } 
    } 
    private function getVoucher():void 
    { 
        drmManager.loadVoucher( drmContentData, LoadVoucherSetting.ALLOW_SERVER ); 
    } 
 
    private function authenticateUser():void 
    { 
        drmManager.authenticate( drmContentData.serverURL, drmContentData.domain, userName, password ); 
    } 
    private function onAuthenticationError( event:DRMAuthenticationErrorEvent ):void 
    { 
        trace( "Authentication error: " + event.errorID + ", " + event.subErrorID ); 
    } 
 
    private function onAuthenticationComplete( event:DRMAuthenticationCompleteEvent ):void 
    { 
        trace( "Authenticated to: " + event.serverURL + ", domain: " + event.domain ); 
        getVoucher(); 
    } 
    private function onDRMStatus( event:DRMStatusEvent ):void 
    { 
        trace( "DRM Status: " + event.detail); 
        trace("--Voucher allows offline playback = " + event.isAvailableOffline ); 
        trace("--Voucher already cached          = " + event.isLocal ); 
        trace("--Voucher required authentication = " + !event.isAnonymous ); 
    } 
    private function onDRMError( event:DRMErrorEvent ):void 
    { 
        trace( "DRM error event: " + event.errorID + ", " + event.subErrorID + ", " + event.text ); 
    } 
    public function onPlayStatus( info:Object ):void 
    { 
        preloadStream.close(); 
    } 
} 
}