Compare commits

...

17 Commits

Author SHA1 Message Date
Electron Bot
ad876ac1b1 Bump v11.0.0-beta.5 2020-09-07 08:01:02 -07:00
trop[bot]
c35ec6bc34 fix: only focus a webContents if the window was not initially hidden (#25323)
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2020-09-04 14:47:08 -07:00
trop[bot]
a08b3682c3 fix: avoid creating client_id file for empty DIR_CRASH_DUMPS (#25310)
Co-authored-by: deepak1556 <hop2deep@gmail.com>
2020-09-03 19:09:20 -07:00
trop[bot]
c3ad33c28b fix: multiple dock icons when calling dock.show/hide (#25300)
* fix: mulitple dock icons when calling dock.show/hide

* test: run dock.show tests after dock.hide tests

Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-09-03 13:57:06 -07:00
Electron Bot
59f9e417d4 Bump v11.0.0-beta.4 2020-09-03 08:01:35 -07:00
trop[bot]
7931c8abfd ci: cleanup up test app directories (#25257)
* ci: cleanup up test app directories

* ci: use electron prefix for a testing apps so that the can be cleaned up

* Revert "ci: cleanup up test app directories"

This reverts commit a47daba812.

* fixup test due to app name change

Co-authored-by: John Kleinschmidt <jkleinsc@github.com>
2020-09-02 10:05:09 +09:00
trop[bot]
622f5f84cf chore: wrap add/remove view in extra check (#25258)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-09-02 10:04:10 +09:00
trop[bot]
c8944df576 chore: force source code and markdown files to use LF line ending (#25176)
* chore: force source code and markdown files to use LF line ending

* chore: replace CRLF with LF

Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-09-01 12:48:18 +09:00
Robo
3efbee2061 fix: client area inset calculation when maximized for framless windows (#25217)
* adopt per monitor scale factor

* fix: client area inset calculation when maximized

* address review feedback

* pass correct glass insets to GetDwmFrameInsetsInPixels

* remove unused code

* Windows 8 and 10 use the same DWM frame calculation

Co-authored-by: Cheng Zhao <zcbenz@gmail.com>

Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-08-31 13:20:28 -07:00
trop[bot]
aafada554f docs: fix supported platforms of powerMonitor (#25211)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-08-31 10:16:26 -07:00
Electron Bot
56e81665fb Bump v11.0.0-beta.3 2020-08-31 08:01:05 -07:00
trop[bot]
e68f086d95 fix: do not reset process_id in URLLoaderFactoryParams (#25180)
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2020-08-31 10:08:52 +09:00
trop[bot]
74edd99570 fix: save dialog extensions should be deterministic (#25193)
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2020-08-28 11:38:07 -07:00
trop[bot]
63720fd603 fix: resolve RegisterSuspendResumeNotification dynamically (#25168)
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2020-08-28 10:15:40 +09:00
Markus Olsson
d6bea2a681 fix: make shell.moveItemToTrash return false on Windows when move unsuccessful (#25171) 2020-08-27 17:43:52 -07:00
Electron Bot
5b53a08132 Bump v11.0.0-beta.2 2020-08-27 08:01:11 -07:00
Electron Bot
09e33b3420 Bump v11.0.0-beta.1 2020-08-26 10:51:08 -07:00
68 changed files with 1494 additions and 1330 deletions

10
.gitattributes vendored
View File

@@ -2,3 +2,13 @@
# files to be checked out with LF endings even if core.autocrlf is true. # files to be checked out with LF endings even if core.autocrlf is true.
*.patch text eol=lf *.patch text eol=lf
patches/**/.patches merge=union patches/**/.patches merge=union
# Source code and markdown files should always use LF as line ending.
*.cc text eol=lf
*.mm text eol=lf
*.h text eol=lf
*.js text eol=lf
*.ts text eol=lf
*.py text eol=lf
*.ps1 text eol=lf
*.md text eol=lf

View File

@@ -1 +1 @@
11.0.0-nightly.20200826 11.0.0-beta.5

View File

@@ -8,19 +8,19 @@ Process: [Main](../glossary.md#main-process)
The `powerMonitor` module emits the following events: The `powerMonitor` module emits the following events:
### Event: 'suspend' ### Event: 'suspend' _macOS_ _Windows_
Emitted when the system is suspending. Emitted when the system is suspending.
### Event: 'resume' ### Event: 'resume' _macOS_ _Windows_
Emitted when system is resuming. Emitted when system is resuming.
### Event: 'on-ac' _Windows_ ### Event: 'on-ac' _macOS_ _Windows_
Emitted when the system changes to AC power. Emitted when the system changes to AC power.
### Event: 'on-battery' _Windows_ ### Event: 'on-battery' _macOS_ _Windows_
Emitted when system changes to battery power. Emitted when system changes to battery power.

View File

@@ -1,95 +1,95 @@
// Modules to control application life and create native browser window // Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, dialog } = require('electron') const { app, BrowserWindow, ipcMain, dialog } = require('electron')
// Keep a global reference of the window object, if you don't, the window will // Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected. // be closed automatically when the JavaScript object is garbage collected.
let mainWindow let mainWindow
function createWindow () { function createWindow () {
// Create the browser window. // Create the browser window.
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 800, width: 800,
height: 600, height: 600,
webPreferences: { webPreferences: {
nodeIntegration: true nodeIntegration: true
} }
}) })
// and load the index.html of the app. // and load the index.html of the app.
mainWindow.loadFile('index.html') mainWindow.loadFile('index.html')
// Open the DevTools. // Open the DevTools.
// mainWindow.webContents.openDevTools() // mainWindow.webContents.openDevTools()
// Emitted when the window is closed. // Emitted when the window is closed.
mainWindow.on('closed', function () { mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows // Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time // in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element. // when you should delete the corresponding element.
mainWindow = null mainWindow = null
}) })
} }
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow) app.whenReady().then(createWindow)
// Quit when all windows are closed. // Quit when all windows are closed.
app.on('window-all-closed', function () { app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar // On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q // to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') { if (process.platform !== 'darwin') {
app.quit() app.quit()
} }
}) })
app.on('activate', function () { app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the // On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open. // dock icon is clicked and there are no other windows open.
if (mainWindow === null) { if (mainWindow === null) {
createWindow() createWindow()
} }
}) })
ipcMain.on('open-error-dialog', event => { ipcMain.on('open-error-dialog', event => {
dialog.showErrorBox('An Error Message', 'Demonstrating an error message.') dialog.showErrorBox('An Error Message', 'Demonstrating an error message.')
}) })
ipcMain.on('open-information-dialog', event => { ipcMain.on('open-information-dialog', event => {
const options = { const options = {
type: 'info', type: 'info',
title: 'Information', title: 'Information',
message: "This is an information dialog. Isn't it nice?", message: "This is an information dialog. Isn't it nice?",
buttons: ['Yes', 'No'] buttons: ['Yes', 'No']
} }
dialog.showMessageBox(options, index => { dialog.showMessageBox(options, index => {
event.sender.send('information-dialog-selection', index) event.sender.send('information-dialog-selection', index)
}) })
}) })
ipcMain.on('open-file-dialog', event => { ipcMain.on('open-file-dialog', event => {
dialog.showOpenDialog( dialog.showOpenDialog(
{ {
properties: ['openFile', 'openDirectory'] properties: ['openFile', 'openDirectory']
}, },
files => { files => {
if (files) { if (files) {
event.sender.send('selected-directory', files) event.sender.send('selected-directory', files)
} }
} }
) )
}) })
ipcMain.on('save-dialog', event => { ipcMain.on('save-dialog', event => {
const options = { const options = {
title: 'Save an Image', title: 'Save an Image',
filters: [{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }] filters: [{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }]
} }
dialog.showSaveDialog(options, filename => { dialog.showSaveDialog(options, filename => {
event.sender.send('saved-file', filename) event.sender.send('saved-file', filename)
}) })
}) })
// In this file you can include the rest of your app's specific main process // In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here. // code. You can also put them in separate files and require them here.

View File

@@ -1,18 +1,18 @@
const { ipcRenderer, shell } = require('electron') const { ipcRenderer, shell } = require('electron')
const links = document.querySelectorAll('a[href]') const links = document.querySelectorAll('a[href]')
const errorBtn = document.getElementById('error-dialog') const errorBtn = document.getElementById('error-dialog')
errorBtn.addEventListener('click', event => { errorBtn.addEventListener('click', event => {
ipcRenderer.send('open-error-dialog') ipcRenderer.send('open-error-dialog')
}) })
Array.prototype.forEach.call(links, (link) => { Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href') const url = link.getAttribute('href')
if (url.indexOf('http') === 0) { if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => { link.addEventListener('click', (e) => {
e.preventDefault() e.preventDefault()
shell.openExternal(url) shell.openExternal(url)
}) })
} }
}) })

View File

@@ -1,70 +1,70 @@
// Modules to control application life and create native browser window // Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, dialog } = require('electron') const { app, BrowserWindow, ipcMain, dialog } = require('electron')
// Keep a global reference of the window object, if you don't, the window will // Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected. // be closed automatically when the JavaScript object is garbage collected.
let mainWindow let mainWindow
function createWindow () { function createWindow () {
// Create the browser window. // Create the browser window.
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 800, width: 800,
height: 600, height: 600,
webPreferences: { webPreferences: {
nodeIntegration: true nodeIntegration: true
} }
}) })
// and load the index.html of the app. // and load the index.html of the app.
mainWindow.loadFile('index.html') mainWindow.loadFile('index.html')
// Open the DevTools. // Open the DevTools.
// mainWindow.webContents.openDevTools() // mainWindow.webContents.openDevTools()
// Emitted when the window is closed. // Emitted when the window is closed.
mainWindow.on('closed', function () { mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows // Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time // in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element. // when you should delete the corresponding element.
mainWindow = null mainWindow = null
}) })
} }
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow) app.whenReady().then(createWindow)
// Quit when all windows are closed. // Quit when all windows are closed.
app.on('window-all-closed', function () { app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar // On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q // to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') { if (process.platform !== 'darwin') {
app.quit() app.quit()
} }
}) })
app.on('activate', function () { app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the // On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open. // dock icon is clicked and there are no other windows open.
if (mainWindow === null) { if (mainWindow === null) {
createWindow() createWindow()
} }
}) })
ipcMain.on('open-information-dialog', event => { ipcMain.on('open-information-dialog', event => {
const options = { const options = {
type: 'info', type: 'info',
title: 'Information', title: 'Information',
message: "This is an information dialog. Isn't it nice?", message: "This is an information dialog. Isn't it nice?",
buttons: ['Yes', 'No'] buttons: ['Yes', 'No']
} }
dialog.showMessageBox(options, index => { dialog.showMessageBox(options, index => {
event.sender.send('information-dialog-selection', index) event.sender.send('information-dialog-selection', index)
}) })
}) })
// In this file you can include the rest of your app's specific main process // In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here. // code. You can also put them in separate files and require them here.

View File

@@ -1,25 +1,25 @@
const { ipcRenderer, shell } = require('electron') const { ipcRenderer, shell } = require('electron')
const informationBtn = document.getElementById('information-dialog') const informationBtn = document.getElementById('information-dialog')
const links = document.querySelectorAll('a[href]') const links = document.querySelectorAll('a[href]')
informationBtn.addEventListener('click', event => { informationBtn.addEventListener('click', event => {
ipcRenderer.send('open-information-dialog') ipcRenderer.send('open-information-dialog')
}) })
ipcRenderer.on('information-dialog-selection', (event, index) => { ipcRenderer.on('information-dialog-selection', (event, index) => {
let message = 'You selected ' let message = 'You selected '
if (index === 0) message += 'yes.' if (index === 0) message += 'yes.'
else message += 'no.' else message += 'no.'
document.getElementById('info-selection').innerHTML = message document.getElementById('info-selection').innerHTML = message
}) })
Array.prototype.forEach.call(links, (link) => { Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href') const url = link.getAttribute('href')
if (url.indexOf('http') === 0) { if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => { link.addEventListener('click', (e) => {
e.preventDefault() e.preventDefault()
shell.openExternal(url) shell.openExternal(url)
}) })
} }
}) })

View File

@@ -1,70 +1,70 @@
// Modules to control application life and create native browser window // Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, dialog } = require('electron') const { app, BrowserWindow, ipcMain, dialog } = require('electron')
// Keep a global reference of the window object, if you don't, the window will // Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected. // be closed automatically when the JavaScript object is garbage collected.
let mainWindow let mainWindow
function createWindow () { function createWindow () {
// Create the browser window. // Create the browser window.
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 800, width: 800,
height: 600, height: 600,
webPreferences: { webPreferences: {
nodeIntegration: true nodeIntegration: true
} }
}) })
// and load the index.html of the app. // and load the index.html of the app.
mainWindow.loadFile('index.html') mainWindow.loadFile('index.html')
// Open the DevTools. // Open the DevTools.
// mainWindow.webContents.openDevTools() // mainWindow.webContents.openDevTools()
// Emitted when the window is closed. // Emitted when the window is closed.
mainWindow.on('closed', function () { mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows // Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time // in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element. // when you should delete the corresponding element.
mainWindow = null mainWindow = null
}) })
} }
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow) app.whenReady().then(createWindow)
// Quit when all windows are closed. // Quit when all windows are closed.
app.on('window-all-closed', function () { app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar // On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q // to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') { if (process.platform !== 'darwin') {
app.quit() app.quit()
} }
}) })
app.on('activate', function () { app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the // On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open. // dock icon is clicked and there are no other windows open.
if (mainWindow === null) { if (mainWindow === null) {
createWindow() createWindow()
} }
}) })
ipcMain.on('open-file-dialog', event => { ipcMain.on('open-file-dialog', event => {
dialog.showOpenDialog( dialog.showOpenDialog(
{ {
properties: ['openFile', 'openDirectory'] properties: ['openFile', 'openDirectory']
}, },
files => { files => {
if (files) { if (files) {
event.sender.send('selected-directory', files) event.sender.send('selected-directory', files)
} }
} }
) )
}) })
// In this file you can include the rest of your app's specific main process // In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here. // code. You can also put them in separate files and require them here.

View File

@@ -1,22 +1,22 @@
const { ipcRenderer, shell } = require('electron') const { ipcRenderer, shell } = require('electron')
const selectDirBtn = document.getElementById('select-directory') const selectDirBtn = document.getElementById('select-directory')
const links = document.querySelectorAll('a[href]') const links = document.querySelectorAll('a[href]')
selectDirBtn.addEventListener('click', event => { selectDirBtn.addEventListener('click', event => {
ipcRenderer.send('open-file-dialog') ipcRenderer.send('open-file-dialog')
}) })
ipcRenderer.on('selected-directory', (event, path) => { ipcRenderer.on('selected-directory', (event, path) => {
document.getElementById('selected-file').innerHTML = `You selected: ${path}` document.getElementById('selected-file').innerHTML = `You selected: ${path}`
}) })
Array.prototype.forEach.call(links, (link) => { Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href') const url = link.getAttribute('href')
if (url.indexOf('http') === 0) { if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => { link.addEventListener('click', (e) => {
e.preventDefault() e.preventDefault()
shell.openExternal(url) shell.openExternal(url)
}) })
} }
}) })

View File

@@ -1,66 +1,66 @@
// Modules to control application life and create native browser window // Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, dialog } = require('electron') const { app, BrowserWindow, ipcMain, dialog } = require('electron')
// Keep a global reference of the window object, if you don't, the window will // Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected. // be closed automatically when the JavaScript object is garbage collected.
let mainWindow let mainWindow
function createWindow () { function createWindow () {
// Create the browser window. // Create the browser window.
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 800, width: 800,
height: 600, height: 600,
webPreferences: { webPreferences: {
nodeIntegration: true nodeIntegration: true
} }
}) })
// and load the index.html of the app. // and load the index.html of the app.
mainWindow.loadFile('index.html') mainWindow.loadFile('index.html')
// Open the DevTools. // Open the DevTools.
// mainWindow.webContents.openDevTools() // mainWindow.webContents.openDevTools()
// Emitted when the window is closed. // Emitted when the window is closed.
mainWindow.on('closed', function () { mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows // Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time // in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element. // when you should delete the corresponding element.
mainWindow = null mainWindow = null
}) })
} }
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow) app.whenReady().then(createWindow)
// Quit when all windows are closed. // Quit when all windows are closed.
app.on('window-all-closed', function () { app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar // On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q // to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') { if (process.platform !== 'darwin') {
app.quit() app.quit()
} }
}) })
app.on('activate', function () { app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the // On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open. // dock icon is clicked and there are no other windows open.
if (mainWindow === null) { if (mainWindow === null) {
createWindow() createWindow()
} }
}) })
ipcMain.on('save-dialog', event => { ipcMain.on('save-dialog', event => {
const options = { const options = {
title: 'Save an Image', title: 'Save an Image',
filters: [{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }] filters: [{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }]
} }
dialog.showSaveDialog(options, filename => { dialog.showSaveDialog(options, filename => {
event.sender.send('saved-file', filename) event.sender.send('saved-file', filename)
}) })
}) })
// In this file you can include the rest of your app's specific main process // In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here. // code. You can also put them in separate files and require them here.

View File

@@ -1,23 +1,23 @@
const { ipcRenderer, shell } = require('electron') const { ipcRenderer, shell } = require('electron')
const saveBtn = document.getElementById('save-dialog') const saveBtn = document.getElementById('save-dialog')
const links = document.querySelectorAll('a[href]') const links = document.querySelectorAll('a[href]')
saveBtn.addEventListener('click', event => { saveBtn.addEventListener('click', event => {
ipcRenderer.send('save-dialog') ipcRenderer.send('save-dialog')
}) })
ipcRenderer.on('saved-file', (event, path) => { ipcRenderer.on('saved-file', (event, path) => {
if (!path) path = 'No path' if (!path) path = 'No path'
document.getElementById('file-saved').innerHTML = `Path selected: ${path}` document.getElementById('file-saved').innerHTML = `Path selected: ${path}`
}) })
Array.prototype.forEach.call(links, (link) => { Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href') const url = link.getAttribute('href')
if (url.indexOf('http') === 0) { if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => { link.addEventListener('click', (e) => {
e.preventDefault() e.preventDefault()
shell.openExternal(url) shell.openExternal(url)
}) })
} }
}) })

View File

@@ -1,56 +1,56 @@
// Modules to control application life and create native browser window // Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron') const { app, BrowserWindow } = require('electron')
// Keep a global reference of the window object, if you don't, the window will // Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected. // be closed automatically when the JavaScript object is garbage collected.
let mainWindow let mainWindow
function createWindow () { function createWindow () {
// Create the browser window. // Create the browser window.
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 800, width: 800,
height: 600, height: 600,
webPreferences: { webPreferences: {
nodeIntegration: true nodeIntegration: true
} }
}) })
// and load the index.html of the app. // and load the index.html of the app.
mainWindow.loadFile('index.html') mainWindow.loadFile('index.html')
// Open the DevTools. // Open the DevTools.
// mainWindow.webContents.openDevTools() // mainWindow.webContents.openDevTools()
// Emitted when the window is closed. // Emitted when the window is closed.
mainWindow.on('closed', function () { mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows // Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time // in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element. // when you should delete the corresponding element.
mainWindow = null mainWindow = null
}) })
} }
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow) app.whenReady().then(createWindow)
// Quit when all windows are closed. // Quit when all windows are closed.
app.on('window-all-closed', function () { app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar // On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q // to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') { if (process.platform !== 'darwin') {
app.quit() app.quit()
} }
}) })
app.on('activate', function () { app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the // On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open. // dock icon is clicked and there are no other windows open.
if (mainWindow === null) { if (mainWindow === null) {
createWindow() createWindow()
} }
}) })
// In this file you can include the rest of your app's specific main process // In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here. // code. You can also put them in separate files and require them here.

View File

@@ -1,13 +1,13 @@
const { shell } = require('electron') const { shell } = require('electron')
const os = require('os') const os = require('os')
const exLinksBtn = document.getElementById('open-ex-links') const exLinksBtn = document.getElementById('open-ex-links')
const fileManagerBtn = document.getElementById('open-file-manager') const fileManagerBtn = document.getElementById('open-file-manager')
fileManagerBtn.addEventListener('click', (event) => { fileManagerBtn.addEventListener('click', (event) => {
shell.showItemInFolder(os.homedir()) shell.showItemInFolder(os.homedir())
}) })
exLinksBtn.addEventListener('click', (event) => { exLinksBtn.addEventListener('click', (event) => {
shell.openExternal('https://electronjs.org') shell.openExternal('https://electronjs.org')
}) })

View File

@@ -1,56 +1,56 @@
// Modules to control application life and create native browser window // Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron') const { app, BrowserWindow } = require('electron')
// Keep a global reference of the window object, if you don't, the window will // Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected. // be closed automatically when the JavaScript object is garbage collected.
let mainWindow let mainWindow
function createWindow () { function createWindow () {
// Create the browser window. // Create the browser window.
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 800, width: 800,
height: 600, height: 600,
webPreferences: { webPreferences: {
nodeIntegration: true nodeIntegration: true
} }
}) })
// and load the index.html of the app. // and load the index.html of the app.
mainWindow.loadFile('index.html') mainWindow.loadFile('index.html')
// Open the DevTools. // Open the DevTools.
// mainWindow.webContents.openDevTools() // mainWindow.webContents.openDevTools()
// Emitted when the window is closed. // Emitted when the window is closed.
mainWindow.on('closed', function () { mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows // Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time // in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element. // when you should delete the corresponding element.
mainWindow = null mainWindow = null
}) })
} }
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow) app.whenReady().then(createWindow)
// Quit when all windows are closed. // Quit when all windows are closed.
app.on('window-all-closed', function () { app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar // On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q // to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') { if (process.platform !== 'darwin') {
app.quit() app.quit()
} }
}) })
app.on('activate', function () { app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the // On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open. // dock icon is clicked and there are no other windows open.
if (mainWindow === null) { if (mainWindow === null) {
createWindow() createWindow()
} }
}) })
// In this file you can include the rest of your app's specific main process // In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here. // code. You can also put them in separate files and require them here.

View File

@@ -1,29 +1,29 @@
const basicNotification = { const basicNotification = {
title: 'Basic Notification', title: 'Basic Notification',
body: 'Short message part' body: 'Short message part'
} }
const notification = { const notification = {
title: 'Notification with image', title: 'Notification with image',
body: 'Short message plus a custom image', body: 'Short message plus a custom image',
icon: 'https://via.placeholder.com/150' icon: 'https://via.placeholder.com/150'
} }
const basicNotificationButton = document.getElementById('basic-noti') const basicNotificationButton = document.getElementById('basic-noti')
const notificationButton = document.getElementById('advanced-noti') const notificationButton = document.getElementById('advanced-noti')
notificationButton.addEventListener('click', () => { notificationButton.addEventListener('click', () => {
const myNotification = new window.Notification(notification.title, notification) const myNotification = new window.Notification(notification.title, notification)
myNotification.onclick = () => { myNotification.onclick = () => {
console.log('Notification clicked') console.log('Notification clicked')
} }
}) })
basicNotificationButton.addEventListener('click', () => { basicNotificationButton.addEventListener('click', () => {
const myNotification = new window.Notification(basicNotification.title, basicNotification) const myNotification = new window.Notification(basicNotification.title, basicNotification)
myNotification.onclick = () => { myNotification.onclick = () => {
console.log('Notification clicked') console.log('Notification clicked')
} }
}) })

File diff suppressed because one or more lines are too long

View File

@@ -1,35 +1,35 @@
const { ipcRenderer, shell } = require('electron') const { ipcRenderer, shell } = require('electron')
const trayBtn = document.getElementById('put-in-tray') const trayBtn = document.getElementById('put-in-tray')
const links = document.querySelectorAll('a[href]') const links = document.querySelectorAll('a[href]')
let trayOn = false let trayOn = false
trayBtn.addEventListener('click', function (event) { trayBtn.addEventListener('click', function (event) {
if (trayOn) { if (trayOn) {
trayOn = false trayOn = false
document.getElementById('tray-countdown').innerHTML = '' document.getElementById('tray-countdown').innerHTML = ''
ipcRenderer.send('remove-tray') ipcRenderer.send('remove-tray')
} else { } else {
trayOn = true trayOn = true
const message = 'Click demo again to remove.' const message = 'Click demo again to remove.'
document.getElementById('tray-countdown').innerHTML = message document.getElementById('tray-countdown').innerHTML = message
ipcRenderer.send('put-in-tray') ipcRenderer.send('put-in-tray')
} }
}) })
// Tray removed from context menu on icon // Tray removed from context menu on icon
ipcRenderer.on('tray-removed', function () { ipcRenderer.on('tray-removed', function () {
ipcRenderer.send('remove-tray') ipcRenderer.send('remove-tray')
trayOn = false trayOn = false
document.getElementById('tray-countdown').innerHTML = '' document.getElementById('tray-countdown').innerHTML = ''
}) })
Array.prototype.forEach.call(links, (link) => { Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href') const url = link.getAttribute('href')
if (url.indexOf('http') === 0) { if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => { link.addEventListener('click', (e) => {
e.preventDefault() e.preventDefault()
shell.openExternal(url) shell.openExternal(url)
}) })
} }
}) })

View File

@@ -1,56 +1,56 @@
// Modules to control application life and create native browser window // Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron') const { app, BrowserWindow } = require('electron')
// Keep a global reference of the window object, if you don't, the window will // Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected. // be closed automatically when the JavaScript object is garbage collected.
let mainWindow let mainWindow
function createWindow () { function createWindow () {
// Create the browser window. // Create the browser window.
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 800, width: 800,
height: 600, height: 600,
webPreferences: { webPreferences: {
nodeIntegration: true nodeIntegration: true
} }
}) })
// and load the index.html of the app. // and load the index.html of the app.
mainWindow.loadFile('index.html') mainWindow.loadFile('index.html')
// Open the DevTools. // Open the DevTools.
// mainWindow.webContents.openDevTools() // mainWindow.webContents.openDevTools()
// Emitted when the window is closed. // Emitted when the window is closed.
mainWindow.on('closed', function () { mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows // Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time // in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element. // when you should delete the corresponding element.
mainWindow = null mainWindow = null
}) })
} }
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow) app.whenReady().then(createWindow)
// Quit when all windows are closed. // Quit when all windows are closed.
app.on('window-all-closed', function () { app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar // On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q // to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') { if (process.platform !== 'darwin') {
app.quit() app.quit()
} }
}) })
app.on('activate', function () { app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the // On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open. // dock icon is clicked and there are no other windows open.
if (mainWindow === null) { if (mainWindow === null) {
createWindow() createWindow()
} }
}) })
// In this file you can include the rest of your app's specific main process // In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here. // code. You can also put them in separate files and require them here.

View File

@@ -1,25 +1,25 @@
const { BrowserWindow } = require('electron').remote const { BrowserWindow } = require('electron').remote
const shell = require('electron').shell const shell = require('electron').shell
const framelessWindowBtn = document.getElementById('frameless-window') const framelessWindowBtn = document.getElementById('frameless-window')
const links = document.querySelectorAll('a[href]') const links = document.querySelectorAll('a[href]')
framelessWindowBtn.addEventListener('click', (event) => { framelessWindowBtn.addEventListener('click', (event) => {
const modalPath = 'https://electronjs.org' const modalPath = 'https://electronjs.org'
let win = new BrowserWindow({ frame: false }) let win = new BrowserWindow({ frame: false })
win.on('close', () => { win = null }) win.on('close', () => { win = null })
win.loadURL(modalPath) win.loadURL(modalPath)
win.show() win.show()
}) })
Array.prototype.forEach.call(links, (link) => { Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href') const url = link.getAttribute('href')
if (url.indexOf('http') === 0) { if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => { link.addEventListener('click', (e) => {
e.preventDefault() e.preventDefault()
shell.openExternal(url) shell.openExternal(url)
}) })
} }
}) })

View File

@@ -1,56 +1,56 @@
// Modules to control application life and create native browser window // Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron') const { app, BrowserWindow } = require('electron')
// Keep a global reference of the window object, if you don't, the window will // Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected. // be closed automatically when the JavaScript object is garbage collected.
let mainWindow let mainWindow
function createWindow () { function createWindow () {
// Create the browser window. // Create the browser window.
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 800, width: 800,
height: 600, height: 600,
webPreferences: { webPreferences: {
nodeIntegration: true nodeIntegration: true
} }
}) })
// and load the index.html of the app. // and load the index.html of the app.
mainWindow.loadFile('index.html') mainWindow.loadFile('index.html')
// Open the DevTools. // Open the DevTools.
// mainWindow.webContents.openDevTools() // mainWindow.webContents.openDevTools()
// Emitted when the window is closed. // Emitted when the window is closed.
mainWindow.on('closed', function () { mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows // Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time // in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element. // when you should delete the corresponding element.
mainWindow = null mainWindow = null
}) })
} }
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow) app.whenReady().then(createWindow)
// Quit when all windows are closed. // Quit when all windows are closed.
app.on('window-all-closed', function () { app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar // On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q // to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') { if (process.platform !== 'darwin') {
app.quit() app.quit()
} }
}) })
app.on('activate', function () { app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the // On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open. // dock icon is clicked and there are no other windows open.
if (mainWindow === null) { if (mainWindow === null) {
createWindow() createWindow()
} }
}) })
// In this file you can include the rest of your app's specific main process // In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here. // code. You can also put them in separate files and require them here.

View File

@@ -1,35 +1,35 @@
const { BrowserWindow } = require('electron').remote const { BrowserWindow } = require('electron').remote
const shell = require('electron').shell const shell = require('electron').shell
const manageWindowBtn = document.getElementById('manage-window') const manageWindowBtn = document.getElementById('manage-window')
const links = document.querySelectorAll('a[href]') const links = document.querySelectorAll('a[href]')
let win let win
manageWindowBtn.addEventListener('click', (event) => { manageWindowBtn.addEventListener('click', (event) => {
const modalPath = 'https://electronjs.org' const modalPath = 'https://electronjs.org'
win = new BrowserWindow({ width: 400, height: 275 }) win = new BrowserWindow({ width: 400, height: 275 })
win.on('resize', updateReply) win.on('resize', updateReply)
win.on('move', updateReply) win.on('move', updateReply)
win.on('close', () => { win = null }) win.on('close', () => { win = null })
win.loadURL(modalPath) win.loadURL(modalPath)
win.show() win.show()
function updateReply () { function updateReply () {
const manageWindowReply = document.getElementById('manage-window-reply') const manageWindowReply = document.getElementById('manage-window-reply')
const message = `Size: ${win.getSize()} Position: ${win.getPosition()}` const message = `Size: ${win.getSize()} Position: ${win.getPosition()}`
manageWindowReply.innerText = message manageWindowReply.innerText = message
} }
}) })
Array.prototype.forEach.call(links, (link) => { Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href') const url = link.getAttribute('href')
if (url.indexOf('http') === 0) { if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => { link.addEventListener('click', (e) => {
e.preventDefault() e.preventDefault()
shell.openExternal(url) shell.openExternal(url)
}) })
} }
}) })

View File

@@ -1,56 +1,56 @@
// Modules to control application life and create native browser window // Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron') const { app, BrowserWindow } = require('electron')
// Keep a global reference of the window object, if you don't, the window will // Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected. // be closed automatically when the JavaScript object is garbage collected.
let mainWindow let mainWindow
function createWindow () { function createWindow () {
// Create the browser window. // Create the browser window.
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 800, width: 800,
height: 600, height: 600,
webPreferences: { webPreferences: {
nodeIntegration: true nodeIntegration: true
} }
}) })
// and load the index.html of the app. // and load the index.html of the app.
mainWindow.loadFile('index.html') mainWindow.loadFile('index.html')
// Open the DevTools. // Open the DevTools.
// mainWindow.webContents.openDevTools() // mainWindow.webContents.openDevTools()
// Emitted when the window is closed. // Emitted when the window is closed.
mainWindow.on('closed', function () { mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows // Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time // in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element. // when you should delete the corresponding element.
mainWindow = null mainWindow = null
}) })
} }
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow) app.whenReady().then(createWindow)
// Quit when all windows are closed. // Quit when all windows are closed.
app.on('window-all-closed', function () { app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar // On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q // to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') { if (process.platform !== 'darwin') {
app.quit() app.quit()
} }
}) })
app.on('activate', function () { app.on('activate', function () {
// On macOS it is common to re-create a window in the app when the // On macOS it is common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open. // dock icon is clicked and there are no other windows open.
if (mainWindow === null) { if (mainWindow === null) {
createWindow() createWindow()
} }
}) })
// In this file you can include the rest of your app's specific main process // In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here. // code. You can also put them in separate files and require them here.

View File

@@ -1,48 +1,48 @@
const { BrowserWindow } = require('electron').remote const { BrowserWindow } = require('electron').remote
const shell = require('electron').shell const shell = require('electron').shell
const listenToWindowBtn = document.getElementById('listen-to-window') const listenToWindowBtn = document.getElementById('listen-to-window')
const focusModalBtn = document.getElementById('focus-on-modal-window') const focusModalBtn = document.getElementById('focus-on-modal-window')
const links = document.querySelectorAll('a[href]') const links = document.querySelectorAll('a[href]')
let win let win
listenToWindowBtn.addEventListener('click', () => { listenToWindowBtn.addEventListener('click', () => {
const modalPath = 'https://electronjs.org' const modalPath = 'https://electronjs.org'
win = new BrowserWindow({ width: 600, height: 400 }) win = new BrowserWindow({ width: 600, height: 400 })
const hideFocusBtn = () => { const hideFocusBtn = () => {
focusModalBtn.classList.add('disappear') focusModalBtn.classList.add('disappear')
focusModalBtn.classList.remove('smooth-appear') focusModalBtn.classList.remove('smooth-appear')
focusModalBtn.removeEventListener('click', clickHandler) focusModalBtn.removeEventListener('click', clickHandler)
} }
const showFocusBtn = (btn) => { const showFocusBtn = (btn) => {
if (!win) return if (!win) return
focusModalBtn.classList.add('smooth-appear') focusModalBtn.classList.add('smooth-appear')
focusModalBtn.classList.remove('disappear') focusModalBtn.classList.remove('disappear')
focusModalBtn.addEventListener('click', clickHandler) focusModalBtn.addEventListener('click', clickHandler)
} }
win.on('focus', hideFocusBtn) win.on('focus', hideFocusBtn)
win.on('blur', showFocusBtn) win.on('blur', showFocusBtn)
win.on('close', () => { win.on('close', () => {
hideFocusBtn() hideFocusBtn()
win = null win = null
}) })
win.loadURL(modalPath) win.loadURL(modalPath)
win.show() win.show()
const clickHandler = () => { win.focus() } const clickHandler = () => { win.focus() }
}) })
Array.prototype.forEach.call(links, (link) => { Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href') const url = link.getAttribute('href')
if (url.indexOf('http') === 0) { if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => { link.addEventListener('click', (e) => {
e.preventDefault() e.preventDefault()
shell.openExternal(url) shell.openExternal(url)
}) })
} }
}) })

View File

@@ -28,9 +28,11 @@ Object.setPrototypeOf(BrowserWindow.prototype, BaseWindow.prototype);
// Though this hack is only needed on macOS when the app is launched from // Though this hack is only needed on macOS when the app is launched from
// Finder, we still do it on all platforms in case of other bugs we don't // Finder, we still do it on all platforms in case of other bugs we don't
// know. // know.
this.webContents.once('load-url' as any, function (this: WebContents) { if (this.webContents._initiallyShown) {
this.focus(); this.webContents.once('load-url' as any, function (this: WebContents) {
}); this.focus();
});
}
// Redirect focus/blur event to app instance too. // Redirect focus/blur event to app instance too.
this.on('blur', (event: Event) => { this.on('blur', (event: Event) => {

View File

@@ -1,6 +1,6 @@
{ {
"name": "electron", "name": "electron",
"version": "11.0.0-nightly.20200826", "version": "11.0.0-beta.5",
"repository": "https://github.com/electron/electron", "repository": "https://github.com/electron/electron",
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS", "description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": { "devDependencies": {

View File

@@ -1,10 +1,10 @@
param([string]$gomaDir=$PWD) param([string]$gomaDir=$PWD)
$cmdPath = Join-Path -Path $gomaDir -ChildPath "goma_ctl.py" $cmdPath = Join-Path -Path $gomaDir -ChildPath "goma_ctl.py"
Start-Process -FilePath cmd -ArgumentList "/C", "python", "$cmdPath", "ensure_start" Start-Process -FilePath cmd -ArgumentList "/C", "python", "$cmdPath", "ensure_start"
$timedOut = $false; $waitTime = 0; $waitIncrement = 5; $timeout=120; $timedOut = $false; $waitTime = 0; $waitIncrement = 5; $timeout=120;
Do { sleep $waitIncrement; $timedOut = (($waitTime+=$waitIncrement) -gt $timeout); iex "$gomaDir\gomacc.exe port 2" > $null; } Until(($LASTEXITCODE -eq 0) -or $timedOut) Do { sleep $waitIncrement; $timedOut = (($waitTime+=$waitIncrement) -gt $timeout); iex "$gomaDir\gomacc.exe port 2" > $null; } Until(($LASTEXITCODE -eq 0) -or $timedOut)
if ($timedOut) { if ($timedOut) {
write-error 'Timed out waiting for goma to start'; exit 1; write-error 'Timed out waiting for goma to start'; exit 1;
} else { } else {
Write-Output "Successfully started goma!" Write-Output "Successfully started goma!"
} }

View File

@@ -744,9 +744,10 @@ void BaseWindow::AddBrowserView(v8::Local<v8::Value> value) {
gin::ConvertFromV8(isolate(), value, &browser_view)) { gin::ConvertFromV8(isolate(), value, &browser_view)) {
auto get_that_view = browser_views_.find(browser_view->ID()); auto get_that_view = browser_views_.find(browser_view->ID());
if (get_that_view == browser_views_.end()) { if (get_that_view == browser_views_.end()) {
window_->AddBrowserView(browser_view->view()); if (browser_view->web_contents()) {
if (browser_view->web_contents()) window_->AddBrowserView(browser_view->view());
browser_view->web_contents()->SetOwnerWindow(window_.get()); browser_view->web_contents()->SetOwnerWindow(window_.get());
}
browser_views_[browser_view->ID()].Reset(isolate(), value); browser_views_[browser_view->ID()].Reset(isolate(), value);
} }
} }
@@ -758,9 +759,10 @@ void BaseWindow::RemoveBrowserView(v8::Local<v8::Value> value) {
gin::ConvertFromV8(isolate(), value, &browser_view)) { gin::ConvertFromV8(isolate(), value, &browser_view)) {
auto get_that_view = browser_views_.find(browser_view->ID()); auto get_that_view = browser_views_.find(browser_view->ID());
if (get_that_view != browser_views_.end()) { if (get_that_view != browser_views_.end()) {
window_->RemoveBrowserView(browser_view->view()); if (browser_view->web_contents()) {
if (browser_view->web_contents()) window_->RemoveBrowserView(browser_view->view());
browser_view->web_contents()->SetOwnerWindow(nullptr); browser_view->web_contents()->SetOwnerWindow(nullptr);
}
(*get_that_view).second.Reset(isolate(), value); (*get_that_view).second.Reset(isolate(), value);
browser_views_.erase(get_that_view); browser_views_.erase(get_that_view);
} }
@@ -1055,9 +1057,10 @@ void BaseWindow::ResetBrowserViews() {
v8::Local<v8::Value>::New(isolate(), item.second), v8::Local<v8::Value>::New(isolate(), item.second),
&browser_view) && &browser_view) &&
!browser_view.IsEmpty()) { !browser_view.IsEmpty()) {
window_->RemoveBrowserView(browser_view->view()); if (browser_view->web_contents()) {
if (browser_view->web_contents())
browser_view->web_contents()->SetOwnerWindow(nullptr); browser_view->web_contents()->SetOwnerWindow(nullptr);
window_->RemoveBrowserView(browser_view->view());
}
} }
item.second.Reset(); item.second.Reset();

View File

@@ -86,18 +86,22 @@ const std::map<std::string, std::string>& GetGlobalCrashKeys() {
return GetGlobalCrashKeysMutable(); return GetGlobalCrashKeysMutable();
} }
base::FilePath GetClientIdPath() { bool GetClientIdPath(base::FilePath* path) {
base::FilePath path; if (base::PathService::Get(electron::DIR_CRASH_DUMPS, path)) {
base::PathService::Get(electron::DIR_CRASH_DUMPS, &path); *path = path->Append("client_id");
return path.Append("client_id"); return true;
}
return false;
} }
std::string ReadClientId() { std::string ReadClientId() {
base::ThreadRestrictions::ScopedAllowIO allow_io; base::ThreadRestrictions::ScopedAllowIO allow_io;
std::string client_id; std::string client_id;
// "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".length == 36 // "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".length == 36
if (!base::ReadFileToStringWithMaxSize(GetClientIdPath(), &client_id, 36) || base::FilePath client_id_path;
client_id.size() != 36) if (GetClientIdPath(&client_id_path) &&
(!base::ReadFileToStringWithMaxSize(client_id_path, &client_id, 36) ||
client_id.size() != 36))
return std::string(); return std::string();
return client_id; return client_id;
} }
@@ -105,7 +109,9 @@ std::string ReadClientId() {
void WriteClientId(const std::string& client_id) { void WriteClientId(const std::string& client_id) {
DCHECK_EQ(client_id.size(), 36u); DCHECK_EQ(client_id.size(), 36u);
base::ThreadRestrictions::ScopedAllowIO allow_io; base::ThreadRestrictions::ScopedAllowIO allow_io;
base::WriteFile(GetClientIdPath(), client_id); base::FilePath client_id_path;
if (GetClientIdPath(&client_id_path))
base::WriteFile(client_id_path, client_id);
} }
std::string GetClientId() { std::string GetClientId() {

View File

@@ -8,7 +8,6 @@
#include <wtsapi32.h> #include <wtsapi32.h>
#include "base/win/windows_types.h" #include "base/win/windows_types.h"
#include "base/win/windows_version.h"
#include "base/win/wrapped_window_proc.h" #include "base/win/wrapped_window_proc.h"
#include "ui/base/win/shell.h" #include "ui/base/win/shell.h"
#include "ui/gfx/win/hwnd_util.h" #include "ui/gfx/win/hwnd_util.h"
@@ -44,7 +43,12 @@ void PowerMonitor::InitPlatformSpecificMonitors() {
// For Windows 8 and later, a new "connected standy" mode has been added and // For Windows 8 and later, a new "connected standy" mode has been added and
// we must explicitly register for its notifications. // we must explicitly register for its notifications.
if (base::win::GetVersion() >= base::win::Version::WIN8) { auto RegisterSuspendResumeNotification =
reinterpret_cast<decltype(&::RegisterSuspendResumeNotification)>(
GetProcAddress(GetModuleHandle(L"user32.dll"),
"RegisterSuspendResumeNotification"));
if (RegisterSuspendResumeNotification) {
RegisterSuspendResumeNotification(static_cast<HANDLE>(window_), RegisterSuspendResumeNotification(static_cast<HANDLE>(window_),
DEVICE_NOTIFY_WINDOW_HANDLE); DEVICE_NOTIFY_WINDOW_HANDLE);
} }

View File

@@ -474,8 +474,8 @@ WebContents::WebContents(v8::Isolate* isolate,
// BrowserViews are not attached to a window initially so they should start // BrowserViews are not attached to a window initially so they should start
// off as hidden. This is also important for compositor recycling. See: // off as hidden. This is also important for compositor recycling. See:
// https://github.com/electron/electron/pull/21372 // https://github.com/electron/electron/pull/21372
bool initially_shown = type_ != Type::BROWSER_VIEW; initially_shown_ = type_ != Type::BROWSER_VIEW;
options.Get(options::kShow, &initially_shown); options.Get(options::kShow, &initially_shown_);
// Obtain the session. // Obtain the session.
std::string partition; std::string partition;
@@ -531,7 +531,7 @@ WebContents::WebContents(v8::Isolate* isolate,
#endif #endif
} else { } else {
content::WebContents::CreateParams params(session->browser_context()); content::WebContents::CreateParams params(session->browser_context());
params.initially_hidden = !initially_shown; params.initially_hidden = !initially_shown_;
web_contents = content::WebContents::Create(params); web_contents = content::WebContents::Create(params);
} }
@@ -2731,6 +2731,10 @@ v8::Local<v8::Value> WebContents::Debugger(v8::Isolate* isolate) {
return v8::Local<v8::Value>::New(isolate, debugger_); return v8::Local<v8::Value>::New(isolate, debugger_);
} }
bool WebContents::WasInitiallyShown() {
return initially_shown_;
}
void WebContents::GrantOriginAccess(const GURL& url) { void WebContents::GrantOriginAccess(const GURL& url) {
content::ChildProcessSecurityPolicy::GetInstance()->GrantCommitOrigin( content::ChildProcessSecurityPolicy::GetInstance()->GrantCommitOrigin(
web_contents()->GetMainFrame()->GetProcess()->GetID(), web_contents()->GetMainFrame()->GetProcess()->GetID(),
@@ -2924,6 +2928,7 @@ v8::Local<v8::ObjectTemplate> WebContents::FillObjectTemplate(
.SetProperty("hostWebContents", &WebContents::HostWebContents) .SetProperty("hostWebContents", &WebContents::HostWebContents)
.SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents) .SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents)
.SetProperty("debugger", &WebContents::Debugger) .SetProperty("debugger", &WebContents::Debugger)
.SetProperty("_initiallyShown", &WebContents::WasInitiallyShown)
.Build(); .Build();
} }

View File

@@ -393,6 +393,7 @@ class WebContents : public gin::Wrappable<WebContents>,
content::WebContents* HostWebContents() const; content::WebContents* HostWebContents() const;
v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate); v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
v8::Local<v8::Value> Debugger(v8::Isolate* isolate); v8::Local<v8::Value> Debugger(v8::Isolate* isolate);
bool WasInitiallyShown();
WebContentsZoomController* GetZoomController() { return zoom_controller_; } WebContentsZoomController* GetZoomController() { return zoom_controller_; }
@@ -683,6 +684,8 @@ class WebContents : public gin::Wrappable<WebContents>,
// Observers of this WebContents. // Observers of this WebContents.
base::ObserverList<ExtendedWebContentsObserver> observers_; base::ObserverList<ExtendedWebContentsObserver> observers_;
bool initially_shown_ = true;
// The ID of the process of the currently committed RenderViewHost. // The ID of the process of the currently committed RenderViewHost.
// -1 means no speculative RVH has been committed yet. // -1 means no speculative RVH has been committed yet.
int currently_committed_process_id_ = -1; int currently_committed_process_id_ = -1;

View File

@@ -355,6 +355,7 @@ class Browser : public WindowListObserver {
#if defined(OS_MAC) #if defined(OS_MAC)
std::unique_ptr<ui::ScopedPasswordInputEnabler> password_input_enabler_; std::unique_ptr<ui::ScopedPasswordInputEnabler> password_input_enabler_;
base::Time last_dock_show_;
#endif #endif
#if defined(OS_LINUX) || defined(OS_WIN) #if defined(OS_LINUX) || defined(OS_WIN)

View File

@@ -383,6 +383,20 @@ std::string Browser::DockGetBadgeText() {
} }
void Browser::DockHide() { void Browser::DockHide() {
// Transforming application state from UIElement to Foreground is an
// asyncronous operation, and unfortunately there is currently no way to know
// when it is finished.
// So if we call DockHide => DockShow => DockHide => DockShow in a very short
// time, we would triger a bug of macOS that, there would be multiple dock
// icons of the app left in system.
// To work around this, we make sure DockHide does nothing if it is called
// immediately after DockShow. After some experiments, 1 second seems to be
// a proper interval.
if (!last_dock_show_.is_null() &&
base::Time::Now() - last_dock_show_ < base::TimeDelta::FromSeconds(1)) {
return;
}
for (auto* const& window : WindowList::GetWindows()) for (auto* const& window : WindowList::GetWindows())
[window->GetNativeWindow().GetNativeNSWindow() setCanHide:NO]; [window->GetNativeWindow().GetNativeNSWindow() setCanHide:NO];
@@ -398,6 +412,7 @@ bool Browser::DockIsVisible() {
} }
v8::Local<v8::Promise> Browser::DockShow(v8::Isolate* isolate) { v8::Local<v8::Promise> Browser::DockShow(v8::Isolate* isolate) {
last_dock_show_ = base::Time::Now();
gin_helper::Promise<void> promise(isolate); gin_helper::Promise<void> promise(isolate);
v8::Local<v8::Promise> handle = promise.GetHandle(); v8::Local<v8::Promise> handle = promise.GetHandle();

View File

@@ -1,65 +1,65 @@
// Copyright (c) 2019 GitHub, Inc. // Copyright (c) 2019 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be // Use of this source code is governed by the MIT license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "shell/browser/electron_autofill_driver.h" #include "shell/browser/electron_autofill_driver.h"
#include <memory> #include <memory>
#include <utility> #include <utility>
#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/render_widget_host_view.h"
#include "shell/browser/api/electron_api_web_contents.h" #include "shell/browser/api/electron_api_web_contents.h"
#include "shell/browser/javascript_environment.h" #include "shell/browser/javascript_environment.h"
#include "shell/browser/native_window.h" #include "shell/browser/native_window.h"
namespace electron { namespace electron {
AutofillDriver::AutofillDriver( AutofillDriver::AutofillDriver(
content::RenderFrameHost* render_frame_host, content::RenderFrameHost* render_frame_host,
mojom::ElectronAutofillDriverAssociatedRequest request) mojom::ElectronAutofillDriverAssociatedRequest request)
: render_frame_host_(render_frame_host), binding_(this) { : render_frame_host_(render_frame_host), binding_(this) {
autofill_popup_ = std::make_unique<AutofillPopup>(); autofill_popup_ = std::make_unique<AutofillPopup>();
binding_.Bind(std::move(request)); binding_.Bind(std::move(request));
} }
AutofillDriver::~AutofillDriver() = default; AutofillDriver::~AutofillDriver() = default;
void AutofillDriver::ShowAutofillPopup( void AutofillDriver::ShowAutofillPopup(
const gfx::RectF& bounds, const gfx::RectF& bounds,
const std::vector<base::string16>& values, const std::vector<base::string16>& values,
const std::vector<base::string16>& labels) { const std::vector<base::string16>& labels) {
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
v8::HandleScope scope(isolate); v8::HandleScope scope(isolate);
auto* web_contents = api::WebContents::From( auto* web_contents = api::WebContents::From(
content::WebContents::FromRenderFrameHost(render_frame_host_)); content::WebContents::FromRenderFrameHost(render_frame_host_));
if (!web_contents || !web_contents->owner_window()) if (!web_contents || !web_contents->owner_window())
return; return;
auto* embedder = web_contents->embedder(); auto* embedder = web_contents->embedder();
bool osr = bool osr =
web_contents->IsOffScreen() || (embedder && embedder->IsOffScreen()); web_contents->IsOffScreen() || (embedder && embedder->IsOffScreen());
gfx::RectF popup_bounds(bounds); gfx::RectF popup_bounds(bounds);
content::RenderFrameHost* embedder_frame_host = nullptr; content::RenderFrameHost* embedder_frame_host = nullptr;
if (embedder) { if (embedder) {
auto* embedder_view = embedder->web_contents()->GetMainFrame()->GetView(); auto* embedder_view = embedder->web_contents()->GetMainFrame()->GetView();
auto* view = web_contents->web_contents()->GetMainFrame()->GetView(); auto* view = web_contents->web_contents()->GetMainFrame()->GetView();
auto offset = view->GetViewBounds().origin() - auto offset = view->GetViewBounds().origin() -
embedder_view->GetViewBounds().origin(); embedder_view->GetViewBounds().origin();
popup_bounds.Offset(offset); popup_bounds.Offset(offset);
embedder_frame_host = embedder->web_contents()->GetMainFrame(); embedder_frame_host = embedder->web_contents()->GetMainFrame();
} }
autofill_popup_->CreateView(render_frame_host_, embedder_frame_host, osr, autofill_popup_->CreateView(render_frame_host_, embedder_frame_host, osr,
web_contents->owner_window()->content_view(), web_contents->owner_window()->content_view(),
popup_bounds); popup_bounds);
autofill_popup_->SetItems(values, labels); autofill_popup_->SetItems(values, labels);
} }
void AutofillDriver::HideAutofillPopup() { void AutofillDriver::HideAutofillPopup() {
if (autofill_popup_) if (autofill_popup_)
autofill_popup_->Hide(); autofill_popup_->Hide();
} }
} // namespace electron } // namespace electron

View File

@@ -1,44 +1,44 @@
// Copyright (c) 2019 GitHub, Inc. // Copyright (c) 2019 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be // Use of this source code is governed by the MIT license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef SHELL_BROWSER_ELECTRON_AUTOFILL_DRIVER_H_ #ifndef SHELL_BROWSER_ELECTRON_AUTOFILL_DRIVER_H_
#define SHELL_BROWSER_ELECTRON_AUTOFILL_DRIVER_H_ #define SHELL_BROWSER_ELECTRON_AUTOFILL_DRIVER_H_
#include <memory> #include <memory>
#include <vector> #include <vector>
#if defined(TOOLKIT_VIEWS) #if defined(TOOLKIT_VIEWS)
#include "shell/browser/ui/autofill_popup.h" #include "shell/browser/ui/autofill_popup.h"
#endif #endif
#include "mojo/public/cpp/bindings/associated_binding.h" #include "mojo/public/cpp/bindings/associated_binding.h"
#include "shell/common/api/api.mojom.h" #include "shell/common/api/api.mojom.h"
namespace electron { namespace electron {
class AutofillDriver : public mojom::ElectronAutofillDriver { class AutofillDriver : public mojom::ElectronAutofillDriver {
public: public:
AutofillDriver(content::RenderFrameHost* render_frame_host, AutofillDriver(content::RenderFrameHost* render_frame_host,
mojom::ElectronAutofillDriverAssociatedRequest request); mojom::ElectronAutofillDriverAssociatedRequest request);
~AutofillDriver() override; ~AutofillDriver() override;
void ShowAutofillPopup(const gfx::RectF& bounds, void ShowAutofillPopup(const gfx::RectF& bounds,
const std::vector<base::string16>& values, const std::vector<base::string16>& values,
const std::vector<base::string16>& labels) override; const std::vector<base::string16>& labels) override;
void HideAutofillPopup() override; void HideAutofillPopup() override;
private: private:
content::RenderFrameHost* const render_frame_host_; content::RenderFrameHost* const render_frame_host_;
#if defined(TOOLKIT_VIEWS) #if defined(TOOLKIT_VIEWS)
std::unique_ptr<AutofillPopup> autofill_popup_; std::unique_ptr<AutofillPopup> autofill_popup_;
#endif #endif
mojo::AssociatedBinding<mojom::ElectronAutofillDriver> binding_; mojo::AssociatedBinding<mojom::ElectronAutofillDriver> binding_;
}; };
} // namespace electron } // namespace electron
#endif // SHELL_BROWSER_ELECTRON_AUTOFILL_DRIVER_H_ #endif // SHELL_BROWSER_ELECTRON_AUTOFILL_DRIVER_H_

View File

@@ -1,111 +1,111 @@
// Copyright (c) 2019 GitHub, Inc. // Copyright (c) 2019 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be // Use of this source code is governed by the MIT license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "shell/browser/electron_autofill_driver_factory.h" #include "shell/browser/electron_autofill_driver_factory.h"
#include <memory> #include <memory>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h" #include "base/callback.h"
#include "content/public/browser/navigation_handle.h" #include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "shell/browser/electron_autofill_driver.h" #include "shell/browser/electron_autofill_driver.h"
namespace electron { namespace electron {
namespace { namespace {
std::unique_ptr<AutofillDriver> CreateDriver( std::unique_ptr<AutofillDriver> CreateDriver(
content::RenderFrameHost* render_frame_host, content::RenderFrameHost* render_frame_host,
mojom::ElectronAutofillDriverAssociatedRequest request) { mojom::ElectronAutofillDriverAssociatedRequest request) {
return std::make_unique<AutofillDriver>(render_frame_host, return std::make_unique<AutofillDriver>(render_frame_host,
std::move(request)); std::move(request));
} }
} // namespace } // namespace
AutofillDriverFactory::~AutofillDriverFactory() = default; AutofillDriverFactory::~AutofillDriverFactory() = default;
// static // static
void AutofillDriverFactory::BindAutofillDriver( void AutofillDriverFactory::BindAutofillDriver(
mojom::ElectronAutofillDriverAssociatedRequest request, mojom::ElectronAutofillDriverAssociatedRequest request,
content::RenderFrameHost* render_frame_host) { content::RenderFrameHost* render_frame_host) {
content::WebContents* web_contents = content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host); content::WebContents::FromRenderFrameHost(render_frame_host);
if (!web_contents) if (!web_contents)
return; return;
AutofillDriverFactory* factory = AutofillDriverFactory* factory =
AutofillDriverFactory::FromWebContents(web_contents); AutofillDriverFactory::FromWebContents(web_contents);
if (!factory) if (!factory)
return; return;
AutofillDriver* driver = factory->DriverForFrame(render_frame_host); AutofillDriver* driver = factory->DriverForFrame(render_frame_host);
if (!driver) if (!driver)
factory->AddDriverForFrame( factory->AddDriverForFrame(
render_frame_host, render_frame_host,
base::BindOnce(CreateDriver, render_frame_host, std::move(request))); base::BindOnce(CreateDriver, render_frame_host, std::move(request)));
} }
AutofillDriverFactory::AutofillDriverFactory(content::WebContents* web_contents) AutofillDriverFactory::AutofillDriverFactory(content::WebContents* web_contents)
: content::WebContentsObserver(web_contents) { : content::WebContentsObserver(web_contents) {
const std::vector<content::RenderFrameHost*> frames = const std::vector<content::RenderFrameHost*> frames =
web_contents->GetAllFrames(); web_contents->GetAllFrames();
for (content::RenderFrameHost* frame : frames) { for (content::RenderFrameHost* frame : frames) {
if (frame->IsRenderFrameLive()) if (frame->IsRenderFrameLive())
RenderFrameCreated(frame); RenderFrameCreated(frame);
} }
} }
void AutofillDriverFactory::RenderFrameDeleted( void AutofillDriverFactory::RenderFrameDeleted(
content::RenderFrameHost* render_frame_host) { content::RenderFrameHost* render_frame_host) {
DeleteDriverForFrame(render_frame_host); DeleteDriverForFrame(render_frame_host);
} }
void AutofillDriverFactory::DidFinishNavigation( void AutofillDriverFactory::DidFinishNavigation(
content::NavigationHandle* navigation_handle) { content::NavigationHandle* navigation_handle) {
// For the purposes of this code, a navigation is not important if it has not // For the purposes of this code, a navigation is not important if it has not
// committed yet or if it's in a subframe. // committed yet or if it's in a subframe.
if (!navigation_handle->HasCommitted() || if (!navigation_handle->HasCommitted() ||
!navigation_handle->IsInMainFrame()) { !navigation_handle->IsInMainFrame()) {
return; return;
} }
CloseAllPopups(); CloseAllPopups();
} }
AutofillDriver* AutofillDriverFactory::DriverForFrame( AutofillDriver* AutofillDriverFactory::DriverForFrame(
content::RenderFrameHost* render_frame_host) { content::RenderFrameHost* render_frame_host) {
auto mapping = driver_map_.find(render_frame_host); auto mapping = driver_map_.find(render_frame_host);
return mapping == driver_map_.end() ? nullptr : mapping->second.get(); return mapping == driver_map_.end() ? nullptr : mapping->second.get();
} }
void AutofillDriverFactory::AddDriverForFrame( void AutofillDriverFactory::AddDriverForFrame(
content::RenderFrameHost* render_frame_host, content::RenderFrameHost* render_frame_host,
CreationCallback factory_method) { CreationCallback factory_method) {
auto insertion_result = auto insertion_result =
driver_map_.insert(std::make_pair(render_frame_host, nullptr)); driver_map_.insert(std::make_pair(render_frame_host, nullptr));
// This can be called twice for the key representing the main frame. // This can be called twice for the key representing the main frame.
if (insertion_result.second) { if (insertion_result.second) {
insertion_result.first->second = std::move(factory_method).Run(); insertion_result.first->second = std::move(factory_method).Run();
} }
} }
void AutofillDriverFactory::DeleteDriverForFrame( void AutofillDriverFactory::DeleteDriverForFrame(
content::RenderFrameHost* render_frame_host) { content::RenderFrameHost* render_frame_host) {
driver_map_.erase(render_frame_host); driver_map_.erase(render_frame_host);
} }
void AutofillDriverFactory::CloseAllPopups() { void AutofillDriverFactory::CloseAllPopups() {
for (auto& it : driver_map_) { for (auto& it : driver_map_) {
it.second->HideAutofillPopup(); it.second->HideAutofillPopup();
} }
} }
WEB_CONTENTS_USER_DATA_KEY_IMPL(AutofillDriverFactory) WEB_CONTENTS_USER_DATA_KEY_IMPL(AutofillDriverFactory)
} // namespace electron } // namespace electron

View File

@@ -1,57 +1,57 @@
// Copyright (c) 2019 GitHub, Inc. // Copyright (c) 2019 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be // Use of this source code is governed by the MIT license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef SHELL_BROWSER_ELECTRON_AUTOFILL_DRIVER_FACTORY_H_ #ifndef SHELL_BROWSER_ELECTRON_AUTOFILL_DRIVER_FACTORY_H_
#define SHELL_BROWSER_ELECTRON_AUTOFILL_DRIVER_FACTORY_H_ #define SHELL_BROWSER_ELECTRON_AUTOFILL_DRIVER_FACTORY_H_
#include <memory> #include <memory>
#include <unordered_map> #include <unordered_map>
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h" #include "content/public/browser/web_contents_user_data.h"
#include "shell/common/api/api.mojom.h" #include "shell/common/api/api.mojom.h"
namespace electron { namespace electron {
class AutofillDriver; class AutofillDriver;
class AutofillDriverFactory class AutofillDriverFactory
: public content::WebContentsObserver, : public content::WebContentsObserver,
public content::WebContentsUserData<AutofillDriverFactory> { public content::WebContentsUserData<AutofillDriverFactory> {
public: public:
typedef base::OnceCallback<std::unique_ptr<AutofillDriver>()> typedef base::OnceCallback<std::unique_ptr<AutofillDriver>()>
CreationCallback; CreationCallback;
~AutofillDriverFactory() override; ~AutofillDriverFactory() override;
static void BindAutofillDriver( static void BindAutofillDriver(
mojom::ElectronAutofillDriverAssociatedRequest request, mojom::ElectronAutofillDriverAssociatedRequest request,
content::RenderFrameHost* render_frame_host); content::RenderFrameHost* render_frame_host);
// content::WebContentsObserver: // content::WebContentsObserver:
void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override; void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
void DidFinishNavigation( void DidFinishNavigation(
content::NavigationHandle* navigation_handle) override; content::NavigationHandle* navigation_handle) override;
AutofillDriver* DriverForFrame(content::RenderFrameHost* render_frame_host); AutofillDriver* DriverForFrame(content::RenderFrameHost* render_frame_host);
void AddDriverForFrame(content::RenderFrameHost* render_frame_host, void AddDriverForFrame(content::RenderFrameHost* render_frame_host,
CreationCallback factory_method); CreationCallback factory_method);
void DeleteDriverForFrame(content::RenderFrameHost* render_frame_host); void DeleteDriverForFrame(content::RenderFrameHost* render_frame_host);
void CloseAllPopups(); void CloseAllPopups();
WEB_CONTENTS_USER_DATA_KEY_DECL(); WEB_CONTENTS_USER_DATA_KEY_DECL();
private: private:
explicit AutofillDriverFactory(content::WebContents* web_contents); explicit AutofillDriverFactory(content::WebContents* web_contents);
friend class content::WebContentsUserData<AutofillDriverFactory>; friend class content::WebContentsUserData<AutofillDriverFactory>;
std::unordered_map<content::RenderFrameHost*, std::unique_ptr<AutofillDriver>> std::unordered_map<content::RenderFrameHost*, std::unique_ptr<AutofillDriver>>
driver_map_; driver_map_;
}; };
} // namespace electron } // namespace electron
#endif // SHELL_BROWSER_ELECTRON_AUTOFILL_DRIVER_FACTORY_H_ #endif // SHELL_BROWSER_ELECTRON_AUTOFILL_DRIVER_FACTORY_H_

View File

@@ -1506,15 +1506,10 @@ void ElectronBrowserClient::OverrideURLLoaderFactoryParams(
const url::Origin& origin, const url::Origin& origin,
bool is_for_isolated_world, bool is_for_isolated_world,
network::mojom::URLLoaderFactoryParams* factory_params) { network::mojom::URLLoaderFactoryParams* factory_params) {
for (const auto& iter : process_preferences_) { // Bypass CORB when web security is disabled.
if (iter.second.browser_context != browser_context) auto it = process_preferences_.find(factory_params->process_id);
continue; if (it != process_preferences_.end() && !it->second.web_security) {
factory_params->is_corb_enabled = false;
if (!iter.second.web_security) {
// bypass CORB
factory_params->process_id = iter.first;
factory_params->is_corb_enabled = false;
}
} }
extensions::URLLoaderFactoryManager::OverrideURLLoaderFactoryParams( extensions::URLLoaderFactoryManager::OverrideURLLoaderFactoryParams(

View File

@@ -1,24 +1,24 @@
// Copyright (c) 2020 Samuel Maddock <sam@samuelmaddock.com>. // Copyright (c) 2020 Samuel Maddock <sam@samuelmaddock.com>.
// Use of this source code is governed by the MIT license that can be // Use of this source code is governed by the MIT license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "shell/browser/extensions/api/i18n/i18n_api.h" #include "shell/browser/extensions/api/i18n/i18n_api.h"
#include <string> #include <string>
#include <vector> #include <vector>
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "shell/common/extensions/api/i18n.h" #include "shell/common/extensions/api/i18n.h"
namespace GetAcceptLanguages = extensions::api::i18n::GetAcceptLanguages; namespace GetAcceptLanguages = extensions::api::i18n::GetAcceptLanguages;
namespace extensions { namespace extensions {
ExtensionFunction::ResponseAction I18nGetAcceptLanguagesFunction::Run() { ExtensionFunction::ResponseAction I18nGetAcceptLanguagesFunction::Run() {
auto locale = g_browser_process->GetApplicationLocale(); auto locale = g_browser_process->GetApplicationLocale();
std::vector<std::string> accept_languages = {locale}; std::vector<std::string> accept_languages = {locale};
return RespondNow( return RespondNow(
ArgumentList(GetAcceptLanguages::Results::Create(accept_languages))); ArgumentList(GetAcceptLanguages::Results::Create(accept_languages)));
} }
} // namespace extensions } // namespace extensions

View File

@@ -1,20 +1,20 @@
// Copyright (c) 2020 Samuel Maddock <sam@samuelmaddock.com>. // Copyright (c) 2020 Samuel Maddock <sam@samuelmaddock.com>.
// Use of this source code is governed by the MIT license that can be // Use of this source code is governed by the MIT license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef SHELL_BROWSER_EXTENSIONS_API_I18N_I18N_API_H_ #ifndef SHELL_BROWSER_EXTENSIONS_API_I18N_I18N_API_H_
#define SHELL_BROWSER_EXTENSIONS_API_I18N_I18N_API_H_ #define SHELL_BROWSER_EXTENSIONS_API_I18N_I18N_API_H_
#include "extensions/browser/extension_function.h" #include "extensions/browser/extension_function.h"
namespace extensions { namespace extensions {
class I18nGetAcceptLanguagesFunction : public ExtensionFunction { class I18nGetAcceptLanguagesFunction : public ExtensionFunction {
~I18nGetAcceptLanguagesFunction() override {} ~I18nGetAcceptLanguagesFunction() override {}
ResponseAction Run() override; ResponseAction Run() override;
DECLARE_EXTENSION_FUNCTION("i18n.getAcceptLanguages", I18N_GETACCEPTLANGUAGES) DECLARE_EXTENSION_FUNCTION("i18n.getAcceptLanguages", I18N_GETACCEPTLANGUAGES)
}; };
} // namespace extensions } // namespace extensions
#endif // SHELL_BROWSER_EXTENSIONS_API_I18N_I18N_API_H_ #endif // SHELL_BROWSER_EXTENSIONS_API_I18N_I18N_API_H_

View File

@@ -50,8 +50,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 11,0,0,20200826 FILEVERSION 11,0,0,5
PRODUCTVERSION 11,0,0,20200826 PRODUCTVERSION 11,0,0,5
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L

View File

@@ -90,7 +90,8 @@ void SetAllowedFileTypes(NSSavePanel* dialog, const Filters& filters) {
// Create array to keep file types and their name. // Create array to keep file types and their name.
for (const Filter& filter : filters) { for (const Filter& filter : filters) {
NSMutableSet* file_type_set = [NSMutableSet set]; NSMutableOrderedSet* file_type_set =
[NSMutableOrderedSet orderedSetWithCapacity:filters.size()];
[filter_names addObject:@(filter.first.c_str())]; [filter_names addObject:@(filter.first.c_str())];
for (std::string ext : filter.second) { for (std::string ext : filter.second) {
// macOS is incapable of understanding multiple file extensions, // macOS is incapable of understanding multiple file extensions,
@@ -104,7 +105,7 @@ void SetAllowedFileTypes(NSSavePanel* dialog, const Filters& filters) {
[file_type_set addObject:@(ext.c_str())]; [file_type_set addObject:@(ext.c_str())];
} }
[file_types_list addObject:[file_type_set allObjects]]; [file_types_list addObject:[file_type_set array]];
} }
// Passing empty array to setAllowedFileTypes will cause exception. // Passing empty array to setAllowedFileTypes will cause exception.

View File

@@ -4,12 +4,31 @@
#include "shell/browser/ui/views/win_frame_view.h" #include "shell/browser/ui/views/win_frame_view.h"
#include "base/win/windows_version.h"
#include "shell/browser/native_window_views.h" #include "shell/browser/native_window_views.h"
#include "ui/display/win/screen_win.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
#include "ui/views/win/hwnd_util.h" #include "ui/views/win/hwnd_util.h"
namespace electron { namespace electron {
namespace {
gfx::Insets GetGlassInsets() {
int frame_height =
display::win::ScreenWin::GetSystemMetricsInDIP(SM_CYSIZEFRAME) +
display::win::ScreenWin::GetSystemMetricsInDIP(SM_CXPADDEDBORDER);
int frame_size =
base::win::GetVersion() < base::win::Version::WIN8
? display::win::ScreenWin::GetSystemMetricsInDIP(SM_CXSIZEFRAME)
: 0;
return gfx::Insets(frame_height, frame_size, frame_size, frame_size);
}
} // namespace
const char WinFrameView::kViewClassName[] = "WinFrameView"; const char WinFrameView::kViewClassName[] = "WinFrameView";
WinFrameView::WinFrameView() {} WinFrameView::WinFrameView() {}
@@ -23,6 +42,17 @@ gfx::Rect WinFrameView::GetWindowBoundsForClientBounds(
client_bounds); client_bounds);
} }
gfx::Rect WinFrameView::GetBoundsForClientView() const {
if (window_->IsMaximized() && !window_->has_frame()) {
gfx::Insets insets = GetGlassInsets();
gfx::Rect result(width(), height());
result.Inset(insets);
return result;
} else {
return bounds();
}
}
int WinFrameView::NonClientHitTest(const gfx::Point& point) { int WinFrameView::NonClientHitTest(const gfx::Point& point) {
if (window_->has_frame()) if (window_->has_frame())
return frame_->client_view()->NonClientHitTest(point); return frame_->client_view()->NonClientHitTest(point);

View File

@@ -16,6 +16,7 @@ class WinFrameView : public FramelessView {
~WinFrameView() override; ~WinFrameView() override;
// views::NonClientFrameView: // views::NonClientFrameView:
gfx::Rect GetBoundsForClientView() const override;
gfx::Rect GetWindowBoundsForClientBounds( gfx::Rect GetWindowBoundsForClientBounds(
const gfx::Rect& client_bounds) const override; const gfx::Rect& client_bounds) const override;
int NonClientHitTest(const gfx::Point& point) override; int NonClientHitTest(const gfx::Point& point) override;

View File

@@ -4,7 +4,12 @@
#include "shell/browser/ui/win/electron_desktop_window_tree_host_win.h" #include "shell/browser/ui/win/electron_desktop_window_tree_host_win.h"
#include "base/win/windows_version.h"
#include "shell/browser/ui/views/win_frame_view.h"
#include "ui/base/win/hwnd_metrics.h" #include "ui/base/win/hwnd_metrics.h"
#include "ui/base/win/shell.h"
#include "ui/display/win/screen_win.h"
#include "ui/views/win/hwnd_util.h"
namespace electron { namespace electron {
@@ -36,18 +41,49 @@ bool ElectronDesktopWindowTreeHostWin::HasNativeFrame() const {
// Since we never use chromium's titlebar implementation, we can just say // Since we never use chromium's titlebar implementation, we can just say
// that we use a native titlebar. This will disable the repaint locking when // that we use a native titlebar. This will disable the repaint locking when
// DWM composition is disabled. // DWM composition is disabled.
return true; return !ui::win::IsAeroGlassEnabled();
}
bool ElectronDesktopWindowTreeHostWin::GetDwmFrameInsetsInPixels(
gfx::Insets* insets) const {
if (IsMaximized() && !native_window_view_->has_frame()) {
HMONITOR monitor = ::MonitorFromWindow(
native_window_view_->GetAcceleratedWidget(), MONITOR_DEFAULTTONEAREST);
int frame_height = display::win::ScreenWin::GetSystemMetricsForMonitor(
monitor, SM_CYSIZEFRAME) +
display::win::ScreenWin::GetSystemMetricsForMonitor(
monitor, SM_CXPADDEDBORDER);
int frame_size = base::win::GetVersion() < base::win::Version::WIN8
? display::win::ScreenWin::GetSystemMetricsForMonitor(
monitor, SM_CXSIZEFRAME)
: 0;
insets->Set(frame_height, frame_size, frame_size, frame_size);
return true;
}
return false;
} }
bool ElectronDesktopWindowTreeHostWin::GetClientAreaInsets( bool ElectronDesktopWindowTreeHostWin::GetClientAreaInsets(
gfx::Insets* insets, gfx::Insets* insets,
HMONITOR monitor) const { HMONITOR monitor) const {
if (IsMaximized() && !native_window_view_->has_frame()) { if (IsMaximized() && !native_window_view_->has_frame()) {
// Windows automatically adds a standard width border to all sides when a if (base::win::GetVersion() < base::win::Version::WIN8) {
// window is maximized. // This tells Windows that most of the window is a client area, meaning
int frame_thickness = ui::GetFrameThickness(monitor) - 1; // Chrome will draw it. Windows still fills in the glass bits because of
*insets = gfx::Insets(frame_thickness, frame_thickness, frame_thickness, // the // DwmExtendFrameIntoClientArea call in |UpdateDWMFrame|.
frame_thickness); // Without this 1 pixel offset on the right and bottom:
// * windows paint in a more standard way, and
// * we get weird black bars at the top when maximized in multiple
// monitor configurations.
int border_thickness = 1;
insets->Set(0, 0, border_thickness, border_thickness);
} else {
const int frame_thickness = ui::GetFrameThickness(monitor);
// Reduce the Windows non-client border size because we extend the border
// into our client area in UpdateDWMFrame(). The top inset must be 0 or
// else Windows will draw a full native titlebar outside the client area.
insets->Set(0, frame_thickness, frame_thickness, frame_thickness);
}
return true; return true;
} }
return false; return false;

View File

@@ -27,6 +27,7 @@ class ElectronDesktopWindowTreeHostWin
LRESULT* result) override; LRESULT* result) override;
bool ShouldPaintAsActive() const override; bool ShouldPaintAsActive() const override;
bool HasNativeFrame() const override; bool HasNativeFrame() const override;
bool GetDwmFrameInsetsInPixels(gfx::Insets* insets) const override;
bool GetClientAreaInsets(gfx::Insets* insets, bool GetClientAreaInsets(gfx::Insets* insets,
HMONITOR monitor) const override; HMONITOR monitor) const override;

View File

@@ -387,10 +387,14 @@ bool MoveItemToTrash(const base::FilePath& path, bool delete_on_fail) {
if (!delete_sink) if (!delete_sink)
return false; return false;
BOOL pfAnyOperationsAborted;
// Processes the queued command DeleteItem. This will trigger // Processes the queued command DeleteItem. This will trigger
// the DeleteFileProgressSink to check for Recycle Bin. // the DeleteFileProgressSink to check for Recycle Bin.
return SUCCEEDED(pfo->DeleteItem(delete_item.Get(), delete_sink.Get())) && return SUCCEEDED(pfo->DeleteItem(delete_item.Get(), delete_sink.Get())) &&
SUCCEEDED(pfo->PerformOperations()); SUCCEEDED(pfo->PerformOperations()) &&
SUCCEEDED(pfo->GetAnyOperationsAborted(&pfAnyOperationsAborted)) &&
!pfAnyOperationsAborted;
} }
bool GetFolderPath(int key, base::FilePath* result) { bool GetFolderPath(int key, base::FilePath* result) {

View File

@@ -1437,6 +1437,16 @@ describe('app module', () => {
}); });
}); });
describe('dock.hide', () => {
it('should not throw', () => {
app.dock.hide();
expect(app.dock.isVisible()).to.equal(false);
});
});
// Note that dock.show tests should run after dock.hide tests, to work
// around a bug of macOS.
// See https://github.com/electron/electron/pull/25269 for more.
describe('dock.show', () => { describe('dock.show', () => {
it('should not throw', () => { it('should not throw', () => {
return app.dock.show().then(() => { return app.dock.show().then(() => {
@@ -1452,13 +1462,6 @@ describe('app module', () => {
await expect(app.dock.show()).to.eventually.be.fulfilled.equal(undefined); await expect(app.dock.show()).to.eventually.be.fulfilled.equal(undefined);
}); });
}); });
describe('dock.hide', () => {
it('should not throw', () => {
app.dock.hide();
expect(app.dock.isVisible()).to.equal(false);
});
});
}); });
describe('whenReady', () => { describe('whenReady', () => {

View File

@@ -245,7 +245,7 @@ ifdescribe(!isLinuxOnArm && !process.mas && !process.env.DISABLE_CRASH_REPORTER_
const crash = await waitForCrash(); const crash = await waitForCrash();
expect(crash.prod).to.equal('Electron'); expect(crash.prod).to.equal('Electron');
expect(crash._productName).to.equal('remote-control'); expect(crash._productName).to.equal('electron-test-remote-control');
expect(crash.process_type).to.equal('renderer'); expect(crash.process_type).to.equal('renderer');
expect(crash['electron.v8-fatal.location']).to.equal('v8::Context::New()'); expect(crash['electron.v8-fatal.location']).to.equal('v8::Context::New()');
expect(crash['electron.v8-fatal.message']).to.equal('Circular extension dependency'); expect(crash['electron.v8-fatal.message']).to.equal('Circular extension dependency');

View File

@@ -7,6 +7,8 @@ import * as fs from 'fs-extra';
import * as path from 'path'; import * as path from 'path';
import { AddressInfo } from 'net'; import { AddressInfo } from 'net';
import { expect } from 'chai'; import { expect } from 'chai';
import { ifit } from './spec-helpers';
import { execSync } from 'child_process';
describe('shell module', () => { describe('shell module', () => {
describe('shell.openExternal()', () => { describe('shell.openExternal()', () => {
@@ -76,5 +78,38 @@ describe('shell module', () => {
const result = shell.moveItemToTrash(filename); const result = shell.moveItemToTrash(filename);
expect(result).to.be.false(); expect(result).to.be.false();
}); });
ifit(process.platform === 'darwin')('returns false when file has immutable flag', async () => {
const dir = await fs.mkdtemp(path.resolve(app.getPath('temp'), 'electron-shell-spec-'));
const tempPath = path.join(dir, 'locked-file');
await fs.writeFile(tempPath, 'delete me if you can');
// https://ss64.com/osx/chflags.html
execSync(`chflags uchg ${tempPath}`);
expect(shell.moveItemToTrash(tempPath)).to.be.false();
expect(await fs.pathExists(tempPath)).to.be.true();
execSync(`chflags nouchg ${tempPath}`);
expect(shell.moveItemToTrash(tempPath)).to.be.true();
expect(await fs.pathExists(tempPath)).to.be.false();
});
ifit(process.platform === 'win32')('returns false when path is in use', async () => {
const tempPath = await fs.mkdtemp(path.resolve(app.getPath('temp'), 'electron-shell-spec-'));
const cwd = process.cwd();
try {
// A process working directory is automatically locked on Windows.
// This is a workaround to avoid pulling in fs-extras flock method.
process.chdir(tempPath);
expect(shell.moveItemToTrash(tempPath)).to.be.false();
expect(await fs.pathExists(tempPath)).to.be.true();
} finally {
process.chdir(cwd);
}
expect(shell.moveItemToTrash(tempPath)).to.be.true();
expect(await fs.pathExists(tempPath)).to.be.false();
});
}); });
}); });

View File

@@ -245,6 +245,14 @@ describe('web security', () => {
<script src="${serverUrl}"></script>`); <script src="${serverUrl}"></script>`);
await p; await p;
}); });
it('does not crash when multiple WebContent are created with web security disabled', () => {
const options = { webPreferences: { webSecurity: false } };
const w1 = new BrowserWindow(options);
w1.loadURL(serverUrl);
const w2 = new BrowserWindow(options);
w2.loadURL(serverUrl);
});
}); });
describe('command line switches', () => { describe('command line switches', () => {

View File

@@ -1,4 +1,4 @@
{ {
"name": "ipc-main-listeners", "name": "electron-test-ipc-main-listeners",
"main": "main.js" "main": "main.js"
} }

View File

@@ -1,4 +1,4 @@
{ {
"name": "net-log", "name": "electron-test-net-log",
"main": "main.js" "main": "main.js"
} }

View File

@@ -1,6 +1,6 @@
self.addEventListener('install', function (event) { self.addEventListener('install', function (event) {
console.log('log log'); console.log('log log');
console.info('info log'); console.info('info log');
console.warn('warn log'); console.warn('warn log');
console.error('error log'); console.error('error log');
}); });

View File

@@ -1,3 +1,3 @@
self.addEventListener('install', function (event) { self.addEventListener('install', function (event) {
console.log('Installed'); console.log('Installed');
}); });

View File

@@ -1,4 +1,4 @@
{ {
"name": "crash", "name": "electron-test-crash",
"main": "main.js" "main": "main.js"
} }

View File

@@ -1,4 +1,4 @@
{ {
"name": "remote-control", "name": "electron-test-remote-control",
"main": "main.js" "main": "main.js"
} }

View File

@@ -1,5 +1,5 @@
{ {
"name": "initial-app", "name": "electron-test-initial-app",
"version": "1.0.0", "version": "1.0.0",
"main": "./index.js" "main": "./index.js"
} }

View File

@@ -1,5 +1,5 @@
{ {
"name": "initial-app", "name": "electron-test-initial-app",
"version": "1.0.0", "version": "1.0.0",
"main": "./index.js" "main": "./index.js"
} }

View File

@@ -1,5 +1,5 @@
{ {
"name": "initial-app", "name": "electron-test-initial-app",
"version": "1.0.0", "version": "1.0.0",
"main": "./index.js" "main": "./index.js"
} }

View File

@@ -1,4 +1,4 @@
{ {
"name": "app-path", "name": "electron-test-app-path",
"main": "lib/index.js" "main": "lib/index.js"
} }

View File

@@ -1,4 +1,4 @@
{ {
"name": "command-line", "name": "electron-test-command-line",
"main": "main.js" "main": "main.js"
} }

View File

@@ -1,4 +1,4 @@
{ {
"name": "default-menu", "name": "electron-test-default-menu",
"main": "main.js" "main": "main.js"
} }

View File

@@ -1,5 +1,5 @@
{ {
"name": "locale-check", "name": "electron-test-locale-check",
"main": "main.js" "main": "main.js"
} }

View File

@@ -1,4 +1,4 @@
{ {
"name": "site-instance-overrides", "name": "electron-test-site-instance-overrides",
"main": "main.js" "main": "main.js"
} }

View File

@@ -1,4 +1,4 @@
{ {
"name": "window-all-closed", "name": "electron-test-window-all-closed",
"main": "main.js" "main": "main.js"
} }

View File

@@ -1,4 +1,4 @@
{ {
"name": "snapshot-items-available", "name": "electron-test-snapshot-items-available",
"main": "main.js" "main": "main.js"
} }

View File

@@ -56,6 +56,7 @@ declare namespace Electron {
getLastWebPreferences(): Electron.WebPreferences; getLastWebPreferences(): Electron.WebPreferences;
_getPreloadPaths(): string[]; _getPreloadPaths(): string[];
equal(other: WebContents): boolean; equal(other: WebContents): boolean;
_initiallyShown: boolean;
} }
interface WebPreferences { interface WebPreferences {