-
Notifications
You must be signed in to change notification settings - Fork 44
/
Copy pathContentFrame.jsx
61 lines (50 loc) · 1.97 KB
/
ContentFrame.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import React from 'react'
import PropTypes from 'prop-types'
import syncLocationHashes from 'src/util/sync-location-hashes'
function fixChromiumInjectedStylesheet(document) {
// Pragmatic workaround for Chromium, which appears to inject two style
// rules into extension pages (with font-size: 75%, for some reason?).
const styleEl = document.createElement('style')
styleEl.innerHTML = `body {
font-size: inherit;
font-family: inherit;
}`
document.head.insertAdjacentElement('afterbegin', styleEl)
}
export default class ContentFrame extends React.Component {
onIframeLoaded() {
const iframe = this.iframeEl
const doc = iframe.contentDocument
// Ensure a head element exists.
if (!doc.head) {
const head = doc.createElement('head')
doc.documentElement.insertAdjacentElement('afterbegin', head)
}
// Make links open in the whole tab, not inside the iframe
const baseEl = doc.createElement('base')
baseEl.setAttribute('target', '_parent')
doc.head.insertAdjacentElement('afterbegin', baseEl)
// Workaround required for Chromium.
fixChromiumInjectedStylesheet(doc)
// Focus on the page so it receives e.g. keyboard input
iframe.contentWindow.focus()
// Keep the iframe's location #hash in sync with that of the window.
syncLocationHashes([window, iframe.contentWindow], { initial: window })
}
render() {
return (
<iframe
id='page'
ref={el => { this.iframeEl = el }}
sandbox='allow-same-origin allow-top-navigation allow-scripts'
seamless
srcDoc={this.props.html}
// XXX The DOMContentLoaded event would be better, but how to listen to that?
onLoad={() => this.onIframeLoaded()}
/>
)
}
}
ContentFrame.propTypes = {
html: PropTypes.string.isRequired,
}