Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: expose executeJavaScriptInIsolatedWorld on webContents #21267

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/api/web-contents.md
Expand Up @@ -1042,6 +1042,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
Expand Down
27 changes: 15 additions & 12 deletions lib/browser/api/web-contents.js
Expand Up @@ -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.
Expand Down
17 changes: 17 additions & 0 deletions spec-main/api-web-contents-spec.ts
Expand Up @@ -219,6 +219,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 () => {
Expand Down