Merge pull request #8120 from electron/implement-window-methods-in-main-process

Implement window methods in main process
This commit is contained in:
Kevin Sawicki 2016-12-05 09:29:11 -08:00 committed by GitHub
commit a9d4d9ad85
6 changed files with 69 additions and 48 deletions

View file

@ -106,8 +106,8 @@ will be passed via `callback(filename)`
* `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
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
used as `cancelId`, not matter whether it is already specified.
buttons. On macOS and Windows the index of the "Cancel" button will always
be used as `cancelId` even if it is specified.
* `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
others as command links in the dialog. This can make the dialog appear in

View file

@ -416,3 +416,34 @@ ipcMain.on('ELECTRON_BROWSER_SEND_TO', function (event, sendToAll, webContentsId
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
})

View file

@ -1,11 +1,13 @@
const timers = require('timers')
const {binding} = process
process.atomBinding = function (name) {
try {
return process.binding(`atom_${process.type}_${name}`)
return binding(`atom_${process.type}_${name}`)
} catch (error) {
if (/No such module/.test(error.message)) {
return process.binding(`atom_common_${name}`)
return binding(`atom_common_${name}`)
} else {
throw error
}

View file

@ -2,6 +2,7 @@
// - `features` input string
// - `emit` function(key, value) - called for each parsed KV
module.exports = function parseFeaturesString (features, emit) {
features = `${features}`
// split the string by ','
features.split(/,\s*/).forEach((feature) => {
// expected form is either a key by itself or a key/value pair in the form of

View file

@ -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.
@ -102,14 +102,14 @@ const setObjectMembers = function (ref, object, metaId, members) {
let descriptor = { enumerable: member.enumerable }
if (member.type === 'method') {
const remoteMemberFunction = function () {
const remoteMemberFunction = function (...args) {
if (this && this.constructor === remoteMemberFunction) {
// 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)
} else {
// 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)
}
}
@ -220,17 +220,17 @@ const metaToValue = function (meta) {
if (meta.type === 'function') {
// A shadow class to represent the remote function object.
let remoteFunction = function () {
let remoteFunction = function (...args) {
if (this && this.constructor === remoteFunction) {
// 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
// with the returned object.
// http://stackoverflow.com/questions/1978049/what-values-can-a-constructor-return-to-avoid-returning-this
return metaToValue(obj)
} else {
// 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)
}
}

View file

@ -1,24 +1,28 @@
'use strict'
const ipcRenderer = require('electron').ipcRenderer
const remote = require('electron').remote
const {ipcRenderer} = require('electron')
const parseFeaturesString = require('../common/parse-features-string')
const {defineProperty} = Object
// Helper function to resolve relative url.
var a = window.top.document.createElement('a')
var resolveURL = function (url) {
const a = window.top.document.createElement('a')
const resolveURL = function (url) {
a.href = url
return a.href
}
// Window object returned by "window.open".
var BrowserWindowProxy = (function () {
const BrowserWindowProxy = (function () {
BrowserWindowProxy.proxies = {}
BrowserWindowProxy.getOrCreate = function (guestId) {
var base = this.proxies
base[guestId] != null ? base[guestId] : base[guestId] = new BrowserWindowProxy(guestId)
return base[guestId]
let proxy = this.proxies[guestId]
if (proxy == null) {
proxy = new BrowserWindowProxy(guestId)
this.proxies[guestId] = proxy
}
return proxy
}
BrowserWindowProxy.remove = function (guestId) {
@ -26,7 +30,7 @@ var BrowserWindowProxy = (function () {
}
function BrowserWindowProxy (guestId1) {
Object.defineProperty(this, 'guestId', {
defineProperty(this, 'guestId', {
configurable: false,
enumerable: true,
writeable: false,
@ -56,7 +60,7 @@ var BrowserWindowProxy = (function () {
ipcRenderer.send('ELECTRON_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', this.guestId, 'print')
}
Object.defineProperty(BrowserWindowProxy.prototype, 'location', {
defineProperty(BrowserWindowProxy.prototype, 'location', {
get: function () {
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) {
// Override default window.close.
window.close = function () {
return remote.getCurrentWindow().close()
ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_CLOSE')
}
}
// Make the browser window or guest view emit "new-window" event.
window.open = function (url, frameName, features) {
var guestId, j, len1, name, options, additionalFeatures
let guestId, j, len1, name, options, additionalFeatures
if (frameName == null) {
frameName = ''
}
@ -160,29 +164,12 @@ window.open = function (url, frameName, features) {
}
}
// Use the dialog API to implement alert().
window.alert = function (message = '', title = '') {
remote.dialog.showMessageBox(remote.getCurrentWindow(), {
message: String(message),
title: String(title),
buttons: ['OK']
})
window.alert = function (message, title) {
ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_ALERT', message, title)
}
// And the confirm().
window.confirm = function (message, title) {
var buttons, cancelId
if (title == null) {
title = ''
}
buttons = ['OK', 'Cancel']
cancelId = 1
return !remote.dialog.showMessageBox(remote.getCurrentWindow(), {
message: message,
title: title,
buttons: buttons,
cancelId: cancelId
})
return ipcRenderer.sendSync('ELECTRON_BROWSER_WINDOW_CONFIRM', message, title)
}
// 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.
var sendHistoryOperation = function (...args) {
const sendHistoryOperation = function (...args) {
ipcRenderer.send('ELECTRON_NAVIGATION_CONTROLLER', ...args)
}
var getHistoryOperation = function (...args) {
const getHistoryOperation = function (...args) {
return ipcRenderer.sendSync('ELECTRON_SYNC_NAVIGATION_CONTROLLER', ...args)
}
@ -226,7 +213,7 @@ window.history.go = function (offset) {
sendHistoryOperation('goToOffset', offset)
}
Object.defineProperty(window.history, 'length', {
defineProperty(window.history, 'length', {
get: function () {
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.
Object.defineProperty(document, 'hidden', {
defineProperty(document, 'hidden', {
get: function () {
return cachedVisibilityState !== 'visible'
}
})
Object.defineProperty(document, 'visibilityState', {
defineProperty(document, 'visibilityState', {
get: function () {
return cachedVisibilityState
}