Browser extension to watch YouTube videos without the distracting cruft around it, in the full window.

youtubecinema/ background.js
126 lines
3.6 KiB

  1. // Be compatible with Chrome|ium. We do not need the full webextension-polyfill.
  2. if (typeof browser === 'undefined') {
  3. this.browser = chrome;
  4. }
  5. // Keep a set of tabIds for which the user disabled the cinema mode (with the pageAction button)
  6. var tabsWithCinemaModeDisabled = {};
  7. function hasCinemaModeEnabled(tabId) {
  8. return !tabsWithCinemaModeDisabled[tabId];
  9. }
  10. // Our request filters should make use of this test unnecessary, but I prefer to keep it explicit.
  11. function isYoutube(url) {
  12. return new URL(url).hostname.endsWith('.youtube.com');
  13. }
  14. function isEmbeddedVideo(url) {
  15. return (
  16. isYoutube(url)
  17. && new URL(url).pathname.startsWith('/embed/')
  18. );
  19. }
  20. function isCruftedVideo(url) {
  21. return (
  22. isYoutube(url)
  23. && new URL(url).pathname === '/watch'
  24. );
  25. }
  26. function cruftedToEmbeddableVideoUrl(url) {
  27. url = new URL(url);
  28. var videoId = url.searchParams.get('v');
  29. url.pathname = '/embed/' + videoId;
  30. url.searchParams.delete('v');
  31. url.searchParams.set('rel', '0'); // no suggestions after my video, please.
  32. url.searchParams.set('autoplay', '1');
  33. return url.href;
  34. }
  35. function embeddableToCruftedVideoUrl(url) {
  36. url = new URL(url);
  37. var videoId = url.pathname.match(/\/embed\/(.*)/)[1];
  38. url.pathname = '/watch';
  39. url.searchParams.set('v', videoId);
  40. url.searchParams.delete('rel');
  41. url.searchParams.delete('autoplay');
  42. return url.href;
  43. }
  44. // Turn a video url into its embeddable (full-window) version, or vice versa if not in cinema mode.
  45. function makeNewUrl(url, cinemaModeEnabled) {
  46. if (cinemaModeEnabled) {
  47. if (isCruftedVideo(url)) {
  48. return cruftedToEmbeddableVideoUrl(url);
  49. }
  50. }
  51. else {
  52. if (isEmbeddedVideo(url)) {
  53. return embeddableToCruftedVideoUrl(url);
  54. }
  55. }
  56. return undefined;
  57. }
  58. // Redirect crufted videos to their full-window version.
  59. function onBeforeRequestListener(details) {
  60. if (hasCinemaModeEnabled(details.tabId)) {
  61. var newUrl = makeNewUrl(details.url, true);
  62. // Return if we were not visiting a embedded youtube video
  63. if (newUrl === undefined) return;
  64. return {redirectUrl: newUrl};
  65. }
  66. }
  67. browser.webRequest.onBeforeRequest.addListener(
  68. onBeforeRequestListener,
  69. {urls: ["*://*.youtube.com/watch*"]},
  70. ['blocking']
  71. );
  72. // Show the pageAction button if looking at a video (either with or without cruft).
  73. var youtubeUrlFilter = {url: [{hostSuffix: '.youtube.com'}]}
  74. browser.webNavigation.onCommitted.addListener(handleNavigation, youtubeUrlFilter);
  75. browser.webNavigation.onHistoryStateUpdated.addListener(handleNavigation, youtubeUrlFilter);
  76. function handleNavigation(details) {
  77. if (details.frameId !== 0) {
  78. return;
  79. }
  80. // If we are on youtube, show the button.
  81. if (isYoutube(details.url)) {
  82. // Show the pageAction button.
  83. browser.pageAction.show(details.tabId);
  84. // In Chrome|ium, listeners stay across page changes, in Firefox they don't. So check first.
  85. if (!browser.pageAction.onClicked.hasListener(handlePageAction))
  86. browser.pageAction.onClicked.addListener(handlePageAction);
  87. }
  88. }
  89. // Enable/Disable cinema mode when the pageAction button is clicked.
  90. function handlePageAction(tab) {
  91. if (
  92. hasCinemaModeEnabled(tab.id)
  93. // When viewing an embedded video with cinema mode disabled, behave as if it was enabled.
  94. || isEmbeddedVideo(tab.url)
  95. ) {
  96. // Disable cinema mode.
  97. tabsWithCinemaModeDisabled[tab.id] = true;
  98. } else {
  99. // Enable cinema mode.
  100. delete tabsWithCinemaModeDisabled[tab.id];
  101. }
  102. // Relocate this page to reflect the new mode.
  103. var newUrl = makeNewUrl(tab.url, hasCinemaModeEnabled(tab.id));
  104. if (newUrl)
  105. browser.tabs.update(tab.id, {url: newUrl});
  106. }