none
[JavaScript][UWP][PlayReady] Hanging trying to call license server, PlayReadyLicenseAcquisitionServiceRequest.BeginServiceRequest RRS feed

  • Question

  • Hi,

    I am trying to get DRM working on a UWP JavaScript app.

    I followed the sample provided here https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/PlayReady with some slight modifications to suit the needs of the app.

    When I reach the step below in the function reactiveLicenseRequest the app hangs. I don't get any errors. None of the callbacks provided to 'then' get called. Looking at the HTTP traffic I do not see the license server being called at all.

    licenseRequest.beginServiceRequest().then(onServiceRequestSuccess, onServiceRequestError, onProgress);
    

    Without any sort of output I'm not sure what is happening or where things are hanging. Is this an issue anyone has come across before or any known ways of handling it.

    Thanks.

    Friday, September 6, 2019 10:42 PM

All replies

  • Hi,

    From your description, the request was not sent successfully, which could be an internal error.

    Please check your Request build process, we are not sure what changes you made.

    You can also try using the catch statement to see if you can catch the error, just like:


    licenseRequest.beginServiceRequest()
      .then(onServiceRequestSuccess, onServiceRequestError, onProgress)
      .catch((err)=>
      {
          //do something
      });

    Best regards.


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, September 9, 2019 1:51 AM
  • Hi,

    It appears that 'licenseRequest.beginServiceRequest()' doesn't allow 'catch' to be used. Looking at the iAsyncAction returned it shows only methods.. 'cancel', 'done', 'then'.

    JavaScript runtime error: Object doesn't support property or method 'catch'

    I also tried using the WinJS Promise onerror event.

    These are the changes I made. Sorry for the code dump

    _getLicenseHeader() {
            try { 
                console.log("_getLicenseHeader")
                let laURI = new Windows.Foundation.Uri(getDrmPlayreadyLicenseServer());
                let keyId = "{6F651AE1-DBE4-4434-BCB4-690D1564C41C}";
                let customData = "Bearer " + this._drmToken;
                let serviceId = '{DEB47F00-8A3B-416D-9B1E-5D55FD023044}';
                let contentHeader = new PlayReady.PlayReadyContentHeader(keyId, null, PlayReady.PlayReadyEncryptionAlgorithm.unspecified , laURI, laURI, customData, serviceId);
        
                return contentHeader;
            } catch (e) {
                console.log(e)
            }
        }
    
        _createMediaProtectionManager() {
            try {
                console.log("_createMediaProtectionManager")
                let mediaProtectionManager = new Windows.Media.Protection.MediaProtectionManager();
    
                let props = new Windows.Foundation.Collections.PropertySet();
                props["{F4637010-03C3-42CD-B932-B48ADF3A6A54}"] =  "Windows.Media.Protection.PlayReady.PlayReadyWinRTTrustedInput";
                mediaProtectionManager.properties["Windows.Media.Protection.MediaProtectionSystemIdMapping"] = props;
                mediaProtectionManager.properties["Windows.Media.Protection.MediaProtectionSystemId"] = "{F4637010-03C3-42CD-B932-B48ADF3A6A54}";
                mediaProtectionManager.properties["Windows.Media.Protection.MediaProtectionContainerGuid"] = "{9A04F079-9840-4286-AB92-E65BE0885F95}";
        
                //Setting up event handler for PlayReady related events
                mediaProtectionManager.addEventListener("servicerequested", this._onServiceRequested, false);
                mediaProtectionManager.addEventListener("componentloadfailed", this._onComponentLoadFailed, false);
        
                return mediaProtectionManager;
            } catch (e) {
                console.log(e)
            }
        }
    
        _onComponentLoadFailed(e) {
            try {
                this.constructor.logger.logPlayer() && this.constructor.logger.debug("Component Load Failed " + e);
    
                //  List the failing components
                for (let 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) {
                console.log(e)
            }
        }
    
        _onServiceRequested(serviceRequest) {
            try {
                console.log("_onServiceRequested")
                this._processServiceRequest(serviceRequest, null);
            } catch (e) {
                this.constructor.logger.logPlayer() && this.constructor.logger.debug("Exception(onServiceRequested): " + e);
            }
        }
        
        _processServiceRequest(serviceRequest) {
            try {
                console.log("_processServiceRequest")
    
                let request = serviceRequest.request;
                let statics = Windows.Media.Protection.PlayReady.PlayReadyStatics;
                switch (request.type)
                {
                    case statics.licenseAcquirerServiceRequestType:
                        this.constructor.logger.logPlayer() && this.constructor.logger.debug("License Service Request Started");
    
                        // Needed to create a clean request, serviceRequest.request from event was throwing an exception that contentHeader is read-only so it cannot be set.
                        let cleanRequest = new PlayReady.PlayReadyLicenseAcquisitionServiceRequest();
                        cleanRequest.uri = new Windows.Foundation.Uri(getDrmPlayreadyLicenseServer());
                        cleanRequest.contentHeader = this._getLicenseHeader();
                        cleanRequest.challengeCustomData = "Bearer " + this._drmToken;
    
                        console.log(cleanRequest)
                        this._reactiveLicenseRequest(cleanRequest, serviceRequest.completion, null);
                        break;
                }
            } catch (e) {
                console.log(e)
            }
        }
    
        _reactiveLicenseRequest(licenseRequest, completionNotifier, complete) {
            try {
                console.log("_reactiveLicenseRequest")
                let currentServiceRequest = licenseRequest;
    
                function onServiceRequestSuccess() {
                    this.constructor.logger.logPlayer() && this.constructor.logger.debug("License Service Request Complete");
    
                    completionNotifier && completionNotifier.complete(true);
                    completionNotifier = null;
        
                    complete && complete();
                }
        
                function onServiceRequestError(e) {
                    this.constructor.logger.logPlayer() && this.constructor.logger.debug("License Service Request Error " + e);
    
                    if (e.number != -2147174251) { // MSPR_E_CONTENT_ENABLING_ACTION_REQUIRED (0x8004b895)
                        // 
                    } else {
                        var nextServiceRequest = currentServiceRequest.nextServiceRequest();
                        if (nextServiceRequest != null) {
                            nextServiceRequest.beginServiceRequest().then(onServiceRequestSuccess, onServiceRequestError);
                        }
                    }
                }
    
                function onProgress(e) {
                    console.log("onProgress");
                    console.log(e)
                }
    
                console.log("beginServiceRequest")
                licenseRequest.beginServiceRequest().then(onServiceRequestSuccess, onServiceRequestError, onProgress);
            } catch (e) {
                console.log(e)
            }
        }

    And it is all initialized like this

    if (this._drmToken) {
                try {
                    console.log(this._drmToken)
                    let mediaProtectionManager = this._createMediaProtectionManager();
                    this._videoTag.msSetMediaProtectionManager(mediaProtectionManager);
                } catch (e) {
                    console.log(e)
                }
            }

    A question I have that could be playing a potential role is, would the DRM security level being configured too high on the license server be causing this hanging? Currently our license server is not configured for SL150, I anticipated an error playing, but I would've thought a more explicit error would occur in this case.

    Thanks.



    • Edited by jmombo Monday, September 9, 2019 3:46 PM
    Monday, September 9, 2019 3:45 PM
  • Hi,

    I tried playing DRM content again after having the license server set to SL150 and the same issue persisted. So this particular issue doesn't seem to be related to the security level as I thought possibly was the case.

    Thanks,

    Tuesday, September 10, 2019 4:03 PM
  • Just wanted to bump this.

    Is there any advice on how to proceed?

    Thanks,

    Thursday, September 12, 2019 8:31 PM
  • Hi,

    I am sorry that I replied late.

    I have already asked the engineer for your question, he will track your problem, thank you for your support.

    Best regards.


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, September 17, 2019 2:51 AM
  • Hi jmombo,

    I tried to reproduce the issue using official sample: https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/PlayReady

    But it runs well. I'm not able to reproduce it.

    Here are a few things you can try:

    1. Log the error with WinJS.log in onServiceRequestError:

    function onServiceRequestError(e) {
        WinJS.log(e);//log the error message
        if (e.number != -2147174251) { // MSPR_E_CONTENT_ENABLING_ACTION_REQUIRED (0x8004b895)
                    // 
        } else {
            var nextServiceRequest = currentServiceRequest.nextServiceRequest();
            if (nextServiceRequest != null) {
                       nextServiceRequest.beginServiceRequest().then(onServiceRequestSuccess, onServiceRequestError);
              }
        }
     }

    2. When your program is running observe the Javascript console, see if there is any errror appears there

    If you still can not see any error, please share a basic demo that can reproduce this issue, feel free to remove any sensitive informations from the project.

    Best Regards,

    Elvis Xia

    Tuesday, September 17, 2019 7:43 AM
  • Hi Elvis,

    Sorry for my late response.

    I was able to see an error message in onServiceRequestError. The logging I had originally added was not printing to the log so I had thought it was just hanging.

    Adding this,

    this.constructor.logger.debug("License Service Request Error " + e);

    Returns the following message,

    [2019-10-03 11:44:23.088] [DEBUG] MediaPlayerServiceXbox - License Service Request Error WinRTError: The text associated with this error code could not be found.
    
    The text associated with this error code could not be found.
    
    app.bundle.js (82,68403)

    Unfortunately it is a very vague error. But at least the error handling is actually being called.

    More information, I tried this in an environment where the license server should be configured for SL150. But looking at the HTTP monitor I don't even see the license server being requested so I'm not sure that is the issue.

    Below is the request that is passed with sensitive information removed,

    [object Windows.Media.Protection.PlayReady.PlayReadyLicenseAcquisitionServiceRequest]
    app.bundle.js (39,207598)
       {
          [functions]: ,
          __proto__: { },
          challengeCustomData: "Bearer {AuthorizationTokenRemovedFromHere}",
          contentHeader: {
             [functions]: ,
             __proto__: { },
             customAttributes: "Bearer {AuthorizationTokenRemovedFromHere}",
             decryptorSetup: 0,
             domainServiceId: "deb47f00-8a3b-416d-9b1e-5d55fd023044",
             encryptionType: 65535,
             headerWithEmbeddedUpdates: null,
             keyId: "6f651ae1-dbe4-4434-bcb4-690d1564c41c",
             keyIds: { },
             keyIdString: "4Rplb+TbNES8tGkNFWTEHA==",
             keyIdStrings: { },
             licenseAcquisitionUrl: { },
             licenseAcquisitionUserInterfaceUrl: { }
          },
          domainServiceId: "00000000-0000-0000-0000-000000000000",
          protectionSystem: "f4637010-03c3-42cd-b932-b48adf3a6a54",
          responseCustomData: <Permission denied>,
          sessionId: "00000000-0000-0000-0000-000000000000",
          type: "45945d72-c506-4b4d-bb50-e856d6188d57",
          uri: {
             [functions]: ,
             __proto__: { },
             absoluteCanonicalUri: "{PlayreadyLicenseUrlRemovedFromHere}",
             absoluteUri: "{PlayreadyLicenseUrlRemovedFromHere}",
             displayIri: "{PlayreadyLicenseUrlRemovedFromHere}",
             displayUri: "{PlayreadyLicenseUrlRemovedFromHere}",
             domain: "{PlayreadyLicenseUrlDomainRemovedFromHere}",
             extension: ".asmx",
             fragment: "",
             host: "{PlayreadyLicenseUrlHostRemovedFromHere}",
             password: "",
             path: "{PlayreadyLicenseUrlPathRemovedFromHere}",
             port: 443,
             query: "",
             queryParsed: { },
             rawUri: "{PlayreadyLicenseUrlRemovedFromHere}",
             schemeName: "https",
             suspicious: false,
             userName: ""
          }
       }
    

    Here is how I generate it. I found that I had to create a new request other than the default on passed automatically in order to actually add the Authorization token/Custom Data

                        let cleanRequest = new PlayReady.PlayReadyLicenseAcquisitionServiceRequest();
                        cleanRequest.uri = new Windows.Foundation.Uri(getDrmPlayreadyLicenseServer());
                        cleanRequest.contentHeader = this._getLicenseHeader();
                        cleanRequest.challengeCustomData = "Bearer " + this._drmToken;
    
                        console.log(cleanRequest)
        _getLicenseHeader() {
            try { 
                console.log("_getLicenseHeader")
                let laURI = new Windows.Foundation.Uri(getDrmPlayreadyLicenseServer());
                let keyId = "{6F651AE1-DBE4-4434-BCB4-690D1564C41C}";
                let customData = "Bearer " + this._drmToken;
                let serviceId = '{DEB47F00-8A3B-416D-9B1E-5D55FD023044}';
                let contentHeader = new PlayReady.PlayReadyContentHeader(keyId, null, PlayReady.PlayReadyEncryptionAlgorithm.unspecified, laURI, laURI, customData, serviceId);
        
                return contentHeader;
            } catch (e) {
                console.log(e)
            }
        }

    Thanks.

    Thursday, October 3, 2019 4:32 PM
  • Hi,

    Any reason why you need use PlayReady.PlayReadyEncryptionAlgorithm.unspecified for Encryption Algorithm?

    And also please note that PlayReady.PlayReadyEncryptionAlgorithm.unspecified is only supported after Windows 10 1709. For detailed explaination, please refer to Remark of this doc:

    https://docs.microsoft.com/en-us/uwp/api/windows.media.protection.playready.playreadycontentheader.-ctor

    Best Regards,

    Elvis Xia


    Wednesday, October 9, 2019 7:34 AM
  • Hi Elvis,

    I don't believe there was any specific reason for setting that. Just was testing things out and must've found that to produce some interesting result.

    Your suggestion made me decide to test the different algorithms though. Here is what I found.

    For 'aes128Cbc' & 'unspecified': I received the error listed above from onServiceRequestError in beginServiceRequest

    For 'uninitialized' & 'unprotected': I received an error I think when trying to create the Header itself. Before beginServiceRequest is ever called

                let contentHeader = new PlayReady.PlayReadyContentHeader(keyId, null, PlayReady.PlayReadyEncryptionAlgorithm.unspecified, laURI, laURI, customData, serviceId);
    

    For 'aes123Ctr' & 'cocktail': I found this would actually say it was successful by hitting the onServiceRequestSuccess function of beginServiceRequest but the video would never play. This option would also repeatedly fire 'servicerequested' events for a period before the video would eventually throw a playback error. Looking at the HTTP monitor I never saw a request to the license server.

        _processServiceRequest(serviceRequest) {
            try {
                console.log("_processServiceRequest")
    
                let request = serviceRequest.request;
                let statics = Windows.Media.Protection.PlayReady.PlayReadyStatics;
                switch (request.type)
                {
                    case statics.licenseAcquirerServiceRequestType:
                        this.constructor.logger.logPlayer() && this.constructor.logger.debug("License Service Request Started");
    
                        // Needed to create a clean request, serviceRequest.request from event was throwing an exception that contentHeader is read-only so it cannot be set.
                        let cleanRequest = new PlayReady.PlayReadyLicenseAcquisitionServiceRequest();
                        cleanRequest.uri = new Windows.Foundation.Uri(getDrmPlayreadyLicenseServer());
                        cleanRequest.contentHeader = this._getLicenseHeader();
                        cleanRequest.challengeCustomData = "Bearer " + this._drmToken;
    
                        console.log(cleanRequest)
                        this._reactiveLicenseRequest(cleanRequest, serviceRequest.completion, null);
                        break;
                }
            } catch (e) {
                console.log(e)
            }
        }

    I'm curious if because I am creating a new license server request here instead of using the default passed by serviceRequest but still using the default serviceRequest.completion for completionNotifier.complete(true) there is some conflict happening?

    Thanks,


    Wednesday, October 9, 2019 10:56 PM
  • Hi,

    >>I'm curious if because I am creating a new license server request here instead of using the default passed by serviceRequest but still using the default serviceRequest.completion for completionNotifier.complete(true) there is some conflict happening

    I can't make a guess without a complete Repo, Since you are modifying the official demo, could you please make a basic demo that can reproduce this issue and highlight the changes that you have made, then post it here? Please replace all the sensitive informations like Tokens, ip address, user name etc. with placeholders. Thus,instead of guessing, I can have a full picture of where is possiblely wrong.  

    Thanks,

    Elvis Xia

    Thursday, October 10, 2019 12:49 AM