Merge pull request #5430 from matrix-org/jryans/fix-encrypted-videos

Fix encrypted video playback in Chrome-based browsers
This commit is contained in:
J. Ryan Stinnett 2020-11-19 13:59:35 +00:00 committed by GitHub
commit dea4fd661a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

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 = {
@ -71,7 +73,7 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
}
}
_getContentUrl(): string|null {
private getContentUrl(): string|null {
const content = this.props.mxEvent.getContent();
if (content.file !== undefined) {
return this.state.decryptedUrl;
@ -80,7 +82,12 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
}
}
_getThumbUrl(): string|null {
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) {
return this.state.decryptedThumbnailUrl;
@ -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,
});
@ -142,8 +152,8 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
}
}
async _videoOnPlay() {
if (this._getContentUrl() || this.state.fetchingData || this.state.error) {
private videoOnPlay = async () => {
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();
}
@ -195,8 +208,8 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
);
}
const contentUrl = this._getContentUrl();
const thumbUrl = this._getThumbUrl();
const contentUrl = this.getContentUrl();
const thumbUrl = this.getThumbUrl();
let height = null;
let width = null;
let poster = null;
@ -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.bind(this)}>
<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>