diff --git a/README.md b/README.md index 09ca0ea..b12e6ce 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,11 @@ Only use it for content for which you own the rights and do not use it for pirac 6. User input into UI 7. popup.js calls pywidevine script using pyodide in browser +## Third-party libraries +* Pyodide +* Pywidevine +* json-view + ### Big Thanks and inspired by https://github.com/emarsden/pssh-box-wasm/ diff --git a/background.js b/background.js index ebf43aa..432589e 100644 --- a/background.js +++ b/background.js @@ -1,5 +1,6 @@ let psshs=[]; let requests=[]; +let pageURL=""; function convertHeaders(obj){ return JSON.stringify(Object.fromEntries(obj.map(header => [header.name, header.value]))) } @@ -26,6 +27,7 @@ chrome.runtime.onMessage.addListener( break; case "PSSH": psshs.push(request.text) + pageURL=request.pageURL break; } } @@ -45,3 +47,7 @@ window.getPsshs = () => { window.getRequests = () => { return requests; }; + +window.getPageURL = () => { + return pageURL; +}; diff --git a/content.js b/content.js index 24e45b7..a9a8cca 100644 --- a/content.js +++ b/content.js @@ -13,6 +13,7 @@ document.addEventListener('pssh', (e) => { console.log(e.detail); chrome.runtime.sendMessage({ type: "PSSH", - text: e.detail + text: e.detail, + pageURL: document.URL },null); }); diff --git a/jsonview.js b/jsonview.js new file mode 100644 index 0000000..d6cef39 --- /dev/null +++ b/jsonview.js @@ -0,0 +1 @@ +!function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.jsonview=n():e.jsonview=n()}(self,(()=>(()=>{"use strict";var e={425:(e,n,t)=>{t.d(n,{Z:()=>s});var r=t(650),o=t.n(r),i=t(196),a=t.n(i)()(o());a.push([e.id,'.json-container{font-family:"Open Sans";font-size:16px;background-color:#fff;color:gray;box-sizing:border-box}.json-container .line{margin:4px 0;display:flex;justify-content:flex-start}.json-container .caret-icon{width:18px;text-align:center;cursor:pointer}.json-container .empty-icon{width:18px}.json-container .json-type{margin-right:4px;margin-left:4px}.json-container .json-key{color:#444;margin-right:4px;margin-left:4px}.json-container .json-index{margin-right:4px;margin-left:4px}.json-container .json-value{margin-left:8px}.json-container .json-number{color:#f9ae58}.json-container .json-boolean{color:#ec5f66}.json-container .json-string{color:#86b25c}.json-container .json-size{margin-right:4px;margin-left:4px}.json-container .hidden{display:none}.json-container .fas{display:inline-block;border-style:solid;width:0;height:0}.json-container .fa-caret-down{border-width:6px 5px 0 5px;border-color:gray rgba(0,0,0,0)}.json-container .fa-caret-right{border-width:5px 0 5px 6px;border-color:rgba(0,0,0,0) rgba(0,0,0,0) rgba(0,0,0,0) gray}',""]);const s=a},196:e=>{e.exports=function(e){var n=[];return n.toString=function(){return this.map((function(n){var t="",r=void 0!==n[5];return n[4]&&(t+="@supports (".concat(n[4],") {")),n[2]&&(t+="@media ".concat(n[2]," {")),r&&(t+="@layer".concat(n[5].length>0?" ".concat(n[5]):""," {")),t+=e(n),r&&(t+="}"),n[2]&&(t+="}"),n[4]&&(t+="}"),t})).join("")},n.i=function(e,t,r,o,i){"string"==typeof e&&(e=[[null,e,void 0]]);var a={};if(r)for(var s=0;s0?" ".concat(d[5]):""," {").concat(d[1],"}")),d[5]=i),t&&(d[2]?(d[1]="@media ".concat(d[2]," {").concat(d[1],"}"),d[2]=t):d[2]=t),o&&(d[4]?(d[1]="@supports (".concat(d[4],") {").concat(d[1],"}"),d[4]=o):d[4]="".concat(o)),n.push(d))}},n}},650:e=>{e.exports=function(e){return e[1]}},62:e=>{var n=[];function t(e){for(var t=-1,r=0;r{var n={};e.exports=function(e,t){var r=function(e){if(void 0===n[e]){var t=document.querySelector(e);if(window.HTMLIFrameElement&&t instanceof window.HTMLIFrameElement)try{t=t.contentDocument.head}catch(e){t=null}n[e]=t}return n[e]}(e);if(!r)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");r.appendChild(t)}},911:e=>{e.exports=function(e){var n=document.createElement("style");return e.setAttributes(n,e.attributes),e.insert(n,e.options),n}},107:(e,n,t)=>{e.exports=function(e){var n=t.nc;n&&e.setAttribute("nonce",n)}},552:e=>{e.exports=function(e){if("undefined"==typeof document)return{update:function(){},remove:function(){}};var n=e.insertStyleElement(e);return{update:function(t){!function(e,n,t){var r="";t.supports&&(r+="@supports (".concat(t.supports,") {")),t.media&&(r+="@media ".concat(t.media," {"));var o=void 0!==t.layer;o&&(r+="@layer".concat(t.layer.length>0?" ".concat(t.layer):""," {")),r+=t.css,o&&(r+="}"),t.media&&(r+="}"),t.supports&&(r+="}");var i=t.sourceMap;i&&"undefined"!=typeof btoa&&(r+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(i))))," */")),n.styleTagTransform(r,e,n.options)}(n,e,t)},remove:function(){!function(e){if(null===e.parentNode)return!1;e.parentNode.removeChild(e)}(n)}}}},227:e=>{e.exports=function(e,n){if(n.styleSheet)n.styleSheet.cssText=e;else{for(;n.firstChild;)n.removeChild(n.firstChild);n.appendChild(document.createTextNode(e))}}}},n={};function t(r){var o=n[r];if(void 0!==o)return o.exports;var i=n[r]={id:r,exports:{}};return e[r](i,i.exports,t),i.exports}t.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return t.d(n,{a:n}),n},t.d=(e,n)=>{for(var r in n)t.o(n,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:n[r]})},t.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),t.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.nc=void 0;var r={};return(()=>{t.r(r),t.d(r,{collapse:()=>A,create:()=>S,default:()=>H,destroy:()=>L,expand:()=>D,render:()=>w,renderJSON:()=>k,toggleNode:()=>N,traverse:()=>C});var e=t(62),n=t.n(e),o=t(552),i=t.n(o),a=t(566),s=t.n(a),c=t(107),l=t.n(c),d=t(911),u=t.n(d),p=t(227),f=t.n(p),v=t(425),y={};function h(e){return Array.isArray(e)?"array":null===e?"null":typeof e}function m(e){return document.createElement(e)}y.styleTagTransform=f(),y.setAttributes=l(),y.insert=s().bind(null,"head"),y.domAPI=i(),y.insertStyleElement=u(),n()(v.Z,y),v.Z&&v.Z.locals&&v.Z.locals;const g={HIDDEN:"hidden",CARET_ICON:"caret-icon",CARET_RIGHT:"fa-caret-right",CARET_DOWN:"fa-caret-down",ICON:"fas"};function x(e){e.children.forEach((e=>{e.el.classList.add(g.HIDDEN),e.isExpanded&&x(e)}))}function j(e){e.children.forEach((e=>{e.el.classList.remove(g.HIDDEN),e.isExpanded&&j(e)}))}function b(e){if(e.children.length>0){const n=e.el.querySelector("."+g.ICON);n&&n.classList.replace(g.CARET_RIGHT,g.CARET_DOWN)}}function E(e){if(e.children.length>0){const n=e.el.querySelector("."+g.ICON);n&&n.classList.replace(g.CARET_DOWN,g.CARET_RIGHT)}}function N(e){e.isExpanded?(e.isExpanded=!1,E(e),x(e)):(e.isExpanded=!0,b(e),j(e))}function C(e,n){n(e),e.children.length>0&&e.children.forEach((e=>{C(e,n)}))}function T(e={}){let n=e.hasOwnProperty("value")?e.value:null;return(e=>"object"===h(e)&&0===Object.keys(e).length)(n)&&(n="{}"),{key:e.key||null,parent:e.parent||null,value:n,isExpanded:e.isExpanded||!1,type:e.type||null,children:e.children||[],el:e.el||null,depth:e.depth||0,dispose:null}}function I(e,n){if("object"==typeof e)for(let t in e){const r=T({value:e[t],key:t,depth:n.depth+1,type:h(e[t]),parent:n});n.children.push(r),I(e[t],r)}}function O(e){return"string"==typeof e?JSON.parse(e):e}function S(e){const n=O(e),t=T({value:n,key:h(n),type:h(n)});return I(n,t),t}function k(e,n){const t=S(O(e));return w(t,n),t}function w(e,n){const t=function(){const e=m("div");return e.className="json-container",e}();C(e,(function(e){e.el=function(e){let n=m("div");const t=e=>{const n=e.children.length;return"array"===e.type?`[${n}]`:"object"===e.type?`{${n}}`:null};if(e.children.length>0){n.innerHTML=function(e={}){const{key:n,size:t}=e;return`\n
\n
\n
${n}
\n
${t}
\n
\n `}({key:e.key,size:t(e)});const r=n.querySelector("."+g.CARET_ICON);e.dispose=function(e,n,t){return e.addEventListener(n,t),()=>e.removeEventListener(n,t)}(r,"click",(()=>N(e)))}else n.innerHTML=function(e={}){const{key:n,value:t,type:r}=e;return`\n
\n
\n
${n}
\n
:
\n
${t}
\n
\n `}({key:e.key,value:e.value,type:"{}"===e.value?"object":typeof e.value});const r=n.children[0];return null!==e.parent&&r.classList.add(g.HIDDEN),r.style="margin-left: "+18*e.depth+"px;",r}(e),t.appendChild(e.el)})),n.appendChild(t)}function D(e){C(e,(function(e){e.el.classList.remove(g.HIDDEN),e.isExpanded=!0,b(e)}))}function A(e){C(e,(function(n){n.isExpanded=!1,n.depth>e.depth&&n.el.classList.add(g.HIDDEN),E(n)}))}function L(e){var n;C(e,(e=>{e.dispose&&e.dispose()})),(n=e.el.parentNode).parentNode.removeChild(n)}const H={toggleNode:N,render:w,create:S,renderJSON:k,expand:D,collapse:A,traverse:C,destroy:L}})(),r})())); \ No newline at end of file diff --git a/manifest.json b/manifest.json index 376c79d..d381166 100644 --- a/manifest.json +++ b/manifest.json @@ -10,7 +10,8 @@ "webRequestBlocking", "", "activeTab", - "windows" + "windows", + "storage" ], "background": { "scripts": ["background.js"], diff --git a/popup.html b/popup.html index 5917265..b108403 100644 --- a/popup.html +++ b/popup.html @@ -2,15 +2,16 @@ Widevine L3 Guessor 2024 - + -
+
Widevine content hasn't detected in this page.
Open widevine-protected website and try again!
-
+ -
+ -
+ + + + diff --git a/popup.js b/popup.js index 7f7933a..13526de 100644 --- a/popup.js +++ b/popup.js @@ -1,5 +1,6 @@ let psshs=chrome.extension.getBackgroundPage().getPsshs(); let requests=chrome.extension.getBackgroundPage().getRequests(); +let pageURL=chrome.extension.getBackgroundPage().getPageURL(); function selectPssh(){ document.getElementById('home').style.display='none'; @@ -11,23 +12,44 @@ function selectRequest(){ document.getElementById('selectRequest').style.display='block'; } +function showHistory(){ + chrome.storage.local.get(null, ((data) => { + jsonview.renderJSON(JSON.stringify(data), document.getElementById('histDisp')); + })); + document.getElementById('home').style.display='none'; + document.getElementById('history').style.display='block'; +} + async function guess(){ + //Init Pyodide let pyodide = await loadPyodide(); await pyodide.loadPackage(["certifi-2024.2.2-py3-none-any.whl","charset_normalizer-3.3.2-py3-none-any.whl","construct-2.8.8-py2.py3-none-any.whl","idna-3.6-py3-none-any.whl","packaging-23.2-py3-none-any.whl","protobuf-4.24.4-cp312-cp312-emscripten_3_1_52_wasm32.whl","pycryptodome-3.20.0-cp35-abi3-emscripten_3_1_52_wasm32.whl","pymp4-1.4.0-py3-none-any.whl","pyodide_http-0.2.1-py3-none-any.whl","pywidevine-1.8.0-py3-none-any.whl","requests-2.31.0-py3-none-any.whl","urllib3-2.2.1-py3-none-any.whl"].map(e=>"wheels/"+e)) + + //Configure Guesser let vars=`pssh="${document.getElementById('pssh').value}"\n` vars+=`licUrl="${requests[userInputs['license']]['url']}"\n` vars+=`licHeaders='${requests[userInputs['license']]['headers'].replace(/\\/g, "\\\\")}'\n` let pre=await fetch('python/pre.py').then(res=>res.text()) let after=await fetch('python/after.py').then(res=>res.text()) let scheme=await fetch(`python/schemes/${document.getElementById("scheme").value}.py`).then(res=>res.text()) + + //Get result let result = await pyodide.runPythonAsync([vars, pre, scheme, after].join("\n")); document.getElementById('result').value=result; + + //Save history + let historyData={ + PSSH: document.getElementById('pssh').value, + KEYS: result.split("\n").slice(0,-1) + } + chrome.storage.local.set({[pageURL]: historyData}, function () {}); } if(psshs.length!=0){ document.addEventListener('DOMContentLoaded', function() { document.getElementById('noEME').style.display='none'; document.getElementById('home').style.display='block'; + document.getElementById('historyButton').addEventListener("click", showHistory); document.getElementById('psshButton').addEventListener("click", selectPssh); document.getElementById('licenseButton').addEventListener("click", selectRequest); document.getElementById('guess').addEventListener("click", guess); diff --git a/popup_showHistory.js b/popup_showHistory.js new file mode 100644 index 0000000..9688162 --- /dev/null +++ b/popup_showHistory.js @@ -0,0 +1,29 @@ +document.getElementById('backHistory').addEventListener("click", backHistory); +function backHistory(){ + document.getElementById('histDisp').innerHTML=""; + document.getElementById('history').style.display='none'; + document.getElementById('home').style.display='block'; +} + +document.getElementById('saveHistory').addEventListener("click", saveHistory); +function saveHistory(){ + chrome.storage.local.get(null, ((data) => { + let blob = new Blob([JSON.stringify(data, null, "\t")], {type: "text/plain"}); + let blobLink = URL.createObjectURL(blob); + let a = document.createElement('a'); + a.download = 'wvgHistory.json'; + a.href = blobLink + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(blobLink); + })); +} + +document.getElementById('clearHistory').addEventListener("click", clearHistory); +function clearHistory(){ + if(confirm("Do you really want to clear history?")){ + chrome.storage.local.clear(); + document.getElementById('histDisp').innerHTML=""; + } +}