prettier formatting, add manifest url in console.log
This commit is contained in:
		
							parent
							
								
									bafe525510
								
							
						
					
					
						commit
						c9ff17558d
					
				
							
								
								
									
										3
									
								
								.prettierignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.prettierignore
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					react/
 | 
				
			||||||
 | 
					frontend/dist/
 | 
				
			||||||
 | 
					frontend/src/assets/
 | 
				
			||||||
							
								
								
									
										8
									
								
								.prettierrc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.prettierrc.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "trailingComma": "es5",
 | 
				
			||||||
 | 
					    "tabWidth": 4,
 | 
				
			||||||
 | 
					    "semi": true,
 | 
				
			||||||
 | 
					    "singleQuote": false,
 | 
				
			||||||
 | 
					    "useTabs": false,
 | 
				
			||||||
 | 
					    "printWidth": 100
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										130
									
								
								background.js
									
									
									
									
									
								
							
							
						
						
									
										130
									
								
								background.js
									
									
									
									
									
								
							@ -1,84 +1,84 @@
 | 
				
			|||||||
// Open popout window when the extension icon is clicked
 | 
					// Open popout window when the extension icon is clicked
 | 
				
			||||||
chrome.browserAction.onClicked.addListener(() => {
 | 
					chrome.browserAction.onClicked.addListener(() => {
 | 
				
			||||||
  chrome.windows.create({
 | 
					    chrome.windows.create({
 | 
				
			||||||
    url: chrome.runtime.getURL("react/index.html"),
 | 
					        url: chrome.runtime.getURL("react/index.html"),
 | 
				
			||||||
    type: "popup",  // opens as a floating window
 | 
					        type: "popup", // opens as a floating window
 | 
				
			||||||
    width: 800,
 | 
					        width: 800,
 | 
				
			||||||
    height: 600
 | 
					        height: 600,
 | 
				
			||||||
  });
 | 
					    });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Listen for messages and store data in chrome.storage.local
 | 
					// Listen for messages and store data in chrome.storage.local
 | 
				
			||||||
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
 | 
					chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
 | 
				
			||||||
  const { type, data } = message;
 | 
					    const { type, data } = message;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  switch (type) {
 | 
					    switch (type) {
 | 
				
			||||||
    case "DRM_TYPE":
 | 
					        case "DRM_TYPE":
 | 
				
			||||||
      console.log("DRM Type:", data);
 | 
					            console.log("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);
 | 
					            console.log("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);
 | 
					            console.log("Storing Decryption Keys:", data);
 | 
				
			||||||
      chrome.storage.local.set({ latestKeys: data });
 | 
					            chrome.storage.local.set({ latestKeys: data });
 | 
				
			||||||
      break;
 | 
					            break;
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    case "LICENSE_URL":
 | 
					 | 
				
			||||||
      console.log("Storling License URL " + data);
 | 
					 | 
				
			||||||
      chrome.storage.local.set({licenseURL: data});
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    default:
 | 
					        case "LICENSE_URL":
 | 
				
			||||||
      console.warn("Unknown message type received:", type);
 | 
					            console.log("Storling License URL " + data);
 | 
				
			||||||
  }
 | 
					            chrome.storage.local.set({ licenseURL: data });
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            console.warn("Unknown message type received:", type);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 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) => {
 | 
				
			||||||
  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.");
 | 
					                console.log("valid_config set to false on first install.");
 | 
				
			||||||
      }
 | 
					            }
 | 
				
			||||||
    });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    chrome.storage.local.set({ injection_type: "LICENSE" }, () => {
 | 
					        chrome.storage.local.set({ injection_type: "LICENSE" }, () => {
 | 
				
			||||||
      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.");
 | 
					                console.log("Injection type set to LICENSE on first install.");
 | 
				
			||||||
      }
 | 
					            }
 | 
				
			||||||
    });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    chrome.storage.local.set({ drm_override: "DISABLED" }, () => {
 | 
					        chrome.storage.local.set({ drm_override: "DISABLED" }, () => {
 | 
				
			||||||
      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.");
 | 
					                console.log("DRM Override type set to DISABLED on first install.");
 | 
				
			||||||
      }
 | 
					            }
 | 
				
			||||||
    });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    chrome.storage.local.set({ cdrm_instance: null }, () => {
 | 
					        chrome.storage.local.set({ cdrm_instance: null }, () => {
 | 
				
			||||||
      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.");
 | 
					                console.log("CDRM instance set to null.");
 | 
				
			||||||
      }
 | 
					            }
 | 
				
			||||||
    });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    chrome.storage.local.set({ cdrm_api_key: null }, () => {
 | 
					        chrome.storage.local.set({ cdrm_api_key: null }, () => {
 | 
				
			||||||
      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.");
 | 
					                console.log("CDRM API Key set.");
 | 
				
			||||||
      }
 | 
					            }
 | 
				
			||||||
    });
 | 
					        });
 | 
				
			||||||
  }
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										115
									
								
								content.js
									
									
									
									
									
								
							
							
						
						
									
										115
									
								
								content.js
									
									
									
									
									
								
							@ -1,67 +1,96 @@
 | 
				
			|||||||
// Inject `inject.js` into the page context
 | 
					// Inject `inject.js` into the page context
 | 
				
			||||||
(function injectScript() {
 | 
					(function injectScript() {
 | 
				
			||||||
  const script = document.createElement('script');
 | 
					    const script = document.createElement("script");
 | 
				
			||||||
  script.src = chrome.runtime.getURL('inject.js');
 | 
					    script.src = chrome.runtime.getURL("inject.js");
 | 
				
			||||||
  script.type = 'text/javascript';
 | 
					    script.type = "text/javascript";
 | 
				
			||||||
  script.onload = () => script.remove(); // Clean up
 | 
					    script.onload = () => script.remove(); // Clean up
 | 
				
			||||||
  // Inject directly into <html> or <head>
 | 
					    // Inject directly into <html> or <head>
 | 
				
			||||||
  (document.documentElement || document.head || document.body).appendChild(script);
 | 
					    (document.documentElement || document.head || document.body).appendChild(script);
 | 
				
			||||||
})();
 | 
					})();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Listen for messages from the injected script
 | 
					// Listen for messages from the injected script
 | 
				
			||||||
window.addEventListener("message", function(event) {
 | 
					window.addEventListener("message", function (event) {
 | 
				
			||||||
    if (event.source !== window) return;
 | 
					    if (event.source !== window) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (["__DRM_TYPE__", "__PSSH_DATA__", "__KEYS_DATA__", "__LICENSE_URL__"].includes(event.data?.type)) {
 | 
					    if (
 | 
				
			||||||
 | 
					        ["__DRM_TYPE__", "__PSSH_DATA__", "__KEYS_DATA__", "__LICENSE_URL__"].includes(
 | 
				
			||||||
 | 
					            event.data?.type
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
        chrome.runtime.sendMessage({
 | 
					        chrome.runtime.sendMessage({
 | 
				
			||||||
            type: event.data.type.replace("__", "").replace("__", ""),
 | 
					            type: event.data.type.replace("__", "").replace("__", ""),
 | 
				
			||||||
            data: event.data.data
 | 
					            data: event.data.data,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (event.data.type === "__GET_CDM_DEVICES__") {
 | 
					    if (event.data.type === "__GET_CDM_DEVICES__") {
 | 
				
			||||||
 | 
					        chrome.storage.local.get(["widevine_device", "playready_device"], (result) => {
 | 
				
			||||||
 | 
					            const widevine_device = result.widevine_device || null;
 | 
				
			||||||
 | 
					            const playready_device = result.playready_device || null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      chrome.storage.local.get(["widevine_device", "playready_device"], (result) => {
 | 
					            window.postMessage(
 | 
				
			||||||
        const widevine_device = result.widevine_device || null;
 | 
					                {
 | 
				
			||||||
        const playready_device = result.playready_device || null;
 | 
					                    type: "__CDM_DEVICES__",
 | 
				
			||||||
 | 
					                    widevine_device,
 | 
				
			||||||
        window.postMessage(
 | 
					                    playready_device,
 | 
				
			||||||
          {
 | 
					                },
 | 
				
			||||||
            type: "__CDM_DEVICES__",
 | 
					                "*"
 | 
				
			||||||
            widevine_device,
 | 
					            );
 | 
				
			||||||
            playready_device
 | 
					        });
 | 
				
			||||||
          },
 | 
					 | 
				
			||||||
          "*"
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (event.data.type === "__GET_INJECTION_TYPE__") {
 | 
					    if (event.data.type === "__GET_INJECTION_TYPE__") {
 | 
				
			||||||
 | 
					        chrome.storage.local.get("injection_type", (result) => {
 | 
				
			||||||
 | 
					            const injectionType = result.injection_type || "LICENSE";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      chrome.storage.local.get("injection_type", (result) => {
 | 
					            window.postMessage(
 | 
				
			||||||
        const injectionType = result.injection_type || "LICENSE";
 | 
					                {
 | 
				
			||||||
 | 
					                    type: "__INJECTION_TYPE__",
 | 
				
			||||||
        window.postMessage(
 | 
					                    injectionType,
 | 
				
			||||||
          {
 | 
					                },
 | 
				
			||||||
            type: "__INJECTION_TYPE__",
 | 
					                "*"
 | 
				
			||||||
            injectionType
 | 
					            );
 | 
				
			||||||
          },
 | 
					        });
 | 
				
			||||||
          "*"
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (event.data.type === "__GET_DRM_OVERRIDE__") {
 | 
					    if (event.data.type === "__GET_DRM_OVERRIDE__") {
 | 
				
			||||||
 | 
					        chrome.storage.local.get("drm_override", (result) => {
 | 
				
			||||||
 | 
					            const drmOverride = result.drm_override || "DISABLED";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      chrome.storage.local.get("drm_override", (result) => {
 | 
					            window.postMessage(
 | 
				
			||||||
        const drmOverride = result.drm_override || "DISABLED";
 | 
					                {
 | 
				
			||||||
 | 
					                    type: "__DRM_OVERRIDE__",
 | 
				
			||||||
 | 
					                    drmOverride,
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                "*"
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        window.postMessage(
 | 
					    // Manifest header and URL
 | 
				
			||||||
          {
 | 
					
 | 
				
			||||||
            type: "__DRM_OVERRIDE__",
 | 
					    const seenManifestUrls = new Set();
 | 
				
			||||||
            drmOverride
 | 
					
 | 
				
			||||||
          },
 | 
					    if (event.data?.type === "__MANIFEST_URL__") {
 | 
				
			||||||
          "*"
 | 
					        const url = event.data.data;
 | 
				
			||||||
        );
 | 
					        if (seenManifestUrls.has(url)) return;
 | 
				
			||||||
      });
 | 
					        seenManifestUrls.add(url);
 | 
				
			||||||
 | 
					        console.log("✅ [Content] Unique manifest URL:", url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        chrome.runtime.sendMessage({
 | 
				
			||||||
 | 
					            type: "MANIFEST_URL_FOUND",
 | 
				
			||||||
 | 
					            data: url,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (event.data?.type === "__MANIFEST_HEADERS__") {
 | 
				
			||||||
 | 
					        const { url, headers } = event.data;
 | 
				
			||||||
 | 
					        console.log("[Content.js] Manifest Headers:", url, headers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        chrome.runtime.sendMessage({
 | 
				
			||||||
 | 
					            type: "MANIFEST_HEADERS",
 | 
				
			||||||
 | 
					            url,
 | 
				
			||||||
 | 
					            headers,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
@ -1,33 +1,30 @@
 | 
				
			|||||||
import js from '@eslint/js'
 | 
					import js from "@eslint/js";
 | 
				
			||||||
import globals from 'globals'
 | 
					import globals from "globals";
 | 
				
			||||||
import reactHooks from 'eslint-plugin-react-hooks'
 | 
					import reactHooks from "eslint-plugin-react-hooks";
 | 
				
			||||||
import reactRefresh from 'eslint-plugin-react-refresh'
 | 
					import reactRefresh from "eslint-plugin-react-refresh";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default [
 | 
					export default [
 | 
				
			||||||
  { ignores: ['dist'] },
 | 
					    { ignores: ["dist"] },
 | 
				
			||||||
  {
 | 
					    {
 | 
				
			||||||
    files: ['**/*.{js,jsx}'],
 | 
					        files: ["**/*.{js,jsx}"],
 | 
				
			||||||
    languageOptions: {
 | 
					        languageOptions: {
 | 
				
			||||||
      ecmaVersion: 2020,
 | 
					            ecmaVersion: 2020,
 | 
				
			||||||
      globals: globals.browser,
 | 
					            globals: globals.browser,
 | 
				
			||||||
      parserOptions: {
 | 
					            parserOptions: {
 | 
				
			||||||
        ecmaVersion: 'latest',
 | 
					                ecmaVersion: "latest",
 | 
				
			||||||
        ecmaFeatures: { jsx: true },
 | 
					                ecmaFeatures: { jsx: true },
 | 
				
			||||||
        sourceType: 'module',
 | 
					                sourceType: "module",
 | 
				
			||||||
      },
 | 
					            },
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        plugins: {
 | 
				
			||||||
 | 
					            "react-hooks": reactHooks,
 | 
				
			||||||
 | 
					            "react-refresh": reactRefresh,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        rules: {
 | 
				
			||||||
 | 
					            ...js.configs.recommended.rules,
 | 
				
			||||||
 | 
					            ...reactHooks.configs.recommended.rules,
 | 
				
			||||||
 | 
					            "no-unused-vars": ["error", { varsIgnorePattern: "^[A-Z_]" }],
 | 
				
			||||||
 | 
					            "react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    plugins: {
 | 
					];
 | 
				
			||||||
      'react-hooks': reactHooks,
 | 
					 | 
				
			||||||
      'react-refresh': reactRefresh,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    rules: {
 | 
					 | 
				
			||||||
      ...js.configs.recommended.rules,
 | 
					 | 
				
			||||||
      ...reactHooks.configs.recommended.rules,
 | 
					 | 
				
			||||||
      'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
 | 
					 | 
				
			||||||
      'react-refresh/only-export-components': [
 | 
					 | 
				
			||||||
        'warn',
 | 
					 | 
				
			||||||
        { allowConstantExport: true },
 | 
					 | 
				
			||||||
      ],
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,12 @@
 | 
				
			|||||||
<!doctype html>
 | 
					<!doctype html>
 | 
				
			||||||
<html lang="en">
 | 
					<html lang="en">
 | 
				
			||||||
  <head>
 | 
					    <head>
 | 
				
			||||||
    <meta charset="UTF-8" />
 | 
					        <meta charset="UTF-8" />
 | 
				
			||||||
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 | 
					        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 | 
				
			||||||
    <title>CDRM Decryption Extension</title>
 | 
					        <title>CDRM Decryption Extension</title>
 | 
				
			||||||
  </head>
 | 
					    </head>
 | 
				
			||||||
  <body class="min-w-full min-h-full w-full h-full">
 | 
					    <body class="min-w-full min-h-full w-full h-full">
 | 
				
			||||||
    <div class="min-w-full min-h-full w-full h-full" id="root"></div>
 | 
					        <div class="min-w-full min-h-full w-full h-full" id="root"></div>
 | 
				
			||||||
    <script type="module" src="/src/main.jsx"></script>
 | 
					        <script type="module" src="/src/main.jsx"></script>
 | 
				
			||||||
  </body>
 | 
					    </body>
 | 
				
			||||||
</html>
 | 
					</html>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										6810
									
								
								frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6810
									
								
								frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -1,30 +1,30 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "frontend",
 | 
					    "name": "frontend",
 | 
				
			||||||
  "private": true,
 | 
					    "private": true,
 | 
				
			||||||
  "version": "0.0.0",
 | 
					    "version": "0.0.0",
 | 
				
			||||||
  "type": "module",
 | 
					    "type": "module",
 | 
				
			||||||
  "scripts": {
 | 
					    "scripts": {
 | 
				
			||||||
    "dev": "vite",
 | 
					        "dev": "vite",
 | 
				
			||||||
    "build": "vite build",
 | 
					        "build": "vite build",
 | 
				
			||||||
    "lint": "eslint .",
 | 
					        "lint": "eslint .",
 | 
				
			||||||
    "preview": "vite preview"
 | 
					        "preview": "vite preview"
 | 
				
			||||||
  },
 | 
					    },
 | 
				
			||||||
  "dependencies": {
 | 
					    "dependencies": {
 | 
				
			||||||
    "@tailwindcss/vite": "^4.1.7",
 | 
					        "@tailwindcss/vite": "^4.1.7",
 | 
				
			||||||
    "react": "^19.1.0",
 | 
					        "react": "^19.1.0",
 | 
				
			||||||
    "react-dom": "^19.1.0",
 | 
					        "react-dom": "^19.1.0",
 | 
				
			||||||
    "react-router-dom": "^7.6.1",
 | 
					        "react-router-dom": "^7.6.1",
 | 
				
			||||||
    "tailwindcss": "^4.1.7"
 | 
					        "tailwindcss": "^4.1.7"
 | 
				
			||||||
  },
 | 
					    },
 | 
				
			||||||
  "devDependencies": {
 | 
					    "devDependencies": {
 | 
				
			||||||
    "@eslint/js": "^9.25.0",
 | 
					        "@eslint/js": "^9.25.0",
 | 
				
			||||||
    "@types/react": "^19.1.2",
 | 
					        "@types/react": "^19.1.2",
 | 
				
			||||||
    "@types/react-dom": "^19.1.2",
 | 
					        "@types/react-dom": "^19.1.2",
 | 
				
			||||||
    "@vitejs/plugin-react": "^4.4.1",
 | 
					        "@vitejs/plugin-react": "^4.4.1",
 | 
				
			||||||
    "eslint": "^9.25.0",
 | 
					        "eslint": "^9.25.0",
 | 
				
			||||||
    "eslint-plugin-react-hooks": "^5.2.0",
 | 
					        "eslint-plugin-react-hooks": "^5.2.0",
 | 
				
			||||||
    "eslint-plugin-react-refresh": "^0.4.19",
 | 
					        "eslint-plugin-react-refresh": "^0.4.19",
 | 
				
			||||||
    "globals": "^16.0.0",
 | 
					        "globals": "^16.0.0",
 | 
				
			||||||
    "vite": "^6.3.5"
 | 
					        "vite": "^6.3.5"
 | 
				
			||||||
  }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,77 +1,72 @@
 | 
				
			|||||||
import { useState, useEffect } from "react";
 | 
					import { useState, useEffect } from "react";
 | 
				
			||||||
import {
 | 
					import { HashRouter as Router, Routes, Route, Navigate } from "react-router-dom";
 | 
				
			||||||
  HashRouter as Router,
 | 
					 | 
				
			||||||
  Routes,
 | 
					 | 
				
			||||||
  Route,
 | 
					 | 
				
			||||||
  Navigate,
 | 
					 | 
				
			||||||
} from "react-router-dom";
 | 
					 | 
				
			||||||
import TopNav from "./components/topnav";
 | 
					import TopNav from "./components/topnav";
 | 
				
			||||||
import SideNav from "./components/sidenav";
 | 
					import SideNav from "./components/sidenav";
 | 
				
			||||||
import Results from "./components/results";
 | 
					import Results from "./components/results";
 | 
				
			||||||
import Settings from "./components/settings";
 | 
					import Settings from "./components/settings";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function App() {
 | 
					function App() {
 | 
				
			||||||
  const [isSideNavOpen, setIsSideNavOpen] = useState(false);
 | 
					    const [isSideNavOpen, setIsSideNavOpen] = useState(false);
 | 
				
			||||||
  const [validConfig, setValidConfig] = useState(null); // null = loading
 | 
					    const [validConfig, setValidConfig] = useState(null); // null = loading
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  useEffect(() => {
 | 
					    useEffect(() => {
 | 
				
			||||||
    chrome.storage.local.get("valid_config", (result) => {
 | 
					        chrome.storage.local.get("valid_config", (result) => {
 | 
				
			||||||
      if (chrome.runtime.lastError) {
 | 
					            if (chrome.runtime.lastError) {
 | 
				
			||||||
        console.error("Error reading valid_config:", chrome.runtime.lastError);
 | 
					                console.error("Error reading valid_config:", chrome.runtime.lastError);
 | 
				
			||||||
        setValidConfig(false); // fallback
 | 
					                setValidConfig(false); // fallback
 | 
				
			||||||
      } else {
 | 
					            } else {
 | 
				
			||||||
        setValidConfig(result.valid_config === true);
 | 
					                setValidConfig(result.valid_config === true);
 | 
				
			||||||
      }
 | 
					            }
 | 
				
			||||||
    });
 | 
					        });
 | 
				
			||||||
  }, []);
 | 
					    }, []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (validConfig === null) {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					            <div className="flex items-center justify-center h-screen bg-black text-white">
 | 
				
			||||||
 | 
					                Loading...
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (validConfig === null) {
 | 
					 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div className="flex items-center justify-center h-screen bg-black text-white">
 | 
					        <Router>
 | 
				
			||||||
        Loading...
 | 
					            <div className="min-w-full min-h-full w-full h-full flex flex-grow bg-black/95 flex-col relative">
 | 
				
			||||||
      </div>
 | 
					                <div className="w-full min-h-16 max-h-16 h-16 shrink-0 flex sticky top-0 z-20 border-b border-b-white bg-black overflow-x-hidden">
 | 
				
			||||||
 | 
					                    <TopNav onMenuClick={() => setIsSideNavOpen(true)} />
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <div id="currentpagecontainer" className="w-full grow overflow-y-auto">
 | 
				
			||||||
 | 
					                    <Routes>
 | 
				
			||||||
 | 
					                        {!validConfig ? (
 | 
				
			||||||
 | 
					                            <>
 | 
				
			||||||
 | 
					                                <Route
 | 
				
			||||||
 | 
					                                    path="/settings"
 | 
				
			||||||
 | 
					                                    element={
 | 
				
			||||||
 | 
					                                        <Settings onConfigSaved={() => setValidConfig(true)} />
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                />
 | 
				
			||||||
 | 
					                                <Route path="*" element={<Navigate to="/settings" replace />} />
 | 
				
			||||||
 | 
					                            </>
 | 
				
			||||||
 | 
					                        ) : (
 | 
				
			||||||
 | 
					                            <>
 | 
				
			||||||
 | 
					                                <Route path="/" element={<Navigate to="/results" replace />} />
 | 
				
			||||||
 | 
					                                <Route path="/results" element={<Results />} />
 | 
				
			||||||
 | 
					                                <Route path="/settings" element={<Settings />} />
 | 
				
			||||||
 | 
					                            </>
 | 
				
			||||||
 | 
					                        )}
 | 
				
			||||||
 | 
					                    </Routes>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <div
 | 
				
			||||||
 | 
					                    className={`fixed top-0 left-0 w-full h-full z-50 bg-black transform transition-transform duration-300 ease-in-out ${
 | 
				
			||||||
 | 
					                        isSideNavOpen ? "translate-x-0" : "-translate-x-full"
 | 
				
			||||||
 | 
					                    }`}
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					                    <SideNav onClose={() => setIsSideNavOpen(false)} />
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </Router>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return (
 | 
					 | 
				
			||||||
    <Router>
 | 
					 | 
				
			||||||
      <div className="min-w-full min-h-full w-full h-full flex flex-grow bg-black/95 flex-col relative">
 | 
					 | 
				
			||||||
        <div className="w-full min-h-16 max-h-16 h-16 shrink-0 flex sticky top-0 z-20 border-b border-b-white bg-black overflow-x-hidden">
 | 
					 | 
				
			||||||
          <TopNav onMenuClick={() => setIsSideNavOpen(true)} />
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <div id="currentpagecontainer" className="w-full grow overflow-y-auto">
 | 
					 | 
				
			||||||
          <Routes>
 | 
					 | 
				
			||||||
            {!validConfig ? (
 | 
					 | 
				
			||||||
              <>
 | 
					 | 
				
			||||||
                <Route
 | 
					 | 
				
			||||||
                  path="/settings"
 | 
					 | 
				
			||||||
                  element={
 | 
					 | 
				
			||||||
                    <Settings onConfigSaved={() => setValidConfig(true)} />
 | 
					 | 
				
			||||||
                  }
 | 
					 | 
				
			||||||
                />
 | 
					 | 
				
			||||||
                <Route path="*" element={<Navigate to="/settings" replace />} />
 | 
					 | 
				
			||||||
              </>
 | 
					 | 
				
			||||||
            ) : (
 | 
					 | 
				
			||||||
              <>
 | 
					 | 
				
			||||||
                <Route path="/" element={<Navigate to="/results" replace />} />
 | 
					 | 
				
			||||||
                <Route path="/results" element={<Results />} />
 | 
					 | 
				
			||||||
                <Route path="/settings" element={<Settings />} />
 | 
					 | 
				
			||||||
              </>
 | 
					 | 
				
			||||||
            )}
 | 
					 | 
				
			||||||
          </Routes>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <div
 | 
					 | 
				
			||||||
          className={`fixed top-0 left-0 w-full h-full z-50 bg-black transform transition-transform duration-300 ease-in-out ${
 | 
					 | 
				
			||||||
            isSideNavOpen ? "translate-x-0" : "-translate-x-full"
 | 
					 | 
				
			||||||
          }`}
 | 
					 | 
				
			||||||
        >
 | 
					 | 
				
			||||||
          <SideNav onClose={() => setIsSideNavOpen(false)} />
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </Router>
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default App;
 | 
					export default App;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,149 +1,139 @@
 | 
				
			|||||||
import React, { useEffect, useState } from "react";
 | 
					import React, { useEffect, useState } from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function Results() {
 | 
					function Results() {
 | 
				
			||||||
  const [drmType, setDrmType] = useState("");
 | 
					    const [drmType, setDrmType] = useState("");
 | 
				
			||||||
  const [pssh, setPssh] = useState("");
 | 
					    const [pssh, setPssh] = useState("");
 | 
				
			||||||
  const [licenseUrl, setLicenseUrl] = useState("");
 | 
					    const [licenseUrl, setLicenseUrl] = useState("");
 | 
				
			||||||
  const [keys, setKeys] = useState([]);
 | 
					    const [keys, setKeys] = useState([]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  useEffect(() => {
 | 
					    useEffect(() => {
 | 
				
			||||||
    chrome.storage.local.get(
 | 
					        chrome.storage.local.get(
 | 
				
			||||||
      [
 | 
					            ["drmType", "latestPSSH", "latestLicenseRequest", "latestKeys", "licenseURL"],
 | 
				
			||||||
        "drmType",
 | 
					            (result) => {
 | 
				
			||||||
        "latestPSSH",
 | 
					                if (result.drmType) setDrmType(result.drmType);
 | 
				
			||||||
        "latestLicenseRequest",
 | 
					                if (result.latestPSSH) setPssh(result.latestPSSH);
 | 
				
			||||||
        "latestKeys",
 | 
					                if (result.licenseURL) setLicenseUrl(result.licenseURL);
 | 
				
			||||||
        "licenseURL",
 | 
					                if (result.latestKeys) {
 | 
				
			||||||
      ],
 | 
					                    try {
 | 
				
			||||||
      (result) => {
 | 
					                        const parsed = Array.isArray(result.latestKeys)
 | 
				
			||||||
        if (result.drmType) setDrmType(result.drmType);
 | 
					                            ? result.latestKeys
 | 
				
			||||||
        if (result.latestPSSH) setPssh(result.latestPSSH);
 | 
					                            : JSON.parse(result.latestKeys);
 | 
				
			||||||
        if (result.licenseURL) setLicenseUrl(result.licenseURL);
 | 
					                        setKeys(parsed);
 | 
				
			||||||
        if (result.latestKeys) {
 | 
					                    } catch (e) {
 | 
				
			||||||
          try {
 | 
					                        console.error("Failed to parse keys:", e);
 | 
				
			||||||
            const parsed = Array.isArray(result.latestKeys)
 | 
					                        setKeys([]);
 | 
				
			||||||
              ? result.latestKeys
 | 
					                    }
 | 
				
			||||||
              : JSON.parse(result.latestKeys);
 | 
					                }
 | 
				
			||||||
            setKeys(parsed);
 | 
					            }
 | 
				
			||||||
          } catch (e) {
 | 
					 | 
				
			||||||
            console.error("Failed to parse keys:", e);
 | 
					 | 
				
			||||||
            setKeys([]);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const handleChange = (changes, area) => {
 | 
					 | 
				
			||||||
      if (area === "local") {
 | 
					 | 
				
			||||||
        if (changes.drmType) {
 | 
					 | 
				
			||||||
          setDrmType(changes.drmType.newValue);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (changes.latestPSSH) {
 | 
					 | 
				
			||||||
          setPssh(changes.latestPSSH.newValue);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (changes.licenseURL) {
 | 
					 | 
				
			||||||
          setLicenseUrl(changes.licenseURL.newValue);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (changes.latestKeys) {
 | 
					 | 
				
			||||||
          setKeys(changes.latestKeys.newValue);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    chrome.storage.onChanged.addListener(handleChange);
 | 
					 | 
				
			||||||
    return () => chrome.storage.onChanged.removeListener(handleChange);
 | 
					 | 
				
			||||||
  }, []);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const handleCapture = () => {
 | 
					 | 
				
			||||||
    // Reset stored values
 | 
					 | 
				
			||||||
    chrome.storage.local.set({
 | 
					 | 
				
			||||||
      drmType: "None",
 | 
					 | 
				
			||||||
      latestPSSH: "None",
 | 
					 | 
				
			||||||
      licenseURL: "None",
 | 
					 | 
				
			||||||
      latestKeys: [],
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Get all normal windows to exclude your popup
 | 
					 | 
				
			||||||
    chrome.windows.getAll(
 | 
					 | 
				
			||||||
      { populate: true, windowTypes: ["normal"] },
 | 
					 | 
				
			||||||
      (windows) => {
 | 
					 | 
				
			||||||
        if (!windows || windows.length === 0) {
 | 
					 | 
				
			||||||
          console.warn("No normal Chrome windows found");
 | 
					 | 
				
			||||||
          return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Find the last focused normal window
 | 
					 | 
				
			||||||
        const lastFocusedWindow = windows.find((w) => w.focused) || windows[0];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!lastFocusedWindow) {
 | 
					 | 
				
			||||||
          console.warn("No focused normal window found");
 | 
					 | 
				
			||||||
          return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Find the active tab in that window (that is a regular webpage)
 | 
					 | 
				
			||||||
        const activeTab = lastFocusedWindow.tabs.find(
 | 
					 | 
				
			||||||
          (tab) => tab.active && tab.url && /^https?:\/\//.test(tab.url)
 | 
					 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (activeTab?.id) {
 | 
					        const handleChange = (changes, area) => {
 | 
				
			||||||
          chrome.tabs.reload(activeTab.id, () => {
 | 
					            if (area === "local") {
 | 
				
			||||||
            if (chrome.runtime.lastError) {
 | 
					                if (changes.drmType) {
 | 
				
			||||||
              console.error("Failed to reload tab:", chrome.runtime.lastError);
 | 
					                    setDrmType(changes.drmType.newValue);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (changes.latestPSSH) {
 | 
				
			||||||
 | 
					                    setPssh(changes.latestPSSH.newValue);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (changes.licenseURL) {
 | 
				
			||||||
 | 
					                    setLicenseUrl(changes.licenseURL.newValue);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (changes.latestKeys) {
 | 
				
			||||||
 | 
					                    setKeys(changes.latestKeys.newValue);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          });
 | 
					        };
 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
          console.warn("No active tab found in the last focused normal window");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					        chrome.storage.onChanged.addListener(handleChange);
 | 
				
			||||||
    <div className="w-full grow flex h-full overflow-y-auto overflow-x-auto flex-col text-white p-4">
 | 
					        return () => chrome.storage.onChanged.removeListener(handleChange);
 | 
				
			||||||
      <button
 | 
					    }, []);
 | 
				
			||||||
        onClick={handleCapture}
 | 
					
 | 
				
			||||||
        className="w-full h-10 bg-sky-500 rounded-md p-2 mt-2 text-white cursor-pointer hover:bg-sky-600"
 | 
					    const handleCapture = () => {
 | 
				
			||||||
      >
 | 
					        // Reset stored values
 | 
				
			||||||
        Capture current tab
 | 
					        chrome.storage.local.set({
 | 
				
			||||||
      </button>
 | 
					            drmType: "None",
 | 
				
			||||||
      <p className="text-2xl mt-5">DRM Type</p>
 | 
					            latestPSSH: "None",
 | 
				
			||||||
      <input
 | 
					            licenseURL: "None",
 | 
				
			||||||
        type="text"
 | 
					            latestKeys: [],
 | 
				
			||||||
        value={drmType}
 | 
					        });
 | 
				
			||||||
        className="w-full h-10 bg-slate-800/50 rounded-md p-2 mt-2 text-white"
 | 
					
 | 
				
			||||||
        placeholder="None"
 | 
					        // Get all normal windows to exclude your popup
 | 
				
			||||||
        disabled
 | 
					        chrome.windows.getAll({ populate: true, windowTypes: ["normal"] }, (windows) => {
 | 
				
			||||||
      />
 | 
					            if (!windows || windows.length === 0) {
 | 
				
			||||||
      <p className="text-2xl mt-5">PSSH</p>
 | 
					                console.warn("No normal Chrome windows found");
 | 
				
			||||||
      <input
 | 
					                return;
 | 
				
			||||||
        type="text"
 | 
					            }
 | 
				
			||||||
        value={pssh}
 | 
					
 | 
				
			||||||
        className="w-full h-10 bg-slate-800/50 rounded-md p-2 mt-2 text-white"
 | 
					            // Find the last focused normal window
 | 
				
			||||||
        placeholder="None"
 | 
					            const lastFocusedWindow = windows.find((w) => w.focused) || windows[0];
 | 
				
			||||||
        disabled
 | 
					
 | 
				
			||||||
      />
 | 
					            if (!lastFocusedWindow) {
 | 
				
			||||||
      <p className="text-2xl mt-5">License URL</p>
 | 
					                console.warn("No focused normal window found");
 | 
				
			||||||
      <input
 | 
					                return;
 | 
				
			||||||
        type="text"
 | 
					            }
 | 
				
			||||||
        value={licenseUrl}
 | 
					
 | 
				
			||||||
        className="w-full h-10 bg-slate-800/50 rounded-md p-2 mt-2 text-white"
 | 
					            // Find the active tab in that window (that is a regular webpage)
 | 
				
			||||||
        placeholder="None"
 | 
					            const activeTab = lastFocusedWindow.tabs.find(
 | 
				
			||||||
        disabled
 | 
					                (tab) => tab.active && tab.url && /^https?:\/\//.test(tab.url)
 | 
				
			||||||
      />
 | 
					            );
 | 
				
			||||||
      <p className="text-2xl mt-5">Keys</p>
 | 
					
 | 
				
			||||||
      <div className="w-full min-h-64 h-64 flex items-center justify-center text-center overflow-y-auto bg-slate-800/50 rounded-md p-2 mt-2 text-white whitespace-pre-line">
 | 
					            if (activeTab?.id) {
 | 
				
			||||||
        {Array.isArray(keys) &&
 | 
					                chrome.tabs.reload(activeTab.id, () => {
 | 
				
			||||||
        keys.filter((k) => k.type !== "SIGNING").length > 0 ? (
 | 
					                    if (chrome.runtime.lastError) {
 | 
				
			||||||
          keys
 | 
					                        console.error("Failed to reload tab:", chrome.runtime.lastError);
 | 
				
			||||||
            .filter((k) => k.type !== "SIGNING")
 | 
					                    }
 | 
				
			||||||
            .map((k) => `${k.key_id || k.keyId}:${k.key}`)
 | 
					                });
 | 
				
			||||||
            .join("\n")
 | 
					            } else {
 | 
				
			||||||
        ) : (
 | 
					                console.warn("No active tab found in the last focused normal window");
 | 
				
			||||||
          <span className="text-gray-400">None</span>
 | 
					            }
 | 
				
			||||||
        )}
 | 
					        });
 | 
				
			||||||
      </div>
 | 
					    };
 | 
				
			||||||
    </div>
 | 
					
 | 
				
			||||||
  );
 | 
					    return (
 | 
				
			||||||
 | 
					        <div className="w-full grow flex h-full overflow-y-auto overflow-x-auto flex-col text-white p-4">
 | 
				
			||||||
 | 
					            <button
 | 
				
			||||||
 | 
					                onClick={handleCapture}
 | 
				
			||||||
 | 
					                className="w-full h-10 bg-sky-500 rounded-md p-2 mt-2 text-white cursor-pointer hover:bg-sky-600"
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					                Capture current tab
 | 
				
			||||||
 | 
					            </button>
 | 
				
			||||||
 | 
					            <p className="text-2xl mt-5">DRM Type</p>
 | 
				
			||||||
 | 
					            <input
 | 
				
			||||||
 | 
					                type="text"
 | 
				
			||||||
 | 
					                value={drmType}
 | 
				
			||||||
 | 
					                className="w-full h-10 bg-slate-800/50 rounded-md p-2 mt-2 text-white"
 | 
				
			||||||
 | 
					                placeholder="None"
 | 
				
			||||||
 | 
					                disabled
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            <p className="text-2xl mt-5">PSSH</p>
 | 
				
			||||||
 | 
					            <input
 | 
				
			||||||
 | 
					                type="text"
 | 
				
			||||||
 | 
					                value={pssh}
 | 
				
			||||||
 | 
					                className="w-full h-10 bg-slate-800/50 rounded-md p-2 mt-2 text-white"
 | 
				
			||||||
 | 
					                placeholder="None"
 | 
				
			||||||
 | 
					                disabled
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            <p className="text-2xl mt-5">License URL</p>
 | 
				
			||||||
 | 
					            <input
 | 
				
			||||||
 | 
					                type="text"
 | 
				
			||||||
 | 
					                value={licenseUrl}
 | 
				
			||||||
 | 
					                className="w-full h-10 bg-slate-800/50 rounded-md p-2 mt-2 text-white"
 | 
				
			||||||
 | 
					                placeholder="None"
 | 
				
			||||||
 | 
					                disabled
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            <p className="text-2xl mt-5">Keys</p>
 | 
				
			||||||
 | 
					            <div className="w-full min-h-64 h-64 flex items-center justify-center text-center overflow-y-auto bg-slate-800/50 rounded-md p-2 mt-2 text-white whitespace-pre-line">
 | 
				
			||||||
 | 
					                {Array.isArray(keys) && keys.filter((k) => k.type !== "SIGNING").length > 0 ? (
 | 
				
			||||||
 | 
					                    keys
 | 
				
			||||||
 | 
					                        .filter((k) => k.type !== "SIGNING")
 | 
				
			||||||
 | 
					                        .map((k) => `${k.key_id || k.keyId}:${k.key}`)
 | 
				
			||||||
 | 
					                        .join("\n")
 | 
				
			||||||
 | 
					                ) : (
 | 
				
			||||||
 | 
					                    <span className="text-gray-400">None</span>
 | 
				
			||||||
 | 
					                )}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default Results;
 | 
					export default Results;
 | 
				
			||||||
 | 
				
			|||||||
@ -2,149 +2,140 @@ import { useState, useEffect } from "react";
 | 
				
			|||||||
import { useNavigate } from "react-router-dom";
 | 
					import { useNavigate } from "react-router-dom";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function Settings({ onConfigSaved }) {
 | 
					function Settings({ onConfigSaved }) {
 | 
				
			||||||
  const [instanceUrl, setInstanceUrl] = useState("");
 | 
					    const [instanceUrl, setInstanceUrl] = useState("");
 | 
				
			||||||
  const [storedUrl, setStoredUrl] = useState(null);
 | 
					    const [storedUrl, setStoredUrl] = useState(null);
 | 
				
			||||||
  const [message, setMessage] = useState(null);
 | 
					    const [message, setMessage] = useState(null);
 | 
				
			||||||
  const [messageType, setMessageType] = useState(null);
 | 
					    const [messageType, setMessageType] = useState(null);
 | 
				
			||||||
  const [loading, setLoading] = useState(false);
 | 
					    const [loading, setLoading] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const navigate = useNavigate();
 | 
					    const navigate = useNavigate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  useEffect(() => {
 | 
					    useEffect(() => {
 | 
				
			||||||
    chrome.storage.local.get("cdrm_instance", (result) => {
 | 
					        chrome.storage.local.get("cdrm_instance", (result) => {
 | 
				
			||||||
      if (chrome.runtime.lastError) {
 | 
					 | 
				
			||||||
        console.error(
 | 
					 | 
				
			||||||
          "Error fetching CDRM instance:",
 | 
					 | 
				
			||||||
          chrome.runtime.lastError
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
      } else if (result.cdrm_instance) {
 | 
					 | 
				
			||||||
        setStoredUrl(result.cdrm_instance);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  }, []);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  const handleSave = async () => {
 | 
					 | 
				
			||||||
    const trimmedUrl = instanceUrl.trim().replace(/\/+$/, "");
 | 
					 | 
				
			||||||
    if (!trimmedUrl) {
 | 
					 | 
				
			||||||
      setMessage("Please enter a valid URL.");
 | 
					 | 
				
			||||||
      setMessageType("error");
 | 
					 | 
				
			||||||
      return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const endpoint = trimmedUrl + "/api/extension";
 | 
					 | 
				
			||||||
    setLoading(true);
 | 
					 | 
				
			||||||
    setMessage(null);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
      const response = await fetch(endpoint, {
 | 
					 | 
				
			||||||
        method: "POST",
 | 
					 | 
				
			||||||
        headers: {
 | 
					 | 
				
			||||||
          "Content-Type": "application/json",
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      const data = await response.json();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (data.status === true) {
 | 
					 | 
				
			||||||
        setMessage("Successfully connected to CDRM Instance.");
 | 
					 | 
				
			||||||
        setMessageType("success");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const widevineRes = await fetch(
 | 
					 | 
				
			||||||
          `${trimmedUrl}/remotecdm/widevine/deviceinfo`
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        if (!widevineRes.ok)
 | 
					 | 
				
			||||||
          throw new Error("Failed to fetch Widevine device info");
 | 
					 | 
				
			||||||
        const widevineData = await widevineRes.json();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const playreadyRes = await fetch(
 | 
					 | 
				
			||||||
          `${trimmedUrl}/remotecdm/playready/deviceinfo`
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        if (!playreadyRes.ok)
 | 
					 | 
				
			||||||
          throw new Error("Failed to fetch PlayReady device info");
 | 
					 | 
				
			||||||
        const playreadyData = await playreadyRes.json();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        chrome.storage.local.set(
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            valid_config: true,
 | 
					 | 
				
			||||||
            cdrm_instance: trimmedUrl,
 | 
					 | 
				
			||||||
            widevine_device: {
 | 
					 | 
				
			||||||
              device_type: widevineData.device_type,
 | 
					 | 
				
			||||||
              system_id: widevineData.system_id,
 | 
					 | 
				
			||||||
              security_level: widevineData.security_level,
 | 
					 | 
				
			||||||
              secret: widevineData.secret,
 | 
					 | 
				
			||||||
              device_name: widevineData.device_name,
 | 
					 | 
				
			||||||
              host: trimmedUrl,
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            playready_device: {
 | 
					 | 
				
			||||||
              security_level: playreadyData.security_level,
 | 
					 | 
				
			||||||
              secret: playreadyData.secret,
 | 
					 | 
				
			||||||
              device_name: playreadyData.device_name,
 | 
					 | 
				
			||||||
              host: trimmedUrl,
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
          },
 | 
					 | 
				
			||||||
          () => {
 | 
					 | 
				
			||||||
            if (chrome.runtime.lastError) {
 | 
					            if (chrome.runtime.lastError) {
 | 
				
			||||||
              console.error(
 | 
					                console.error("Error fetching CDRM instance:", chrome.runtime.lastError);
 | 
				
			||||||
                "Error saving to chrome.storage:",
 | 
					            } else if (result.cdrm_instance) {
 | 
				
			||||||
                chrome.runtime.lastError
 | 
					                setStoredUrl(result.cdrm_instance);
 | 
				
			||||||
              );
 | 
					 | 
				
			||||||
              setMessage("Error saving configuration.");
 | 
					 | 
				
			||||||
              setMessageType("error");
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
              console.log("Configuration saved.");
 | 
					 | 
				
			||||||
              setStoredUrl(trimmedUrl);
 | 
					 | 
				
			||||||
              setInstanceUrl("");
 | 
					 | 
				
			||||||
              if (onConfigSaved) onConfigSaved();
 | 
					 | 
				
			||||||
              navigate("/results"); // Automatically redirect after success
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
          }
 | 
					        });
 | 
				
			||||||
        );
 | 
					    }, []);
 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        throw new Error("Invalid response from endpoint.");
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    } catch (err) {
 | 
					 | 
				
			||||||
      console.error("Connection error:", err);
 | 
					 | 
				
			||||||
      setMessage("Invalid endpoint or device info could not be retrieved.");
 | 
					 | 
				
			||||||
      setMessageType("error");
 | 
					 | 
				
			||||||
    } finally {
 | 
					 | 
				
			||||||
      setLoading(false);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					    const handleSave = async () => {
 | 
				
			||||||
    <div className="w-full h-full overflow-y-auto overflow-x-auto flex flex-col p-4">
 | 
					        const trimmedUrl = instanceUrl.trim().replace(/\/+$/, "");
 | 
				
			||||||
      <input
 | 
					        if (!trimmedUrl) {
 | 
				
			||||||
        type="text"
 | 
					            setMessage("Please enter a valid URL.");
 | 
				
			||||||
        value={instanceUrl}
 | 
					            setMessageType("error");
 | 
				
			||||||
        onChange={(e) => setInstanceUrl(e.target.value)}
 | 
					            return;
 | 
				
			||||||
        placeholder={
 | 
					 | 
				
			||||||
          storedUrl
 | 
					 | 
				
			||||||
            ? `Current CDRM Instance: ${storedUrl}`
 | 
					 | 
				
			||||||
            : "CDRM Instance URL (e.g., https://cdrm-project.com/, http://127.0.0.1:5000/)"
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        className="w-full p-4 text-lg bg-gray-800 text-white border border-gray-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 mt-4"
 | 
					 | 
				
			||||||
      />
 | 
					 | 
				
			||||||
      <button
 | 
					 | 
				
			||||||
        onClick={handleSave}
 | 
					 | 
				
			||||||
        disabled={loading}
 | 
					 | 
				
			||||||
        className={`mt-4 p-2 ${
 | 
					 | 
				
			||||||
          loading ? "bg-blue-400" : "bg-blue-600 hover:bg-blue-700"
 | 
					 | 
				
			||||||
        } text-white rounded-md transition duration-300`}
 | 
					 | 
				
			||||||
      >
 | 
					 | 
				
			||||||
        {loading ? "Connecting..." : "Save Settings"}
 | 
					 | 
				
			||||||
      </button>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      {message && (
 | 
					        const endpoint = trimmedUrl + "/api/extension";
 | 
				
			||||||
        <p
 | 
					        setLoading(true);
 | 
				
			||||||
          className={`mt-2 text-sm text-center ${
 | 
					        setMessage(null);
 | 
				
			||||||
            messageType === "success" ? "text-green-400" : "text-red-400"
 | 
					
 | 
				
			||||||
          }`}
 | 
					        try {
 | 
				
			||||||
        >
 | 
					            const response = await fetch(endpoint, {
 | 
				
			||||||
          {message}
 | 
					                method: "POST",
 | 
				
			||||||
        </p>
 | 
					                headers: {
 | 
				
			||||||
      )}
 | 
					                    "Content-Type": "application/json",
 | 
				
			||||||
    </div>
 | 
					                },
 | 
				
			||||||
  );
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const data = await response.json();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (data.status === true) {
 | 
				
			||||||
 | 
					                setMessage("Successfully connected to CDRM Instance.");
 | 
				
			||||||
 | 
					                setMessageType("success");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                const widevineRes = await fetch(`${trimmedUrl}/remotecdm/widevine/deviceinfo`);
 | 
				
			||||||
 | 
					                if (!widevineRes.ok) throw new Error("Failed to fetch Widevine device info");
 | 
				
			||||||
 | 
					                const widevineData = await widevineRes.json();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                const playreadyRes = await fetch(`${trimmedUrl}/remotecdm/playready/deviceinfo`);
 | 
				
			||||||
 | 
					                if (!playreadyRes.ok) throw new Error("Failed to fetch PlayReady device info");
 | 
				
			||||||
 | 
					                const playreadyData = await playreadyRes.json();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                chrome.storage.local.set(
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        valid_config: true,
 | 
				
			||||||
 | 
					                        cdrm_instance: trimmedUrl,
 | 
				
			||||||
 | 
					                        widevine_device: {
 | 
				
			||||||
 | 
					                            device_type: widevineData.device_type,
 | 
				
			||||||
 | 
					                            system_id: widevineData.system_id,
 | 
				
			||||||
 | 
					                            security_level: widevineData.security_level,
 | 
				
			||||||
 | 
					                            secret: widevineData.secret,
 | 
				
			||||||
 | 
					                            device_name: widevineData.device_name,
 | 
				
			||||||
 | 
					                            host: trimmedUrl,
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                        playready_device: {
 | 
				
			||||||
 | 
					                            security_level: playreadyData.security_level,
 | 
				
			||||||
 | 
					                            secret: playreadyData.secret,
 | 
				
			||||||
 | 
					                            device_name: playreadyData.device_name,
 | 
				
			||||||
 | 
					                            host: trimmedUrl,
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    () => {
 | 
				
			||||||
 | 
					                        if (chrome.runtime.lastError) {
 | 
				
			||||||
 | 
					                            console.error(
 | 
				
			||||||
 | 
					                                "Error saving to chrome.storage:",
 | 
				
			||||||
 | 
					                                chrome.runtime.lastError
 | 
				
			||||||
 | 
					                            );
 | 
				
			||||||
 | 
					                            setMessage("Error saving configuration.");
 | 
				
			||||||
 | 
					                            setMessageType("error");
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            console.log("Configuration saved.");
 | 
				
			||||||
 | 
					                            setStoredUrl(trimmedUrl);
 | 
				
			||||||
 | 
					                            setInstanceUrl("");
 | 
				
			||||||
 | 
					                            if (onConfigSaved) onConfigSaved();
 | 
				
			||||||
 | 
					                            navigate("/results"); // Automatically redirect after success
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                throw new Error("Invalid response from endpoint.");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (err) {
 | 
				
			||||||
 | 
					            console.error("Connection error:", err);
 | 
				
			||||||
 | 
					            setMessage("Invalid endpoint or device info could not be retrieved.");
 | 
				
			||||||
 | 
					            setMessageType("error");
 | 
				
			||||||
 | 
					        } finally {
 | 
				
			||||||
 | 
					            setLoading(false);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <div className="w-full h-full overflow-y-auto overflow-x-auto flex flex-col p-4">
 | 
				
			||||||
 | 
					            <input
 | 
				
			||||||
 | 
					                type="text"
 | 
				
			||||||
 | 
					                value={instanceUrl}
 | 
				
			||||||
 | 
					                onChange={(e) => setInstanceUrl(e.target.value)}
 | 
				
			||||||
 | 
					                placeholder={
 | 
				
			||||||
 | 
					                    storedUrl
 | 
				
			||||||
 | 
					                        ? `Current CDRM Instance: ${storedUrl}`
 | 
				
			||||||
 | 
					                        : "CDRM Instance URL (e.g., https://cdrm-project.com/, http://127.0.0.1:5000/)"
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                className="w-full p-4 text-lg bg-gray-800 text-white border border-gray-700 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 mt-4"
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            <button
 | 
				
			||||||
 | 
					                onClick={handleSave}
 | 
				
			||||||
 | 
					                disabled={loading}
 | 
				
			||||||
 | 
					                className={`mt-4 p-2 ${
 | 
				
			||||||
 | 
					                    loading ? "bg-blue-400" : "bg-blue-600 hover:bg-blue-700"
 | 
				
			||||||
 | 
					                } text-white rounded-md transition duration-300`}
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					                {loading ? "Connecting..." : "Save Settings"}
 | 
				
			||||||
 | 
					            </button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            {message && (
 | 
				
			||||||
 | 
					                <p
 | 
				
			||||||
 | 
					                    className={`mt-2 text-sm text-center ${
 | 
				
			||||||
 | 
					                        messageType === "success" ? "text-green-400" : "text-red-400"
 | 
				
			||||||
 | 
					                    }`}
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					                    {message}
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					            )}
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default Settings;
 | 
					export default Settings;
 | 
				
			||||||
 | 
				
			|||||||
@ -4,48 +4,45 @@ import settingsIcon from "../assets/settings.svg";
 | 
				
			|||||||
import closeIcon from "../assets/close.svg";
 | 
					import closeIcon from "../assets/close.svg";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function SideNav({ onClose }) {
 | 
					function SideNav({ onClose }) {
 | 
				
			||||||
  return (
 | 
					    return (
 | 
				
			||||||
    <div className="w-full h-full overflow-y-auto overflow-x-auto flex flex-col bg-black">
 | 
					        <div className="w-full h-full overflow-y-auto overflow-x-auto flex flex-col bg-black">
 | 
				
			||||||
      <div className="w-full min-h-16 max-h-16 h-16 shrink-0 flex sticky top-0 z-20 border-b border-b-white bg-black">
 | 
					            <div className="w-full min-h-16 max-h-16 h-16 shrink-0 flex sticky top-0 z-20 border-b border-b-white bg-black">
 | 
				
			||||||
        <button
 | 
					                <button onClick={onClose} className="h-full ml-auto p-3 hover:cursor-pointer">
 | 
				
			||||||
          onClick={onClose}
 | 
					                    <img src={closeIcon} alt="Close" className="h-full" />
 | 
				
			||||||
          className="h-full ml-auto p-3 hover:cursor-pointer"
 | 
					                </button>
 | 
				
			||||||
        >
 | 
					            </div>
 | 
				
			||||||
          <img src={closeIcon} alt="Close" className="h-full" />
 | 
					 | 
				
			||||||
        </button>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div className="w-full h-16 flex items-center justify-center mt-2">
 | 
					            <div className="w-full h-16 flex items-center justify-center mt-2">
 | 
				
			||||||
        <NavLink
 | 
					                <NavLink
 | 
				
			||||||
          to="/results"
 | 
					                    to="/results"
 | 
				
			||||||
          onClick={onClose}
 | 
					                    onClick={onClose}
 | 
				
			||||||
          className="text-white text-2xl font-bold flex flex-row items-center border-l-white hover:border-l-1 w-full hover:bg-black/50 transition duration-300 ease-in-out p-2"
 | 
					                    className="text-white text-2xl font-bold flex flex-row items-center border-l-white hover:border-l-1 w-full hover:bg-black/50 transition duration-300 ease-in-out p-2"
 | 
				
			||||||
        >
 | 
					                >
 | 
				
			||||||
          <img
 | 
					                    <img
 | 
				
			||||||
            src={homeIcon}
 | 
					                        src={homeIcon}
 | 
				
			||||||
            alt="Home"
 | 
					                        alt="Home"
 | 
				
			||||||
            className="h-full w-16 p-2 flex items-center cursor-pointer"
 | 
					                        className="h-full w-16 p-2 flex items-center cursor-pointer"
 | 
				
			||||||
          />
 | 
					                    />
 | 
				
			||||||
          Home
 | 
					                    Home
 | 
				
			||||||
        </NavLink>
 | 
					                </NavLink>
 | 
				
			||||||
      </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <div className="w-full h-16 flex items-center justify-center mt-2">
 | 
					            <div className="w-full h-16 flex items-center justify-center mt-2">
 | 
				
			||||||
        <NavLink
 | 
					                <NavLink
 | 
				
			||||||
          to="/settings"
 | 
					                    to="/settings"
 | 
				
			||||||
          onClick={onClose}
 | 
					                    onClick={onClose}
 | 
				
			||||||
          className="text-white text-2xl font-bold flex flex-row items-center hover:border-l-1 border-l-white w-full hover:bg-black/50 transition duration-300 ease-in-out p-2"
 | 
					                    className="text-white text-2xl font-bold flex flex-row items-center hover:border-l-1 border-l-white w-full hover:bg-black/50 transition duration-300 ease-in-out p-2"
 | 
				
			||||||
        >
 | 
					                >
 | 
				
			||||||
          <img
 | 
					                    <img
 | 
				
			||||||
            src={settingsIcon}
 | 
					                        src={settingsIcon}
 | 
				
			||||||
            alt="Settings"
 | 
					                        alt="Settings"
 | 
				
			||||||
            className="h-full w-16 p-2 flex items-center cursor-pointer"
 | 
					                        className="h-full w-16 p-2 flex items-center cursor-pointer"
 | 
				
			||||||
          />
 | 
					                    />
 | 
				
			||||||
          Settings
 | 
					                    Settings
 | 
				
			||||||
        </NavLink>
 | 
					                </NavLink>
 | 
				
			||||||
      </div>
 | 
					            </div>
 | 
				
			||||||
    </div>
 | 
					        </div>
 | 
				
			||||||
  );
 | 
					    );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default SideNav;
 | 
					export default SideNav;
 | 
				
			||||||
 | 
				
			|||||||
@ -2,84 +2,81 @@ import { useEffect, useState } from "react";
 | 
				
			|||||||
import hamburgerIcon from "../assets/hamburger.svg";
 | 
					import hamburgerIcon from "../assets/hamburger.svg";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function TopNav({ onMenuClick }) {
 | 
					function TopNav({ onMenuClick }) {
 | 
				
			||||||
  const [injectionType, setInjectionType] = useState("LICENSE");
 | 
					    const [injectionType, setInjectionType] = useState("LICENSE");
 | 
				
			||||||
  const [drmOverride, setDrmOverride] = useState("DISABLED");
 | 
					    const [drmOverride, setDrmOverride] = useState("DISABLED");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  useEffect(() => {
 | 
					    useEffect(() => {
 | 
				
			||||||
    chrome.storage.local.get(["injection_type", "drm_override"], (result) => {
 | 
					        chrome.storage.local.get(["injection_type", "drm_override"], (result) => {
 | 
				
			||||||
      if (result.injection_type !== undefined) {
 | 
					            if (result.injection_type !== undefined) {
 | 
				
			||||||
        setInjectionType(result.injection_type);
 | 
					                setInjectionType(result.injection_type);
 | 
				
			||||||
      }
 | 
					            }
 | 
				
			||||||
      if (result.drm_override !== undefined) {
 | 
					            if (result.drm_override !== undefined) {
 | 
				
			||||||
        setDrmOverride(result.drm_override);
 | 
					                setDrmOverride(result.drm_override);
 | 
				
			||||||
      }
 | 
					            }
 | 
				
			||||||
    });
 | 
					        });
 | 
				
			||||||
  }, []);
 | 
					    }, []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const handleInjectionTypeChange = (type) => {
 | 
					    const handleInjectionTypeChange = (type) => {
 | 
				
			||||||
    chrome.storage.local.set({ injection_type: type }, () => {
 | 
					        chrome.storage.local.set({ injection_type: type }, () => {
 | 
				
			||||||
      if (chrome.runtime.lastError) {
 | 
					            if (chrome.runtime.lastError) {
 | 
				
			||||||
        console.error(
 | 
					                console.error("Error updating injection_type:", chrome.runtime.lastError);
 | 
				
			||||||
          "Error updating injection_type:",
 | 
					            } else {
 | 
				
			||||||
          chrome.runtime.lastError
 | 
					                setInjectionType(type);
 | 
				
			||||||
        );
 | 
					                console.log(`Injection type updated to ${type}`);
 | 
				
			||||||
      } else {
 | 
					            }
 | 
				
			||||||
        setInjectionType(type);
 | 
					        });
 | 
				
			||||||
        console.log(`Injection type updated to ${type}`);
 | 
					    };
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const handleDrmOverrideChange = (type) => {
 | 
					    const handleDrmOverrideChange = (type) => {
 | 
				
			||||||
    chrome.storage.local.set({ drm_override: type }, () => {
 | 
					        chrome.storage.local.set({ drm_override: type }, () => {
 | 
				
			||||||
      if (chrome.runtime.lastError) {
 | 
					            if (chrome.runtime.lastError) {
 | 
				
			||||||
        console.error("Error updating drm_override:", chrome.runtime.lastError);
 | 
					                console.error("Error updating drm_override:", chrome.runtime.lastError);
 | 
				
			||||||
      } else {
 | 
					            } else {
 | 
				
			||||||
        setDrmOverride(type);
 | 
					                setDrmOverride(type);
 | 
				
			||||||
        console.log(`DRM Override updated to ${type}`);
 | 
					                console.log(`DRM Override updated to ${type}`);
 | 
				
			||||||
      }
 | 
					            }
 | 
				
			||||||
    });
 | 
					        });
 | 
				
			||||||
  };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					    return (
 | 
				
			||||||
    <div className="w-full h-full flex flex-row overflow-x-hidden">
 | 
					        <div className="w-full h-full flex flex-row overflow-x-hidden">
 | 
				
			||||||
      <img
 | 
					            <img
 | 
				
			||||||
        src={hamburgerIcon}
 | 
					                src={hamburgerIcon}
 | 
				
			||||||
        alt="Menu"
 | 
					                alt="Menu"
 | 
				
			||||||
        className="h-full w-16 p-2 flex items-center cursor-pointer"
 | 
					                className="h-full w-16 p-2 flex items-center cursor-pointer"
 | 
				
			||||||
        onClick={onMenuClick}
 | 
					                onClick={onMenuClick}
 | 
				
			||||||
      />
 | 
					            />
 | 
				
			||||||
      <div className="flex flex-row h-full justify-center items-center ml-auto mr-2">
 | 
					            <div className="flex flex-row h-full justify-center items-center ml-auto mr-2">
 | 
				
			||||||
        <p className="text-white text-lg p-2 mr-2 border-r-2 border-r-white text-nowrap">
 | 
					                <p className="text-white text-lg p-2 mr-2 border-r-2 border-r-white text-nowrap">
 | 
				
			||||||
          Injection Type:
 | 
					                    Injection Type:
 | 
				
			||||||
        </p>
 | 
					                </p>
 | 
				
			||||||
        <button
 | 
					                <button
 | 
				
			||||||
          onClick={() => handleInjectionTypeChange("LICENSE")}
 | 
					                    onClick={() => handleInjectionTypeChange("LICENSE")}
 | 
				
			||||||
          className={`text-white text-lg p-2 rounded-md m-1 cursor-pointer ${
 | 
					                    className={`text-white text-lg p-2 rounded-md m-1 cursor-pointer ${
 | 
				
			||||||
            injectionType === "LICENSE" ? "bg-sky-500/70" : "bg-black"
 | 
					                        injectionType === "LICENSE" ? "bg-sky-500/70" : "bg-black"
 | 
				
			||||||
          }`}
 | 
					                    }`}
 | 
				
			||||||
        >
 | 
					                >
 | 
				
			||||||
          License
 | 
					                    License
 | 
				
			||||||
        </button>
 | 
					                </button>
 | 
				
			||||||
        <button
 | 
					                <button
 | 
				
			||||||
          onClick={() => handleInjectionTypeChange("EME")}
 | 
					                    onClick={() => handleInjectionTypeChange("EME")}
 | 
				
			||||||
          className={`text-white text-lg p-2 rounded-md m-1 cursor-pointer ${
 | 
					                    className={`text-white text-lg p-2 rounded-md m-1 cursor-pointer ${
 | 
				
			||||||
            injectionType === "EME" ? "bg-green-500/70" : "bg-black"
 | 
					                        injectionType === "EME" ? "bg-green-500/70" : "bg-black"
 | 
				
			||||||
          }`}
 | 
					                    }`}
 | 
				
			||||||
        >
 | 
					                >
 | 
				
			||||||
          EME
 | 
					                    EME
 | 
				
			||||||
        </button>
 | 
					                </button>
 | 
				
			||||||
        <button
 | 
					                <button
 | 
				
			||||||
          onClick={() => handleInjectionTypeChange("DISABLED")}
 | 
					                    onClick={() => handleInjectionTypeChange("DISABLED")}
 | 
				
			||||||
          className={`text-white text-lg p-2 rounded-md m-1 cursor-pointer ${
 | 
					                    className={`text-white text-lg p-2 rounded-md m-1 cursor-pointer ${
 | 
				
			||||||
            injectionType === "DISABLED" ? "bg-red-500/70" : "bg-black"
 | 
					                        injectionType === "DISABLED" ? "bg-red-500/70" : "bg-black"
 | 
				
			||||||
          }`}
 | 
					                    }`}
 | 
				
			||||||
        >
 | 
					                >
 | 
				
			||||||
          Disabled
 | 
					                    Disabled
 | 
				
			||||||
        </button>
 | 
					                </button>
 | 
				
			||||||
      </div>
 | 
					            </div>
 | 
				
			||||||
    </div>
 | 
					        </div>
 | 
				
			||||||
  );
 | 
					    );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default TopNav;
 | 
					export default TopNav;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,10 @@
 | 
				
			|||||||
@import "tailwindcss";
 | 
					@import "tailwindcss";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
html, body, #root {
 | 
					html,
 | 
				
			||||||
  height: 100%;
 | 
					body,
 | 
				
			||||||
  width: 100%;
 | 
					#root {
 | 
				
			||||||
  margin: 0;
 | 
					    height: 100%;
 | 
				
			||||||
  padding: 0;
 | 
					    width: 100%;
 | 
				
			||||||
}
 | 
					    margin: 0;
 | 
				
			||||||
 | 
					    padding: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,10 @@
 | 
				
			|||||||
import { StrictMode } from 'react'
 | 
					import { StrictMode } from "react";
 | 
				
			||||||
import { createRoot } from 'react-dom/client'
 | 
					import { createRoot } from "react-dom/client";
 | 
				
			||||||
import './index.css'
 | 
					import "./index.css";
 | 
				
			||||||
import App from './App.jsx'
 | 
					import App from "./App.jsx";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
createRoot(document.getElementById('root')).render(
 | 
					createRoot(document.getElementById("root")).render(
 | 
				
			||||||
  <StrictMode>
 | 
					    <StrictMode>
 | 
				
			||||||
    <App />
 | 
					        <App />
 | 
				
			||||||
  </StrictMode>,
 | 
					    </StrictMode>
 | 
				
			||||||
)
 | 
					);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,9 @@
 | 
				
			|||||||
import { defineConfig } from 'vite'
 | 
					import { defineConfig } from "vite";
 | 
				
			||||||
import react from '@vitejs/plugin-react'
 | 
					import react from "@vitejs/plugin-react";
 | 
				
			||||||
import tailwindcss from '@tailwindcss/vite'
 | 
					import tailwindcss from "@tailwindcss/vite";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// https://vite.dev/config/
 | 
					// https://vite.dev/config/
 | 
				
			||||||
export default defineConfig({
 | 
					export default defineConfig({
 | 
				
			||||||
  base: './',
 | 
					    base: "./",
 | 
				
			||||||
  plugins: [react(), tailwindcss()],
 | 
					    plugins: [react(), tailwindcss()],
 | 
				
			||||||
})
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
@ -1,41 +1,41 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "manifest_version": 2,
 | 
					    "manifest_version": 2,
 | 
				
			||||||
  "name": "CDRM Extension 2.0",
 | 
					    "name": "CDRM Extension 2.0",
 | 
				
			||||||
  "version": "2.0",
 | 
					    "version": "2.0",
 | 
				
			||||||
  "description": "Decrypt DRM Protected content",
 | 
					    "description": "Decrypt DRM Protected content",
 | 
				
			||||||
  "permissions": [
 | 
					    "permissions": [
 | 
				
			||||||
    "webRequest",
 | 
					        "webRequest",
 | 
				
			||||||
    "webRequestBlocking",
 | 
					        "webRequestBlocking",
 | 
				
			||||||
    "<all_urls>",
 | 
					        "<all_urls>",
 | 
				
			||||||
    "activeTab",
 | 
					        "activeTab",
 | 
				
			||||||
    "storage",
 | 
					        "storage",
 | 
				
			||||||
    "tabs",
 | 
					        "tabs",
 | 
				
			||||||
    "contextMenus"
 | 
					        "contextMenus"
 | 
				
			||||||
  ],
 | 
					    ],
 | 
				
			||||||
  "background": {
 | 
					    "background": {
 | 
				
			||||||
    "scripts": ["background.js"],
 | 
					        "scripts": ["background.js"],
 | 
				
			||||||
    "persistent": true
 | 
					        "persistent": true
 | 
				
			||||||
  },
 | 
					    },
 | 
				
			||||||
  "content_scripts": [
 | 
					    "content_scripts": [
 | 
				
			||||||
    {
 | 
					        {
 | 
				
			||||||
      "matches": ["<all_urls>"],
 | 
					            "matches": ["<all_urls>"],
 | 
				
			||||||
      "js": ["content.js"],
 | 
					            "js": ["content.js"],
 | 
				
			||||||
      "run_at": "document_start",
 | 
					            "run_at": "document_start",
 | 
				
			||||||
      "all_frames": true
 | 
					            "all_frames": true
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "web_accessible_resources": ["inject.js"],
 | 
				
			||||||
 | 
					    "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
 | 
				
			||||||
 | 
					    "browser_action": {
 | 
				
			||||||
 | 
					        "default_icon": {
 | 
				
			||||||
 | 
					            "16": "icons/icon16.png",
 | 
				
			||||||
 | 
					            "32": "icons/icon32.png",
 | 
				
			||||||
 | 
					            "128": "icons/icon128.png"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "icons": {
 | 
				
			||||||
 | 
					        "16": "icons/icon16.png",
 | 
				
			||||||
 | 
					        "32": "icons/icon32.png",
 | 
				
			||||||
 | 
					        "128": "icons/icon128.png"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ],
 | 
					 | 
				
			||||||
  "web_accessible_resources": ["inject.js"],
 | 
					 | 
				
			||||||
  "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
 | 
					 | 
				
			||||||
  "browser_action": {
 | 
					 | 
				
			||||||
    "default_icon": {
 | 
					 | 
				
			||||||
      "16": "icons/icon16.png",
 | 
					 | 
				
			||||||
      "32": "icons/icon32.png",
 | 
					 | 
				
			||||||
      "128": "icons/icon128.png"
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  "icons": {
 | 
					 | 
				
			||||||
    "16": "icons/icon16.png",
 | 
					 | 
				
			||||||
    "32": "icons/icon32.png",
 | 
					 | 
				
			||||||
    "128": "icons/icon128.png"
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user