Fix encrypted video playback in Chrome-based browsers

For Chrome-based browsers, it seems we need to set some non-empty `src` URI for
the video element's play button to be enabled, so this crafts an empty `data`
URI and ensures playing is triggered once the real content has been fetched.

Fixes https://github.com/vector-im/element-web/issues/15694
Regressed by https://github.com/matrix-org/matrix-react-sdk/pull/5352
This commit is contained in:
J. Ryan Stinnett 2020-11-19 13:26:14 +00:00
parent f7e2d70ddf
commit 3e85b6d085

View file

@ -39,6 +39,8 @@ interface IState {
}
export default class MVideoBody extends React.PureComponent<IProps, IState> {
private videoRef = React.createRef<HTMLVideoElement>();
constructor(props) {
super(props);
this.state = {
@ -80,6 +82,11 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
}
}
private hasContentUrl(): boolean {
const url = this.getContentUrl();
return url && !url.startsWith("data:");
}
private getThumbUrl(): string|null {
const content = this.props.mxEvent.getContent();
if (content.file !== undefined) {
@ -118,7 +125,10 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
} else {
console.log("NOT preloading video");
this.setState({
decryptedUrl: null,
// For Chrome and Electron, we need to set some non-empty `src` to
// enable the play button. Firefox does not seem to care either
// way, so it's fine to do for all browsers.
decryptedUrl: `data:${content?.info?.mimetype},`,
decryptedThumbnailUrl: thumbnailUrl,
decryptedBlob: null,
});
@ -143,7 +153,7 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
}
private videoOnPlay = async () => {
if (this.getContentUrl() || this.state.fetchingData || this.state.error) {
if (this.hasContentUrl() || this.state.fetchingData || this.state.error) {
// We have the file, we are fetching the file, or there is an error.
return;
}
@ -164,6 +174,9 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
decryptedUrl: contentUrl,
decryptedBlob: decryptedBlob,
fetchingData: false,
}, () => {
if (!this.videoRef.current) return;
this.videoRef.current.play();
});
this.props.onHeightChanged();
}
@ -215,9 +228,20 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
}
return (
<span className="mx_MVideoBody">
<video className="mx_MVideoBody" src={contentUrl} title={content.body}
controls preload={preload} muted={autoplay} autoPlay={autoplay}
height={height} width={width} poster={poster} onPlay={this.videoOnPlay}>
<video
className="mx_MVideoBody"
ref={this.videoRef}
src={contentUrl}
title={content.body}
controls
preload={preload}
muted={autoplay}
autoPlay={autoplay}
height={height}
width={width}
poster={poster}
onPlay={this.videoOnPlay}
>
</video>
<MFileBody {...this.props} decryptedBlob={this.state.decryptedBlob} />
</span>