commit 8f13e670c5d2f8c7eacf909c2f30f5a76e49e0f0 Author: TheBrokenRail Date: Fri Mar 18 23:58:19 2022 -0400 Initial Commit diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2eee90d --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 TheBrokenRail + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e74b777 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# Force High-Resolution DisneyNOW +This browser extension forces DisneyNOW to use their higher-resolution video stream by imitating the Android app. diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..51c711d --- /dev/null +++ b/manifest.json @@ -0,0 +1,21 @@ +{ + "description": "This browser extension forces DisneyNOW to use their higher-resolution video stream by imitating the Android app.", + "manifest_version": 2, + "name": "Force High-Resolution DisneyNOW", + "version": "1.0", + "content_scripts": [ + { + "matches": ["*://disneynow.com/*"], + "js": ["content.js"], + "run_at": "document_end" + } + ], + "web_accessible_resources": [ + "page.js" + ], + "browser_specific_settings": { + "gecko": { + "id": "high-res-disneynow@thebrokenrail.com" + } + } +} diff --git a/src/content.js b/src/content.js new file mode 100644 index 0000000..16347e8 --- /dev/null +++ b/src/content.js @@ -0,0 +1,6 @@ +const script = document.createElement('SCRIPT'); +script.src = chrome.runtime.getURL('page.js'); +script.onload = function() { + this.remove(); +}; +(document.head || document.documentElement).appendChild(script); diff --git a/src/manifest.json b/src/manifest.json new file mode 100755 index 0000000..14f18cf --- /dev/null +++ b/src/manifest.json @@ -0,0 +1,21 @@ +{ + "description": "This extension forces DisneyNOW to use their higher-resolution HLS video stream instead of their low-resolution DASH video stream.", + "manifest_version": 2, + "name": "Force High-Resolution DisneyNOW", + "version": "1.0", + "content_scripts": [ + { + "matches": ["*://disneynow.com/*"], + "js": ["content.js"], + "run_at": "document_end" + } + ], + "web_accessible_resources": [ + "page.js" + ], + "browser_specific_settings": { + "gecko": { + "id": "high-res-disneynow@thebrokenrail.com" + } + } +} diff --git a/src/page.js b/src/page.js new file mode 100644 index 0000000..729d558 --- /dev/null +++ b/src/page.js @@ -0,0 +1,58 @@ +'use strict'; + +// Constants +const DEVICE_ID = '031_04'; // Found in the APK as @string/device_id +const BRAND_ID = '011'; // Selected from the function mapBrandCode(), which is found in embed.min.js (a script loaded by the website) + +// Patch XMLHttpRequest.open +const oldOpen = XMLHttpRequest.prototype.open; +Object.defineProperty(XMLHttpRequest.prototype, 'open', { + value: function (method, url, ...args) { + // Flag + this._isTargetUrl = (new URL(url)).pathname.endsWith('/playmanifest_secure.json'); + + // Call Original Method + oldOpen.call(this, method, url, ...args); + }, + enumerable: false, + configurable: false, + writable: false +}); + +// Patch XMLHttpRequest.send +const oldSend = XMLHttpRequest.prototype.send; +Object.defineProperty(XMLHttpRequest.prototype, 'send', { + value: function (body, ...args) { + // Check + if (body && this._isTargetUrl) { + // Parse Request Body + const params = new URLSearchParams(body); + + // Pretend to be an Android device + if (params.has('device')) { + params.set('device', DEVICE_ID); + } + + // Switch brand to one without ads + if (params.has('brand')) { + params.set('brand', BRAND_ID); + } + + // Apply Patch + body = params.toString(); + + // Verify + this.addEventListener("load", function () { + const obj = JSON.parse(this.responseText); + const assetUrl = new URL(obj.video.assets.asset[0].value); + console.log('Video Stream URL: ' + assetUrl); + }); + } + + // Call Original Method + oldSend.call(this, body, ...args); + }, + enumerable: false, + configurable: false, + writable: false +});