Merge pull request #8120 from electron/implement-window-methods-in-main-process
Implement window methods in main process
This commit is contained in:
commit
a9d4d9ad85
6 changed files with 69 additions and 48 deletions
|
@ -106,8 +106,8 @@ will be passed via `callback(filename)`
|
||||||
* `cancelId` Integer (optional) - The value will be returned when user cancels the dialog
|
* `cancelId` Integer (optional) - The value will be returned when user cancels the dialog
|
||||||
instead of clicking the buttons of the dialog. By default it is the index
|
instead of clicking the buttons of the dialog. By default it is the index
|
||||||
of the buttons that have "cancel" or "no" as label, or 0 if there is no such
|
of the buttons that have "cancel" or "no" as label, or 0 if there is no such
|
||||||
buttons. On macOS and Windows the index of "Cancel" button will always be
|
buttons. On macOS and Windows the index of the "Cancel" button will always
|
||||||
used as `cancelId`, not matter whether it is already specified.
|
be used as `cancelId` even if it is specified.
|
||||||
* `noLink` Boolean (optional) - On Windows Electron will try to figure out which one of
|
* `noLink` Boolean (optional) - On Windows Electron will try to figure out which one of
|
||||||
the `buttons` are common buttons (like "Cancel" or "Yes"), and show the
|
the `buttons` are common buttons (like "Cancel" or "Yes"), and show the
|
||||||
others as command links in the dialog. This can make the dialog appear in
|
others as command links in the dialog. This can make the dialog appear in
|
||||||
|
|
|
@ -416,3 +416,34 @@ ipcMain.on('ELECTRON_BROWSER_SEND_TO', function (event, sendToAll, webContentsId
|
||||||
contents.send(channel, ...args)
|
contents.send(channel, ...args)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Implements window.alert(message, title)
|
||||||
|
ipcMain.on('ELECTRON_BROWSER_WINDOW_ALERT', function (event, message, title) {
|
||||||
|
if (message == null) message = ''
|
||||||
|
if (title == null) title = ''
|
||||||
|
|
||||||
|
event.returnValue = electron.dialog.showMessageBox(event.sender.getOwnerBrowserWindow(), {
|
||||||
|
message: `${message}`,
|
||||||
|
title: `${title}`,
|
||||||
|
buttons: ['OK']
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Implements window.confirm(message, title)
|
||||||
|
ipcMain.on('ELECTRON_BROWSER_WINDOW_CONFIRM', function (event, message, title) {
|
||||||
|
if (message == null) message = ''
|
||||||
|
if (title == null) title = ''
|
||||||
|
|
||||||
|
event.returnValue = !electron.dialog.showMessageBox(event.sender.getOwnerBrowserWindow(), {
|
||||||
|
message: `${message}`,
|
||||||
|
title: `${title}`,
|
||||||
|
buttons: ['OK', 'Cancel'],
|
||||||
|
cancelId: 1
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Implements window.close()
|
||||||
|
ipcMain.on('ELECTRON_BROWSER_WINDOW_CLOSE', function (event) {
|
||||||
|
event.sender.getOwnerBrowserWindow().close()
|
||||||
|
event.returnValue = null
|
||||||
|
})
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
const timers = require('timers')
|
const timers = require('timers')
|
||||||
|
|
||||||
|
const {binding} = process
|
||||||
|
|
||||||
process.atomBinding = function (name) {
|
process.atomBinding = function (name) {
|
||||||
try {
|
try {
|
||||||
return process.binding(`atom_${process.type}_${name}`)
|
return binding(`atom_${process.type}_${name}`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (/No such module/.test(error.message)) {
|
if (/No such module/.test(error.message)) {
|
||||||
return process.binding(`atom_common_${name}`)
|
return binding(`atom_common_${name}`)
|
||||||
} else {
|
} else {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// - `features` input string
|
// - `features` input string
|
||||||
// - `emit` function(key, value) - called for each parsed KV
|
// - `emit` function(key, value) - called for each parsed KV
|
||||||
module.exports = function parseFeaturesString (features, emit) {
|
module.exports = function parseFeaturesString (features, emit) {
|
||||||
|
features = `${features}`
|
||||||
// split the string by ','
|
// split the string by ','
|
||||||
features.split(/,\s*/).forEach((feature) => {
|
features.split(/,\s*/).forEach((feature) => {
|
||||||
// expected form is either a key by itself or a key/value pair in the form of
|
// expected form is either a key by itself or a key/value pair in the form of
|
||||||
|
|
|
@ -88,7 +88,7 @@ const wrapArgs = function (args, visited) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Array.prototype.slice.call(args).map(valueToMeta)
|
return args.map(valueToMeta)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate object's members from descriptors.
|
// Populate object's members from descriptors.
|
||||||
|
@ -102,14 +102,14 @@ const setObjectMembers = function (ref, object, metaId, members) {
|
||||||
|
|
||||||
let descriptor = { enumerable: member.enumerable }
|
let descriptor = { enumerable: member.enumerable }
|
||||||
if (member.type === 'method') {
|
if (member.type === 'method') {
|
||||||
const remoteMemberFunction = function () {
|
const remoteMemberFunction = function (...args) {
|
||||||
if (this && this.constructor === remoteMemberFunction) {
|
if (this && this.constructor === remoteMemberFunction) {
|
||||||
// Constructor call.
|
// Constructor call.
|
||||||
let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', metaId, member.name, wrapArgs(arguments))
|
let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', metaId, member.name, wrapArgs(args))
|
||||||
return metaToValue(ret)
|
return metaToValue(ret)
|
||||||
} else {
|
} else {
|
||||||
// Call member function.
|
// Call member function.
|
||||||
let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CALL', metaId, member.name, wrapArgs(arguments))
|
let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CALL', metaId, member.name, wrapArgs(args))
|
||||||
return metaToValue(ret)
|
return metaToValue(ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,17 +220,17 @@ const metaToValue = function (meta) {
|
||||||
|
|
||||||
if (meta.type === 'function') {
|
if (meta.type === 'function') {
|
||||||
// A shadow class to represent the remote function object.
|
// A shadow class to represent the remote function object.
|
||||||
let remoteFunction = function () {
|
let remoteFunction = function (...args) {
|
||||||
if (this && this.constructor === remoteFunction) {
|
if (this && this.constructor === remoteFunction) {
|
||||||
// Constructor call.
|
// Constructor call.
|
||||||
let obj = ipcRenderer.sendSync('ELECTRON_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(arguments))
|
let obj = ipcRenderer.sendSync('ELECTRON_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(args))
|
||||||
// Returning object in constructor will replace constructed object
|
// Returning object in constructor will replace constructed object
|
||||||
// with the returned object.
|
// with the returned object.
|
||||||
// http://stackoverflow.com/questions/1978049/what-values-can-a-constructor-return-to-avoid-returning-this
|
// http://stackoverflow.com/questions/1978049/what-values-can-a-constructor-return-to-avoid-returning-this
|
||||||
return metaToValue(obj)
|
return metaToValue(obj)
|
||||||
} else {
|
} else {
|
||||||
// Function call.
|
// Function call.
|
||||||
let obj = ipcRenderer.sendSync('ELECTRON_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(arguments))
|
let obj = ipcRenderer.sendSync('ELECTRON_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(args))
|
||||||
return metaToValue(obj)
|
return metaToValue(obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,28 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const ipcRenderer = require('electron').ipcRenderer
|
const {ipcRenderer} = require('electron')
|
||||||
const remote = require('electron').remote
|
|
||||||
const parseFeaturesString = require('../common/parse-features-string')
|
const parseFeaturesString = require('../common/parse-features-string')
|
||||||
|
|
||||||
|
const {defineProperty} = Object
|
||||||
|
|
||||||
// Helper function to resolve relative url.
|
// Helper function to resolve relative url.
|
||||||
var a = window.top.document.createElement('a')
|
const a = window.top.document.createElement('a')
|
||||||
var resolveURL = function (url) {
|
const resolveURL = function (url) {
|
||||||
a.href = url
|
a.href = url
|
||||||
return a.href
|
return a.href
|
||||||
}
|
}
|
||||||
|
|
||||||
// Window object returned by "window.open".
|
// Window object returned by "window.open".
|
||||||
var BrowserWindowProxy = (function () {
|
const BrowserWindowProxy = (function () {
|
||||||
BrowserWindowProxy.proxies = {}
|
BrowserWindowProxy.proxies = {}
|
||||||
|
|
||||||
BrowserWindowProxy.getOrCreate = function (guestId) {
|
BrowserWindowProxy.getOrCreate = function (guestId) {
|
||||||
var base = this.proxies
|
let proxy = this.proxies[guestId]
|
||||||
base[guestId] != null ? base[guestId] : base[guestId] = new BrowserWindowProxy(guestId)
|
if (proxy == null) {
|
||||||
return base[guestId]
|
proxy = new BrowserWindowProxy(guestId)
|
||||||
|
this.proxies[guestId] = proxy
|
||||||
|
}
|
||||||
|
return proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
BrowserWindowProxy.remove = function (guestId) {
|
BrowserWindowProxy.remove = function (guestId) {
|
||||||
|
@ -26,7 +30,7 @@ var BrowserWindowProxy = (function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
function BrowserWindowProxy (guestId1) {
|
function BrowserWindowProxy (guestId1) {
|
||||||
Object.defineProperty(this, 'guestId', {
|
defineProperty(this, 'guestId', {
|
||||||
configurable: false,
|
configurable: false,
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
writeable: false,
|
writeable: false,
|
||||||
|
@ -56,7 +60,7 @@ var BrowserWindowProxy = (function () {
|
||||||
ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', this.guestId, 'print')
|
ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', this.guestId, 'print')
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.defineProperty(BrowserWindowProxy.prototype, 'location', {
|
defineProperty(BrowserWindowProxy.prototype, 'location', {
|
||||||
get: function () {
|
get: function () {
|
||||||
return ipcRenderer.sendSync('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD_SYNC', this.guestId, 'getURL')
|
return ipcRenderer.sendSync('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD_SYNC', this.guestId, 'getURL')
|
||||||
},
|
},
|
||||||
|
@ -83,13 +87,13 @@ var BrowserWindowProxy = (function () {
|
||||||
if (process.guestInstanceId == null) {
|
if (process.guestInstanceId == null) {
|
||||||
// Override default window.close.
|
// Override default window.close.
|
||||||
window.close = function () {
|
window.close = function () {
|
||||||
return remote.getCurrentWindow().close()
|
ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_CLOSE')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the browser window or guest view emit "new-window" event.
|
// Make the browser window or guest view emit "new-window" event.
|
||||||
window.open = function (url, frameName, features) {
|
window.open = function (url, frameName, features) {
|
||||||
var guestId, j, len1, name, options, additionalFeatures
|
let guestId, j, len1, name, options, additionalFeatures
|
||||||
if (frameName == null) {
|
if (frameName == null) {
|
||||||
frameName = ''
|
frameName = ''
|
||||||
}
|
}
|
||||||
|
@ -160,29 +164,12 @@ window.open = function (url, frameName, features) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the dialog API to implement alert().
|
window.alert = function (message, title) {
|
||||||
window.alert = function (message = '', title = '') {
|
ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_ALERT', message, title)
|
||||||
remote.dialog.showMessageBox(remote.getCurrentWindow(), {
|
|
||||||
message: String(message),
|
|
||||||
title: String(title),
|
|
||||||
buttons: ['OK']
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// And the confirm().
|
|
||||||
window.confirm = function (message, title) {
|
window.confirm = function (message, title) {
|
||||||
var buttons, cancelId
|
return ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_CONFIRM', message, title)
|
||||||
if (title == null) {
|
|
||||||
title = ''
|
|
||||||
}
|
|
||||||
buttons = ['OK', 'Cancel']
|
|
||||||
cancelId = 1
|
|
||||||
return !remote.dialog.showMessageBox(remote.getCurrentWindow(), {
|
|
||||||
message: message,
|
|
||||||
title: title,
|
|
||||||
buttons: buttons,
|
|
||||||
cancelId: cancelId
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// But we do not support prompt().
|
// But we do not support prompt().
|
||||||
|
@ -206,11 +193,11 @@ ipcRenderer.on('ELECTRON_GUEST_WINDOW_POSTMESSAGE', function (event, sourceId, m
|
||||||
})
|
})
|
||||||
|
|
||||||
// Forward history operations to browser.
|
// Forward history operations to browser.
|
||||||
var sendHistoryOperation = function (...args) {
|
const sendHistoryOperation = function (...args) {
|
||||||
ipcRenderer.send('ELECTRON_NAVIGATION_CONTROLLER', ...args)
|
ipcRenderer.send('ELECTRON_NAVIGATION_CONTROLLER', ...args)
|
||||||
}
|
}
|
||||||
|
|
||||||
var getHistoryOperation = function (...args) {
|
const getHistoryOperation = function (...args) {
|
||||||
return ipcRenderer.sendSync('ELECTRON_SYNC_NAVIGATION_CONTROLLER', ...args)
|
return ipcRenderer.sendSync('ELECTRON_SYNC_NAVIGATION_CONTROLLER', ...args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,7 +213,7 @@ window.history.go = function (offset) {
|
||||||
sendHistoryOperation('goToOffset', offset)
|
sendHistoryOperation('goToOffset', offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.defineProperty(window.history, 'length', {
|
defineProperty(window.history, 'length', {
|
||||||
get: function () {
|
get: function () {
|
||||||
return getHistoryOperation('length')
|
return getHistoryOperation('length')
|
||||||
}
|
}
|
||||||
|
@ -244,13 +231,13 @@ ipcRenderer.on('ELECTRON_RENDERER_WINDOW_VISIBILITY_CHANGE', function (event, vi
|
||||||
})
|
})
|
||||||
|
|
||||||
// Make document.hidden and document.visibilityState return the correct value.
|
// Make document.hidden and document.visibilityState return the correct value.
|
||||||
Object.defineProperty(document, 'hidden', {
|
defineProperty(document, 'hidden', {
|
||||||
get: function () {
|
get: function () {
|
||||||
return cachedVisibilityState !== 'visible'
|
return cachedVisibilityState !== 'visible'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
Object.defineProperty(document, 'visibilityState', {
|
defineProperty(document, 'visibilityState', {
|
||||||
get: function () {
|
get: function () {
|
||||||
return cachedVisibilityState
|
return cachedVisibilityState
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue