Skip to content

Commit

Permalink
Set server certificate before Store and Delete (#1639)
Browse files Browse the repository at this point in the history
Call setServerCertificate before store and
delete operations, when serverCertificate
exists.
In demo application, request and
configure certificate when certificateUri
is given in asset.

Fixes #1623
  • Loading branch information
gigon authored and TheModMaker committed Oct 24, 2018
1 parent 140105b commit 5177309
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 34 deletions.
40 changes: 25 additions & 15 deletions demo/offline_section.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,23 +202,33 @@ shakaDemo.storeDeleteAsset_ = function() {
return shakaDemo.refreshAssetList_();
});
} else {
let configureCertificate = Promise.resolve();

let asset = shakaDemo.preparePlayer_(option.asset);
let nameField = document.getElementById('offlineName').value;
let assetName = asset.name ? '[OFFLINE] ' + asset.name : null;
let metadata = {name: assetName || nameField || asset.manifestUri};
p = storage.store(asset.manifestUri, metadata).then(function() {
if (option.asset) {
option.isStored = true;
}
return shakaDemo.refreshAssetList_().then(function() {
// Auto-select offline copy of asset after storing.
let group = shakaDemo.offlineOptGroup_;
for (let i = 0; i < group.childNodes.length; i++) {
let option = group.childNodes[i];
if (option.textContent == assetName) {
assetList.selectedIndex = option.index;
}

if (asset.certificateUri) {
configureCertificate = shakaDemo.requestCertificate_(asset.certificateUri)
.then(shakaDemo.configureCertificate_);
}

p = configureCertificate.then(function() {
let nameField = document.getElementById('offlineName').value;
let assetName = asset.name ? '[OFFLINE] ' + asset.name : null;
let metadata = {name: assetName || nameField || asset.manifestUri};
return storage.store(asset.manifestUri, metadata).then(function() {
if (option.asset) {
option.isStored = true;
}
return shakaDemo.refreshAssetList_().then(function() {
// Auto-select offline copy of asset after storing.
let group = shakaDemo.offlineOptGroup_;
for (let i = 0; i < group.childNodes.length; i++) {
let option = group.childNodes[i];
if (option.textContent == assetName) {
assetList.selectedIndex = option.index;
}
}
});
});
});
}
Expand Down
5 changes: 5 additions & 0 deletions externs/shaka/offline.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ shaka.extern.SegmentDataDB;
* sessionId: string,
* keySystem: string,
* licenseUri: string,
* serverCertificate: Uint8Array,
* audioCapabilities: !Array.<MediaKeySystemMediaCapability>,
* videoCapabilities: !Array.<MediaKeySystemMediaCapability>
* }}
Expand All @@ -222,6 +223,10 @@ shaka.extern.SegmentDataDB;
* The EME key system string the session belongs to.
* @property {string} licenseUri
* The URI for the license server.
* @property {Uint8Array} serverCertificate
* A key-system-specific server certificate used to encrypt license requests.
* Its use is optional and is meant as an optimization to avoid a round-trip
* to request a certificate.
* @property {!Array.<MediaKeySystemMediacapability>} audioCapabilities
* The EME audio capabilities used to create the session.
* @property {!Array.<MediaKeySystemMediacapability>} videoCapabilities
Expand Down
55 changes: 36 additions & 19 deletions lib/media/drm_engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -307,12 +307,14 @@ shaka.media.DrmEngine.prototype.initForPlayback = function(
*
* @param {string} keySystem
* @param {string} licenseServerUri
* @param {Uint8Array} serverCertificate
* @param {!Array.<MediaKeySystemMediaCapability>} audioCapabilities
* @param {!Array.<MediaKeySystemMediaCapability>} videoCapabilities
* @return {!Promise}
*/
shaka.media.DrmEngine.prototype.initForRemoval = function(
keySystem, licenseServerUri, audioCapabilities, videoCapabilities) {
keySystem, licenseServerUri, serverCertificate,
audioCapabilities, videoCapabilities) {
/** @type {!Map.<string, MediaKeySystemConfiguration>} */
const configsByKeySystem = new Map();
configsByKeySystem.set(keySystem, {
Expand All @@ -329,7 +331,7 @@ shaka.media.DrmEngine.prototype.initForRemoval = function(
persistentStateRequired: true,
audioRobustness: '', // Not required by queryMediaKeys_
videoRobustness: '', // Same
serverCertificate: null,
serverCertificate: serverCertificate,
initData: null,
keyIds: null,
}], // Tracked by us, ignored by EME.
Expand Down Expand Up @@ -439,23 +441,7 @@ shaka.media.DrmEngine.prototype.attach = function(video) {
exception.message));
});

let setServerCertificate = null;
if (this.currentDrmInfo_.serverCertificate &&
this.currentDrmInfo_.serverCertificate.length) {
setServerCertificate = this.mediaKeys_.setServerCertificate(
this.currentDrmInfo_.serverCertificate).then(function(supported) {
if (!supported) {
shaka.log.warning('Server certificates are not supported by the key' +
' system. The server certificate has been ignored.');
}
}).catch(function(exception) {
return Promise.reject(new shaka.util.Error(
shaka.util.Error.Severity.CRITICAL,
shaka.util.Error.Category.DRM,
shaka.util.Error.Code.INVALID_SERVER_CERTIFICATE,
exception.message));
});
}
let setServerCertificate = this.setServerCertificate();

return Promise.all([setMediaKeys, setServerCertificate]).then(() => {
if (this.destroyed_) return Promise.reject();
Expand All @@ -476,6 +462,37 @@ shaka.media.DrmEngine.prototype.attach = function(video) {
};


/**
* Sets the server certificate based on the current DrmInfo.
*
* @return {!Promise}
*/
shaka.media.DrmEngine.prototype.setServerCertificate = async function() {
goog.asserts.assert(this.initialized_,
'Must call init() before setServerCertificate');

if (this.mediaKeys_ &&
this.currentDrmInfo_ &&
this.currentDrmInfo_.serverCertificate &&
this.currentDrmInfo_.serverCertificate.length) {
try {
const supported = await this.mediaKeys_.setServerCertificate(
this.currentDrmInfo_.serverCertificate);
if (!supported) {
shaka.log.warning('Server certificates are not supported by the key' +
' system. The server certificate has been ignored.');
}
} catch (exception) {
return Promise.reject(new shaka.util.Error(
shaka.util.Error.Severity.CRITICAL,
shaka.util.Error.Category.DRM,
shaka.util.Error.Code.INVALID_SERVER_CERTIFICATE,
exception.message));
}
}
};


/**
* Remove an offline session and delete it's data. This can only be called
* after a successful call to |init|. This will wait until the 'license-release'
Expand Down
9 changes: 9 additions & 0 deletions lib/offline/session_deleter.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,22 @@ shaka.offline.SessionDeleter = class {
drmEngine.configure(config);
await drmEngine.initForRemoval(
bucket.info.keySystem, bucket.info.licenseUri,
bucket.info.serverCertificate,
bucket.info.audioCapabilities, bucket.info.videoCapabilities);
} catch (e) {
shaka.log.warning('Error initializing EME', e);
await drmEngine.destroy();
return [];
}

try {
await drmEngine.setServerCertificate();
} catch (e) {
shaka.log.warning('Error setting server certificate', e);
await drmEngine.destroy();
return [];
}

/** @type {!Array.<string>} */
const sessionIds = [];
await Promise.all(bucket.sessionIds.map(async (sessionId) => {
Expand Down
2 changes: 2 additions & 0 deletions lib/offline/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,7 @@ shaka.offline.Storage.prototype.createDrmEngine = async function(
const config = this.config_;
drmEngine.configure(config.drm);
await drmEngine.initForStorage(variants, config.offline.usePersistentLicense);
await drmEngine.setServerCertificate();
await drmEngine.createOrLoad();

return drmEngine;
Expand Down Expand Up @@ -1189,6 +1190,7 @@ shaka.offline.Storage.deleteLicenseFor_ = async function(
sessionId: sessionId,
keySystem: manifestDb.drmInfo.keySystem,
licenseUri: manifestDb.drmInfo.licenseServerUri,
serverCertificate: manifestDb.drmInfo.serverCertificate,
audioCapabilities: shaka.offline.Storage.getCapabilities_(
manifestDb,
/* isVideo */ false),
Expand Down

0 comments on commit 5177309

Please sign in to comment.