Skip to content

Commit

Permalink
Merge pull request #3053 from brave/webtorrent-render
Browse files Browse the repository at this point in the history
WebTorrent: Support rendering images, PDFs, more media formats, and text-like files
  • Loading branch information
yrliou committed Jul 31, 2019
2 parents 4d4ac87 + 64822b6 commit 9b41325
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const createServer = (torrent: WebTorrent.Torrent, cb: (serverURL: string
origin: window.location.origin,
// Use hostname option to mitigate DNS rebinding
// Ref: https://github.com/brave/browser-laptop/issues/12616
hostname: 'localhost'
hostname: '127.0.0.1'
}
const server = torrent.createServer(opts)
if (!server) return
Expand Down
92 changes: 73 additions & 19 deletions components/brave_webtorrent/extension/components/mediaViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,47 @@ import * as React from 'react'
// Constants
import { TorrentObj, File } from '../constants/webtorrentState'

const SUPPORTED_VIDEO_EXTENSIONS = ['m4v', 'mkv', 'mov', 'mp4', 'ogv', 'webm']

const SUPPORTED_AUDIO_EXTENSIONS = ['aac', 'mp3', 'ogg', 'wav', 'm4a']
const SUPPORTED_VIDEO_EXTENSIONS = [
'm4v',
'mkv',
'mov',
'mp4',
'ogv',
'webm'
]

const SUPPORTED_AUDIO_EXTENSIONS = [
'aac',
'flac',
'm4a',
'm4b',
'm4p',
'mp3',
'oga',
'ogg',
'wav'
]

const SUPPORTED_IMAGE_EXTENSIONS = [
'bmp',
'gif',
'jpeg',
'jpg',
'png',
'svg'
]

const SUPPORTED_PDF_EXTENSIONS = [
'pdf'
]

const SUPPORTED_IFRAME_EXTENSIONS = [
'css',
'html',
'js',
'md',
'txt'
]

// Given 'foo.txt', returns 'txt'
// Given eg. null, undefined, '', or 'README', returns null
Expand All @@ -26,18 +64,21 @@ const getSelectedFile = (torrent: TorrentObj, ix: number) => {
: null
}

const fileIsVideo = (file: File | null) => {
if (!file) return false
const fileExt = getExtension(file.name)
if (!fileExt) return false
return SUPPORTED_VIDEO_EXTENSIONS.includes(fileExt)
}
const fileIsType = (file: File | null, type: String) => {
const supportedExtensions = type === 'video'
? SUPPORTED_VIDEO_EXTENSIONS
: type === 'audio'
? SUPPORTED_AUDIO_EXTENSIONS
: type === 'image'
? SUPPORTED_IMAGE_EXTENSIONS
: type === 'pdf'
? SUPPORTED_PDF_EXTENSIONS
: SUPPORTED_IFRAME_EXTENSIONS

const fileIsAudio = (file: File | null) => {
if (!file) return false
const fileExt = getExtension(file.name)
if (!fileExt) return false
return SUPPORTED_AUDIO_EXTENSIONS.includes(fileExt)
return supportedExtensions.includes(fileExt)
}

interface Props {
Expand All @@ -63,7 +104,8 @@ export default class MediaViewer extends React.PureComponent<Props, {}> {
// Set page background to black when video or audio is being viewed
const { torrent, ix } = this.props
const file = getSelectedFile(torrent, ix)
const isMedia = fileIsAudio(file) || fileIsVideo(file)
const isMedia = fileIsType(file, 'video') || fileIsType(file, 'audio') ||
fileIsType(file, 'image')
if (isMedia) {
document.body.style.backgroundColor = 'rgb(0, 0, 0)'
} else {
Expand All @@ -79,26 +121,38 @@ export default class MediaViewer extends React.PureComponent<Props, {}> {
const { torrent, ix } = this.props

const file = getSelectedFile(torrent, ix)
const isAudio = fileIsAudio(file)
const isVideo = fileIsVideo(file)
const fileURL = torrent.serverURL && torrent.serverURL + '/' + ix

let content
if (!file || !fileURL) {
content = <div className='loading'>Loading Media</div>
} else if (isVideo) {
} else if (fileIsType(file, 'video')) {
content = (
<video id='video' src={fileURL} ref={this.ref} controls={true} />
)
} else if (isAudio) {
} else if (fileIsType(file, 'audio')) {
content = (
<audio id='audio' src={fileURL} ref={this.ref} controls={true} />
)
} else {
} else if (fileIsType(file, 'image')) {
content = (
<img id='image' src={fileURL} />
)
} else if (fileIsType(file, 'pdf')) {
content = (
<object id='object' type='application/pdf' data={fileURL} />
)
} else if (fileIsType(file, 'iframe')) {
// For security, sandbox and disallow scripts.
// We need allow-same-origin so that the iframe can load from
// http://localhost:...
content = <iframe id='other' src={fileURL} sandbox='allow-same-origin' />
// http://127.0.0.1:port...
content = (
<iframe id='iframe' src={fileURL} sandbox='allow-same-origin' />
)
} else {
content = (
<div>Unsupported file type</div>
)
}

return <div className='mediaViewer'>{content}</div>
Expand Down
2 changes: 1 addition & 1 deletion components/brave_webtorrent/extension/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@
"listen": "*:*"
}
},
"content_security_policy": "default-src 'self'; connect-src 'self' http: https:; font-src 'self' data:; script-src 'self'; media-src 'self' http://127.0.0.1:*; form-action 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-src 'self' http://127.0.0.1:*;",
"content_security_policy": "default-src 'self'; connect-src 'self' http: https:; font-src 'self' data:; script-src 'self'; media-src 'self' http://127.0.0.1:*; form-action 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data: http://127.0.0.1:*; object-src 'self' http://127.0.0.1:*; frame-src 'self' http://127.0.0.1:*;",
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArfOx1MW/cb3YPNlmT37CuISYgRbtR1SIdgnx/cfTyXO/PuD1VVsQWLDmrZGDmYVCzZvP36t75uhpJH4IoXL58U16yhdXZeSlb0LKcgMZB6cMNyjznV4NTEeY+tLnwGaB1TVdkJgSlY09psyfvcdzQd8xz9CNE6CXDzEq8+uMSaoAyEJ3nP78yV33nBrMj3jbjTi1fr2QsrpoISql/pJ9Zr5V0QbK4wIqln20ly96KuAO5c1DM9z9VnoYFdirEZBfkT/4gB7pBfyd4ScoMhXuaa9w53N8Espu1bC0RGmaKB679rGQdaBTrEUGF+PNfsucjnyrsnup6GMVhc91CXTDjQIDAQAB"
}
11 changes: 10 additions & 1 deletion components/styles/webtorrent.css
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ a {
margin: 0 0 18px;
}

#video, #audio {
#video, #audio, #image, #object, #iframe {
position: absolute;
top: 0px;
right: 0px;
Expand All @@ -88,3 +88,12 @@ a {
max-width: 100%;
margin: auto;
}

#object, #iframe {
width: 100%;
height: 100%;
}

#iframe {
border: 0;
}
30 changes: 28 additions & 2 deletions components/test/brave_webtorrent/components/mediaViewer_test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe('mediaViewer component', () => {
expect(assertion.length).toBe(1)
})

it('renders iframe for other ext', () => {
it('renders img for image', () => {
const files = [ { name: 'file.jpg', length: 500 } ]
const torrentWithJpgFile = { ...torrentObj, files, serverURL }
const wrapper = shallow(
Expand All @@ -57,7 +57,33 @@ describe('mediaViewer component', () => {
ix={ix}
/>
)
const assertion = wrapper.find('#other')
const assertion = wrapper.find('#image')
expect(assertion.length).toBe(1)
})

it('renders object for PDF file', () => {
const files = [ { name: 'file.pdf', length: 500 } ]
const torrentWithPdfFile = { ...torrentObj, files, serverURL }
const wrapper = shallow(
<MediaViewer
torrent={torrentWithPdfFile}
ix={ix}
/>
)
const assertion = wrapper.find('#object')
expect(assertion.length).toBe(1)
})

it('renders iframe for text file', () => {
const files = [ { name: 'file.txt', length: 500 } ]
const torrentWithTxtFile = { ...torrentObj, files, serverURL }
const wrapper = shallow(
<MediaViewer
torrent={torrentWithTxtFile}
ix={ix}
/>
)
const assertion = wrapper.find('#iframe')
expect(assertion.length).toBe(1)
})
})
Expand Down

0 comments on commit 9b41325

Please sign in to comment.