Skip to content

Commit

Permalink
Set server certificate before Store and Delete
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 shaka-project#1623.
  • Loading branch information
gigon committed Oct 21, 2018
1 parent 189e710 commit 47f615b
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 20 deletions.
12 changes: 11 additions & 1 deletion demo/offline_section.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,20 @@ shakaDemo.storeDeleteAsset_ = function() {
return shakaDemo.refreshAssetList_();
});
} else {
let configureCertificate = Promise.resolve();

let asset = shakaDemo.preparePlayer_(option.asset);

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};
p = storage.store(asset.manifestUri, metadata).then(function() {
return storage.store(asset.manifestUri, metadata).then(function() {
if (option.asset) {
option.isStored = true;
}
Expand All @@ -221,6 +230,7 @@ shakaDemo.storeDeleteAsset_ = function() {
}
});
});
});
}

p.catch(function(reason) {
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
58 changes: 39 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,40 @@ shaka.media.DrmEngine.prototype.attach = function(video) {
};


/**
* Create a promise that will be resolved after the server certificate
* will be set.
*
* @return {!Promise|null}
*/
shaka.media.DrmEngine.prototype.setServerCertificate = function() {
goog.asserts.assert(this.initialized_,
'Must call init() before setServerCertificate');

let setServerCertificate = null;
if (this.mediaKeys_ &&
this.currentDrmInfo_ &&
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));
});
}

return setServerCertificate;
};


/**
* 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 {
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 @@ -814,6 +814,7 @@ shaka.offline.Storage.prototype.createDrmEngine = async function(
const config = this.config_;
drmEngine.configure(config.drm);
await drmEngine.initForStorage(variants, config.offline.usePersistentLicense);
drmEngine.setServerCertificate();
await drmEngine.createOrLoad();

return drmEngine;
Expand Down Expand Up @@ -1194,6 +1195,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 47f615b

Please sign in to comment.