Merge pull request #7658 from figma/webview-manual-guest-resize
Allow webview guests to be resized manually
This commit is contained in:
commit
0ef6d4631d
9 changed files with 217 additions and 3 deletions
|
@ -1131,6 +1131,17 @@ win.webContents.on('did-finish-load', () => {
|
|||
|
||||
Shows pop-up dictionary that searches the selected word on the page.
|
||||
|
||||
#### `contents.setSize(options)`
|
||||
|
||||
Set the size of the page. This is only supported for `<webview>` guest contents.
|
||||
|
||||
* `options` Object
|
||||
* `normal` Object (optional) - Normal size of the page. This can be used in
|
||||
combination with the [`disableguestresize`](web-view-tag.md#disableguestresize)
|
||||
attribute to manually resize the webview guest contents.
|
||||
* `width` Integer
|
||||
* `height` Integer
|
||||
|
||||
#### `contents.isOffscreen()`
|
||||
|
||||
Returns `Boolean` - Indicates whether *offscreen rendering* is enabled.
|
||||
|
|
|
@ -243,6 +243,44 @@ webview.
|
|||
The existing webview will see the `destroy` event and will then create a new
|
||||
webContents when a new url is loaded.
|
||||
|
||||
### `disableguestresize`
|
||||
|
||||
```html
|
||||
<webview src="https://www.github.com/" disableguestresize></webview>
|
||||
```
|
||||
|
||||
Prevents the webview contents from resizing when the webview element itself is
|
||||
resized.
|
||||
|
||||
This can be used in combination with
|
||||
[`webContents.setSize`](web-contents.md#contentssetsizeoptions) to manually
|
||||
resize the webview contents in reaction to a window size change. This can
|
||||
make resizing faster compared to relying on the webview element bounds to
|
||||
automatically resize the contents.
|
||||
|
||||
```javascript
|
||||
const {webContents} = require('electron')
|
||||
|
||||
// We assume that `win` points to a `BrowserWindow` instance containing a
|
||||
// `<webview>` with `disableguestresize`.
|
||||
|
||||
win.on('resize', () => {
|
||||
const [width, height] = win.getContentSize()
|
||||
for (let wc of webContents.getAllWebContents()) {
|
||||
// Check if `wc` belongs to a webview in the `win` window.
|
||||
if (wc.hostWebContents &&
|
||||
wc.hostWebContents.id === win.webContents.id) {
|
||||
wc.setSize({
|
||||
normal: {
|
||||
width: width,
|
||||
height: height
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
The `webview` tag has the following methods:
|
||||
|
|
|
@ -327,6 +327,7 @@ WebViewImpl.prototype.setupWebViewAttributes = function () {
|
|||
this.attributes[webViewConstants.ATTRIBUTE_BLINKFEATURES] = new BlinkFeaturesAttribute(this)
|
||||
this.attributes[webViewConstants.ATTRIBUTE_DISABLEBLINKFEATURES] = new DisableBlinkFeaturesAttribute(this)
|
||||
this.attributes[webViewConstants.ATTRIBUTE_GUESTINSTANCE] = new GuestInstanceAttribute(this)
|
||||
this.attributes[webViewConstants.ATTRIBUTE_DISABLEGUESTRESIZE] = new BooleanAttribute(webViewConstants.ATTRIBUTE_DISABLEGUESTRESIZE, this)
|
||||
this.attributes[webViewConstants.ATTRIBUTE_WEBPREFERENCES] = new WebPreferencesAttribute(this)
|
||||
|
||||
const autosizeAttributes = [webViewConstants.ATTRIBUTE_MAXHEIGHT, webViewConstants.ATTRIBUTE_MAXWIDTH, webViewConstants.ATTRIBUTE_MINHEIGHT, webViewConstants.ATTRIBUTE_MINWIDTH]
|
||||
|
|
|
@ -18,6 +18,7 @@ module.exports = {
|
|||
ATTRIBUTE_BLINKFEATURES: 'blinkfeatures',
|
||||
ATTRIBUTE_DISABLEBLINKFEATURES: 'disableblinkfeatures',
|
||||
ATTRIBUTE_GUESTINSTANCE: 'guestinstance',
|
||||
ATTRIBUTE_DISABLEGUESTRESIZE: 'disableguestresize',
|
||||
ATTRIBUTE_WEBPREFERENCES: 'webpreferences',
|
||||
|
||||
// Internal attribute.
|
||||
|
|
|
@ -172,7 +172,8 @@ class WebViewImpl {
|
|||
resizeEvent.newWidth = newSize.width
|
||||
resizeEvent.newHeight = newSize.height
|
||||
this.dispatchEvent(resizeEvent)
|
||||
if (this.guestInstanceId) {
|
||||
if (this.guestInstanceId &&
|
||||
!this.attributes[webViewConstants.ATTRIBUTE_DISABLEGUESTRESIZE].getValue()) {
|
||||
guestViewInternal.setSize(this.guestInstanceId, {
|
||||
normal: newSize
|
||||
})
|
||||
|
|
9
spec/fixtures/pages/resize.html
vendored
Normal file
9
spec/fixtures/pages/resize.html
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
<html>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
const {ipcRenderer} = require('electron')
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
ipcRenderer.send('webview-guest-resize', window.innerWidth, window.innerHeight)
|
||||
}, false);
|
||||
</script>
|
||||
</html>
|
20
spec/fixtures/pages/webview-guest-resize.html
vendored
Normal file
20
spec/fixtures/pages/webview-guest-resize.html
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
<html>
|
||||
<style>
|
||||
* {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<webview id="webview" nodeintegration src="resize.html"/>
|
||||
</body>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
const {ipcRenderer} = require('electron')
|
||||
|
||||
const webview = document.getElementById('webview')
|
||||
webview.addEventListener('resize', event => {
|
||||
ipcRenderer.send('webview-element-resize', event.newWidth, event.newHeight)
|
||||
}, false)
|
||||
</script>
|
||||
</html>
|
20
spec/fixtures/pages/webview-no-guest-resize.html
vendored
Normal file
20
spec/fixtures/pages/webview-no-guest-resize.html
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
<html>
|
||||
<style>
|
||||
* {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<webview id="webview" nodeintegration disableguestresize src="resize.html"/>
|
||||
</body>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
const {ipcRenderer} = require('electron')
|
||||
|
||||
const webview = document.getElementById('webview')
|
||||
webview.addEventListener('resize', event => {
|
||||
ipcRenderer.send('webview-element-resize', event.newWidth, event.newHeight)
|
||||
}, false)
|
||||
</script>
|
||||
</html>
|
|
@ -2,11 +2,11 @@ const assert = require('assert')
|
|||
const path = require('path')
|
||||
const http = require('http')
|
||||
const url = require('url')
|
||||
const {app, session, getGuestWebContents, ipcMain, BrowserWindow} = require('electron').remote
|
||||
const {app, session, getGuestWebContents, ipcMain, BrowserWindow, webContents} = require('electron').remote
|
||||
const {closeWindow} = require('./window-helpers')
|
||||
|
||||
describe('<webview> tag', function () {
|
||||
this.timeout(20000)
|
||||
this.timeout(60000)
|
||||
|
||||
var fixtures = path.join(__dirname, 'fixtures')
|
||||
|
||||
|
@ -1346,4 +1346,117 @@ describe('<webview> tag', function () {
|
|||
document.body.appendChild(div)
|
||||
})
|
||||
})
|
||||
|
||||
describe('disableguestresize attribute', () => {
|
||||
it('does not have attribute by default', () => {
|
||||
document.body.appendChild(webview)
|
||||
assert(!webview.hasAttribute('disableguestresize'))
|
||||
})
|
||||
|
||||
it('resizes guest when attribute is not present', done => {
|
||||
w = new BrowserWindow({show: false, width: 200, height: 200})
|
||||
w.loadURL('file://' + fixtures + '/pages/webview-guest-resize.html')
|
||||
|
||||
w.webContents.once('did-finish-load', () => {
|
||||
const CONTENT_SIZE = 300
|
||||
|
||||
const elementResizePromise = new Promise(resolve => {
|
||||
ipcMain.once('webview-element-resize', (event, width, height) => {
|
||||
assert.equal(width, CONTENT_SIZE)
|
||||
assert.equal(height, CONTENT_SIZE)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
const guestResizePromise = new Promise(resolve => {
|
||||
ipcMain.once('webview-guest-resize', (event, width, height) => {
|
||||
assert.equal(width, CONTENT_SIZE)
|
||||
assert.equal(height, CONTENT_SIZE)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
Promise.all([elementResizePromise, guestResizePromise]).then(() => done())
|
||||
|
||||
w.setContentSize(CONTENT_SIZE, CONTENT_SIZE)
|
||||
})
|
||||
})
|
||||
|
||||
it('does not resize guest when attribute is present', done => {
|
||||
w = new BrowserWindow({show: false, width: 200, height: 200})
|
||||
w.loadURL('file://' + fixtures + '/pages/webview-no-guest-resize.html')
|
||||
|
||||
w.webContents.once('did-finish-load', () => {
|
||||
const CONTENT_SIZE = 300
|
||||
|
||||
const elementResizePromise = new Promise(resolve => {
|
||||
ipcMain.once('webview-element-resize', (event, width, height) => {
|
||||
assert.equal(width, CONTENT_SIZE)
|
||||
assert.equal(height, CONTENT_SIZE)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
const noGuestResizePromise = new Promise(resolve => {
|
||||
const onGuestResize = (event, width, height) => {
|
||||
done(new Error('Unexpected guest resize message'))
|
||||
}
|
||||
ipcMain.once('webview-guest-resize', onGuestResize)
|
||||
|
||||
setTimeout(() => {
|
||||
ipcMain.removeListener('webview-guest-resize', onGuestResize)
|
||||
resolve()
|
||||
}, 500)
|
||||
})
|
||||
|
||||
Promise.all([elementResizePromise, noGuestResizePromise]).then(() => done())
|
||||
|
||||
w.setContentSize(CONTENT_SIZE, CONTENT_SIZE)
|
||||
})
|
||||
})
|
||||
|
||||
it('dispatches element resize event even when attribute is present', done => {
|
||||
w = new BrowserWindow({show: false, width: 200, height: 200})
|
||||
w.loadURL('file://' + fixtures + '/pages/webview-no-guest-resize.html')
|
||||
|
||||
w.webContents.once('did-finish-load', () => {
|
||||
const CONTENT_SIZE = 300
|
||||
|
||||
ipcMain.once('webview-element-resize', (event, width, height) => {
|
||||
assert.equal(width, CONTENT_SIZE)
|
||||
done()
|
||||
})
|
||||
|
||||
w.setContentSize(CONTENT_SIZE, CONTENT_SIZE)
|
||||
})
|
||||
})
|
||||
|
||||
it('can be manually resized with setSize even when attribute is present', done => {
|
||||
w = new BrowserWindow({show: false, width: 200, height: 200})
|
||||
w.loadURL('file://' + fixtures + '/pages/webview-no-guest-resize.html')
|
||||
|
||||
w.webContents.once('did-finish-load', () => {
|
||||
const GUEST_WIDTH = 10
|
||||
const GUEST_HEIGHT = 20
|
||||
|
||||
ipcMain.once('webview-guest-resize', (event, width, height) => {
|
||||
assert.equal(width, GUEST_WIDTH)
|
||||
assert.equal(height, GUEST_HEIGHT)
|
||||
done()
|
||||
})
|
||||
|
||||
for (const wc of webContents.getAllWebContents()) {
|
||||
if (wc.hostWebContents &&
|
||||
wc.hostWebContents.id === w.webContents.id) {
|
||||
wc.setSize({
|
||||
normal: {
|
||||
width: GUEST_WIDTH,
|
||||
height: GUEST_HEIGHT
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue