@@ -17,7 +17,7 @@ export type StartupPreloadHint = {
1717 artifactPath : string ;
1818 as : "fetch" | "image" | "video" ;
1919 contentType ?: string ;
20- crossOrigin : "anonymous" | "use-credentials ";
20+ crossOrigin ? : "anonymous" ;
2121 url : string ;
2222} ;
2323
@@ -123,7 +123,25 @@ export function playbackCredentialMode(data: WatchPlaybackBootstrapResponse | nu
123123}
124124
125125export function playbackCrossOrigin ( data : WatchPlaybackBootstrapResponse | null | undefined ) {
126- return playbackCredentialMode ( data ) === "omit" ? "anonymous" : "use-credentials" ;
126+ // Tigris authorizes private playback with cookies, but its S3 CORS response
127+ // does not include Access-Control-Allow-Credentials. Omitting crossorigin
128+ // lets the media element use its credentialed no-CORS path; public playback
129+ // remains explicitly anonymous and CORS-readable.
130+ return playbackCredentialMode ( data ) === "omit" ? "anonymous" : undefined ;
131+ }
132+
133+ export function scriptedHlsAllowed (
134+ data : WatchPlaybackBootstrapResponse | null | undefined ,
135+ pageUrl : string ,
136+ ) {
137+ const ready = readyBootstrap ( data ) ;
138+ if ( ! ready ?. manifest_url ) return false ;
139+ if ( playbackCredentialMode ( ready ) === "omit" ) return true ;
140+ try {
141+ return new URL ( ready . manifest_url , pageUrl ) . origin === new URL ( pageUrl ) . origin ;
142+ } catch {
143+ return false ;
144+ }
127145}
128146
129147function hlsStartupConfig ( data : WatchPlaybackBootstrapReady ) {
@@ -745,6 +763,12 @@ export function attachPlayback(
745763 const ready = readyBootstrap ( options . initialBootstrap ) ;
746764 telemetry ?. playerLoad ( ) ;
747765
766+ const applyCrossOrigin = ( data : WatchPlaybackBootstrapReady | null ) => {
767+ const value = playbackCrossOrigin ( data ) ;
768+ if ( value ) video . crossOrigin = value ;
769+ else video . removeAttribute ( "crossorigin" ) ;
770+ } ;
771+
748772 const applyProgressiveSource = (
749773 selection : SourceSelection ,
750774 data : WatchPlaybackBootstrapReady | null = ready ,
@@ -753,7 +777,7 @@ export function attachPlayback(
753777 setSelection ( player , selection ) ;
754778 setState ( player , "ready" ) ;
755779 telemetry ?. sourceSelected ( selection ) ;
756- video . crossOrigin = playbackCrossOrigin ( data ) ;
780+ applyCrossOrigin ( data ) ;
757781 if ( video . currentSrc !== selection . url && video . getAttribute ( "src" ) !== selection . url ) {
758782 video . src = selection . url ;
759783 setAttribute ( player , "data-rend-src-assigned-ms" , Math . max ( 0 , Math . round ( performance . now ( ) ) ) ) ;
@@ -775,7 +799,7 @@ export function attachPlayback(
775799 setSelection ( player , selection ) ;
776800 setState ( player , "ready" ) ;
777801 telemetry ?. sourceSelected ( selection ) ;
778- video . crossOrigin = playbackCrossOrigin ( data ) ;
802+ applyCrossOrigin ( data ) ;
779803 if ( ! video . currentSrc && ! video . getAttribute ( "src" ) ) {
780804 video . src = selection . url ;
781805 setAttribute ( player , "data-rend-src-assigned-ms" , Math . max ( 0 , Math . round ( performance . now ( ) ) ) ) ;
@@ -786,7 +810,11 @@ export function attachPlayback(
786810 }
787811
788812 let Hls : HlsConstructor | null = null ;
789- if ( data . manifest_url && ( options . playbackEngine === "mse" || ! nativeHls ) ) {
813+ if (
814+ data . manifest_url &&
815+ scriptedHlsAllowed ( data , window . location . href ) &&
816+ ( options . playbackEngine === "mse" || ! nativeHls )
817+ ) {
790818 try {
791819 Hls = await loadHlsConstructor ( ) ;
792820 } catch {
@@ -812,7 +840,7 @@ export function attachPlayback(
812840 setSelection ( player , selection ) ;
813841 setState ( player , "ready" ) ;
814842 telemetry ?. sourceSelected ( selection ) ;
815- video . crossOrigin = playbackCrossOrigin ( data ) ;
843+ applyCrossOrigin ( data ) ;
816844 video . removeAttribute ( "src" ) ;
817845 video . load ( ) ;
818846 hls = new Hls ( hlsStartupConfig ( data ) ) ;
0 commit comments