fix: regressions introduced by adding world isolation to Chrome extension content scripts (#17422)
This commit is contained in:
parent
2fb9085e5b
commit
53f4af7722
6 changed files with 83 additions and 11 deletions
|
@ -7,9 +7,11 @@ const { EventEmitter } = require('events')
|
||||||
process.electronBinding = require('@electron/internal/common/atom-binding-setup').electronBindingSetup(nodeProcess.binding, 'renderer')
|
process.electronBinding = require('@electron/internal/common/atom-binding-setup').electronBindingSetup(nodeProcess.binding, 'renderer')
|
||||||
|
|
||||||
const v8Util = process.electronBinding('v8_util')
|
const v8Util = process.electronBinding('v8_util')
|
||||||
|
|
||||||
// The `lib/renderer/ipc-renderer-internal.js` module looks for the ipc object in the
|
// The `lib/renderer/ipc-renderer-internal.js` module looks for the ipc object in the
|
||||||
// "ipc-internal" hidden value
|
// "ipc-internal" hidden value
|
||||||
v8Util.setHiddenValue(global, 'ipc-internal', new EventEmitter())
|
v8Util.setHiddenValue(global, 'ipc-internal', v8Util.getHiddenValue(isolatedWorld, 'ipc-internal'))
|
||||||
|
|
||||||
// The process object created by browserify is not an event emitter, fix it so
|
// The process object created by browserify is not an event emitter, fix it so
|
||||||
// the API is more compatible with non-sandboxed renderers.
|
// the API is more compatible with non-sandboxed renderers.
|
||||||
for (const prop of Object.keys(EventEmitter.prototype)) {
|
for (const prop of Object.keys(EventEmitter.prototype)) {
|
||||||
|
|
|
@ -45,7 +45,7 @@ const runContentScript = function (this: any, extensionId: string, url: string,
|
||||||
})
|
})
|
||||||
|
|
||||||
const sources = [{ code, url }]
|
const sources = [{ code, url }]
|
||||||
webFrame.executeJavaScriptInIsolatedWorld(worldId, sources)
|
return webFrame.executeJavaScriptInIsolatedWorld(worldId, sources)
|
||||||
}
|
}
|
||||||
|
|
||||||
const runAllContentScript = function (scripts: Array<Electron.InjectionBase>, extensionId: string) {
|
const runAllContentScript = function (scripts: Array<Electron.InjectionBase>, extensionId: string) {
|
||||||
|
@ -102,8 +102,9 @@ ipcRendererInternal.on('CHROME_TABS_EXECUTESCRIPT', function (
|
||||||
url: string,
|
url: string,
|
||||||
code: string
|
code: string
|
||||||
) {
|
) {
|
||||||
const result = runContentScript.call(window, extensionId, url, code)
|
runContentScript.call(window, extensionId, url, code).then(result => {
|
||||||
ipcRendererInternal.sendToAll(senderWebContentsId, `CHROME_TABS_EXECUTESCRIPT_RESULT_${requestId}`, result)
|
ipcRendererInternal.sendToAll(senderWebContentsId, `CHROME_TABS_EXECUTESCRIPT_RESULT_${requestId}`, result)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = (getRenderProcessPreferences: typeof process.getRenderProcessPreferences) => {
|
module.exports = (getRenderProcessPreferences: typeof process.getRenderProcessPreferences) => {
|
||||||
|
|
|
@ -35,14 +35,46 @@ describe('chrome api', () => {
|
||||||
return JSON.parse(data)
|
return JSON.parse(data)
|
||||||
})()
|
})()
|
||||||
|
|
||||||
w.loadURL('about:blank')
|
await w.loadURL('about:blank')
|
||||||
|
|
||||||
const p = emittedOnce(w.webContents, 'console-message')
|
const promise = emittedOnce(w.webContents, 'console-message')
|
||||||
w.webContents.executeJavaScript(`window.postMessage('getManifest', '*')`)
|
|
||||||
const [,, manifestString] = await p
|
const message = { method: 'getManifest' }
|
||||||
|
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`)
|
||||||
|
|
||||||
|
const [,, manifestString] = await promise
|
||||||
const manifest = JSON.parse(manifestString)
|
const manifest = JSON.parse(manifestString)
|
||||||
|
|
||||||
expect(manifest.name).to.equal(actualManifest.name)
|
expect(manifest.name).to.equal(actualManifest.name)
|
||||||
expect(manifest.content_scripts.length).to.equal(actualManifest.content_scripts.length)
|
expect(manifest.content_scripts.length).to.equal(actualManifest.content_scripts.length)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('chrome.tabs.sendMessage receives the response', async function () {
|
||||||
|
await w.loadURL('about:blank')
|
||||||
|
|
||||||
|
const promise = emittedOnce(w.webContents, 'console-message')
|
||||||
|
|
||||||
|
const message = { method: 'sendMessage', args: ['Hello World!'] }
|
||||||
|
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`)
|
||||||
|
|
||||||
|
const [,, responseString] = await promise
|
||||||
|
const response = JSON.parse(responseString)
|
||||||
|
|
||||||
|
expect(response.message).to.equal('Hello World!')
|
||||||
|
expect(response.tabId).to.equal(w.webContents.id)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('chrome.tabs.executeScript receives the response', async function () {
|
||||||
|
await w.loadURL('about:blank')
|
||||||
|
|
||||||
|
const promise = emittedOnce(w.webContents, 'console-message')
|
||||||
|
|
||||||
|
const message = { method: 'executeScript', args: ['1 + 2'] }
|
||||||
|
w.webContents.executeJavaScript(`window.postMessage('${JSON.stringify(message)}', '*')`)
|
||||||
|
|
||||||
|
const [,, responseString] = await promise
|
||||||
|
const response = JSON.parse(responseString)
|
||||||
|
|
||||||
|
expect(response).to.equal(3)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
20
spec/fixtures/extensions/chrome-api/background.js
vendored
Normal file
20
spec/fixtures/extensions/chrome-api/background.js
vendored
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/* global chrome */
|
||||||
|
|
||||||
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||||
|
const { method, args = [] } = message
|
||||||
|
const tabId = sender.tab.id
|
||||||
|
|
||||||
|
switch (method) {
|
||||||
|
case 'sendMessage': {
|
||||||
|
const [message] = args
|
||||||
|
chrome.tabs.sendMessage(tabId, { message, tabId }, undefined, sendResponse)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'executeScript': {
|
||||||
|
const [code] = args
|
||||||
|
chrome.tabs.executeScript(tabId, { code }, ([result]) => sendResponse(result))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
19
spec/fixtures/extensions/chrome-api/main.js
vendored
19
spec/fixtures/extensions/chrome-api/main.js
vendored
|
@ -1,15 +1,28 @@
|
||||||
/* global chrome */
|
/* global chrome */
|
||||||
|
|
||||||
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||||
|
sendResponse(message)
|
||||||
|
})
|
||||||
|
|
||||||
const testMap = {
|
const testMap = {
|
||||||
getManifest () {
|
getManifest () {
|
||||||
const manifest = chrome.runtime.getManifest()
|
const manifest = chrome.runtime.getManifest()
|
||||||
console.log(JSON.stringify(manifest))
|
console.log(JSON.stringify(manifest))
|
||||||
|
},
|
||||||
|
sendMessage (message) {
|
||||||
|
chrome.runtime.sendMessage({ method: 'sendMessage', args: [message] }, response => {
|
||||||
|
console.log(JSON.stringify(response))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
executeScript (code) {
|
||||||
|
chrome.runtime.sendMessage({ method: 'executeScript', args: [code] }, response => {
|
||||||
|
console.log(JSON.stringify(response))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const dispatchTest = (event) => {
|
const dispatchTest = (event) => {
|
||||||
const testName = event.data
|
const { method, args = [] } = JSON.parse(event.data)
|
||||||
const test = testMap[testName]
|
testMap[method](...args)
|
||||||
test()
|
|
||||||
}
|
}
|
||||||
window.addEventListener('message', dispatchTest, false)
|
window.addEventListener('message', dispatchTest, false)
|
||||||
|
|
|
@ -8,5 +8,9 @@
|
||||||
"run_at": "document_start"
|
"run_at": "document_start"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"background": {
|
||||||
|
"scripts": ["background.js"],
|
||||||
|
"persistent": false
|
||||||
|
},
|
||||||
"manifest_version": 2
|
"manifest_version": 2
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue