Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Commit

Permalink
automatically upgrade default YouTube video playback quality to HD 14…
Browse files Browse the repository at this point in the history
…40p (fixes issue #1051); hide `Full screen is unavailable` message (fixes issue #1056)

- or via `vq=`/`query=` query-string parameter in URLs for youtube.com and youtube-nocookie.com
  • Loading branch information
cvan committed Apr 6, 2019
1 parent 33768e3 commit 7debaaf
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
import static org.mozilla.vrbrowser.utils.ServoUtils.isServoAvailable;

public class SessionStore implements ContentBlocking.Delegate, GeckoSession.NavigationDelegate,
GeckoSession.ProgressDelegate, GeckoSession.ContentDelegate, GeckoSession.TextInputDelegate,
GeckoSession.ProgressDelegate, GeckoSession.ContentDelegate, GeckoSession.TextInputDelegate,
GeckoSession.PromptDelegate, GeckoSession.MediaDelegate, SharedPreferences.OnSharedPreferenceChangeListener {

private static SessionStore mInstance;
Expand Down Expand Up @@ -1042,7 +1042,9 @@ public void onCanGoForward(@NonNull GeckoSession aSession, boolean aCanGoForward
private String checkYoutubeOverride(String aUri) {
try {
Uri uri = Uri.parse(aUri);
if (!uri.getHost().toLowerCase().contains("www.youtube.")) {
String hostLower = uri.getHost().toLowerCase();
if (!hostLower.endsWith(".youtube.com") &&
!hostLower.endsWith(".youtube-nocookie.com")) {
return null;
}
String query = uri.getQueryParameter("disable_polymer");
Expand Down
7 changes: 4 additions & 3 deletions app/src/main/assets/web_extensions/youtube_webcompat/main.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* To hide harmless warning about 360° video playback. */
div.alert-with-button-renderer,
ytm-alert-with-button-renderer {
/* To hide harmless warnings. */
.alert-with-button-renderer, .ytm-alert-with-button-renderer, ytm-alert-with-button-renderer,
.ytp-ad-module, ytp-ad-module
.ytp-generic-popup, ytp-generic-popup {
display: none;
}
179 changes: 167 additions & 12 deletions app/src/main/assets/web_extensions/youtube_webcompat/main.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,174 @@
(function () {
// If missing, inject a `<meta name="viewport">` tag to trigger YouTube's mobile layout.
const viewport = document.head.querySelector('meta[name="viewport"]');
if (!viewport) {
viewport = document.createElement('meta');
viewport.name = 'viewport';
viewport.content = 'width=user-width, initial-scale=1';
document.head.appendChild(viewport);
window.addEventListener('load', () => {
let viewport = document.head.querySelector('meta[name="viewport"]');
if (!viewport) {
viewport = document.createElement('meta');
viewport.name = 'viewport';
viewport.content = 'width=device-width, initial-scale=1';
document.head.appendChild(viewport);
}
});

const LOGTAG = '[firefoxreality:webcompat]'
const qs = new URLSearchParams(window.location.search);
let retryTimeout = null;

function getTruthyQS (key) {
if (!qs || !qs.has(key)) {
return false;
}
const valueLower = (qs.get('key') || '').trim().toLowerCase();
return valueLower === '' || valueLower === '1' || valueLower === 'true' || valueLower === 'yes' || valueLower === 'on';
}

// Open the `Settings` menu.
document.querySelector('ytp-settings-button, .ytp-settings-button').click();
const prefs = {
hd: false,
quality: 1440,
log: qs.get('mozDebug') ? getTruthyQS('mozDebug') : true,
retryAttempts: parseInt(qs.get('retryAttempts') || qs.get('retryattempts') || '5', 10),
retryTimeout: parseInt(qs.get('retryTimeout') || qs.get('retrytimeout') || '500', 10)
};

const printLog = String(prefs.log) === 'true';

const log = (...args) => printLog && console.log(LOGTAG, ...args);
const logError = (...args) => printLog && console.error(LOGTAG, ...args);
const logWarn = (...args) => printLog && console.warn(LOGTAG, ...args);

const ytImprover = window.ytImprover = (state, attempts) => {
if (ytImprover.completed) {
return;
}

if (typeof attempts === 'undefined') {
attempts = 1;
}
if (attempts >= prefs.retryAttempts) {
return;
}

const player = document.getElementById('movie_player');
if (state !== 1 || !player) {
attempts++;
retryTimeout = setTimeout(() => {
ytImprover(state, attempts);
}, prefs.retryInterval);
return;
}

const levels = player.getAvailableQualityLevels();
if (!levels || !levels.length) {
logWarn('Cannot read `player.getAvailableQualityLevels()`');
return;
}

clearTimeout(retryTimeout);
ytImprover.completed = true;

const prefs.qualities = [
'highres', 'h2880', 'hd2160', 'hd1440', 'hd1080', 'hd720', 'large', 'medium', 'small', 'tiny', 'auto'
];
const prefs.qualityLabels = {
'4320': 'highres', // 8K / 4320p / QUHD
'2880': 'hd2880', // 5K / 2880p / UHD+
'2160': 'hd2160', // 4K / 2160p / UHD
'1440': 'hd1440', // 1440p / QHD
'1080': 'hd1080', // 1080p / FHD
'720': 'hd720', // 720p / HD
'480': 'large', // 480p
'360': 'medium', // 360p
'240': 'small', // 240p
'144': 'tiny', // 144p
'0': 'auto'
};

// Select the `Quality` sub-menu.
document.querySelector('ytp-settings-menu ytp-menuitem:last-child, .ytp-settings-menu .ytp-menuitem:last-child').click();
const getDesiredQuality = () => {
const qsQuality = (qs.get('vq') || qs.get('quality') || '').trim().toLowerCase();
if (qsQuality) {
if (qsQuality in prefs.qualityLabels) {
prefs.quality = prefs.qualityLabels[qsQuality];
} else {
const qsQualityNumber = parseInt(qsQuality, 10);
if (Number.isInteger(qsQualityNumber)) {
prefs.quality = qsQualityNumber;
} else {
prefs.quality = qsQuality;
}
}
}
prefs.quality = String(prefs.quality).toLowerCase();
if (qsQuality === 'auto' || qsQuality === 'default') {
prefs.quality = 'auto';
}
if (prefs.quality in prefs.qualityLabels) {
prefs.quality = prefs.qualityLabels[prefs.quality];
}
return prefs.quality;
};

// Select the best `Quality`.
document.querySelector('ytp-quality-menu ytp-menuitem:first-child, .ytp-quality-menu .ytp-menuitem:first-child').click();
prefs.quality = getDesiredQuality();
if (prefs.quality === 'auto') {
return log(`Desired quality is fine (${prefs.quality})`);
}

const currentQuality = player.getPlaybackQuality();
if (prefs.quality === currentQuality) {
return log(`Current quality is desired quality (${currentQuality})`);
}

const findBestQuality = increase => {
if (prefs.quality === 'highest' || prefs.quality === 'best' || prefs.quality === 'max' || prefs.quality === 'maximum') {
return levels[0];
}
if (prefs.quality === 'lowest' || prefs.quality === 'worst' || prefs.quality === 'min' || prefs.quality === 'minimum') {
return levels[levels.length - 1];
}
if (increase) {
prefs.quality = prefs.qualities[prefs.qualities.indexOf(prefs.quality) - 1] || levels[0];
}
const index = levels.indexOf(prefs.quality);
if (index !== -1) {
return prefs.quality;
}
return findBestQuality(true);
};
const newBestQuality = findBestQuality();
if (currentQuality === newBestQuality) {
return log(`Current quality "${currentQuality}" is the best available quality`);
}

if (!player.setPlaybackQuality) {
return logError('`player.setPlaybackQuality` not available');
}
player.setPlaybackQuality(newBestQuality);

if (!player.setPlaybackQualityRange) {
return logError('`player.setPlaybackQualityRange` not available');
}
try {
player.setPlaybackQualityRange(newBestQuality, newBestQuality);
} catch (e) {
}

log(`Changed quality from "${currentQuality}" to "${newBestQuality}"`);
};

if (window.location.pathname.startsWith('/watch')) {
const onYouTubePlayerReady = window.onYouTubePlayerReady = evt => {
log('`onYouTubePlayerReady` called');
window.ytImprover(1);
evt.addEventListener('onStateChange', 'ytImprover');
};

window.addEventListener('spfready', () => {
log('`spfready` event fired');
if (typeof window.ytplayer === 'object' && window.ytplayer.config) {
log('`window.ytplayer.config.args.jsapicallback` set');
window.ytplayer.config.args.jsapicallback = 'onYouTubePlayerReady';
}
});

ytImprover(1);
}
})();
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@
"content_scripts": [
{
"matches": [
"*://*.youtube.com/*"
"*://*.youtube.com/*",
"*://*.youtube-nocookie.com/*"
],
"css": [
"main.css"
],
"js": [
"main.js"
],
"run_at": "document_end"
"run_at": "document_start",
"all_frames": true
}
]
}

0 comments on commit 7debaaf

Please sign in to comment.