Merge pull request #5913 from electron/webview-devtools-extensions
Enable DevTools extensions in webviews
This commit is contained in:
commit
20372f057e
8 changed files with 97 additions and 25 deletions
|
@ -744,6 +744,15 @@ int WebContents::GetID() const {
|
|||
return web_contents()->GetRenderProcessHost()->GetID();
|
||||
}
|
||||
|
||||
std::string WebContents::GetType() const {
|
||||
switch (type_) {
|
||||
case BROWSER_WINDOW: return "window";
|
||||
case WEB_VIEW: return "webview";
|
||||
case REMOTE: return "remote";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
bool WebContents::Equal(const WebContents* web_contents) const {
|
||||
return GetID() == web_contents->GetID();
|
||||
}
|
||||
|
@ -1287,6 +1296,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
|||
.SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription)
|
||||
.SetMethod("setSize", &WebContents::SetSize)
|
||||
.SetMethod("isGuest", &WebContents::IsGuest)
|
||||
.SetMethod("getType", &WebContents::GetType)
|
||||
.SetMethod("getWebPreferences", &WebContents::GetWebPreferences)
|
||||
.SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow)
|
||||
.SetMethod("hasServiceWorker", &WebContents::HasServiceWorker)
|
||||
|
@ -1365,6 +1375,8 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
|||
dict.SetMethod("_setWrapWebContents", &atom::api::SetWrapWebContents);
|
||||
dict.SetMethod("fromId",
|
||||
&mate::TrackableObject<atom::api::WebContents>::FromWeakMapID);
|
||||
dict.SetMethod("getAllWebContents",
|
||||
&mate::TrackableObject<atom::api::WebContents>::GetAll);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -59,6 +59,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
|||
v8::Local<v8::ObjectTemplate> prototype);
|
||||
|
||||
int GetID() const;
|
||||
std::string GetType() const;
|
||||
bool Equal(const WebContents* web_contents) const;
|
||||
void LoadURL(const GURL& url, const mate::Dictionary& options);
|
||||
void DownloadURL(const GURL& url);
|
||||
|
|
|
@ -10,6 +10,14 @@ session
|
|||
const binding = process.atomBinding('web_contents')
|
||||
const debuggerBinding = process.atomBinding('debugger')
|
||||
|
||||
const WebContents = new EventEmitter()
|
||||
WebContents.create = (options = {}) => {
|
||||
return binding.create(options)
|
||||
}
|
||||
WebContents.fromId = (id) => {
|
||||
return binding.fromId(id)
|
||||
}
|
||||
|
||||
let nextId = 0
|
||||
const getNextId = function () {
|
||||
return ++nextId
|
||||
|
@ -223,6 +231,8 @@ const wrapWebContents = function (webContents) {
|
|||
|
||||
this._printToPDF(printingSetting, callback)
|
||||
}
|
||||
|
||||
WebContents.emit('web-contents-created', webContents)
|
||||
}
|
||||
|
||||
binding._setWrapWebContents(wrapWebContents)
|
||||
|
@ -235,12 +245,4 @@ const wrapDebugger = function (webContentsDebugger) {
|
|||
|
||||
debuggerBinding._setWrapDebugger(wrapDebugger)
|
||||
|
||||
module.exports = {
|
||||
create (options = {}) {
|
||||
return binding.create(options)
|
||||
},
|
||||
|
||||
fromId (id) {
|
||||
return binding.fromId(id)
|
||||
}
|
||||
}
|
||||
module.exports = WebContents
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const {app, ipcMain, protocol, webContents, BrowserWindow} = require('electron')
|
||||
const {getAllWebContents} = process.atomBinding('web_contents')
|
||||
const renderProcessPreferences = process.atomBinding('render_process_preferences').forAllBrowserWindow()
|
||||
|
||||
const fs = require('fs')
|
||||
|
@ -81,13 +82,13 @@ const removeBackgroundPages = function (manifest) {
|
|||
}
|
||||
|
||||
// Dispatch tabs events.
|
||||
const hookWindowForTabEvents = function (win) {
|
||||
const tabId = win.webContents.id
|
||||
const hookWebContentsForTabEvents = function (webContents) {
|
||||
const tabId = webContents.id
|
||||
for (const page of objectValues(backgroundPages)) {
|
||||
page.webContents.sendToAll('CHROME_TABS_ONCREATED', tabId)
|
||||
}
|
||||
|
||||
win.once('closed', () => {
|
||||
webContents.once('destroyed', () => {
|
||||
for (const page of objectValues(backgroundPages)) {
|
||||
page.webContents.sendToAll('CHROME_TABS_ONREMOVED', tabId)
|
||||
}
|
||||
|
@ -221,6 +222,15 @@ const loadDevToolsExtensions = function (win, manifests) {
|
|||
win.devToolsWebContents.executeJavaScript(`DevToolsAPI.addExtensions(${JSON.stringify(extensionInfoArray)})`)
|
||||
}
|
||||
|
||||
webContents.on('web-contents-created', function (webContents) {
|
||||
if (webContents.getType() === 'remote') return
|
||||
|
||||
hookWebContentsForTabEvents(webContents)
|
||||
webContents.on('devtools-opened', function () {
|
||||
loadDevToolsExtensions(webContents, objectValues(manifestMap))
|
||||
})
|
||||
})
|
||||
|
||||
// The persistent path of "DevTools Extensions" preference file.
|
||||
let loadedExtensionsPath = null
|
||||
|
||||
|
@ -295,12 +305,15 @@ app.once('ready', function () {
|
|||
BrowserWindow.addDevToolsExtension = function (srcDirectory) {
|
||||
const manifest = getManifestFromPath(srcDirectory)
|
||||
if (manifest) {
|
||||
for (const win of BrowserWindow.getAllWindows()) {
|
||||
loadDevToolsExtensions(win, [manifest])
|
||||
for (const webContents of getAllWebContents()) {
|
||||
if (webContents.getType() !== 'remote') {
|
||||
loadDevToolsExtensions(webContents, [manifest])
|
||||
}
|
||||
}
|
||||
return manifest.name
|
||||
}
|
||||
}
|
||||
|
||||
BrowserWindow.removeDevToolsExtension = function (name) {
|
||||
const manifest = manifestNameMap[name]
|
||||
if (!manifest) return
|
||||
|
@ -310,14 +323,4 @@ app.once('ready', function () {
|
|||
delete manifestMap[manifest.extensionId]
|
||||
delete manifestNameMap[name]
|
||||
}
|
||||
|
||||
// Load extensions automatically when devtools is opened.
|
||||
const init = BrowserWindow.prototype._init
|
||||
BrowserWindow.prototype._init = function () {
|
||||
init.call(this)
|
||||
hookWindowForTabEvents(this)
|
||||
this.webContents.on('devtools-opened', () => {
|
||||
loadDevToolsExtensions(this, objectValues(manifestMap))
|
||||
})
|
||||
}
|
||||
})
|
||||
|
|
|
@ -864,6 +864,7 @@ describe('browser-window module', function () {
|
|||
|
||||
ipcMain.once('answer', function (event, message) {
|
||||
assert.equal(message.runtimeId, 'foo')
|
||||
assert.equal(message.tabId, w.webContents.id)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
@ -875,6 +876,7 @@ describe('browser-window module', function () {
|
|||
|
||||
ipcMain.once('answer', function (event, message, extensionId) {
|
||||
assert.equal(message.runtimeId, 'foo')
|
||||
assert.equal(message.tabId, w.webContents.id)
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
<title></title>
|
||||
<script>
|
||||
var message = JSON.stringify({
|
||||
runtimeId: chrome.runtime.id
|
||||
runtimeId: chrome.runtime.id,
|
||||
tabId: chrome.devtools.inspectedWindow.tabId
|
||||
})
|
||||
var sendMessage = `require('electron').ipcRenderer.send('answer', ${message})`
|
||||
window.chrome.devtools.inspectedWindow.eval(sendMessage, function () {})
|
||||
|
|
30
spec/fixtures/pages/webview-devtools.html
vendored
Normal file
30
spec/fixtures/pages/webview-devtools.html
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<webview nodeintegration src="./a.html"></webview>
|
||||
<script>
|
||||
var wv = document.querySelector('webview')
|
||||
wv.addEventListener('dom-ready', () => {
|
||||
const webContents = wv.getWebContents()
|
||||
webContents.on('devtools-opened', function () {
|
||||
var showPanelIntevalId = setInterval(function () {
|
||||
if (webContents.devToolsWebContents) {
|
||||
webContents.devToolsWebContents.executeJavaScript('(' + (function () {
|
||||
var lastPanelId = WebInspector.inspectorView._tabbedPane._tabs.peekLast().id
|
||||
WebInspector.inspectorView.showPanel(lastPanelId)
|
||||
}).toString() + ')()')
|
||||
} else {
|
||||
clearInterval(showPanelIntevalId)
|
||||
}
|
||||
}, 100)
|
||||
})
|
||||
|
||||
wv.openDevTools()
|
||||
})
|
||||
</script>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -912,4 +912,25 @@ describe('<webview> tag', function () {
|
|||
|
||||
w.loadURL('file://' + fixtures + '/pages/webview-visibilitychange.html')
|
||||
})
|
||||
|
||||
it('loads devtools extensions registered on the parent window', function (done) {
|
||||
this.timeout(10000)
|
||||
|
||||
w = new BrowserWindow({
|
||||
show: false
|
||||
})
|
||||
|
||||
BrowserWindow.removeDevToolsExtension('foo')
|
||||
|
||||
var extensionPath = path.join(__dirname, 'fixtures', 'devtools-extensions', 'foo')
|
||||
BrowserWindow.addDevToolsExtension(extensionPath)
|
||||
|
||||
w.loadURL('file://' + fixtures + '/pages/webview-devtools.html')
|
||||
|
||||
ipcMain.once('answer', function (event, message) {
|
||||
assert.equal(message.runtimeId, 'foo')
|
||||
assert.notEqual(message.tabId, w.webContents.id)
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue