@@ -403,15 +403,19 @@ function runApp() {
403403 sameSite : 'no_restriction' ,
404404 } )
405405
406- // make InnerTube requests work with the fetch function
407- // InnerTube rejects requests if the referer isn't YouTube or empty
408- const innertubeAndMediaRequestFilter = { urls : [ 'https://www.youtube.com/youtubei/*' , 'https://*.googlevideo.com/videoplayback?*' ] }
409-
410- session . defaultSession . webRequest . onBeforeSendHeaders ( innertubeAndMediaRequestFilter , ( { requestHeaders, url, resourceType } , callback ) => {
411- requestHeaders . Referer = 'https://www.youtube.com/'
412- requestHeaders . Origin = 'https://www.youtube.com'
406+ const onBeforeSendHeadersRequestFilter = {
407+ urls : [ 'https://*/*' , 'http://*/*' ] ,
408+ types : [ 'xhr' , 'media' , 'image' ]
409+ }
410+ session . defaultSession . webRequest . onBeforeSendHeaders ( onBeforeSendHeadersRequestFilter , ( { requestHeaders, url, resourceType, webContents } , callback ) => {
411+ const urlObj = new URL ( url )
413412
414413 if ( url . startsWith ( 'https://www.youtube.com/youtubei/' ) ) {
414+ // make InnerTube requests work with the fetch function
415+ // InnerTube rejects requests if the referer isn't YouTube or empty
416+ requestHeaders . Referer = 'https://www.youtube.com/'
417+ requestHeaders . Origin = 'https://www.youtube.com'
418+
415419 // Make iOS requests work and look more realistic
416420 if ( requestHeaders [ 'x-youtube-client-name' ] === '5' ) {
417421 delete requestHeaders . Referer
@@ -430,41 +434,50 @@ function runApp() {
430434 requestHeaders [ 'Sec-Fetch-Mode' ] = 'same-origin'
431435 requestHeaders [ 'X-Youtube-Bootstrap-Logged-In' ] = 'false'
432436 }
433- } else {
437+ } else if ( urlObj . origin . endsWith ( '.googlevideo.com' ) && urlObj . pathname === '/videoplayback' ) {
438+ requestHeaders . Referer = 'https://www.youtube.com/'
439+ requestHeaders . Origin = 'https://www.youtube.com'
440+
434441 // YouTube doesn't send the Content-Type header for the media requests, so we shouldn't either
435442 delete requestHeaders [ 'Content-Type' ]
436- }
437443
438- // YouTube throttles the adaptive formats if you request a chunk larger than 10MiB.
439- // For the DASH formats we are fine as video.js doesn't seem to ever request chunks that big.
440- // The legacy formats don't have any chunk size limits.
441- // For the audio formats we need to handle it ourselves, as the browser requests the entire audio file,
442- // which means that for most videos that are longer than 10 mins, we get throttled, as the audio track file sizes surpass that 10MiB limit.
444+ // YouTube throttles the adaptive formats if you request a chunk larger than 10MiB.
445+ // For the DASH formats we are fine as video.js doesn't seem to ever request chunks that big.
446+ // The legacy formats don't have any chunk size limits.
447+ // For the audio formats we need to handle it ourselves, as the browser requests the entire audio file,
448+ // which means that for most videos that are longer than 10 mins, we get throttled, as the audio track file sizes surpass that 10MiB limit.
443449
444- // This code checks if the file is larger than the limit, by checking the `clen` query param,
445- // which YouTube helpfully populates with the content length for us.
446- // If it does surpass that limit, it then checks if the requested range is larger than the limit
447- // (seeking right at the end of the video, would result in a small enough range to be under the chunk limit)
448- // if that surpasses the limit too, it then limits the requested range to 10MiB, by setting the range to `start-${start + 10MiB}`.
449- if ( resourceType === 'media' && url . includes ( '& mime= audio') && requestHeaders . Range ) {
450- const TEN_MIB = 10 * 1024 * 1024
450+ // This code checks if the file is larger than the limit, by checking the `clen` query param,
451+ // which YouTube helpfully populates with the content length for us.
452+ // If it does surpass that limit, it then checks if the requested range is larger than the limit
453+ // (seeking right at the end of the video, would result in a small enough range to be under the chunk limit)
454+ // if that surpasses the limit too, it then limits the requested range to 10MiB, by setting the range to `start-${start + 10MiB}`.
455+ if ( resourceType === 'media' && urlObj . searchParams . get ( ' mime' ) ?. startsWith ( ' audio/ ') && requestHeaders . Range ) {
456+ const TEN_MIB = 10 * 1024 * 1024
451457
452- const contentLength = parseInt ( new URL ( url ) . searchParams . get ( 'clen' ) )
458+ const contentLength = parseInt ( new URL ( url ) . searchParams . get ( 'clen' ) )
453459
454- if ( contentLength > TEN_MIB ) {
455- const [ startStr , endStr ] = requestHeaders . Range . split ( '=' ) [ 1 ] . split ( '-' )
460+ if ( contentLength > TEN_MIB ) {
461+ const [ startStr , endStr ] = requestHeaders . Range . split ( '=' ) [ 1 ] . split ( '-' )
456462
457- const start = parseInt ( startStr )
463+ const start = parseInt ( startStr )
458464
459- // handle open ended ranges like `0-` and `1234-`
460- const end = endStr . length === 0 ? contentLength : parseInt ( endStr )
465+ // handle open ended ranges like `0-` and `1234-`
466+ const end = endStr . length === 0 ? contentLength : parseInt ( endStr )
461467
462- if ( end - start > TEN_MIB ) {
463- const newEnd = start + TEN_MIB
468+ if ( end - start > TEN_MIB ) {
469+ const newEnd = start + TEN_MIB
464470
465- requestHeaders . Range = `bytes=${ start } -${ newEnd } `
471+ requestHeaders . Range = `bytes=${ start } -${ newEnd } `
472+ }
466473 }
467474 }
475+ } else if ( webContents ) {
476+ const invidiousAuthorization = invidiousAuthorizations . get ( webContents . id )
477+
478+ if ( invidiousAuthorization && url . startsWith ( invidiousAuthorization . url ) ) {
479+ requestHeaders . Authorization = invidiousAuthorization . authorization
480+ }
468481 }
469482
470483 // eslint-disable-next-line n/no-callback-literal
@@ -488,8 +501,10 @@ function runApp() {
488501 const imageCache = new ImageCache ( )
489502
490503 protocol . handle ( 'imagecache' , ( request ) => {
504+ const [ requestUrl , rawWebContentsId ] = request . url . split ( '#' )
505+
491506 return new Promise ( ( resolve , reject ) => {
492- const url = decodeURIComponent ( request . url . substring ( 13 ) )
507+ const url = decodeURIComponent ( requestUrl . substring ( 13 ) )
493508 if ( imageCache . has ( url ) ) {
494509 const cached = imageCache . get ( url )
495510
@@ -499,9 +514,22 @@ function runApp() {
499514 return
500515 }
501516
517+ let headers
518+
519+ if ( rawWebContentsId ) {
520+ const invidiousAuthorization = invidiousAuthorizations . get ( parseInt ( rawWebContentsId ) )
521+
522+ if ( invidiousAuthorization && url . startsWith ( invidiousAuthorization . url ) ) {
523+ headers = {
524+ Authorization : invidiousAuthorization . authorization
525+ }
526+ }
527+ }
528+
502529 const newRequest = net . request ( {
503530 method : request . method ,
504- url
531+ url,
532+ headers
505533 } )
506534
507535 // Electron doesn't allow certain headers to be set:
@@ -548,19 +576,20 @@ function runApp() {
548576 } )
549577 } )
550578
551- const imageRequestFilter = { urls : [ 'https://*/*' , 'http://*/*' ] }
579+ const imageRequestFilter = { urls : [ 'https://*/*' , 'http://*/*' ] , types : [ 'image' ] }
552580 session . defaultSession . webRequest . onBeforeRequest ( imageRequestFilter , ( details , callback ) => {
553581 // the requests made by the imagecache:// handler to fetch the image,
554582 // are allowed through, as their resourceType is 'other'
555- if ( details . resourceType === 'image' ) {
556- // eslint-disable-next-line n/no-callback-literal
557- callback ( {
558- redirectURL : `imagecache://${ encodeURIComponent ( details . url ) } `
559- } )
560- } else {
561- // eslint-disable-next-line n/no-callback-literal
562- callback ( { } )
583+
584+ let redirectURL = `imagecache://${ encodeURIComponent ( details . url ) } `
585+
586+ if ( details . webContents ) {
587+ redirectURL += `#${ details . webContents . id } `
563588 }
589+
590+ callback ( {
591+ redirectURL
592+ } )
564593 } )
565594
566595 // --- end of `if experimentsDisableDiskCache` ---
@@ -1011,6 +1040,21 @@ function runApp() {
10111040 await asyncFs . writeFile ( filePath , new Uint8Array ( value ) )
10121041 } )
10131042
1043+ /** @type {Map<number, { url: string, authorization: string }> } */
1044+ const invidiousAuthorizations = new Map ( )
1045+
1046+ ipcMain . on ( IpcChannels . SET_INVIDIOUS_AUTHORIZATION , ( event , authorization , url ) => {
1047+ if ( ! isFreeTubeUrl ( event . senderFrame . url ) ) {
1048+ return
1049+ }
1050+
1051+ if ( ! authorization ) {
1052+ invidiousAuthorizations . delete ( event . sender . id )
1053+ } else if ( typeof authorization === 'string' && typeof url === 'string' ) {
1054+ invidiousAuthorizations . set ( event . sender . id , { authorization, url } )
1055+ }
1056+ } )
1057+
10141058 // ************************************************* //
10151059 // DB related IPC calls
10161060 // *********** //
@@ -1376,6 +1420,12 @@ function runApp() {
13761420 }
13771421 } )
13781422
1423+ app . on ( 'web-contents-created' , ( _ , webContents ) => {
1424+ webContents . once ( 'destroyed' , ( ) => {
1425+ invidiousAuthorizations . delete ( webContents . id )
1426+ } )
1427+ } )
1428+
13791429 /*
13801430 * Check if an argument was passed and send it over to the GUI (Linux / Windows).
13811431 * Remove freetube:// protocol if present
0 commit comments