Skip to content

Instantly share code, notes, and snippets.

@peaBerberian
Created December 11, 2017 16:34
Show Gist options
  • Save peaBerberian/6cb562768648f13ab2df4219d6ff37c1 to your computer and use it in GitHub Desktop.
Save peaBerberian/6cb562768648f13ab2df4219d6ff37c1 to your computer and use it in GitHub Desktop.
getConfiguration: [],
load: [],
remove: [],
requestMediaKeySystemAccess: [],
setMediaKeys: [],
setServerCertificate: [],
update: [],
};
/**
* Define the logger for spyEME.
* Allows to re-define a specific logger on runtime / before applying this
* script.
* @type {Object}
*/
const spyLogger = window.spyLogger || {
/* eslint-disable no-console */
log: function(...args) {
console.log(...args);
},
debug: function(...args) {
console.debug(...args);
},
info: function(...args) {
console.info(...args);
},
error: function(...args) {
console.error(...args);
},
warning: function(...args) {
console.warning(...args);
},
/* eslint-enable no-console */
};
/**
* Start spying on EME API calls.
* @returns {Object} - Object with a "restore" function, restoring all stubs
* done here.
*/
function spyEME() {
/**
* Log when a function is called with its arguments.
* @param {string} fnName
* @param {Array.<*>} args
*/
function onAPICall(fnName, args) {
if (args.length) {
spyLogger.debug(`>>> ${fnName} called with arguments:`, args);
} else {
spyLogger.debug(`>>> ${fnName} called`);
}
}
const saveRequestMediaKeySystemAccess = navigator.requestMediaKeySystemAccess;
navigator.requestMediaKeySystemAccess = function(...args) {
const robustnesses = [
"HW_SECURE_ALL",
"HW_SECURE_DECODE",
"HW_SECURE_CRYPTO",
"SW_SECURE_DECODE",
"SW_SECURE_CRYPTO",
];
if (!args[1]) {
args[1] = [{}];
}
const secondArg = args[1];
secondArg.forEach(function (cap) {
const cap2 = Object.assign({}, cap);
cap2.audioCapabilities = undefined;
cap2.videoCapabilities = undefined;
secondArg.push(cap2);
cap.audioCapabilities = robustnesses.map(robustness => {
return {
contentType: "audio/mp4;codecs=\"mp4a.40.2\"", // standard mp4 codec
robustness,
};
});
cap.videoCapabilities = robustnesses.map(robustness => {
return {
contentType: "video/mp4;codecs=\"avc1.4d401e\"", // standard mp4 codec
robustness,
};
});
})
onAPICall("navigator.requestMediaKeySystemAccess", args);
const myObj = {
self: this,
date: Date.now(),
args,
};
EME_CALLS.requestMediaKeySystemAccess.push(myObj);
let prom;
try {
prom = saveRequestMediaKeySystemAccess.apply(navigator, args);
} catch (e) {
spyLogger.error(">> navigator.requestMediaKeySystemAccess failed:", e);
myObj.error = e;
myObj.errorDate = Date.now();
throw e;
}
myObj.response = prom;
myObj.responseDate = Date.now();
prom.then((r) => {
spyLogger.debug(">> navigator.requestMediaKeySystemAccess resolved:", r);
myObj.responseResolved = r;
myObj.responseResolvedDate = Date.now();
}, (e) => {
spyLogger.error(">> navigator.requestMediaKeySystemAccess rejected:", e);
myObj.responseError = e;
myObj.responseErrorDate = Date.now();
});
return prom;
};
const saveUpdate = MediaKeySession.prototype.update;
MediaKeySession.prototype.update = function(...args) {
onAPICall("MediaKeySession.prototype.update", args);
const myObj = {
self: this,
date: Date.now(),
args,
};
EME_CALLS.update.push(myObj);
let prom;
try {
prom = saveUpdate.apply(this, args);
} catch (e) {
spyLogger.error(">> MediaKeySession.prototype.update failed:", e);
myObj.error = e;
myObj.errorDate = Date.now();
throw e;
}
myObj.response = prom;
myObj.responseDate = Date.now();
prom.then((r) => {
spyLogger.debug(">> MediaKeySession.prototype.update resolved:", r);
myObj.responseResolved = r;
myObj.responseResolvedDate = Date.now();
}, (e) => {
spyLogger.error(">> MediaKeySession.prototype.update rejected:", e);
myObj.responseError = e;
myObj.responseErrorDate = Date.now();
});
return prom;
};
const saveload = MediaKeySession.prototype.load;
MediaKeySession.prototype.load = function(...args) {
onAPICall("MediaKeySession.prototype.load", args);
const myObj = {
self: this,
date: Date.now(),
args,
};
EME_CALLS.load.push(myObj);
let prom;
try {
prom = saveload.apply(this, args);
} catch (e) {
spyLogger.error(">> MediaKeySession.prototype.load failed:", e);
myObj.error = e;
myObj.errorDate = Date.now();
throw e;
}
myObj.response = prom;
myObj.responseDate = Date.now();
prom.then((r) => {
spyLogger.debug(">> MediaKeySession.prototype.load resolved:", r);
myObj.responseResolved = r;
myObj.responseResolvedDate = Date.now();
}, (e) => {
spyLogger.error(">> MediaKeySession.prototype.load rejected:", e);
myObj.responseError = e;
myObj.responseErrorDate = Date.now();
});
return prom;
};
const saveremove = MediaKeySession.prototype.remove;
MediaKeySession.prototype.remove = function(...args) {
onAPICall("MediaKeySession.prototype.remove", args);
const myObj = {
self: this,
date: Date.now(),
args,
};
EME_CALLS.remove.push(myObj);
let prom;
try {
prom = saveremove.apply(this, args);
} catch (e) {
spyLogger.error(">> MediaKeySession.prototype.remove failed:", e);
myObj.error = e;
myObj.errorDate = Date.now();
throw e;
}
myObj.response = prom;
myObj.responseDate = Date.now();
prom.then((r) => {
spyLogger.debug(">> MediaKeySession.prototype.remove resolved:", r);
myObj.responseResolved = r;
myObj.responseResolvedDate = Date.now();
}, (e) => {
spyLogger.error(">> MediaKeySession.prototype.remove rejected:", e);
myObj.responseError = e;
myObj.responseErrorDate = Date.now();
});
return prom;
};
const saveclose = MediaKeySession.prototype.close;
MediaKeySession.prototype.close = function(...args) {
onAPICall("MediaKeySession.prototype.close", args);
const myObj = {
self: this,
date: Date.now(),
args,
};
EME_CALLS.close.push(myObj);
let prom;
try {
prom = saveclose.apply(this, args);
} catch (e) {
spyLogger.error(">> MediaKeySession.prototype.close failed:", e);
myObj.error = e;
myObj.errorDate = Date.now();
throw e;
}
myObj.response = prom;
myObj.responseDate = Date.now();
prom.then((r) => {
spyLogger.debug(">> MediaKeySession.prototype.close resolved:", r);
myObj.responseResolved = r;
myObj.responseResolvedDate = Date.now();
}, (e) => {
spyLogger.error(">> MediaKeySession.prototype.close rejected:", e);
myObj.responseError = e;
myObj.responseErrorDate = Date.now();
});
return prom;
};
const savegenerateRequest = MediaKeySession.prototype.generateRequest;
MediaKeySession.prototype.generateRequest = function(...args) {
onAPICall("MediaKeySession.prototype.generateRequest", args);
const myObj = {
self: this,
date: Date.now(),
args,
};
EME_CALLS.generateRequest.push(myObj);
let prom;
try {
prom = savegenerateRequest.apply(this, args);
} catch (e) {
spyLogger.error(">> MediaKeySession.prototype.generateRequest failed:", e);
myObj.error = e;
myObj.errorDate = Date.now();
throw e;
}
myObj.response = prom;
myObj.responseDate = Date.now();
prom.then((r) => {
spyLogger.debug(">> MediaKeySession.prototype.generateRequest resolved:", r);
myObj.responseResolved = r;
myObj.responseResolvedDate = Date.now();
}, (e) => {
spyLogger.error(">> MediaKeySession.prototype.generateRequest rejected:", e);
myObj.responseError = e;
myObj.responseErrorDate = Date.now();
});
return prom;
};
const savecreateSession = MediaKeys.prototype.createSession;
MediaKeys.prototype.createSession = function(...args) {
onAPICall("MediaKeys.prototype.createSession", args);
const myObj = {
self: this,
date: Date.now(),
args,
};
EME_CALLS.createSession.push(myObj);
let session;
try {
session = savecreateSession.apply(this, args);
} catch (e) {
spyLogger.error(">> MediaKeys.prototype.createSession failed:", e);
myObj.error = e;
myObj.errorDate = Date.now();
throw e;
}
spyLogger.debug(">> MediaKeys.prototype.createSession succeeded:", session);
myObj.response = session;
myObj.responseDate = Date.now();
return session;
};
const savesetServerCertificate = MediaKeys.prototype.setServerCertificate;
MediaKeys.prototype.setServerCertificate = function(...args) {
onAPICall("MediaKeys.prototype.setServerCertificate", args);
const myObj = {
self: this,
date: Date.now(),
args,
};
EME_CALLS.setServerCertificate.push(myObj);
let prom;
try {
prom = savesetServerCertificate.apply(this, args);
} catch (e) {
spyLogger.error(">> MediaKeys.prototype.setServerCertificate failed:", e);
myObj.error = e;
myObj.errorDate = Date.now();
throw e;
}
myObj.response = prom;
myObj.responseDate = Date.now();
prom.then((r) => {
spyLogger.debug(">> MediaKeys.prototype.setServerCertificate resolved:", r);
myObj.responseResolved = r;
myObj.responseResolvedDate = Date.now();
}, (e) => {
spyLogger.error(">> MediaKeys.prototype.setServerCertificate rejected:", e);
myObj.responseError = e;
myObj.responseErrorDate = Date.now();
});
return prom;
};
const savecreateMediaKeys = MediaKeySystemAccess.prototype.createMediaKeys;
MediaKeySystemAccess.prototype.createMediaKeys = function(...args) {
onAPICall("MediaKeySystemAccess.prototype.createMediaKeys", args);
const myObj = {
self: this,
date: Date.now(),
args,
};
EME_CALLS.createMediaKeys.push(myObj);
let prom;
try {
prom = savecreateMediaKeys.apply(this, args);
} catch (e) {
spyLogger.error(">> MediaKeySystemAccess.prototype.createMediaKeys failed:", e);
myObj.error = e;
myObj.errorDate = Date.now();
throw e;
}
myObj.response = prom;
myObj.responseDate = Date.now();
prom.then((r) => {
spyLogger.debug(">> MediaKeySystemAccess.prototype.createMediaKeys resolved:", r);
myObj.responseResolved = r;
myObj.responseResolvedDate = Date.now();
}, (e) => {
spyLogger.error(">> MediaKeySystemAccess.prototype.createMediaKeys rejected:", e);
myObj.responseError = e;
myObj.responseErrorDate = Date.now();
});
return prom;
};
const savegetConfiguration = MediaKeySystemAccess.prototype.getConfiguration;
MediaKeySystemAccess.prototype.getConfiguration = function(...args) {
onAPICall("MediaKeySystemAccess.prototype.getConfiguration", args);
const myObj = {
self: this,
date: Date.now(),
args,
};
EME_CALLS.getConfiguration.push(myObj);
let mk;
try {
mk = savegetConfiguration.apply(this, args);
} catch (e) {
spyLogger.error(">> MediaKeySystemAccess.prototype.getConfiguration failed:", e);
myObj.error = e;
myObj.errorDate = Date.now();
throw e;
}
spyLogger.debug(">> MediaKeySystemAccess.prototype.getConfiguration succeeded:", mk);
myObj.response = mk;
myObj.responseDate = Date.now();
return mk;
};
const savesetMediaKeys = HTMLMediaElement.prototype.setMediaKeys;
HTMLMediaElement.prototype.setMediaKeys = function(...args) {
onAPICall("HTMLMediaElement.prototype.setMediaKeys", args);
const myObj = {
self: this,
date: Date.now(),
args,
};
EME_CALLS.setMediaKeys.push(myObj);
let prom;
try {
prom = savesetMediaKeys.apply(this, args);
} catch (e) {
spyLogger.error(">> HTMLMediaElement.prototype.setMediaKeys failed:", e);
myObj.error = e;
myObj.errorDate = Date.now();
throw e;
}
myObj.response = prom;
myObj.responseDate = Date.now();
prom.then((r) => {
spyLogger.debug(">> HTMLMediaElement.prototype.setMediaKeys resolved:", r);
myObj.responseResolved = r;
myObj.responseResolvedDate = Date.now();
}, (e) => {
spyLogger.error(">> HTMLMediaElement.prototype.setMediaKeys rejected:", e);
myObj.responseError = e;
myObj.responseErrorDate = Date.now();
});
return prom;
};
return {
restore: function () {
navigator.requestMediaKeySystemAccess = saveRequestMediaKeySystemAccess;
MediaKeySession.prototype.update = saveUpdate;
MediaKeySession.prototype.load = saveload;
MediaKeySession.prototype.close = saveclose;
MediaKeySession.prototype.remove = saveremove;
MediaKeySession.prototype.generateRequest = savegenerateRequest;
MediaKeys.prototype.createSession = savecreateSession;
MediaKeys.prototype.setServerCertificate = savesetServerCertificate;
MediaKeySystemAccess.prototype.createMediaKeys = savecreateMediaKeys;
MediaKeySystemAccess.prototype.getConfiguration = savegetConfiguration;
HTMLMediaElement.prototype.setMediaKeys = savesetMediaKeys;
},
};
}
window.EME_CALLS = EME_CALLS;
window.spyLogger = spyLogger;
window.spyEME = spyEME;
window.restoreEME = spyEME().restore;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment