feat: expose executeJavaScriptInIsolatedWorld on webContents (#21190)

* feat: expose executeJavaScriptInIsolatedWorld on webContents

* Apply suggestions from code review

Co-Authored-By: loc <andy@slack-corp.com>
This commit is contained in:
Samuel Attard 2019-11-22 15:33:55 -08:00 committed by GitHub
parent a7c2f79a94
commit 34452ee69e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 12 deletions

View file

@ -1031,6 +1031,17 @@ contents.executeJavaScript('fetch("https://jsonplaceholder.typicode.com/users/1"
})
```
#### `contents.executeJavaScriptInIsolatedWorld(worldId, scripts[, userGesture])`
* `worldId` Integer - The ID of the world to run the javascript in, `0` is the default world, `999` is the world used by Electron's `contextIsolation` feature. You can provide any integer here.
* `scripts` [WebSource[]](structures/web-source.md)
* `userGesture` Boolean (optional) - Default is `false`.
Returns `Promise<any>` - A promise that resolves with the result of the executed code
or is rejected if the result of the code is a rejected promise.
Works like `executeJavaScript` but evaluates `scripts` in an isolated context.
#### `contents.setIgnoreMenuShortcuts(ignore)` _Experimental_
* `ignore` Boolean

View file

@ -183,22 +183,25 @@ for (const method of webFrameMethods) {
}
}
const executeJavaScript = (contents, code, hasUserGesture) => {
return ipcMainUtils.invokeInWebContents(contents, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScript', code, hasUserGesture)
const waitTillCanExecuteJavaScript = async (webContents) => {
if (webContents.getURL() && !webContents.isLoadingMainFrame()) return
return new Promise((resolve) => {
webContents.once('did-stop-loading', () => {
resolve()
})
})
}
// Make sure WebContents::executeJavaScript would run the code only when the
// WebContents has been loaded.
WebContents.prototype.executeJavaScript = function (code, hasUserGesture) {
if (this.getURL() && !this.isLoadingMainFrame()) {
return executeJavaScript(this, code, hasUserGesture)
} else {
return new Promise((resolve, reject) => {
this.once('did-stop-loading', () => {
executeJavaScript(this, code, hasUserGesture).then(resolve, reject)
})
})
}
WebContents.prototype.executeJavaScript = async function (code, hasUserGesture) {
await waitTillCanExecuteJavaScript(this)
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScript', code, hasUserGesture)
}
WebContents.prototype.executeJavaScriptInIsolatedWorld = async function (code, hasUserGesture) {
await waitTillCanExecuteJavaScript(this)
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScriptInIsolatedWorld', code, hasUserGesture)
}
// Translate the options of printToPDF.

View file

@ -214,6 +214,23 @@ describe('webContents module', () => {
})
})
describe('webContents.executeJavaScriptInIsolatedWorld', () => {
let w: BrowserWindow
before(async () => {
w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } })
await w.loadURL('about:blank')
})
it('resolves the returned promise with the result', async () => {
await w.webContents.executeJavaScriptInIsolatedWorld(999, [{ code: 'window.X = 123' }])
const isolatedResult = await w.webContents.executeJavaScriptInIsolatedWorld(999, [{ code: 'window.X' }])
const mainWorldResult = await w.webContents.executeJavaScript('window.X')
expect(isolatedResult).to.equal(123)
expect(mainWorldResult).to.equal(undefined)
})
})
describe('loadURL() promise API', () => {
let w: BrowserWindow
beforeEach(async () => {