How to use pluggable DRM (HTML)

[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]

You can enable Digital Rights Management (DRM) protected content in your Windows Runtime app using JavaScript by using the MediaProtectionManager.

This topic assumes that you can create a basic Windows Runtime app using JavaScript. For help creating your first app, see Create your first Windows Store app using JavaScript.

The following steps describe how to play protected content on a computer by using the MediaProtectionManager API.

1. Create a MediaProtectionManager object.

This class allows your application to attach listeners to receive events that are fired.

The following code sample shows how to create a MediaProtectionManager object.

    var mediaProtectionManager = new Windows.Media.Protection.MediaProtectionManager();

2. Set the MediaProtectionManager.Properties property.

Use Properties property to provide information to the media protection system. Currently there are three properties that can be set.

  • Windows.Media.ContentProtection.VideoFrameAccessCertificate - a UINT 8 array that represents the application certificate for accessing frames in frame server mode.

  • Windows.Media.ContentProtection.ContentProtectionSystemId - a GUID that represents the protection system ID. This value determines which 3rd party protection system should be used to handle protected content in a WMDRM Advanced Streaming Format (ASF) file.

  • Windows.Media.ContentProtection.ContentProtectionSystemContext - a UINT 8 array that represents additional data that the application wants to pass to the protection system for the current content.

This example shows how to set the Properties property.

    mediaProtectionManager.properties["Windows.Media.Protection.MediaProtectionSystemId"] =
        '{F4637010-03C3-42CD-B932-B48ADF3A6A54}';
        // Microsoft.Media.PlayReadyClient.PlayReadyStatics.mediaProtectionSystemId;

3. Set the MediaProtectionManager on the HTML Video Tag or the XAML MediaElement.

Set the msSetMediaProtectionManager method to the instance of the video or audio tag.

The following code sample shows how to set the MediaProtectionManager on the video player.

    video.msSetMediaProtectionManager(mediaProtectionManager);

4. Handle the events.

Attach listeners to handle the events and implement the delegates to handle the protection tasks.

  • ComponentLoadFailed - fired when the load of binary data fails.

  • RebootNeeded - fired when a reboot is needed after the component is renewed.

  • ServiceRequested - fired when the content protection system encounters an issue and needs the application's help.

This example shows how to add event listeners.

    mediaProtectionManager.addEventListener("componentloadfailed", componentLoadFailed);
    mediaProtectionManager.addEventListener("servicerequested", serviceRequested);

Example

The following example shows how to set up the MediaProtectionManager to play back a media file.

var mpmCompletionNotifier;

function btnPlayOnClick()
{
    try
    {
        clearLog();

        var videoPlayer;
        var mediaProtectionManager;
        var mediaFilename;

        logMsg( 'Beginning playback attempt...' );

        videoPlayer = document.getElementById( 'video' );

        logMsg( '--- Setting up video player object' );
        videoPlayer.addEventListener.addEventListener( 'canplay', onCanPlay, false);
        videoPlayer.addEventListener( 'error', onPlayError, false);

        logMsg( '--- Creating new Windows.Media.Protection.MediaProtectionManager' );
        mediaProtectionManager = new Windows.Media.Protection.MediaProtectionManager();

        logMsg( '--- Setting up MediaProtectionManager' );
        mediaProtectionManager.addEventListener( "componentloadfailed", componentLoadFailed, false);
        mediaProtectionManager.addEventListener( "servicerequested", serviceRequested, false);
        mediaProtectionManager.properties["Windows.Media.Protection.MediaProtectionSystemId"] =
            '{F4637010-03C3-42CD-B932-B48ADF3A6A54}'; 
            // Microsoft.Media.PlayReadyClient.PlayReadyStatics.mediaProtectionSystemId;
       
        var registrar = new Windows.Media.MediaExtensionManager();

        registrar.registerByteStreamHandler('Microsoft.Media.PlayReadyClient.PlayReadyByteStreamHandler', '.asf', null);
        registrar.registerByteStreamHandler('Microsoft.Media.PlayReadyClient.PlayReadyByteStreamHandler', '.pyv', null);

        logMsg( '--- Setting MediaProtectionManager to video player' );
        videoPlayer.msSetMediaProtectionManager( mediaProtectionManager );
        
        //playback PR content which has been renamed to .asf
        //media content has been packed with application for now
        logMsg( '--- Setting player source' );
        mediaFilename = 'pr_006_1_01_v4_0_wmv.pyv.asf';
        videoPlayer.src = mediaFilename;
    }
    catch ( e )
    {
        // handle the error.
        logWarning( e, 'btnPlayOnClick' );       
    }
}

function onCanPlay()
{
    var videoPlayer = document.getElementById( 'video' );

    logMsg( 'Attempting to start playback' );

    try
    {
        videoPlayer.play();
    }
    catch ( e )
    {
        logWarning( e, 'onCanPlay' );
        // Handle the error.  
    }
}

function componentLoadFailed( e )
{
    try
    {
        logMsg( e.information.items.size + " failed components!" );
        logMsg( "Components:" );

        //  List the failing components
        for ( var i = 0; i < e.information.items.size; i++ )
        {
            logMsg( e.information.items[i].name + "\nReasons=0x" + e.information.items[i].reasons + '\n'
                                                + "Renewal Id=" + e.information.items[i].renewalId  );
        }

        e.completion.complete( false );
        logMsg( "Resumed source (false)" );
    }
    catch ( e )
    {
        logWarning( e, 'componentLoadFailed' );
        // Handle the error. 
    }
}

function serviceRequested( e )
{
    try
    {
        logMsg( "Service request required before playback can happen, service request type: " + getSRType( e.request ) );

        var serviceRequestOperation = e.request.operation;
        mpmCompletionNotifier = e.completion;
        logMsg( "--- Request type: " + getSRType( e.request )  );

        serviceRequestOperation.enablingActionRequired = function ( sender, enabler ){ onEnablingActionRequired( sender, enabler ); };

        if ( g_fUsePromises )
        {
            logMsg( '--- using promises model ( e.request.then(..) )' );        
            e.request.then( onPlaySRCompleted, onPlaySRError );
        }
        else
        {
            serviceRequestOperation.completed = function ( asyncOp ){ onPlaySRCompleted( asyncOp ); };
            serviceRequestOperation.start();
        }
    }
    catch ( e )
    {
        logWarning( e, 'serviceRequested' );
        // Handle error.  
    }
}

function onPlaySRCompleted( asyncOp )
{
    try
    {
        logMsg( 'Service Request completed with status: ' + getAsyncStatus( asyncOp )  );
        mpmCompletionNotifier.complete( true );
        logMsg( 'after mpmCompletionNotifier.complete( true )' );
    }
    catch ( e )
    {
        logWarning( e, 'onPlaySRCompleted' );
        taef_testFailed( e, 'onPlaySRCompleted', 'playback' );          
    }
}

function onPlaySRError( sender, e )
{
    logWarning( e, 'onPlaySRError' );      
}

function onPlayError( )
{
    logMsg( 'Play back failed' );     
}