Add manifest URL field, reset keys when manifest changes, organize repo, update to Manifest v3 #3
@ -13,27 +13,27 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "DRM_TYPE":
|
case "DRM_TYPE":
|
||||||
console.log("DRM Type:", data);
|
logWithPrefix("DRM Type:", data);
|
||||||
chrome.storage.local.set({ drmType: data });
|
chrome.storage.local.set({ drmType: data });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "PSSH_DATA":
|
case "PSSH_DATA":
|
||||||
console.log("Storing PSSH:", data);
|
logWithPrefix("Storing PSSH:", data);
|
||||||
chrome.storage.local.set({ latestPSSH: data });
|
chrome.storage.local.set({ latestPSSH: data });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "KEYS_DATA":
|
case "KEYS_DATA":
|
||||||
console.log("Storing Decryption Keys:", data);
|
logWithPrefix("Storing Decryption Keys:", data);
|
||||||
chrome.storage.local.set({ latestKeys: data });
|
chrome.storage.local.set({ latestKeys: data });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "LICENSE_URL":
|
case "LICENSE_URL":
|
||||||
console.log("Storling License URL " + data);
|
logWithPrefix("Storling License URL " + data);
|
||||||
chrome.storage.local.set({ licenseURL: data });
|
chrome.storage.local.set({ licenseURL: data });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "MANIFEST_URL":
|
case "MANIFEST_URL":
|
||||||
console.log("Storing Manifest URL:", data);
|
logWithPrefix("Storing Manifest URL:", data);
|
||||||
chrome.storage.local.set({ manifestURL: data });
|
chrome.storage.local.set({ manifestURL: data });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -44,12 +44,27 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|||||||
|
|
||||||
// Set initial config and injection type on install
|
// Set initial config and injection type on install
|
||||||
chrome.runtime.onInstalled.addListener((details) => {
|
chrome.runtime.onInstalled.addListener((details) => {
|
||||||
|
const EXTENSION_PREFIX = "[CDRM EXTENSION]";
|
||||||
|
const PREFIX_COLOR = "black";
|
||||||
|
const PREFIX_BACKGROUND_COLOR = "yellow";
|
||||||
|
|
||||||
|
const logWithPrefix = (...args) => {
|
||||||
|
const style = `color: ${PREFIX_COLOR}; background: ${PREFIX_BACKGROUND_COLOR}; font-weight: bold; padding: 2px 4px; border-radius: 2px;`;
|
||||||
|
if (typeof args[0] === "string") {
|
||||||
|
// If the first arg is a string, prepend the prefix
|
||||||
|
console.log(`%c${EXTENSION_PREFIX}%c ${args[0]}`, style, "", ...args.slice(1));
|
||||||
|
} else {
|
||||||
|
// If not, just log the prefix and the rest
|
||||||
|
console.log(`%c${EXTENSION_PREFIX}`, style, ...args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (details.reason === "install") {
|
if (details.reason === "install") {
|
||||||
chrome.storage.local.set({ valid_config: false }, () => {
|
chrome.storage.local.set({ valid_config: false }, () => {
|
||||||
if (chrome.runtime.lastError) {
|
if (chrome.runtime.lastError) {
|
||||||
console.error("Error setting valid_config:", chrome.runtime.lastError);
|
console.error("Error setting valid_config:", chrome.runtime.lastError);
|
||||||
} else {
|
} else {
|
||||||
console.log("valid_config set to false on first install.");
|
logWithPrefix("valid_config set to false on first install.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -57,7 +72,7 @@ chrome.runtime.onInstalled.addListener((details) => {
|
|||||||
if (chrome.runtime.lastError) {
|
if (chrome.runtime.lastError) {
|
||||||
console.error("Error setting Injection Type:", chrome.runtime.lastError);
|
console.error("Error setting Injection Type:", chrome.runtime.lastError);
|
||||||
} else {
|
} else {
|
||||||
console.log("Injection type set to LICENSE on first install.");
|
logWithPrefix("Injection type set to LICENSE on first install.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -65,7 +80,7 @@ chrome.runtime.onInstalled.addListener((details) => {
|
|||||||
if (chrome.runtime.lastError) {
|
if (chrome.runtime.lastError) {
|
||||||
console.error("Error setting DRM Override type:", chrome.runtime.lastError);
|
console.error("Error setting DRM Override type:", chrome.runtime.lastError);
|
||||||
} else {
|
} else {
|
||||||
console.log("DRM Override type set to DISABLED on first install.");
|
logWithPrefix("DRM Override type set to DISABLED on first install.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -73,7 +88,7 @@ chrome.runtime.onInstalled.addListener((details) => {
|
|||||||
if (chrome.runtime.lastError) {
|
if (chrome.runtime.lastError) {
|
||||||
console.error("Error setting CDRM instance:", chrome.runtime.lastError);
|
console.error("Error setting CDRM instance:", chrome.runtime.lastError);
|
||||||
} else {
|
} else {
|
||||||
console.log("CDRM instance set to null.");
|
logWithPrefix("CDRM instance set to null.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -81,7 +96,7 @@ chrome.runtime.onInstalled.addListener((details) => {
|
|||||||
if (chrome.runtime.lastError) {
|
if (chrome.runtime.lastError) {
|
||||||
console.error("Error setting CDRM API Key:", chrome.runtime.lastError);
|
console.error("Error setting CDRM API Key:", chrome.runtime.lastError);
|
||||||
} else {
|
} else {
|
||||||
console.log("CDRM API Key set.");
|
logWithPrefix("CDRM API Key set.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,19 @@ window.addEventListener("message", function (event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Manifest header and URL
|
// Manifest header and URL
|
||||||
|
const EXTENSION_PREFIX = "[CDRM EXTENSION]";
|
||||||
|
const PREFIX_COLOR = "black";
|
||||||
|
const PREFIX_BACKGROUND_COLOR = "yellow";
|
||||||
|
const logWithPrefix = (...args) => {
|
||||||
|
const style = `color: ${PREFIX_COLOR}; background: ${PREFIX_BACKGROUND_COLOR}; font-weight: bold; padding: 2px 4px; border-radius: 2px;`;
|
||||||
|
if (typeof args[0] === "string") {
|
||||||
|
// If the first arg is a string, prepend the prefix
|
||||||
|
console.log(`%c${EXTENSION_PREFIX}%c ${args[0]}`, style, "", ...args.slice(1));
|
||||||
|
} else {
|
||||||
|
// If not, just log the prefix and the rest
|
||||||
|
console.log(`%c${EXTENSION_PREFIX}`, style, ...args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const seenManifestUrls = new Set();
|
const seenManifestUrls = new Set();
|
||||||
|
|
||||||
@ -75,7 +88,7 @@ window.addEventListener("message", function (event) {
|
|||||||
const url = event.data.data;
|
const url = event.data.data;
|
||||||
if (seenManifestUrls.has(url)) return;
|
if (seenManifestUrls.has(url)) return;
|
||||||
seenManifestUrls.add(url);
|
seenManifestUrls.add(url);
|
||||||
console.log("✅ [Content] Unique manifest URL:", url);
|
logWithPrefix("✅ [Content] Unique manifest URL:", url);
|
||||||
|
|
||||||
chrome.runtime.sendMessage({
|
chrome.runtime.sendMessage({
|
||||||
type: "MANIFEST_URL",
|
type: "MANIFEST_URL",
|
||||||
@ -85,7 +98,7 @@ window.addEventListener("message", function (event) {
|
|||||||
|
|
||||||
if (event.data?.type === "__MANIFEST_HEADERS__") {
|
if (event.data?.type === "__MANIFEST_HEADERS__") {
|
||||||
const { url, headers } = event.data;
|
const { url, headers } = event.data;
|
||||||
console.log("[Content.js] Manifest Headers:", url, headers);
|
logWithPrefix("[Content.js] Manifest Headers:", url, headers);
|
||||||
|
|
||||||
chrome.runtime.sendMessage({
|
chrome.runtime.sendMessage({
|
||||||
type: "MANIFEST_HEADERS",
|
type: "MANIFEST_HEADERS",
|
||||||
|
149
src/inject.js
149
src/inject.js
@ -24,6 +24,21 @@ const DRM_SIGNATURES = {
|
|||||||
WIDEVINE_INIT: "CAQ=",
|
WIDEVINE_INIT: "CAQ=",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const EXTENSION_PREFIX = "[CDRM EXTENSION]";
|
||||||
|
const PREFIX_COLOR = "black";
|
||||||
|
const PREFIX_BACKGROUND_COLOR = "yellow";
|
||||||
|
|
||||||
|
const logWithPrefix = (...args) => {
|
||||||
|
const style = `color: ${PREFIX_COLOR}; background: ${PREFIX_BACKGROUND_COLOR}; font-weight: bold; padding: 2px 4px; border-radius: 2px;`;
|
||||||
|
if (typeof args[0] === "string") {
|
||||||
|
// If the first arg is a string, prepend the prefix
|
||||||
|
console.log(`%c${EXTENSION_PREFIX}%c ${args[0]}`, style, "", ...args.slice(1));
|
||||||
|
} else {
|
||||||
|
// If not, just log the prefix and the rest
|
||||||
|
console.log(`%c${EXTENSION_PREFIX}`, style, ...args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Post message to content.js to get DRM override
|
// Post message to content.js to get DRM override
|
||||||
window.postMessage({ type: "__GET_DRM_OVERRIDE__" }, "*");
|
window.postMessage({ type: "__GET_DRM_OVERRIDE__" }, "*");
|
||||||
|
|
||||||
@ -32,7 +47,7 @@ window.addEventListener("message", function (event) {
|
|||||||
if (event.source !== window) return;
|
if (event.source !== window) return;
|
||||||
if (event.data.type === "__DRM_OVERRIDE__") {
|
if (event.data.type === "__DRM_OVERRIDE__") {
|
||||||
drmOverride = event.data.drmOverride || "DISABLED";
|
drmOverride = event.data.drmOverride || "DISABLED";
|
||||||
console.log("DRM Override set to:", drmOverride);
|
logWithPrefix("DRM Override set to:", drmOverride);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -45,7 +60,7 @@ window.addEventListener("message", function (event) {
|
|||||||
|
|
||||||
if (event.data.type === "__INJECTION_TYPE__") {
|
if (event.data.type === "__INJECTION_TYPE__") {
|
||||||
interceptType = event.data.injectionType || "DISABLED";
|
interceptType = event.data.injectionType || "DISABLED";
|
||||||
console.log("Injection type set to:", interceptType);
|
logWithPrefix("Injection type set to:", interceptType);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -59,7 +74,7 @@ window.addEventListener("message", function (event) {
|
|||||||
if (event.data.type === "__CDM_DEVICES__") {
|
if (event.data.type === "__CDM_DEVICES__") {
|
||||||
const { widevine_device, playready_device } = event.data;
|
const { widevine_device, playready_device } = event.data;
|
||||||
|
|
||||||
console.log("Received device info:", widevine_device, playready_device);
|
logWithPrefix("Received device info:", widevine_device, playready_device);
|
||||||
|
|
||||||
widevineDeviceInfo = widevine_device;
|
widevineDeviceInfo = widevine_device;
|
||||||
playreadyDeviceInfo = playready_device;
|
playreadyDeviceInfo = playready_device;
|
||||||
@ -90,7 +105,7 @@ function headersToFlags(headersObj) {
|
|||||||
|
|
||||||
function handleManifestDetection(url, headersObj, contentType, source) {
|
function handleManifestDetection(url, headersObj, contentType, source) {
|
||||||
window.postMessage({ type: "__MANIFEST_URL__", data: url }, "*");
|
window.postMessage({ type: "__MANIFEST_URL__", data: url }, "*");
|
||||||
console.log(`[Manifest][${source}]`, url, contentType);
|
logWithPrefix(`[Manifest][${source}]`, url, contentType);
|
||||||
|
|
||||||
const headerFlags = headersToFlags(headersObj);
|
const headerFlags = headersToFlags(headersObj);
|
||||||
|
|
||||||
@ -209,7 +224,7 @@ class RemoteCDMBase {
|
|||||||
const jsonData = JSON.parse(xhr.responseText);
|
const jsonData = JSON.parse(xhr.responseText);
|
||||||
if (jsonData.data?.session_id) {
|
if (jsonData.data?.session_id) {
|
||||||
this.session_id = jsonData.data.session_id;
|
this.session_id = jsonData.data.session_id;
|
||||||
console.log("Session opened:", this.session_id);
|
logWithPrefix("Session opened:", this.session_id);
|
||||||
} else {
|
} else {
|
||||||
console.error("Failed to open session:", jsonData.message);
|
console.error("Failed to open session:", jsonData.message);
|
||||||
throw new Error("Failed to open session");
|
throw new Error("Failed to open session");
|
||||||
@ -225,10 +240,10 @@ class RemoteCDMBase {
|
|||||||
const jsonData = JSON.parse(xhr.responseText);
|
const jsonData = JSON.parse(xhr.responseText);
|
||||||
if (jsonData.data?.challenge) {
|
if (jsonData.data?.challenge) {
|
||||||
this.challenge = btoa(jsonData.data.challenge);
|
this.challenge = btoa(jsonData.data.challenge);
|
||||||
console.log("Challenge received:", this.challenge);
|
logWithPrefix("Challenge received:", this.challenge);
|
||||||
} else if (jsonData.data?.challenge_b64) {
|
} else if (jsonData.data?.challenge_b64) {
|
||||||
this.challenge = jsonData.data.challenge_b64;
|
this.challenge = jsonData.data.challenge_b64;
|
||||||
console.log("Challenge received:", this.challenge);
|
logWithPrefix("Challenge received:", this.challenge);
|
||||||
} else {
|
} else {
|
||||||
console.error("Failed to get challenge:", jsonData.message);
|
console.error("Failed to get challenge:", jsonData.message);
|
||||||
throw new Error("Failed to get challenge");
|
throw new Error("Failed to get challenge");
|
||||||
@ -243,7 +258,7 @@ class RemoteCDMBase {
|
|||||||
xhr.send(JSON.stringify(body));
|
xhr.send(JSON.stringify(body));
|
||||||
const jsonData = JSON.parse(xhr.responseText);
|
const jsonData = JSON.parse(xhr.responseText);
|
||||||
if (jsonData.status === 200 || jsonData.message?.includes("parsed and loaded")) {
|
if (jsonData.status === 200 || jsonData.message?.includes("parsed and loaded")) {
|
||||||
console.log("License response parsed successfully");
|
logWithPrefix("License response parsed successfully");
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
console.error("Failed to parse license response:", jsonData.message);
|
console.error("Failed to parse license response:", jsonData.message);
|
||||||
@ -260,7 +275,7 @@ class RemoteCDMBase {
|
|||||||
const jsonData = JSON.parse(xhr.responseText);
|
const jsonData = JSON.parse(xhr.responseText);
|
||||||
if (jsonData.data?.keys) {
|
if (jsonData.data?.keys) {
|
||||||
this.keys = jsonData.data.keys;
|
this.keys = jsonData.data.keys;
|
||||||
console.log("Keys received:", this.keys);
|
logWithPrefix("Keys received:", this.keys);
|
||||||
} else {
|
} else {
|
||||||
console.error("Failed to get keys:", jsonData.message);
|
console.error("Failed to get keys:", jsonData.message);
|
||||||
throw new Error("Failed to get keys");
|
throw new Error("Failed to get keys");
|
||||||
@ -275,7 +290,7 @@ class RemoteCDMBase {
|
|||||||
xhr.send();
|
xhr.send();
|
||||||
const jsonData = JSON.parse(xhr.responseText);
|
const jsonData = JSON.parse(xhr.responseText);
|
||||||
if (jsonData) {
|
if (jsonData) {
|
||||||
console.log("Session closed successfully");
|
logWithPrefix("Session closed successfully");
|
||||||
} else {
|
} else {
|
||||||
console.error("Failed to close session:", jsonData.message);
|
console.error("Failed to close session:", jsonData.message);
|
||||||
throw new Error("Failed to close session");
|
throw new Error("Failed to close session");
|
||||||
@ -342,7 +357,7 @@ class remoteWidevineCDM extends RemoteCDMBase {
|
|||||||
xhr.send(JSON.stringify(body));
|
xhr.send(JSON.stringify(body));
|
||||||
const jsonData = JSON.parse(xhr.responseText);
|
const jsonData = JSON.parse(xhr.responseText);
|
||||||
if (jsonData.status === 200) {
|
if (jsonData.status === 200) {
|
||||||
console.log("Service certificate set successfully");
|
logWithPrefix("Service certificate set successfully");
|
||||||
} else {
|
} else {
|
||||||
console.error("Failed to set service certificate:", jsonData.message);
|
console.error("Failed to set service certificate:", jsonData.message);
|
||||||
throw new Error("Failed to set service certificate");
|
throw new Error("Failed to set service certificate");
|
||||||
@ -363,7 +378,7 @@ class remoteWidevineCDM extends RemoteCDMBase {
|
|||||||
const jsonData = JSON.parse(xhr.responseText);
|
const jsonData = JSON.parse(xhr.responseText);
|
||||||
if (jsonData.data?.challenge_b64) {
|
if (jsonData.data?.challenge_b64) {
|
||||||
this.challenge = jsonData.data.challenge_b64;
|
this.challenge = jsonData.data.challenge_b64;
|
||||||
console.log("Widevine challenge received:", this.challenge);
|
logWithPrefix("Widevine challenge received:", this.challenge);
|
||||||
} else {
|
} else {
|
||||||
console.error("Failed to get Widevine challenge:", jsonData.message);
|
console.error("Failed to get Widevine challenge:", jsonData.message);
|
||||||
throw new Error("Failed to get Widevine challenge");
|
throw new Error("Failed to get Widevine challenge");
|
||||||
@ -501,30 +516,74 @@ function arrayBufferToBase64(uint8array) {
|
|||||||
return window.btoa(binary);
|
return window.btoa(binary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function bufferToBase64(buffer) {
|
||||||
|
const uint8 = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
|
||||||
|
return window.btoa(String.fromCharCode(...uint8));
|
||||||
|
}
|
||||||
|
|
||||||
|
// DRM type detection
|
||||||
|
function isWidevine(base64str) {
|
||||||
|
return base64str.startsWith(DRM_SIGNATURES.WIDEVINE);
|
||||||
|
}
|
||||||
|
function isPlayReady(base64str) {
|
||||||
|
return base64str.startsWith(DRM_SIGNATURES.PLAYREADY);
|
||||||
|
}
|
||||||
|
function isServiceCertificate(base64str) {
|
||||||
|
return base64str.startsWith(DRM_SIGNATURES.SERVICE_CERT);
|
||||||
|
}
|
||||||
|
|
||||||
|
function postDRMTypeAndPssh(type, pssh) {
|
||||||
|
window.postMessage({ type: "__DRM_TYPE__", data: type }, "*");
|
||||||
|
window.postMessage({ type: "__PSSH_DATA__", data: pssh }, "*");
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureRemoteCDM(type, deviceInfo, pssh) {
|
||||||
|
if (!remoteCDM) {
|
||||||
|
if (type === "Widevine") {
|
||||||
|
const { device_type, system_id, security_level, host, secret, device_name } =
|
||||||
|
deviceInfo;
|
||||||
|
remoteCDM = new remoteWidevineCDM(
|
||||||
|
device_type,
|
||||||
|
system_id,
|
||||||
|
security_level,
|
||||||
|
host,
|
||||||
|
secret,
|
||||||
|
device_name
|
||||||
|
);
|
||||||
|
remoteCDM.openSession();
|
||||||
|
remoteCDM.getChallenge(pssh);
|
||||||
|
} else if (type === "PlayReady") {
|
||||||
|
const { security_level, host, secret, device_name } = deviceInfo;
|
||||||
|
remoteCDM = new remotePlayReadyCDM(security_level, host, secret, device_name);
|
||||||
|
remoteCDM.openSession();
|
||||||
|
remoteCDM.getChallenge(pssh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Challenge generator interceptor
|
// Challenge generator interceptor
|
||||||
const originalGenerateRequest = MediaKeySession.prototype.generateRequest;
|
const originalGenerateRequest = MediaKeySession.prototype.generateRequest;
|
||||||
MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
|
MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
|
||||||
const session = this;
|
const session = this;
|
||||||
let playReadyPssh = getPlayReadyPssh(initData);
|
let playReadyPssh = getPlayReadyPssh(initData);
|
||||||
if (playReadyPssh) {
|
if (playReadyPssh) {
|
||||||
console.log("[DRM Detected] PlayReady");
|
logWithPrefix("[DRM Detected] PlayReady");
|
||||||
foundPlayreadyPssh = playReadyPssh;
|
foundPlayreadyPssh = playReadyPssh;
|
||||||
console.log("[PlayReady PSSH found] " + playReadyPssh);
|
logWithPrefix("[PlayReady PSSH found] " + playReadyPssh);
|
||||||
}
|
}
|
||||||
let wideVinePssh = getWidevinePssh(initData);
|
let wideVinePssh = getWidevinePssh(initData);
|
||||||
if (wideVinePssh) {
|
if (wideVinePssh) {
|
||||||
// Widevine code
|
// Widevine code
|
||||||
console.log("[DRM Detected] Widevine");
|
logWithPrefix("[DRM Detected] Widevine");
|
||||||
foundWidevinePssh = wideVinePssh;
|
foundWidevinePssh = wideVinePssh;
|
||||||
console.log("[Widevine PSSH found] " + wideVinePssh);
|
logWithPrefix("[Widevine PSSH found] " + wideVinePssh);
|
||||||
}
|
}
|
||||||
// Challenge message interceptor
|
// Challenge message interceptor
|
||||||
if (!remoteListenerMounted) {
|
if (!remoteListenerMounted) {
|
||||||
remoteListenerMounted = true;
|
remoteListenerMounted = true;
|
||||||
session.addEventListener("message", function messageInterceptor(event) {
|
session.addEventListener("message", function messageInterceptor(event) {
|
||||||
event.stopImmediatePropagation();
|
event.stopImmediatePropagation();
|
||||||
const uint8Array = new Uint8Array(event.message);
|
const base64challenge = bufferToBase64(event.message);
|
||||||
const base64challenge = arrayBufferToBase64(uint8Array);
|
|
||||||
if (
|
if (
|
||||||
base64challenge === DRM_SIGNATURES.WIDEVINE_INIT &&
|
base64challenge === DRM_SIGNATURES.WIDEVINE_INIT &&
|
||||||
interceptType !== "DISABLED" &&
|
interceptType !== "DISABLED" &&
|
||||||
@ -554,27 +613,9 @@ MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
|
|||||||
originalChallenge = base64challenge;
|
originalChallenge = base64challenge;
|
||||||
}
|
}
|
||||||
if (originalChallenge.startsWith(DRM_SIGNATURES.WIDEVINE)) {
|
if (originalChallenge.startsWith(DRM_SIGNATURES.WIDEVINE)) {
|
||||||
window.postMessage({ type: "__DRM_TYPE__", data: "Widevine" }, "*");
|
postDRMTypeAndPssh("Widevine", foundWidevinePssh);
|
||||||
window.postMessage({ type: "__PSSH_DATA__", data: foundWidevinePssh }, "*");
|
if (interceptType === "EME") {
|
||||||
if (interceptType === "EME" && !remoteCDM) {
|
ensureRemoteCDM("Widevine", widevineDeviceInfo, foundWidevinePssh);
|
||||||
const {
|
|
||||||
device_type,
|
|
||||||
system_id,
|
|
||||||
security_level,
|
|
||||||
host,
|
|
||||||
secret,
|
|
||||||
device_name,
|
|
||||||
} = widevineDeviceInfo;
|
|
||||||
remoteCDM = new remoteWidevineCDM(
|
|
||||||
device_type,
|
|
||||||
system_id,
|
|
||||||
security_level,
|
|
||||||
host,
|
|
||||||
secret,
|
|
||||||
device_name
|
|
||||||
);
|
|
||||||
remoteCDM.openSession();
|
|
||||||
remoteCDM.getChallenge(foundWidevinePssh);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!originalChallenge.startsWith(DRM_SIGNATURES.WIDEVINE)) {
|
if (!originalChallenge.startsWith(DRM_SIGNATURES.WIDEVINE)) {
|
||||||
@ -585,23 +626,10 @@ MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
|
|||||||
/<Challenge encoding="base64encoded">([^<]+)<\/Challenge>/
|
/<Challenge encoding="base64encoded">([^<]+)<\/Challenge>/
|
||||||
);
|
);
|
||||||
if (match) {
|
if (match) {
|
||||||
window.postMessage({ type: "__DRM_TYPE__", data: "PlayReady" }, "*");
|
postDRMTypeAndPssh("PlayReady", foundPlayreadyPssh);
|
||||||
window.postMessage(
|
|
||||||
{ type: "__PSSH_DATA__", data: foundPlayreadyPssh },
|
|
||||||
"*"
|
|
||||||
);
|
|
||||||
originalChallenge = match[1];
|
originalChallenge = match[1];
|
||||||
if (interceptType === "EME" && !remoteCDM) {
|
if (interceptType === "EME") {
|
||||||
const { security_level, host, secret, device_name } =
|
ensureRemoteCDM("PlayReady", playreadyDeviceInfo, foundPlayreadyPssh);
|
||||||
playreadyDeviceInfo;
|
|
||||||
remoteCDM = new remotePlayReadyCDM(
|
|
||||||
security_level,
|
|
||||||
host,
|
|
||||||
secret,
|
|
||||||
device_name
|
|
||||||
);
|
|
||||||
remoteCDM.openSession();
|
|
||||||
remoteCDM.getChallenge(foundPlayreadyPssh);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -618,12 +646,12 @@ MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
|
|||||||
Object.defineProperty(syntheticEvent, "message", {
|
Object.defineProperty(syntheticEvent, "message", {
|
||||||
get: () => challengeBuffer,
|
get: () => challengeBuffer,
|
||||||
});
|
});
|
||||||
console.log("Intercepted EME Challenge and injected custom one.");
|
logWithPrefix("Intercepted EME Challenge and injected custom one.");
|
||||||
session.dispatchEvent(syntheticEvent);
|
session.dispatchEvent(syntheticEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log("Message interceptor mounted.");
|
logWithPrefix("Message interceptor mounted.");
|
||||||
}
|
}
|
||||||
return originalGenerateRequest.call(session, initDataType, initData);
|
return originalGenerateRequest.call(session, initDataType, initData);
|
||||||
};
|
};
|
||||||
@ -631,8 +659,7 @@ MediaKeySession.prototype.generateRequest = function (initDataType, initData) {
|
|||||||
// Message update interceptors
|
// Message update interceptors
|
||||||
const originalUpdate = MediaKeySession.prototype.update;
|
const originalUpdate = MediaKeySession.prototype.update;
|
||||||
MediaKeySession.prototype.update = function (response) {
|
MediaKeySession.prototype.update = function (response) {
|
||||||
const uint8 = response instanceof Uint8Array ? response : new Uint8Array(response);
|
const base64Response = bufferToBase64(response);
|
||||||
const base64Response = window.btoa(String.fromCharCode(...uint8));
|
|
||||||
if (
|
if (
|
||||||
base64Response.startsWith(DRM_SIGNATURES.SERVICE_CERT) &&
|
base64Response.startsWith(DRM_SIGNATURES.SERVICE_CERT) &&
|
||||||
foundWidevinePssh &&
|
foundWidevinePssh &&
|
||||||
@ -667,7 +694,7 @@ MediaKeySession.prototype.update = function (response) {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
let clearKeys = getClearkey(response);
|
let clearKeys = getClearkey(response);
|
||||||
if (clearKeys && clearKeys.length > 0) {
|
if (clearKeys && clearKeys.length > 0) {
|
||||||
console.log("[CLEARKEY] ", clearKeys);
|
logWithPrefix("[CLEARKEY] ", clearKeys);
|
||||||
const drmType = {
|
const drmType = {
|
||||||
type: "__DRM_TYPE__",
|
type: "__DRM_TYPE__",
|
||||||
data: "ClearKey",
|
data: "ClearKey",
|
||||||
@ -681,7 +708,7 @@ MediaKeySession.prototype.update = function (response) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
console.log("[CLEARKEY] Not found");
|
logWithPrefix("[CLEARKEY] Not found");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user