Skip to content

Commit

Permalink
Replace player patching with JSON.parse() hook 🖖🖖🖖
Browse files Browse the repository at this point in the history
  • Loading branch information
dannvix committed Apr 25, 2020
1 parent cc60f5b commit 9bd3db3
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 468 deletions.
11 changes: 0 additions & 11 deletions src/background.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,6 @@
const kDefaultSettings = require('./default-settings');


chrome.webRequest.onBeforeRequest.addListener(details => {
console.log(`Denying: ${details.url}`);
return { cancel: true, };
},
{
urls: ['https://assets.nflxext.com/*cadmium-playercore*'],
types: ['script'],
},
['blocking']);


////////////////////////////////////////////////////////////////////////////////


Expand Down
105 changes: 0 additions & 105 deletions src/content.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
const acorn = require('acorn');
const console = require('./console');
const { patch } = require('./nflx-player-patch');


////////////////////////////////////////////////////////////////////////////////


// updated when we got `<script src...>` in the observer
Expand Down Expand Up @@ -33,108 +28,8 @@ window.addEventListener('load', () => {
////////////////////////////////////////////////////////////////////////////////


function mutateUrl(url) {
const u = new URL(url);
const doubleSlashPath = u.pathname.replace(/\//g, '//');
const encodedPath = doubleSlashPath.replace('-', '%2d');
const port = (uu.port || (/https:/i.test(u.protocol) ? ':443' : ':80'));
const mutatedUrl = `${u.protocol}\/\/:@${u.host}${port}${encodedPath}#`;
return mutatedUrl;
}


const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeName.toLowerCase() !== 'script') return;
if (node.id !== 'player-core-js') return;

const playerNode = node;
let playerUrl = playerNode.getAttribute('src');
playerNode.removeAttribute('src');
console.log(`Intercepted: ${playerUrl}`);

// URL looks like "https://assets.nflxext.com/en_us/ffe/player/html/cadmium-playercore-5.0008.727.011.js"
origPlayerUrl = playerUrl;
let match = /playercore-(\d+\.\d+\.\d+\.\d+)\.js/.exec(origPlayerUrl);
if (match) {
origPlayerVersion = match[1];
}

const _patchCodeAndLoad = (playerScript) => {
const patched = patch(playerScript);
const blob = new Blob([patched], { type: 'text/javascript' });

if (BROWSER === 'chrome') {
playerNode.setAttribute('src', URL.createObjectURL(blob));
playerNode.addEventListener('load', () => {
URL.revokeObjectURL(playerNode.getAttribute('src'));
});
}
else if (BROWSER === 'firefox') {
// replacing "src" does not trigger execution in Firefox,
// thus we need to replace the <script> node;
// fortunately, Netflix player page works well with the replacement
const newPlayer = document.createElement('script');
newPlayer.setAttribute('id', playerNode.getAttribute('id'));
newPlayer.setAttribute('src', URL.createObjectURL(blob));
newPlayer.addEventListener('load', () => {
URL.revokeObjectURL(newPlayer.getAttribute('src'));
});
playerNode.replaceWith(newPlayer);
}
};

// fetch original player code, and patch it!
fetch(playerUrl).then(r => r.text()).then(body => {
if ((typeof origPlayerVersion === 'string') &&
(body.indexOf(origPlayerVersion) < 0))
{
// trying to bypass other extensinos :-)
// they intercept the request and reply with a local patched code (likely out-dated)
console.warn("Warning: the player might be tempered by others -- let's bypass them ^_<");

const mutatedUrl = mutateUrl(playerUrl);
fetch(mutatedUrl).then(r => r.text()).then(body2 => {
if (body2.indexOf(origPlayerVersion) < 0) {
console.warn('Warning: still got a outdated player, fine :-(');
_patchCodeAndLoad(body); // body2 may be more corrupt
}
else {
console.log('Success: got the latest official player, hehe!');
_patchCodeAndLoad(body2);
}
});
}
else {
_patchCodeAndLoad(body);
}
});

observer.disconnect();

// FYI to users who open the developer console
if (BROWSER === 'chrome') {
console.log(`FYI: "net::ERR_BLOCKED_BY_CLIENT" error is intented`,
`(for player code patching)`);
}
else if (BROWSER === 'firefox') {
console.log(`FYI: "Loading failed for the <script>" error is intented`,
`(for player code patching)`);
}
});
});
});
const options = { subtree: true, childList: true, };
observer.observe(document, options);


////////////////////////////////////////////////////////////////////////////////


// Firefox: the target website (our injected agent) cannot connect to extensions
// directly, thus we need to relay the connection in this content script.

let gMsgPort;
window.addEventListener('message', evt => {
if (!evt.data || evt.data.namespace !== 'nflxmultisubs') return;
Expand Down
Loading

0 comments on commit 9bd3db3

Please sign in to comment.