mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
20 Commits
v11.0.0-ni
...
v11.0.0-ni
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
462fa9d6ce | ||
|
|
cbb47570bd | ||
|
|
e18f508e66 | ||
|
|
6c4017ff45 | ||
|
|
5737fda154 | ||
|
|
8847517798 | ||
|
|
c9aa68e32c | ||
|
|
42f716bbc6 | ||
|
|
ef9addcb92 | ||
|
|
dcb56923cb | ||
|
|
eb6616e4e9 | ||
|
|
9bd0fc5348 | ||
|
|
66d65a6d35 | ||
|
|
4305707ca8 | ||
|
|
8d25847318 | ||
|
|
ad16e6c647 | ||
|
|
80a6adb597 | ||
|
|
7dd365784d | ||
|
|
e59370f541 | ||
|
|
6cfbee9f34 |
@@ -1 +1 @@
|
||||
11.0.0-nightly.20200708
|
||||
11.0.0-nightly.20200713
|
||||
@@ -1,2 +1,2 @@
|
||||
process.env.PRINT_WEBPACK_GRAPH = true
|
||||
require('./run-compiler')
|
||||
process.env.PRINT_WEBPACK_GRAPH = true;
|
||||
require('./run-compiler');
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path')
|
||||
const webpack = require('webpack')
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
|
||||
const configPath = process.argv[2]
|
||||
const outPath = path.resolve(process.argv[3])
|
||||
const config = require(configPath)
|
||||
const configPath = process.argv[2];
|
||||
const outPath = path.resolve(process.argv[3]);
|
||||
const config = require(configPath);
|
||||
config.output = {
|
||||
path: path.dirname(outPath),
|
||||
filename: path.basename(outPath)
|
||||
}
|
||||
};
|
||||
|
||||
const { wrapInitWithProfilingTimeout } = config;
|
||||
delete config.wrapInitWithProfilingTimeout;
|
||||
|
||||
webpack(config, (err, stats) => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
} else if (stats.hasErrors()) {
|
||||
console.error(stats.toString('normal'))
|
||||
process.exit(1)
|
||||
console.error(stats.toString('normal'));
|
||||
process.exit(1);
|
||||
} else {
|
||||
if (wrapInitWithProfilingTimeout) {
|
||||
const contents = fs.readFileSync(outPath, 'utf8');
|
||||
@@ -33,6 +33,6 @@ if ((globalThis.process || binding.process).argv.includes("--profile-electron-in
|
||||
}`;
|
||||
fs.writeFileSync(outPath, newContents);
|
||||
}
|
||||
process.exit(0)
|
||||
process.exit(0);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const webpack = require('webpack')
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
|
||||
const electronRoot = path.resolve(__dirname, '../..')
|
||||
const electronRoot = path.resolve(__dirname, '../..');
|
||||
|
||||
const onlyPrintingGraph = !!process.env.PRINT_WEBPACK_GRAPH
|
||||
const onlyPrintingGraph = !!process.env.PRINT_WEBPACK_GRAPH;
|
||||
|
||||
class AccessDependenciesPlugin {
|
||||
apply(compiler) {
|
||||
apply (compiler) {
|
||||
// Only hook into webpack when we are printing the dependency graph
|
||||
if (!onlyPrintingGraph) return
|
||||
if (!onlyPrintingGraph) return;
|
||||
|
||||
compiler.hooks.compilation.tap('AccessDependenciesPlugin', compilation => {
|
||||
compilation.hooks.finishModules.tap('AccessDependenciesPlugin', modules => {
|
||||
const filePaths = modules.map(m => m.resource).filter(p => p).map(p => path.relative(electronRoot, p))
|
||||
console.info(JSON.stringify(filePaths))
|
||||
})
|
||||
})
|
||||
const filePaths = modules.map(m => m.resource).filter(p => p).map(p => path.relative(electronRoot, p));
|
||||
console.info(JSON.stringify(filePaths));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const defines = {
|
||||
BUILDFLAG: onlyPrintingGraph ? '(a => a)' : ''
|
||||
}
|
||||
};
|
||||
|
||||
const buildFlagsPrefix = '--buildflags='
|
||||
const buildFlagsPrefix = '--buildflags=';
|
||||
const buildFlagArg = process.argv.find(arg => arg.startsWith(buildFlagsPrefix));
|
||||
|
||||
if (buildFlagArg) {
|
||||
const buildFlagPath = buildFlagArg.substr(buildFlagsPrefix.length)
|
||||
const buildFlagPath = buildFlagArg.substr(buildFlagsPrefix.length);
|
||||
|
||||
const flagFile = fs.readFileSync(buildFlagPath, 'utf8')
|
||||
const flagFile = fs.readFileSync(buildFlagPath, 'utf8');
|
||||
for (const line of flagFile.split(/(\r\n|\r|\n)/g)) {
|
||||
const flagMatch = line.match(/#define BUILDFLAG_INTERNAL_(.+?)\(\) \(([01])\)/)
|
||||
const flagMatch = line.match(/#define BUILDFLAG_INTERNAL_(.+?)\(\) \(([01])\)/);
|
||||
if (flagMatch) {
|
||||
const [, flagName, flagValue] = flagMatch;
|
||||
defines[flagName] = JSON.stringify(Boolean(parseInt(flagValue, 10)));
|
||||
@@ -41,27 +41,27 @@ if (buildFlagArg) {
|
||||
}
|
||||
}
|
||||
|
||||
const ignoredModules = []
|
||||
const ignoredModules = [];
|
||||
|
||||
if (defines['ENABLE_DESKTOP_CAPTURER'] === 'false') {
|
||||
if (defines.ENABLE_DESKTOP_CAPTURER === 'false') {
|
||||
ignoredModules.push(
|
||||
'@electron/internal/browser/desktop-capturer',
|
||||
'@electron/internal/browser/api/desktop-capturer',
|
||||
'@electron/internal/renderer/api/desktop-capturer'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (defines['ENABLE_REMOTE_MODULE'] === 'false') {
|
||||
if (defines.ENABLE_REMOTE_MODULE === 'false') {
|
||||
ignoredModules.push(
|
||||
'@electron/internal/browser/remote/server',
|
||||
'@electron/internal/renderer/api/remote'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (defines['ENABLE_VIEWS_API'] === 'false') {
|
||||
if (defines.ENABLE_VIEWS_API === 'false') {
|
||||
ignoredModules.push(
|
||||
'@electron/internal/browser/api/views/image-view.js'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = ({
|
||||
@@ -71,9 +71,9 @@ module.exports = ({
|
||||
target,
|
||||
wrapInitWithProfilingTimeout
|
||||
}) => {
|
||||
let entry = path.resolve(electronRoot, 'lib', target, 'init.ts')
|
||||
let entry = path.resolve(electronRoot, 'lib', target, 'init.ts');
|
||||
if (!fs.existsSync(entry)) {
|
||||
entry = path.resolve(electronRoot, 'lib', target, 'init.js')
|
||||
entry = path.resolve(electronRoot, 'lib', target, 'init.js');
|
||||
}
|
||||
|
||||
return ({
|
||||
@@ -88,16 +88,16 @@ module.exports = ({
|
||||
resolve: {
|
||||
alias: {
|
||||
'@electron/internal': path.resolve(electronRoot, 'lib'),
|
||||
'electron': path.resolve(electronRoot, 'lib', loadElectronFromAlternateTarget || target, 'api', 'exports', 'electron.ts'),
|
||||
electron: path.resolve(electronRoot, 'lib', loadElectronFromAlternateTarget || target, 'api', 'exports', 'electron.ts'),
|
||||
// Force timers to resolve to our dependency that doesn't use window.postMessage
|
||||
'timers': path.resolve(electronRoot, 'node_modules', 'timers-browserify', 'main.js')
|
||||
timers: path.resolve(electronRoot, 'node_modules', 'timers-browserify', 'main.js')
|
||||
},
|
||||
extensions: ['.ts', '.js']
|
||||
},
|
||||
module: {
|
||||
rules: [{
|
||||
test: (moduleName) => !onlyPrintingGraph && ignoredModules.includes(moduleName),
|
||||
loader: 'null-loader',
|
||||
loader: 'null-loader'
|
||||
}, {
|
||||
test: /\.ts$/,
|
||||
loader: 'ts-loader',
|
||||
@@ -106,7 +106,7 @@ module.exports = ({
|
||||
transpileOnly: onlyPrintingGraph,
|
||||
ignoreDiagnostics: [
|
||||
// File '{0}' is not under 'rootDir' '{1}'.
|
||||
6059,
|
||||
6059
|
||||
]
|
||||
}
|
||||
}]
|
||||
@@ -116,7 +116,7 @@ module.exports = ({
|
||||
__filename: false,
|
||||
// We provide our own "timers" import above, any usage of setImmediate inside
|
||||
// one of our renderer bundles should import it from the 'timers' package
|
||||
setImmediate: false,
|
||||
setImmediate: false
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
@@ -124,10 +124,10 @@ module.exports = ({
|
||||
new TerserPlugin({
|
||||
terserOptions: {
|
||||
keep_classnames: true,
|
||||
keep_fnames: true,
|
||||
},
|
||||
}),
|
||||
],
|
||||
keep_fnames: true
|
||||
}
|
||||
})
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new AccessDependenciesPlugin(),
|
||||
@@ -135,13 +135,13 @@ module.exports = ({
|
||||
new webpack.ProvidePlugin({
|
||||
process: ['@electron/internal/renderer/webpack-provider', 'process'],
|
||||
global: ['@electron/internal/renderer/webpack-provider', '_global'],
|
||||
Buffer: ['@electron/internal/renderer/webpack-provider', 'Buffer'],
|
||||
Buffer: ['@electron/internal/renderer/webpack-provider', 'Buffer']
|
||||
})
|
||||
] : []),
|
||||
new webpack.ProvidePlugin({
|
||||
Promise: ['@electron/internal/common/webpack-globals-provider', 'Promise'],
|
||||
Promise: ['@electron/internal/common/webpack-globals-provider', 'Promise']
|
||||
}),
|
||||
new webpack.DefinePlugin(defines),
|
||||
new webpack.DefinePlugin(defines)
|
||||
]
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module.exports = require('./webpack.config.base')({
|
||||
target: 'browser',
|
||||
alwaysHasNode: true
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module.exports = require('./webpack.config.base')({
|
||||
target: 'isolated_renderer',
|
||||
alwaysHasNode: false
|
||||
})
|
||||
});
|
||||
|
||||
@@ -3,4 +3,4 @@ module.exports = require('./webpack.config.base')({
|
||||
alwaysHasNode: true,
|
||||
targetDeletesNodeGlobals: true,
|
||||
wrapInitWithProfilingTimeout: true
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module.exports = require('./webpack.config.base')({
|
||||
target: 'sandboxed_renderer',
|
||||
alwaysHasNode: false,
|
||||
wrapInitWithProfilingTimeout: true,
|
||||
})
|
||||
wrapInitWithProfilingTimeout: true
|
||||
});
|
||||
|
||||
@@ -3,4 +3,4 @@ module.exports = require('./webpack.config.base')({
|
||||
loadElectronFromAlternateTarget: 'renderer',
|
||||
alwaysHasNode: true,
|
||||
targetDeletesNodeGlobals: true
|
||||
})
|
||||
});
|
||||
|
||||
@@ -53,31 +53,31 @@
|
||||
<nav>
|
||||
<div class="linkcol">
|
||||
<a class="hero-link" target="_blank" href="https://electronjs.org/blog">
|
||||
<span class="octicon hero-octicon octicon-gist" aria-hidden="true"></span>
|
||||
<span class="octicon hero-octicon octicon-code-square-24" aria-hidden="true"></span>
|
||||
<h4>Blog</h4>
|
||||
</a>
|
||||
</div>
|
||||
<div class="linkcol">
|
||||
<a class="hero-link" target="_blank" href="https://github.com/electron/electron">
|
||||
<span class="octicon hero-octicon octicon-mark-github" aria-hidden="true"></span>
|
||||
<span class="octicon hero-octicon octicon-mark-github-16" aria-hidden="true"></span>
|
||||
<h4>Repository</h4>
|
||||
</a>
|
||||
</div>
|
||||
<div class="linkcol">
|
||||
<a class="hero-link" target="_blank" href="https://electronjs.org/docs">
|
||||
<span class="octicon hero-octicon octicon-gear" aria-hidden="true"></span>
|
||||
<span class="octicon hero-octicon octicon-book-24" aria-hidden="true"></span>
|
||||
<h4>Docs</h4>
|
||||
</a>
|
||||
</div>
|
||||
<div class="linkcol">
|
||||
<a class="hero-link" target="_blank" href="https://github.com/electron/electron-api-demos">
|
||||
<span class="octicon hero-octicon octicon-star" aria-hidden="true"></span>
|
||||
<span class="octicon hero-octicon octicon-star-fill-24" aria-hidden="true"></span>
|
||||
<h4>API Demos</h4>
|
||||
</a>
|
||||
</div>
|
||||
<div class="linkcol">
|
||||
<a class="hero-link" target="_blank" href="https://electronforge.io">
|
||||
<span class="octicon hero-octicon octicon-gift" aria-hidden="true"></span>
|
||||
<span class="octicon hero-octicon octicon-gift-24" aria-hidden="true"></span>
|
||||
<h4>Forge</h4>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -990,6 +990,7 @@ if (!gotTheLock) {
|
||||
|
||||
// Create myWindow, load the rest of the app, etc...
|
||||
app.whenReady().then(() => {
|
||||
myWindow = createWindow()
|
||||
})
|
||||
}
|
||||
```
|
||||
@@ -1105,8 +1106,10 @@ For `infoType` equal to `complete`:
|
||||
For `infoType` equal to `basic`:
|
||||
Promise is fulfilled with `Object` containing fewer attributes than when requested with `complete`. Here's an example of basic response:
|
||||
```js
|
||||
{ auxAttributes:
|
||||
{ amdSwitchable: true,
|
||||
{
|
||||
auxAttributes:
|
||||
{
|
||||
amdSwitchable: true,
|
||||
canSupportThreadedTextureMailbox: false,
|
||||
directComposition: false,
|
||||
directRendering: true,
|
||||
@@ -1119,12 +1122,14 @@ For `infoType` equal to `basic`:
|
||||
sandboxed: false,
|
||||
softwareRendering: false,
|
||||
supportsOverlays: false,
|
||||
videoDecodeAcceleratorFlags: 0 },
|
||||
gpuDevice:
|
||||
[ { active: true, deviceId: 26657, vendorId: 4098 },
|
||||
{ active: false, deviceId: 3366, vendorId: 32902 } ],
|
||||
machineModelName: 'MacBookPro',
|
||||
machineModelVersion: '11.5' }
|
||||
videoDecodeAcceleratorFlags: 0
|
||||
},
|
||||
gpuDevice:
|
||||
[{ active: true, deviceId: 26657, vendorId: 4098 },
|
||||
{ active: false, deviceId: 3366, vendorId: 32902 }],
|
||||
machineModelName: 'MacBookPro',
|
||||
machineModelVersion: '11.5'
|
||||
}
|
||||
```
|
||||
|
||||
Using `basic` should be preferred if only basic information like `vendorId` or `driverId` is needed.
|
||||
|
||||
@@ -28,25 +28,6 @@ view.webContents.loadURL('https://electronjs.org')
|
||||
* `options` Object (optional)
|
||||
* `webPreferences` Object (optional) - See [BrowserWindow](browser-window.md).
|
||||
|
||||
### Static Methods
|
||||
|
||||
#### `BrowserView.getAllViews()`
|
||||
|
||||
Returns `BrowserView[]` - An array of all opened BrowserViews.
|
||||
|
||||
#### `BrowserView.fromWebContents(webContents)`
|
||||
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
|
||||
Returns `BrowserView | null` - The BrowserView that owns the given `webContents`
|
||||
or `null` if the contents are not owned by a BrowserView.
|
||||
|
||||
#### `BrowserView.fromId(id)`
|
||||
|
||||
* `id` Integer
|
||||
|
||||
Returns `BrowserView` - The view with the given `id`.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
Objects created with `new BrowserView` have the following properties:
|
||||
@@ -55,10 +36,6 @@ Objects created with `new BrowserView` have the following properties:
|
||||
|
||||
A [`WebContents`](web-contents.md) object owned by this view.
|
||||
|
||||
#### `view.id` _Experimental_
|
||||
|
||||
A `Integer` representing the unique ID of the view.
|
||||
|
||||
### Instance Methods
|
||||
|
||||
Objects created with `new BrowserView` have the following instance methods:
|
||||
|
||||
@@ -38,7 +38,7 @@ the window after this event will have no visual flash:
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow({ show: false })
|
||||
const win = new BrowserWindow({ show: false })
|
||||
win.once('ready-to-show', () => {
|
||||
win.show()
|
||||
})
|
||||
@@ -60,7 +60,7 @@ immediately, and use a `backgroundColor` close to your app's background:
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
let win = new BrowserWindow({ backgroundColor: '#2e2c29' })
|
||||
const win = new BrowserWindow({ backgroundColor: '#2e2c29' })
|
||||
win.loadURL('https://github.com')
|
||||
```
|
||||
|
||||
@@ -74,8 +74,8 @@ By using `parent` option, you can create child windows:
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
let top = new BrowserWindow()
|
||||
let child = new BrowserWindow({ parent: top })
|
||||
const top = new BrowserWindow()
|
||||
const child = new BrowserWindow({ parent: top })
|
||||
child.show()
|
||||
top.show()
|
||||
```
|
||||
@@ -90,7 +90,7 @@ window, you have to set both `parent` and `modal` options:
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
let child = new BrowserWindow({ parent: top, modal: true, show: false })
|
||||
const child = new BrowserWindow({ parent: top, modal: true, show: false })
|
||||
child.loadURL('https://github.com')
|
||||
child.once('ready-to-show', () => {
|
||||
child.show()
|
||||
@@ -597,7 +597,7 @@ e.g. `APPCOMMAND_BROWSER_BACKWARD` is emitted as `browser-backward`.
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow()
|
||||
const win = new BrowserWindow()
|
||||
win.on('app-command', (e, cmd) => {
|
||||
// Navigate the window back when the user hits their mouse back button
|
||||
if (cmd === 'browser-backward' && win.webContents.canGoBack()) {
|
||||
@@ -772,7 +772,7 @@ To check if a DevTools extension is installed you can run the following:
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
let installed = BrowserWindow.getDevToolsExtensions().hasOwnProperty('devtron')
|
||||
const installed = 'devtron' in BrowserWindow.getDevToolsExtensions()
|
||||
console.log(installed)
|
||||
```
|
||||
|
||||
@@ -789,7 +789,7 @@ Objects created with `new BrowserWindow` have the following properties:
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
// In this example `win` is our instance
|
||||
let win = new BrowserWindow({ width: 800, height: 600 })
|
||||
const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
win.loadURL('https://github.com')
|
||||
```
|
||||
|
||||
@@ -1123,7 +1123,7 @@ Disable or enable the window.
|
||||
|
||||
#### `win.isEnabled()`
|
||||
|
||||
Returns Boolean - whether the window is enabled.
|
||||
Returns `Boolean` - whether the window is enabled.
|
||||
|
||||
#### `win.setSize(width, height[, animate])`
|
||||
|
||||
@@ -1314,9 +1314,9 @@ a HTML-rendered toolbar. For example:
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow()
|
||||
const win = new BrowserWindow()
|
||||
|
||||
let toolbarRect = document.getElementById('toolbar').getBoundingClientRect()
|
||||
const toolbarRect = document.getElementById('toolbar').getBoundingClientRect()
|
||||
win.setSheetOffset(toolbarRect.height)
|
||||
```
|
||||
|
||||
@@ -1440,7 +1440,7 @@ Node's [`url.format`](https://nodejs.org/api/url.html#url_url_format_urlobject)
|
||||
method:
|
||||
|
||||
```javascript
|
||||
let url = require('url').format({
|
||||
const url = require('url').format({
|
||||
protocol: 'file',
|
||||
slashes: true,
|
||||
pathname: require('path').join(__dirname, 'index.html')
|
||||
|
||||
@@ -9,7 +9,7 @@ runtime that allows interacting with pages and instrumenting them.
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow()
|
||||
const win = new BrowserWindow()
|
||||
|
||||
try {
|
||||
win.webContents.debugger.attach('1.1')
|
||||
|
||||
@@ -11,7 +11,7 @@ control the download item.
|
||||
```javascript
|
||||
// In the main process.
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow()
|
||||
const win = new BrowserWindow()
|
||||
win.webContents.session.on('will-download', (event, item, webContents) => {
|
||||
// Set the save path, making Electron not to prompt a save dialog.
|
||||
item.setSavePath('/tmp/save.pdf')
|
||||
|
||||
@@ -15,7 +15,7 @@ To create a frameless window, you need to set `frame` to `false` in
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow({ width: 800, height: 600, frame: false })
|
||||
const win = new BrowserWindow({ width: 800, height: 600, frame: false })
|
||||
win.show()
|
||||
```
|
||||
|
||||
@@ -33,7 +33,7 @@ Results in a hidden title bar and a full size content window, yet the title bar
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow({ titleBarStyle: 'hidden' })
|
||||
const win = new BrowserWindow({ titleBarStyle: 'hidden' })
|
||||
win.show()
|
||||
```
|
||||
|
||||
@@ -43,7 +43,7 @@ Results in a hidden title bar with an alternative look where the traffic light b
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow({ titleBarStyle: 'hiddenInset' })
|
||||
const win = new BrowserWindow({ titleBarStyle: 'hiddenInset' })
|
||||
win.show()
|
||||
```
|
||||
|
||||
@@ -58,7 +58,7 @@ This option is only applicable for frameless windows.
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow({ titleBarStyle: 'customButtonsOnHover', frame: false })
|
||||
const win = new BrowserWindow({ titleBarStyle: 'customButtonsOnHover', frame: false })
|
||||
win.show()
|
||||
```
|
||||
|
||||
@@ -69,7 +69,7 @@ window transparent:
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow({ transparent: true, frame: false })
|
||||
const win = new BrowserWindow({ transparent: true, frame: false })
|
||||
win.show()
|
||||
```
|
||||
|
||||
@@ -100,7 +100,7 @@ API:
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow()
|
||||
const win = new BrowserWindow()
|
||||
win.setIgnoreMouseEvents(true)
|
||||
```
|
||||
|
||||
@@ -112,8 +112,8 @@ optional parameter can be used to forward mouse move messages to the web page,
|
||||
allowing events such as `mouseleave` to be emitted:
|
||||
|
||||
```javascript
|
||||
let win = require('electron').remote.getCurrentWindow()
|
||||
let el = document.getElementById('clickThroughElement')
|
||||
const win = require('electron').remote.getCurrentWindow()
|
||||
const el = document.getElementById('clickThroughElement')
|
||||
el.addEventListener('mouseenter', () => {
|
||||
win.setIgnoreMouseEvents(true, { forward: true })
|
||||
})
|
||||
|
||||
@@ -17,7 +17,7 @@ renderer process:
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron').remote
|
||||
let win = new BrowserWindow({ width: 800, height: 600 })
|
||||
const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
win.loadURL('https://github.com')
|
||||
```
|
||||
|
||||
|
||||
@@ -33,8 +33,8 @@ const { app, BrowserWindow, screen } = require('electron')
|
||||
let win
|
||||
|
||||
app.whenReady().then(() => {
|
||||
let displays = screen.getAllDisplays()
|
||||
let externalDisplay = displays.find((display) => {
|
||||
const displays = screen.getAllDisplays()
|
||||
const externalDisplay = displays.find((display) => {
|
||||
return display.bounds.x !== 0 || display.bounds.y !== 0
|
||||
})
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ property of [`WebContents`](web-contents.md), or from the `session` module.
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
let win = new BrowserWindow({ width: 800, height: 600 })
|
||||
const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
win.loadURL('http://github.com')
|
||||
|
||||
const ses = win.webContents.session
|
||||
@@ -332,7 +332,7 @@ verify proc.
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow()
|
||||
const win = new BrowserWindow()
|
||||
|
||||
win.webContents.session.setCertificateVerifyProc((request, callback) => {
|
||||
const { hostname } = request
|
||||
@@ -655,7 +655,7 @@ const path = require('path')
|
||||
app.whenReady().then(() => {
|
||||
const protocol = session.fromPartition('some-partition').protocol
|
||||
protocol.registerFileProtocol('atom', (request, callback) => {
|
||||
let url = request.url.substr(7)
|
||||
const url = request.url.substr(7)
|
||||
callback({ path: path.normalize(`${__dirname}/${url}`) })
|
||||
}, (error) => {
|
||||
if (error) console.error('Failed to register protocol')
|
||||
|
||||
@@ -41,7 +41,7 @@ An example TraceConfig that roughly matches what Chrome DevTools records:
|
||||
'disabled-by-default-v8.cpu_profiler',
|
||||
'disabled-by-default-v8.cpu_profiler.hires'
|
||||
],
|
||||
excluded_categories: [ '*' ]
|
||||
excluded_categories: ['*']
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -209,7 +209,7 @@ not (transparent windows won't work correctly when DWM composition is disabled):
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow, systemPreferences } = require('electron')
|
||||
let browserOptions = { width: 1000, height: 800 }
|
||||
const browserOptions = { width: 1000, height: 800 }
|
||||
|
||||
// Make the window transparent only if the platform supports it.
|
||||
if (process.platform !== 'win32' || systemPreferences.isAeroGlassEnabled()) {
|
||||
@@ -218,7 +218,7 @@ if (process.platform !== 'win32' || systemPreferences.isAeroGlassEnabled()) {
|
||||
}
|
||||
|
||||
// Create the window.
|
||||
let win = new BrowserWindow(browserOptions)
|
||||
const win = new BrowserWindow(browserOptions)
|
||||
|
||||
// Navigate.
|
||||
if (browserOptions.transparent) {
|
||||
|
||||
@@ -12,10 +12,10 @@ the [`BrowserWindow`](browser-window.md) object. An example of accessing the
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
let win = new BrowserWindow({ width: 800, height: 1500 })
|
||||
const win = new BrowserWindow({ width: 800, height: 1500 })
|
||||
win.loadURL('http://github.com')
|
||||
|
||||
let contents = win.webContents
|
||||
const contents = win.webContents
|
||||
console.log(contents)
|
||||
```
|
||||
|
||||
@@ -418,7 +418,7 @@ To only prevent the menu shortcuts, use
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
let win = new BrowserWindow({ width: 800, height: 600 })
|
||||
const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
|
||||
win.webContents.on('before-input-event', (event, input) => {
|
||||
// For example, only enable application menu keyboard shortcuts when
|
||||
@@ -665,7 +665,7 @@ app.whenReady().then(() => {
|
||||
win = new BrowserWindow({ width: 800, height: 600 })
|
||||
win.webContents.on('select-bluetooth-device', (event, deviceList, callback) => {
|
||||
event.preventDefault()
|
||||
let result = deviceList.find((device) => {
|
||||
const result = deviceList.find((device) => {
|
||||
return device.deviceName === 'test'
|
||||
})
|
||||
if (!result) {
|
||||
@@ -691,7 +691,7 @@ buffer.
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
let win = new BrowserWindow({ webPreferences: { offscreen: true } })
|
||||
const win = new BrowserWindow({ webPreferences: { offscreen: true } })
|
||||
win.webContents.on('paint', (event, dirty, image) => {
|
||||
// updateBitmap(dirty, image.getBitmap())
|
||||
})
|
||||
@@ -907,7 +907,7 @@ Returns `String` - The URL of the current web page.
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow({ width: 800, height: 600 })
|
||||
const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
win.loadURL('http://github.com').then(() => {
|
||||
const currentURL = win.webContents.getURL()
|
||||
console.log(currentURL)
|
||||
@@ -1311,6 +1311,8 @@ Returns [`PrinterInfo[]`](structures/printer-info.md)
|
||||
* `success` Boolean - Indicates success of the print call.
|
||||
* `failureReason` String - Error description called back if the print fails.
|
||||
|
||||
When a custom `pageSize` is passed, Chromium attempts to validate platform specific minumum values for `width_microns` and `height_microns`. Width and height must both be minimum 353 microns but may be higher on some operating systems.
|
||||
|
||||
Prints window's web page. When `silent` is set to `true`, Electron will pick
|
||||
the system's default printer if `deviceName` is empty and the default settings for printing.
|
||||
|
||||
@@ -1334,13 +1336,12 @@ win.webContents.print(options, (success, errorType) => {
|
||||
* `landscape` Boolean (optional) - `true` for landscape, `false` for portrait.
|
||||
* `marginsType` Integer (optional) - Specifies the type of margins to use. Uses 0 for
|
||||
default margin, 1 for no margin, and 2 for minimum margin.
|
||||
and `width` in microns.
|
||||
* `scaleFactor` Number (optional) - The scale factor of the web page. Can range from 0 to 100.
|
||||
* `pageRanges` Record<string, number> (optional) - The page range to print.
|
||||
* `from` Number - the first page to print.
|
||||
* `to` Number - the last page to print (inclusive).
|
||||
* `pageSize` String | Size (optional) - Specify page size of the generated PDF. Can be `A3`,
|
||||
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`
|
||||
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` and `width` in microns.
|
||||
* `printBackground` Boolean (optional) - Whether to print CSS backgrounds.
|
||||
* `printSelectionOnly` Boolean (optional) - Whether to print selection only.
|
||||
|
||||
@@ -1372,7 +1373,7 @@ An example of `webContents.printToPDF`:
|
||||
const { BrowserWindow } = require('electron')
|
||||
const fs = require('fs')
|
||||
|
||||
let win = new BrowserWindow({ width: 800, height: 600 })
|
||||
const win = new BrowserWindow({ width: 800, height: 600 })
|
||||
win.loadURL('http://github.com')
|
||||
|
||||
win.webContents.on('did-finish-load', () => {
|
||||
@@ -1397,7 +1398,7 @@ creation:
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow()
|
||||
const win = new BrowserWindow()
|
||||
win.webContents.on('devtools-opened', () => {
|
||||
win.webContents.addWorkSpace(__dirname)
|
||||
})
|
||||
@@ -1718,7 +1719,7 @@ Returns `Promise<void>` - resolves if the page is saved.
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow()
|
||||
const win = new BrowserWindow()
|
||||
|
||||
win.loadURL('https://github.com')
|
||||
|
||||
|
||||
@@ -816,7 +816,7 @@ const { shell } = require('electron')
|
||||
const webview = document.querySelector('webview')
|
||||
|
||||
webview.addEventListener('new-window', async (e) => {
|
||||
const protocol = require('url').parse(e.url).protocol
|
||||
const protocol = (new URL(e.url)).protocol
|
||||
if (protocol === 'http:' || protocol === 'https:') {
|
||||
await shell.openExternal(e.url)
|
||||
}
|
||||
|
||||
@@ -94,6 +94,6 @@ mainWindow.webContents.on('new-window', (event, url, frameName, disposition, opt
|
||||
|
||||
```javascript
|
||||
// renderer process (mainWindow)
|
||||
let modal = window.open('', 'modal')
|
||||
const modal = window.open('', 'modal')
|
||||
modal.document.write('<h1>Hello</h1>')
|
||||
```
|
||||
|
||||
@@ -266,7 +266,7 @@ const getGuestForWebContents = (webContentsId, contents) => {
|
||||
throw new Error(`Invalid webContentsId: ${webContentsId}`)
|
||||
}
|
||||
if (guest.hostWebContents !== contents) {
|
||||
throw new Error(`Access denied to webContents`)
|
||||
throw new Error('Access denied to webContents')
|
||||
}
|
||||
return guest
|
||||
}
|
||||
@@ -610,11 +610,11 @@ const { memory } = metrics[0] // Deprecated property
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
let optionsA = { webPreferences: { blinkFeatures: '' } }
|
||||
let windowA = new BrowserWindow(optionsA)
|
||||
const optionsA = { webPreferences: { blinkFeatures: '' } }
|
||||
const windowA = new BrowserWindow(optionsA)
|
||||
// Replace with
|
||||
let optionsB = { webPreferences: { enableBlinkFeatures: '' } }
|
||||
let windowB = new BrowserWindow(optionsB)
|
||||
const optionsB = { webPreferences: { enableBlinkFeatures: '' } }
|
||||
const windowB = new BrowserWindow(optionsB)
|
||||
|
||||
// Deprecated
|
||||
window.on('app-command', (e, cmd) => {
|
||||
@@ -785,11 +785,11 @@ The following list includes the breaking API changes made in Electron 2.0.
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
let optionsA = { titleBarStyle: 'hidden-inset' }
|
||||
let windowA = new BrowserWindow(optionsA)
|
||||
const optionsA = { titleBarStyle: 'hidden-inset' }
|
||||
const windowA = new BrowserWindow(optionsA)
|
||||
// Replace with
|
||||
let optionsB = { titleBarStyle: 'hiddenInset' }
|
||||
let windowB = new BrowserWindow(optionsB)
|
||||
const optionsB = { titleBarStyle: 'hiddenInset' }
|
||||
const windowB = new BrowserWindow(optionsB)
|
||||
```
|
||||
|
||||
### `menu`
|
||||
|
||||
@@ -107,7 +107,7 @@ To solve this, you can turn off node integration in Electron:
|
||||
```javascript
|
||||
// In the main process.
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow({
|
||||
const win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
nodeIntegration: false
|
||||
}
|
||||
@@ -155,7 +155,7 @@ To achieve this goal, set the background in the constructor for [BrowserWindow][
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow({
|
||||
const win = new BrowserWindow({
|
||||
backgroundColor: '#fff'
|
||||
})
|
||||
```
|
||||
|
||||
@@ -15,7 +15,7 @@ can open them programmatically by calling the `openDevTools()` API on the
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
let win = new BrowserWindow()
|
||||
const win = new BrowserWindow()
|
||||
win.webContents.openDevTools()
|
||||
```
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ fs.readdirSync('/path/to/example.asar')
|
||||
Use a module from the archive:
|
||||
|
||||
```javascript
|
||||
require('/path/to/example.asar/dir/module.js')
|
||||
require('./path/to/example.asar/dir/module.js')
|
||||
```
|
||||
|
||||
You can also display a web page in an `asar` archive with `BrowserWindow`:
|
||||
|
||||
@@ -9,9 +9,9 @@ const childProcess = require('child_process')
|
||||
const electronPath = require('electron')
|
||||
|
||||
// spawn the process
|
||||
let env = { /* ... */ }
|
||||
let stdio = ['inherit', 'inherit', 'inherit', 'ipc']
|
||||
let appProcess = childProcess.spawn(electronPath, ['./app'], { stdio, env })
|
||||
const env = { /* ... */ }
|
||||
const stdio = ['inherit', 'inherit', 'inherit', 'ipc']
|
||||
const appProcess = childProcess.spawn(electronPath, ['./app'], { stdio, env })
|
||||
|
||||
// listen for IPC messages from the app
|
||||
appProcess.on('message', (msg) => {
|
||||
@@ -50,7 +50,7 @@ class TestDriver {
|
||||
// handle rpc responses
|
||||
this.process.on('message', (message) => {
|
||||
// pop the handler
|
||||
let rpcCall = this.rpcCalls[message.msgId]
|
||||
const rpcCall = this.rpcCalls[message.msgId]
|
||||
if (!rpcCall) return
|
||||
this.rpcCalls[message.msgId] = null
|
||||
// reject/resolve
|
||||
@@ -70,7 +70,7 @@ class TestDriver {
|
||||
// to use: driver.rpc('method', 1, 2, 3).then(...)
|
||||
async rpc (cmd, ...args) {
|
||||
// send rpc request
|
||||
let msgId = this.rpcCalls.length
|
||||
const msgId = this.rpcCalls.length
|
||||
this.process.send({ msgId, cmd, args })
|
||||
return new Promise((resolve, reject) => this.rpcCalls.push({ resolve, reject }))
|
||||
}
|
||||
@@ -92,10 +92,10 @@ async function onMessage ({ msgId, cmd, args }) {
|
||||
let method = METHODS[cmd]
|
||||
if (!method) method = () => new Error('Invalid method: ' + cmd)
|
||||
try {
|
||||
let resolve = await method(...args)
|
||||
const resolve = await method(...args)
|
||||
process.send({ msgId, resolve })
|
||||
} catch (err) {
|
||||
let reject = {
|
||||
const reject = {
|
||||
message: err.message,
|
||||
stack: err.stack,
|
||||
name: err.name
|
||||
@@ -119,7 +119,7 @@ Then, in your test suite, you can use your test-driver as follows:
|
||||
const test = require('ava')
|
||||
const electronPath = require('electron')
|
||||
|
||||
let app = new TestDriver({
|
||||
const app = new TestDriver({
|
||||
path: electronPath,
|
||||
args: ['./app'],
|
||||
env: {
|
||||
|
||||
@@ -96,7 +96,7 @@ const { app, BrowserWindow } = require('electron')
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
let win = new BrowserWindow({
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
|
||||
@@ -37,18 +37,18 @@ inAppPurchase.on('transactions-updated', (event, transactions) => {
|
||||
|
||||
// Check each transaction.
|
||||
transactions.forEach(function (transaction) {
|
||||
let payment = transaction.payment
|
||||
const payment = transaction.payment
|
||||
|
||||
switch (transaction.transactionState) {
|
||||
case 'purchasing':
|
||||
console.log(`Purchasing ${payment.productIdentifier}...`)
|
||||
break
|
||||
case 'purchased':
|
||||
|
||||
case 'purchased': {
|
||||
console.log(`${payment.productIdentifier} purchased.`)
|
||||
|
||||
// Get the receipt url.
|
||||
let receiptURL = inAppPurchase.getReceiptURL()
|
||||
const receiptURL = inAppPurchase.getReceiptURL()
|
||||
|
||||
console.log(`Receipt URL: ${receiptURL}`)
|
||||
|
||||
@@ -62,6 +62,8 @@ inAppPurchase.on('transactions-updated', (event, transactions) => {
|
||||
inAppPurchase.finishTransactionByDate(transaction.transactionDate)
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
case 'failed':
|
||||
|
||||
console.log(`Failed to purchase ${payment.productIdentifier}.`)
|
||||
@@ -105,8 +107,8 @@ inAppPurchase.getProducts(PRODUCT_IDS).then(products => {
|
||||
})
|
||||
|
||||
// Ask the user which product he/she wants to purchase.
|
||||
let selectedProduct = products[0]
|
||||
let selectedQuantity = 1
|
||||
const selectedProduct = products[0]
|
||||
const selectedQuantity = 1
|
||||
|
||||
// Purchase the selected product.
|
||||
inAppPurchase.purchaseProduct(selectedProduct.productIdentifier, selectedQuantity).then(isProductValid => {
|
||||
|
||||
@@ -10,7 +10,7 @@ so the `nodeIntegrationInWorker` option should be set to `true` in
|
||||
`webPreferences`.
|
||||
|
||||
```javascript
|
||||
let win = new BrowserWindow({
|
||||
const win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
nodeIntegrationInWorker: true
|
||||
}
|
||||
@@ -44,7 +44,7 @@ loads no native modules after the Web Workers get started.
|
||||
process.dlopen = () => {
|
||||
throw new Error('Load native module is not safe')
|
||||
}
|
||||
let worker = new Worker('script.js')
|
||||
const worker = new Worker('script.js')
|
||||
```
|
||||
|
||||
[web-workers]: https://developer.mozilla.org/en/docs/Web/API/Web_Workers_API/Using_web_workers
|
||||
|
||||
@@ -10,7 +10,7 @@ you want to show Notifications in the main process please check out the
|
||||
[Notification](../api/notification.md) module.
|
||||
|
||||
```javascript
|
||||
let myNotification = new Notification('Title', {
|
||||
const myNotification = new Notification('Title', {
|
||||
body: 'Lorem Ipsum Dolor Sit Amet'
|
||||
})
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ app.commandLine.appendSwitch('ppapi-flash-path', path.join(__dirname, pluginName
|
||||
app.commandLine.appendSwitch('ppapi-flash-version', '17.0.0.169')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
let win = new BrowserWindow({
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
|
||||
@@ -146,7 +146,7 @@ const options = {
|
||||
}
|
||||
}
|
||||
|
||||
let client = webdriverio.remote(options)
|
||||
const client = webdriverio.remote(options)
|
||||
|
||||
client
|
||||
.init()
|
||||
|
||||
@@ -149,7 +149,7 @@ To set the overlay icon for a window, you can use the
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow()
|
||||
const win = new BrowserWindow()
|
||||
win.setOverlayIcon('path/to/overlay.png', 'Description for overlay')
|
||||
```
|
||||
|
||||
@@ -168,7 +168,7 @@ To flash the BrowserWindow taskbar button, you can use the
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
let win = new BrowserWindow()
|
||||
const win = new BrowserWindow()
|
||||
win.once('focus', () => win.flashFrame(false))
|
||||
win.flashFrame(true)
|
||||
```
|
||||
|
||||
@@ -174,7 +174,7 @@ auto_filenames = {
|
||||
]
|
||||
|
||||
isolated_bundle_deps = [
|
||||
"lib/isolated_renderer/init.js",
|
||||
"lib/isolated_renderer/init.ts",
|
||||
"lib/renderer/web-view/web-view-constants.ts",
|
||||
"lib/renderer/web-view/web-view-element.ts",
|
||||
"package.json",
|
||||
@@ -327,7 +327,7 @@ auto_filenames = {
|
||||
"lib/renderer/ipc-renderer-internal.ts",
|
||||
"lib/renderer/remote/callbacks-registry.ts",
|
||||
"lib/renderer/webpack-provider.ts",
|
||||
"lib/worker/init.js",
|
||||
"lib/worker/init.ts",
|
||||
"package.json",
|
||||
"tsconfig.electron.json",
|
||||
"tsconfig.json",
|
||||
|
||||
@@ -14,11 +14,11 @@ filenames = {
|
||||
|
||||
default_app_octicon_sources = [
|
||||
"node_modules/@primer/octicons/build/build.css",
|
||||
"node_modules/@primer/octicons/build/svg/gear.svg",
|
||||
"node_modules/@primer/octicons/build/svg/gift.svg",
|
||||
"node_modules/@primer/octicons/build/svg/gist.svg",
|
||||
"node_modules/@primer/octicons/build/svg/mark-github.svg",
|
||||
"node_modules/@primer/octicons/build/svg/star.svg",
|
||||
"node_modules/@primer/octicons/build/svg/book-24.svg",
|
||||
"node_modules/@primer/octicons/build/svg/code-square-24.svg",
|
||||
"node_modules/@primer/octicons/build/svg/gift-24.svg",
|
||||
"node_modules/@primer/octicons/build/svg/mark-github-16.svg",
|
||||
"node_modules/@primer/octicons/build/svg/star-fill-24.svg",
|
||||
]
|
||||
|
||||
lib_sources = [
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
const { BrowserView } = process._linkedBinding('electron_browser_browser_view');
|
||||
|
||||
Object.setPrototypeOf(BrowserView.prototype, EventEmitter.prototype);
|
||||
|
||||
BrowserView.fromWebContents = (webContents: Electron.WebContents) => {
|
||||
for (const view of BrowserView.getAllViews()) {
|
||||
if (view.webContents.equal(webContents)) return view;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default BrowserView;
|
||||
|
||||
@@ -134,6 +134,7 @@ class SlurpStream extends Writable {
|
||||
this._data = Buffer.concat([this._data, chunk]);
|
||||
callback();
|
||||
}
|
||||
|
||||
data () { return this._data; }
|
||||
}
|
||||
|
||||
@@ -300,6 +301,10 @@ class ClientRequest extends Writable implements Electron.ClientRequest {
|
||||
this._redirectPolicy = redirectPolicy;
|
||||
}
|
||||
|
||||
get chunkedEncoding () {
|
||||
return this._chunkedEncoding || false;
|
||||
}
|
||||
|
||||
set chunkedEncoding (value: boolean) {
|
||||
if (this._started) {
|
||||
throw new Error('chunkedEncoding can only be set before the request is started');
|
||||
|
||||
@@ -72,6 +72,19 @@ const PDFPageSizes: Record<string, MediaSize> = {
|
||||
}
|
||||
};
|
||||
|
||||
// The minimum micron size Chromium accepts is that where:
|
||||
// Per printing/units.h:
|
||||
// * kMicronsPerInch - Length of an inch in 0.001mm unit.
|
||||
// * kPointsPerInch - Length of an inch in CSS's 1pt unit.
|
||||
//
|
||||
// Formula: (kPointsPerInch / kMicronsPerInch) * size >= 1
|
||||
//
|
||||
// Practically, this means microns need to be > 352 microns.
|
||||
// We therefore need to verify this or it will silently fail.
|
||||
const isValidCustomPageSize = (width: number, height: number) => {
|
||||
return [width, height].every(x => x > 352);
|
||||
};
|
||||
|
||||
// Default printing setting
|
||||
const defaultPrintingSetting = {
|
||||
// Customizable.
|
||||
@@ -204,11 +217,11 @@ const waitTillCanExecuteJavaScript = async (webContents: WebContentsInternal) =>
|
||||
// WebContents has been loaded.
|
||||
WebContents.prototype.executeJavaScript = async function (code, hasUserGesture) {
|
||||
await waitTillCanExecuteJavaScript(this);
|
||||
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScript', code, hasUserGesture);
|
||||
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScript', String(code), !!hasUserGesture);
|
||||
};
|
||||
WebContents.prototype.executeJavaScriptInIsolatedWorld = async function (code, hasUserGesture) {
|
||||
WebContents.prototype.executeJavaScriptInIsolatedWorld = async function (worldId, code, hasUserGesture) {
|
||||
await waitTillCanExecuteJavaScript(this);
|
||||
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScriptInIsolatedWorld', code, hasUserGesture);
|
||||
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', 'executeJavaScriptInIsolatedWorld', worldId, code, !!hasUserGesture);
|
||||
};
|
||||
|
||||
// Translate the options of printToPDF.
|
||||
@@ -315,13 +328,20 @@ WebContents.prototype.printToPDF = function (options) {
|
||||
const error = new Error('height and width properties are required for pageSize');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
// Dimensions in Microns
|
||||
// 1 meter = 10^6 microns
|
||||
|
||||
// Dimensions in Microns - 1 meter = 10^6 microns
|
||||
const height = Math.ceil(pageSize.height);
|
||||
const width = Math.ceil(pageSize.width);
|
||||
if (!isValidCustomPageSize(width, height)) {
|
||||
const error = new Error('height and width properties must be minimum 352 microns.');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
printSettings.mediaSize = {
|
||||
name: 'CUSTOM',
|
||||
custom_display_name: 'Custom',
|
||||
height_microns: Math.ceil(pageSize.height),
|
||||
width_microns: Math.ceil(pageSize.width)
|
||||
height_microns: height,
|
||||
width_microns: width
|
||||
};
|
||||
} else if (Object.prototype.hasOwnProperty.call(PDFPageSizes, pageSize)) {
|
||||
printSettings.mediaSize = PDFPageSizes[pageSize];
|
||||
@@ -356,12 +376,19 @@ WebContents.prototype.print = function (options = {}, callback) {
|
||||
if (!pageSize.height || !pageSize.width) {
|
||||
throw new Error('height and width properties are required for pageSize');
|
||||
}
|
||||
|
||||
// Dimensions in Microns - 1 meter = 10^6 microns
|
||||
const height = Math.ceil(pageSize.height);
|
||||
const width = Math.ceil(pageSize.width);
|
||||
if (!isValidCustomPageSize(width, height)) {
|
||||
throw new Error('height and width properties must be minimum 352 microns.');
|
||||
}
|
||||
|
||||
(options as any).mediaSize = {
|
||||
name: 'CUSTOM',
|
||||
custom_display_name: 'Custom',
|
||||
height_microns: Math.ceil(pageSize.height),
|
||||
width_microns: Math.ceil(pageSize.width)
|
||||
height_microns: height,
|
||||
width_microns: width
|
||||
};
|
||||
} else if (PDFPageSizes[pageSize]) {
|
||||
(options as any).mediaSize = PDFPageSizes[pageSize];
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
'use strict';
|
||||
|
||||
/* global require */
|
||||
|
||||
// Monkey-patch the fs module.
|
||||
require('electron/js2c/asar').wrapFsWithAsar(require('fs'));
|
||||
|
||||
@@ -196,8 +196,6 @@ export class WebViewImpl {
|
||||
this.internalElement.contentWindow!
|
||||
);
|
||||
|
||||
// ResizeObserver is a browser global not recognized by "standard".
|
||||
/* globals ResizeObserver */
|
||||
// TODO(zcbenz): Should we deprecate the "resize" event? Wait, it is not
|
||||
// even documented.
|
||||
this.resizeObserver = new ResizeObserver(this.onElementResize.bind(this));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint no-eval: "off" */
|
||||
/* global binding, Buffer */
|
||||
/* global binding */
|
||||
import * as events from 'events';
|
||||
|
||||
const { EventEmitter } = events;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
'use strict';
|
||||
import * as path from 'path';
|
||||
|
||||
const path = require('path');
|
||||
const Module = require('module');
|
||||
|
||||
// We modified the original process.argv to let node.js load the
|
||||
75
package.json
75
package.json
@@ -1,68 +1,68 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "11.0.0-nightly.20200708",
|
||||
"version": "11.0.0-nightly.20200713",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
"@electron/docs-parser": "^0.7.2",
|
||||
"@electron/typescript-definitions": "^8.7.2",
|
||||
"@electron/docs-parser": "^0.9.1",
|
||||
"@electron/typescript-definitions": "^8.7.4",
|
||||
"@octokit/rest": "^16.3.2",
|
||||
"@primer/octicons": "^9.1.1",
|
||||
"@primer/octicons": "^10.0.0",
|
||||
"@types/basic-auth": "^1.1.3",
|
||||
"@types/busboy": "^0.2.3",
|
||||
"@types/chai": "^4.2.11",
|
||||
"@types/chai-as-promised": "^7.1.2",
|
||||
"@types/chai-as-promised": "^7.1.3",
|
||||
"@types/dirty-chai": "^2.0.2",
|
||||
"@types/express": "^4.17.3",
|
||||
"@types/fs-extra": "^8.1.0",
|
||||
"@types/express": "^4.17.7",
|
||||
"@types/fs-extra": "^9.0.1",
|
||||
"@types/mocha": "^7.0.2",
|
||||
"@types/node": "^12.12.6",
|
||||
"@types/semver": "^7.1.0",
|
||||
"@types/semver": "^7.3.1",
|
||||
"@types/send": "^0.14.5",
|
||||
"@types/split": "^1.0.0",
|
||||
"@types/uuid": "^3.4.6",
|
||||
"@types/webpack": "^4.41.7",
|
||||
"@types/webpack-env": "^1.15.1",
|
||||
"@typescript-eslint/eslint-plugin": "^2.24.0",
|
||||
"@typescript-eslint/parser": "^2.24.0",
|
||||
"asar": "^3.0.1",
|
||||
"@types/webpack": "^4.41.21",
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"@typescript-eslint/eslint-plugin": "^3.6.0",
|
||||
"@typescript-eslint/parser": "^3.6.0",
|
||||
"asar": "^3.0.3",
|
||||
"check-for-leaks": "^1.2.1",
|
||||
"colors": "^1.1.2",
|
||||
"colors": "^1.4.0",
|
||||
"dotenv-safe": "^4.0.4",
|
||||
"dugite": "^1.45.0",
|
||||
"eslint": "^5.13.0",
|
||||
"eslint-config-standard": "^12.0.0",
|
||||
"eslint-plugin-import": "^2.17.2",
|
||||
"eslint-plugin-mocha": "^5.2.0",
|
||||
"eslint-plugin-node": "^8.0.1",
|
||||
"eslint-plugin-standard": "^4.0.0",
|
||||
"eslint": "^7.4.0",
|
||||
"eslint-config-standard": "^14.1.1",
|
||||
"eslint-plugin-import": "^2.22.0",
|
||||
"eslint-plugin-mocha": "^7.0.1",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-standard": "^4.0.1",
|
||||
"eslint-plugin-typescript": "^0.14.0",
|
||||
"express": "^4.16.4",
|
||||
"folder-hash": "^2.1.1",
|
||||
"fs-extra": "^7.0.1",
|
||||
"fs-extra": "^9.0.1",
|
||||
"husky": "^2.2.0",
|
||||
"klaw": "^3.0.0",
|
||||
"lint": "^1.1.2",
|
||||
"lint-staged": "^8.1.0",
|
||||
"minimist": "^1.2.0",
|
||||
"lint-staged": "^10.2.11",
|
||||
"minimist": "^1.2.5",
|
||||
"nugget": "^2.0.1",
|
||||
"null-loader": "^4.0.0",
|
||||
"pre-flight": "^1.1.0",
|
||||
"remark-cli": "^4.0.0",
|
||||
"remark-preset-lint-markdown-style-guide": "^2.1.1",
|
||||
"request": "^2.88.0",
|
||||
"request": "^2.88.2",
|
||||
"semver": "^5.6.0",
|
||||
"shx": "^0.3.2",
|
||||
"standard-markdown": "^5.0.0",
|
||||
"standard-markdown": "^6.0.0",
|
||||
"sumchecker": "^2.0.2",
|
||||
"tap-xunit": "^2.4.1",
|
||||
"temp": "^0.8.3",
|
||||
"timers-browserify": "1.4.2",
|
||||
"ts-loader": "^6.0.2",
|
||||
"ts-node": "^6.0.3",
|
||||
"typescript": "^3.8.3",
|
||||
"webpack": "^4.42.0",
|
||||
"webpack-cli": "^3.3.11"
|
||||
"ts-loader": "^7.0.5",
|
||||
"ts-node": "6.2.0",
|
||||
"typescript": "^3.9.6",
|
||||
"webpack": "^4.43.0",
|
||||
"webpack-cli": "^3.3.12"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@@ -105,28 +105,23 @@
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,ts}": [
|
||||
"node script/lint.js --js --fix --only --",
|
||||
"git add"
|
||||
"node script/lint.js --js --fix --only --"
|
||||
],
|
||||
"*.{js,ts,d.ts}": [
|
||||
"node script/gen-filenames.js",
|
||||
"git add"
|
||||
"node script/gen-filenames.js"
|
||||
],
|
||||
"*.{cc,mm,c,h}": [
|
||||
"python script/run-clang-format.py -r -c --fix",
|
||||
"git add"
|
||||
"python script/run-clang-format.py -r -c --fix"
|
||||
],
|
||||
"*.md": [
|
||||
"npm run lint:docs"
|
||||
],
|
||||
"*.{gn,gni}": [
|
||||
"npm run gn-check",
|
||||
"python script/run-gn-format.py",
|
||||
"git add"
|
||||
"python script/run-gn-format.py"
|
||||
],
|
||||
"*.py": [
|
||||
"node script/lint.js --py --fix --only --",
|
||||
"git add"
|
||||
"node script/lint.js --py --fix --only --"
|
||||
],
|
||||
"docs/api/**/*.md": [
|
||||
"node script/gen-filenames.js",
|
||||
|
||||
@@ -90,7 +90,7 @@ index adb208ba3589e32536527219aaf4e89e3ee3311a..301f6416898445eed814d67901254ef8
|
||||
}
|
||||
|
||||
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
|
||||
index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc473bbd0da 100644
|
||||
index 8a743d0dd74b087059ff812019ae568a22c5fa01..551dbc7b0bfdbf4ca549278bb3dfc4e3abb5cf0f 100644
|
||||
--- a/chrome/browser/printing/print_view_manager_base.cc
|
||||
+++ b/chrome/browser/printing/print_view_manager_base.cc
|
||||
@@ -27,10 +27,7 @@
|
||||
@@ -194,7 +194,19 @@ index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc4
|
||||
#endif
|
||||
|
||||
ReleasePrinterQuery();
|
||||
@@ -463,9 +476,13 @@ void PrintViewManagerBase::OnNotifyPrintJobEvent(
|
||||
@@ -382,6 +395,11 @@ void PrintViewManagerBase::OnScriptedPrint(
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::OnShowInvalidPrinterSettingsError() {
|
||||
+ if (!callback_.is_null()) {
|
||||
+ std::string cb_str = "Invalid printer settings";
|
||||
+ std::move(callback_).Run(printing_succeeded_, cb_str);
|
||||
+ }
|
||||
+
|
||||
base::ThreadTaskRunnerHandle::Get()->PostTask(
|
||||
FROM_HERE, base::BindOnce(&ShowWarningMessageBox,
|
||||
l10n_util::GetStringUTF16(
|
||||
@@ -463,9 +481,13 @@ void PrintViewManagerBase::OnNotifyPrintJobEvent(
|
||||
content::NotificationService::NoDetails());
|
||||
break;
|
||||
}
|
||||
@@ -210,7 +222,7 @@ index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc4
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
@@ -560,8 +577,10 @@ bool PrintViewManagerBase::CreateNewPrintJob(
|
||||
@@ -560,8 +582,10 @@ bool PrintViewManagerBase::CreateNewPrintJob(
|
||||
DCHECK(!quit_inner_loop_);
|
||||
DCHECK(query);
|
||||
|
||||
@@ -223,7 +235,7 @@ index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc4
|
||||
|
||||
// We can't print if there is no renderer.
|
||||
if (!web_contents()->GetRenderViewHost() ||
|
||||
@@ -582,8 +601,6 @@ bool PrintViewManagerBase::CreateNewPrintJob(
|
||||
@@ -582,8 +606,6 @@ bool PrintViewManagerBase::CreateNewPrintJob(
|
||||
print_job_->SetSource(source, /*source_id=*/"");
|
||||
#endif
|
||||
|
||||
@@ -232,7 +244,7 @@ index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc4
|
||||
printing_succeeded_ = false;
|
||||
return true;
|
||||
}
|
||||
@@ -632,14 +649,22 @@ void PrintViewManagerBase::ReleasePrintJob() {
|
||||
@@ -632,14 +654,22 @@ void PrintViewManagerBase::ReleasePrintJob() {
|
||||
content::RenderFrameHost* rfh = printing_rfh_;
|
||||
printing_rfh_ = nullptr;
|
||||
|
||||
@@ -257,7 +269,7 @@ index 8a743d0dd74b087059ff812019ae568a22c5fa01..20c43be03706617a276d210190897dc4
|
||||
// Don't close the worker thread.
|
||||
print_job_ = nullptr;
|
||||
}
|
||||
@@ -675,7 +700,7 @@ bool PrintViewManagerBase::RunInnerMessageLoop() {
|
||||
@@ -675,7 +705,7 @@ bool PrintViewManagerBase::RunInnerMessageLoop() {
|
||||
}
|
||||
|
||||
bool PrintViewManagerBase::OpportunisticallyCreatePrintJob(int cookie) {
|
||||
|
||||
@@ -90,7 +90,7 @@ const LINTERS = [{
|
||||
}
|
||||
}, {
|
||||
key: 'javascript',
|
||||
roots: ['lib', 'spec', 'spec-main', 'script', 'default_app'],
|
||||
roots: ['lib', 'spec', 'spec-main', 'script', 'default_app', 'build'],
|
||||
ignoreRoots: ['spec/node_modules', 'spec-main/node_modules'],
|
||||
test: filename => filename.endsWith('.js') || filename.endsWith('.ts'),
|
||||
run: (opts, filenames) => {
|
||||
|
||||
@@ -40,6 +40,7 @@ class GHKey {
|
||||
this.repo = repo;
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
static NewFromPull (pull) {
|
||||
const owner = pull.base.repo.owner.login;
|
||||
const repo = pull.base.repo.name;
|
||||
@@ -405,7 +406,7 @@ function getOldestMajorBranchOfPull (pull) {
|
||||
}
|
||||
|
||||
function getOldestMajorBranchOfCommit (commit, pool) {
|
||||
return [ ...commit.prKeys.values() ]
|
||||
return [...commit.prKeys.values()]
|
||||
.map(prKey => pool.pulls[prKey.number])
|
||||
.filter(pull => !!pull)
|
||||
.map(pull => getOldestMajorBranchOfPull(pull))
|
||||
@@ -531,13 +532,13 @@ const removeSupercededStackUpdates = (commits) => {
|
||||
notupdates.push(commit);
|
||||
continue;
|
||||
}
|
||||
const [ , dep, version ] = match;
|
||||
const [, dep, version] = match;
|
||||
if (!newest[dep] || newest[dep].version < version) {
|
||||
newest[dep] = { commit, version };
|
||||
}
|
||||
}
|
||||
|
||||
return [ ...notupdates, ...Object.values(newest).map(o => o.commit) ];
|
||||
return [...notupdates, ...Object.values(newest).map(o => o.commit)];
|
||||
};
|
||||
|
||||
/***
|
||||
|
||||
@@ -738,11 +738,11 @@ void BaseWindow::AddBrowserView(v8::Local<v8::Value> value) {
|
||||
gin::Handle<BrowserView> browser_view;
|
||||
if (value->IsObject() &&
|
||||
gin::ConvertFromV8(isolate(), value, &browser_view)) {
|
||||
auto get_that_view = browser_views_.find(browser_view->weak_map_id());
|
||||
auto get_that_view = browser_views_.find(browser_view->ID());
|
||||
if (get_that_view == browser_views_.end()) {
|
||||
window_->AddBrowserView(browser_view->view());
|
||||
browser_view->web_contents()->SetOwnerWindow(window_.get());
|
||||
browser_views_[browser_view->weak_map_id()].Reset(isolate(), value);
|
||||
browser_views_[browser_view->ID()].Reset(isolate(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -751,7 +751,7 @@ void BaseWindow::RemoveBrowserView(v8::Local<v8::Value> value) {
|
||||
gin::Handle<BrowserView> browser_view;
|
||||
if (value->IsObject() &&
|
||||
gin::ConvertFromV8(isolate(), value, &browser_view)) {
|
||||
auto get_that_view = browser_views_.find(browser_view->weak_map_id());
|
||||
auto get_that_view = browser_views_.find(browser_view->ID());
|
||||
if (get_that_view != browser_views_.end()) {
|
||||
window_->RemoveBrowserView(browser_view->view());
|
||||
browser_view->web_contents()->SetOwnerWindow(nullptr);
|
||||
|
||||
@@ -52,12 +52,24 @@ struct Converter<electron::AutoResizeFlags> {
|
||||
|
||||
} // namespace gin
|
||||
|
||||
namespace {
|
||||
|
||||
int32_t GetNextId() {
|
||||
static int32_t next_id = 1;
|
||||
return next_id++;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace electron {
|
||||
|
||||
namespace api {
|
||||
|
||||
gin::WrapperInfo BrowserView::kWrapperInfo = {gin::kEmbedderNativeGin};
|
||||
|
||||
BrowserView::BrowserView(gin::Arguments* args,
|
||||
const gin_helper::Dictionary& options) {
|
||||
const gin_helper::Dictionary& options)
|
||||
: id_(GetNextId()) {
|
||||
v8::Isolate* isolate = args->isolate();
|
||||
gin_helper::Dictionary web_preferences =
|
||||
gin::Dictionary::CreateEmpty(isolate);
|
||||
@@ -72,8 +84,6 @@ BrowserView::BrowserView(gin::Arguments* args,
|
||||
|
||||
view_.reset(
|
||||
NativeBrowserView::Create(api_web_contents_->managed_web_contents()));
|
||||
|
||||
InitWithArgs(args);
|
||||
}
|
||||
|
||||
BrowserView::~BrowserView() {
|
||||
@@ -87,24 +97,24 @@ BrowserView::~BrowserView() {
|
||||
void BrowserView::WebContentsDestroyed() {
|
||||
api_web_contents_ = nullptr;
|
||||
web_contents_.Reset();
|
||||
Unpin();
|
||||
}
|
||||
|
||||
// static
|
||||
gin_helper::WrappableBase* BrowserView::New(gin_helper::ErrorThrower thrower,
|
||||
gin::Arguments* args) {
|
||||
gin::Handle<BrowserView> BrowserView::New(gin_helper::ErrorThrower thrower,
|
||||
gin::Arguments* args) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
thrower.ThrowError("Cannot create BrowserView before app is ready");
|
||||
return nullptr;
|
||||
return gin::Handle<BrowserView>();
|
||||
}
|
||||
|
||||
gin::Dictionary options = gin::Dictionary::CreateEmpty(args->isolate());
|
||||
args->GetNext(&options);
|
||||
|
||||
return new BrowserView(args, options);
|
||||
}
|
||||
|
||||
int32_t BrowserView::ID() const {
|
||||
return weak_map_id();
|
||||
auto handle =
|
||||
gin::CreateHandle(args->isolate(), new BrowserView(args, options));
|
||||
handle->Pin(args->isolate());
|
||||
return handle;
|
||||
}
|
||||
|
||||
void BrowserView::SetAutoResize(AutoResizeFlags flags) {
|
||||
@@ -123,26 +133,25 @@ void BrowserView::SetBackgroundColor(const std::string& color_name) {
|
||||
view_->SetBackgroundColor(ParseHexColor(color_name));
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> BrowserView::GetWebContents() {
|
||||
v8::Local<v8::Value> BrowserView::GetWebContents(v8::Isolate* isolate) {
|
||||
if (web_contents_.IsEmpty()) {
|
||||
return v8::Null(isolate());
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
return v8::Local<v8::Value>::New(isolate(), web_contents_);
|
||||
return v8::Local<v8::Value>::New(isolate, web_contents_);
|
||||
}
|
||||
|
||||
// static
|
||||
void BrowserView::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(gin::StringToV8(isolate, "BrowserView"));
|
||||
gin_helper::Destroyable::MakeDestroyable(isolate, prototype);
|
||||
gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
v8::Local<v8::ObjectTemplate> BrowserView::FillObjectTemplate(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::ObjectTemplate> templ) {
|
||||
return gin::ObjectTemplateBuilder(isolate, "BrowserView", templ)
|
||||
.SetMethod("setAutoResize", &BrowserView::SetAutoResize)
|
||||
.SetMethod("setBounds", &BrowserView::SetBounds)
|
||||
.SetMethod("getBounds", &BrowserView::GetBounds)
|
||||
.SetMethod("setBackgroundColor", &BrowserView::SetBackgroundColor)
|
||||
.SetProperty("webContents", &BrowserView::GetWebContents)
|
||||
.SetProperty("id", &BrowserView::ID);
|
||||
.Build();
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
@@ -158,16 +167,9 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
BrowserView::SetConstructor(isolate, base::BindRepeating(&BrowserView::New));
|
||||
|
||||
gin_helper::Dictionary browser_view(isolate,
|
||||
BrowserView::GetConstructor(isolate)
|
||||
->GetFunction(context)
|
||||
.ToLocalChecked());
|
||||
browser_view.SetMethod("fromId", &BrowserView::FromWeakMapID);
|
||||
browser_view.SetMethod("getAllViews", &BrowserView::GetAll);
|
||||
gin_helper::Dictionary dict(isolate, exports);
|
||||
dict.Set("BrowserView", browser_view);
|
||||
dict.Set("BrowserView", BrowserView::GetConstructor(context));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -10,9 +10,11 @@
|
||||
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "gin/handle.h"
|
||||
#include "gin/wrappable.h"
|
||||
#include "shell/browser/native_browser_view.h"
|
||||
#include "shell/common/gin_helper/constructible.h"
|
||||
#include "shell/common/gin_helper/error_thrower.h"
|
||||
#include "shell/common/gin_helper/trackable_object.h"
|
||||
#include "shell/common/gin_helper/pinnable.h"
|
||||
|
||||
namespace gfx {
|
||||
class Rect;
|
||||
@@ -30,19 +32,25 @@ namespace api {
|
||||
|
||||
class WebContents;
|
||||
|
||||
class BrowserView : public gin_helper::TrackableObject<BrowserView>,
|
||||
class BrowserView : public gin::Wrappable<BrowserView>,
|
||||
public gin_helper::Constructible<BrowserView>,
|
||||
public gin_helper::Pinnable<BrowserView>,
|
||||
public content::WebContentsObserver {
|
||||
public:
|
||||
static gin_helper::WrappableBase* New(gin_helper::ErrorThrower thrower,
|
||||
gin::Arguments* args);
|
||||
// gin_helper::Constructible
|
||||
static gin::Handle<BrowserView> New(gin_helper::ErrorThrower thrower,
|
||||
gin::Arguments* args);
|
||||
static v8::Local<v8::ObjectTemplate> FillObjectTemplate(
|
||||
v8::Isolate*,
|
||||
v8::Local<v8::ObjectTemplate>);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
// gin::Wrappable
|
||||
static gin::WrapperInfo kWrapperInfo;
|
||||
|
||||
WebContents* web_contents() const { return api_web_contents_; }
|
||||
NativeBrowserView* view() const { return view_.get(); }
|
||||
|
||||
int32_t ID() const;
|
||||
int32_t ID() const { return id_; }
|
||||
|
||||
protected:
|
||||
BrowserView(gin::Arguments* args, const gin_helper::Dictionary& options);
|
||||
@@ -56,13 +64,15 @@ class BrowserView : public gin_helper::TrackableObject<BrowserView>,
|
||||
void SetBounds(const gfx::Rect& bounds);
|
||||
gfx::Rect GetBounds();
|
||||
void SetBackgroundColor(const std::string& color_name);
|
||||
v8::Local<v8::Value> GetWebContents();
|
||||
v8::Local<v8::Value> GetWebContents(v8::Isolate*);
|
||||
|
||||
v8::Global<v8::Value> web_contents_;
|
||||
class WebContents* api_web_contents_ = nullptr;
|
||||
|
||||
std::unique_ptr<NativeBrowserView> view_;
|
||||
|
||||
int32_t id_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BrowserView);
|
||||
};
|
||||
|
||||
|
||||
@@ -276,6 +276,10 @@ void BrowserWindow::OnCloseButtonClicked(bool* prevent_default) {
|
||||
}
|
||||
|
||||
void BrowserWindow::OnWindowClosed() {
|
||||
// We need to reset the browser views before we call Cleanup, because the
|
||||
// browser views are child views of the main web contents view, which will be
|
||||
// deleted by Cleanup.
|
||||
BaseWindow::ResetBrowserViews();
|
||||
Cleanup();
|
||||
// See BaseWindow::OnWindowClosed on why calling InvalidateWeakPtrs.
|
||||
weak_factory_.InvalidateWeakPtrs();
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 11,0,0,20200708
|
||||
PRODUCTVERSION 11,0,0,20200708
|
||||
FILEVERSION 11,0,0,20200713
|
||||
PRODUCTVERSION 11,0,0,20200713
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
@@ -71,9 +71,8 @@ void Clipboard::WriteBuffer(const std::string& format,
|
||||
base::span<const uint8_t> payload_span(
|
||||
reinterpret_cast<const uint8_t*>(node::Buffer::Data(buffer)),
|
||||
node::Buffer::Length(buffer));
|
||||
writer.WriteData(
|
||||
base::UTF8ToUTF16(ui::ClipboardFormatType::GetType(format).Serialize()),
|
||||
mojo_base::BigBuffer(payload_span));
|
||||
writer.WriteData(base::UTF8ToUTF16(format),
|
||||
mojo_base::BigBuffer(payload_span));
|
||||
}
|
||||
|
||||
void Clipboard::Write(const gin_helper::Dictionary& data,
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
#ifndef SHELL_COMMON_GIN_HELPER_CONSTRUCTIBLE_H_
|
||||
#define SHELL_COMMON_GIN_HELPER_CONSTRUCTIBLE_H_
|
||||
|
||||
#include "gin/per_isolate_data.h"
|
||||
#include "gin/wrappable.h"
|
||||
#include "shell/browser/event_emitter_mixin.h"
|
||||
#include "shell/common/gin_helper/function_template_extensions.h"
|
||||
|
||||
namespace gin_helper {
|
||||
|
||||
@@ -96,25 +96,25 @@ ELECTRON_DESKTOP_CAPTURER_MODULE(V)
|
||||
namespace {
|
||||
|
||||
void stop_and_close_uv_loop(uv_loop_t* loop) {
|
||||
// Close any active handles
|
||||
uv_stop(loop);
|
||||
uv_walk(
|
||||
loop,
|
||||
[](uv_handle_t* handle, void*) {
|
||||
if (!uv_is_closing(handle)) {
|
||||
uv_close(handle, nullptr);
|
||||
}
|
||||
},
|
||||
nullptr);
|
||||
int error = uv_loop_close(loop);
|
||||
|
||||
// Run the loop to let it finish all the closing handles
|
||||
// NB: after uv_stop(), uv_run(UV_RUN_DEFAULT) returns 0 when that's done
|
||||
for (;;)
|
||||
if (!uv_run(loop, UV_RUN_DEFAULT))
|
||||
break;
|
||||
while (error) {
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
uv_stop(loop);
|
||||
uv_walk(
|
||||
loop,
|
||||
[](uv_handle_t* handle, void*) {
|
||||
if (!uv_is_closing(handle)) {
|
||||
uv_close(handle, nullptr);
|
||||
}
|
||||
},
|
||||
nullptr);
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
error = uv_loop_close(loop);
|
||||
}
|
||||
|
||||
DCHECK(!uv_loop_alive(loop));
|
||||
uv_loop_close(loop);
|
||||
DCHECK_EQ(error, 0);
|
||||
}
|
||||
|
||||
bool g_is_initialized = false;
|
||||
@@ -274,6 +274,7 @@ NodeBindings::~NodeBindings() {
|
||||
// Quit the embed thread.
|
||||
embed_closed_ = true;
|
||||
uv_sem_post(&embed_sem_);
|
||||
|
||||
WakeupEmbedThread();
|
||||
|
||||
// Wait for everything to be done.
|
||||
@@ -284,7 +285,7 @@ NodeBindings::~NodeBindings() {
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&dummy_uv_handle_), nullptr);
|
||||
|
||||
// Clean up worker loop
|
||||
if (uv_loop_ == &worker_loop_)
|
||||
if (in_worker_loop())
|
||||
stop_and_close_uv_loop(uv_loop_);
|
||||
}
|
||||
|
||||
@@ -501,7 +502,8 @@ void NodeBindings::WakeupMainThread() {
|
||||
}
|
||||
|
||||
void NodeBindings::WakeupEmbedThread() {
|
||||
uv_async_send(&dummy_uv_handle_);
|
||||
if (!in_worker_loop())
|
||||
uv_async_send(&dummy_uv_handle_);
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -58,6 +58,8 @@ class NodeBindings {
|
||||
|
||||
uv_loop_t* uv_loop() const { return uv_loop_; }
|
||||
|
||||
bool in_worker_loop() const { return uv_loop_ == &worker_loop_; }
|
||||
|
||||
protected:
|
||||
explicit NodeBindings(BrowserEnvironment browser_env);
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { expect } from 'chai';
|
||||
import * as ChildProcess from 'child_process';
|
||||
import * as path from 'path';
|
||||
import { emittedOnce } from './events-helpers';
|
||||
import { BrowserView, BrowserWindow } from 'electron/main';
|
||||
import { BrowserView, BrowserWindow, webContents } from 'electron/main';
|
||||
import { closeWindow } from './window-helpers';
|
||||
import { defer, startRemoteControlApp } from './spec-helpers';
|
||||
|
||||
describe('BrowserView module', () => {
|
||||
const fixtures = path.resolve(__dirname, '..', 'spec', 'fixtures');
|
||||
@@ -12,6 +12,7 @@ describe('BrowserView module', () => {
|
||||
let view: BrowserView;
|
||||
|
||||
beforeEach(() => {
|
||||
expect(webContents.getAllWebContents()).to.have.length(0);
|
||||
w = new BrowserWindow({
|
||||
show: false,
|
||||
width: 400,
|
||||
@@ -23,27 +24,19 @@ describe('BrowserView module', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
const p = emittedOnce(w.webContents, 'destroyed');
|
||||
await closeWindow(w);
|
||||
w = null as any;
|
||||
await p;
|
||||
|
||||
if (view) {
|
||||
view.destroy();
|
||||
const p = emittedOnce(view.webContents, 'destroyed');
|
||||
(view.webContents as any).destroy();
|
||||
view = null as any;
|
||||
await p;
|
||||
}
|
||||
});
|
||||
|
||||
describe('BrowserView.destroy()', () => {
|
||||
it('does not throw', () => {
|
||||
view = new BrowserView();
|
||||
view.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('BrowserView.isDestroyed()', () => {
|
||||
it('returns correct value', () => {
|
||||
view = new BrowserView();
|
||||
expect(view.isDestroyed()).to.be.false('view is destroyed');
|
||||
view.destroy();
|
||||
expect(view.isDestroyed()).to.be.true('view is destroyed');
|
||||
});
|
||||
expect(webContents.getAllWebContents()).to.have.length(0);
|
||||
});
|
||||
|
||||
describe('BrowserView.setBackgroundColor()', () => {
|
||||
@@ -119,7 +112,6 @@ describe('BrowserView module', () => {
|
||||
it('returns the set view', () => {
|
||||
view = new BrowserView();
|
||||
w.setBrowserView(view);
|
||||
expect(view.id).to.not.be.null('view id');
|
||||
|
||||
const view2 = w.getBrowserView();
|
||||
expect(view2!.webContents.id).to.equal(view.webContents.id);
|
||||
@@ -134,11 +126,13 @@ describe('BrowserView module', () => {
|
||||
describe('BrowserWindow.addBrowserView()', () => {
|
||||
it('does not throw for valid args', () => {
|
||||
const view1 = new BrowserView();
|
||||
defer(() => (view1.webContents as any).destroy());
|
||||
w.addBrowserView(view1);
|
||||
defer(() => w.removeBrowserView(view1));
|
||||
const view2 = new BrowserView();
|
||||
defer(() => (view2.webContents as any).destroy());
|
||||
w.addBrowserView(view2);
|
||||
view1.destroy();
|
||||
view2.destroy();
|
||||
defer(() => w.removeBrowserView(view2));
|
||||
});
|
||||
it('does not throw if called multiple times with same view', () => {
|
||||
view = new BrowserView();
|
||||
@@ -160,18 +154,18 @@ describe('BrowserView module', () => {
|
||||
describe('BrowserWindow.getBrowserViews()', () => {
|
||||
it('returns same views as was added', () => {
|
||||
const view1 = new BrowserView();
|
||||
defer(() => (view1.webContents as any).destroy());
|
||||
w.addBrowserView(view1);
|
||||
defer(() => w.removeBrowserView(view1));
|
||||
const view2 = new BrowserView();
|
||||
defer(() => (view2.webContents as any).destroy());
|
||||
w.addBrowserView(view2);
|
||||
defer(() => w.removeBrowserView(view2));
|
||||
|
||||
expect(view1.id).to.be.not.null('view id');
|
||||
const views = w.getBrowserViews();
|
||||
expect(views).to.have.lengthOf(2);
|
||||
expect(views[0].webContents.id).to.equal(view1.webContents.id);
|
||||
expect(views[1].webContents.id).to.equal(view2.webContents.id);
|
||||
|
||||
view1.destroy();
|
||||
view2.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -188,46 +182,33 @@ describe('BrowserView module', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('BrowserView.fromId()', () => {
|
||||
it('returns the view with given id', () => {
|
||||
view = new BrowserView();
|
||||
w.setBrowserView(view);
|
||||
expect(view.id).to.not.be.null('view id');
|
||||
|
||||
const view2 = BrowserView.fromId(view.id);
|
||||
expect(view2.webContents.id).to.equal(view.webContents.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('BrowserView.fromWebContents()', () => {
|
||||
it('returns the view with given id', () => {
|
||||
view = new BrowserView();
|
||||
w.setBrowserView(view);
|
||||
expect(view.id).to.not.be.null('view id');
|
||||
|
||||
const view2 = BrowserView.fromWebContents(view.webContents);
|
||||
expect(view2!.webContents.id).to.equal(view.webContents.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('BrowserView.getAllViews()', () => {
|
||||
it('returns all views', () => {
|
||||
view = new BrowserView();
|
||||
w.setBrowserView(view);
|
||||
expect(view.id).to.not.be.null('view id');
|
||||
|
||||
const views = BrowserView.getAllViews();
|
||||
expect(views).to.be.an('array').that.has.lengthOf(1);
|
||||
expect(views[0].webContents.id).to.equal(view.webContents.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('new BrowserView()', () => {
|
||||
describe('shutdown behavior', () => {
|
||||
it('does not crash on exit', async () => {
|
||||
const appPath = path.join(__dirname, 'fixtures', 'api', 'leak-exit-browserview.js');
|
||||
const electronPath = process.execPath;
|
||||
const appProcess = ChildProcess.spawn(electronPath, [appPath]);
|
||||
const [code] = await emittedOnce(appProcess, 'exit');
|
||||
const rc = await startRemoteControlApp();
|
||||
await rc.remotely(() => {
|
||||
const { BrowserView, app } = require('electron');
|
||||
new BrowserView({}) // eslint-disable-line
|
||||
setTimeout(() => {
|
||||
app.quit();
|
||||
});
|
||||
});
|
||||
const [code] = await emittedOnce(rc.process, 'exit');
|
||||
expect(code).to.equal(0);
|
||||
});
|
||||
|
||||
it('does not crash on exit if added to a browser window', async () => {
|
||||
const rc = await startRemoteControlApp();
|
||||
await rc.remotely(() => {
|
||||
const { app, BrowserView, BrowserWindow } = require('electron');
|
||||
const bv = new BrowserView();
|
||||
bv.webContents.loadURL('about:blank');
|
||||
const bw = new BrowserWindow({ show: false });
|
||||
bw.addBrowserView(bv);
|
||||
setTimeout(() => {
|
||||
app.quit();
|
||||
});
|
||||
});
|
||||
const [code] = await emittedOnce(rc.process, 'exit');
|
||||
expect(code).to.equal(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@ import { AddressInfo } from 'net';
|
||||
import { app, BrowserWindow, BrowserView, ipcMain, OnBeforeSendHeadersListenerDetails, protocol, screen, webContents, session, WebContents } from 'electron/main';
|
||||
|
||||
import { emittedOnce, emittedUntil } from './events-helpers';
|
||||
import { ifit, ifdescribe, delay } from './spec-helpers';
|
||||
import { ifit, ifdescribe, defer, delay } from './spec-helpers';
|
||||
import { closeWindow, closeAllWindows } from './window-helpers';
|
||||
|
||||
const features = process._linkedBinding('electron_common_features');
|
||||
@@ -1007,7 +1007,7 @@ describe('BrowserWindow module', () => {
|
||||
});
|
||||
});
|
||||
|
||||
ifdescribe(process.platform === 'win32')(`Fullscreen state`, () => {
|
||||
ifdescribe(process.platform === 'win32')('Fullscreen state', () => {
|
||||
it('with properties', () => {
|
||||
it('can be set with the fullscreen constructor option', () => {
|
||||
w = new BrowserWindow({ fullscreen: true });
|
||||
@@ -1021,7 +1021,7 @@ describe('BrowserWindow module', () => {
|
||||
expect(w.fullScreen).to.be.true();
|
||||
});
|
||||
|
||||
it(`checks normal bounds when fullscreen'ed`, async () => {
|
||||
it('checks normal bounds when fullscreen\'ed', async () => {
|
||||
const bounds = w.getBounds();
|
||||
const enterFullScreen = emittedOnce(w, 'enter-full-screen');
|
||||
w.show();
|
||||
@@ -1030,7 +1030,7 @@ describe('BrowserWindow module', () => {
|
||||
expectBoundsEqual(w.getNormalBounds(), bounds);
|
||||
});
|
||||
|
||||
it(`checks normal bounds when unfullscreen'ed`, async () => {
|
||||
it('checks normal bounds when unfullscreen\'ed', async () => {
|
||||
const bounds = w.getBounds();
|
||||
w.once('enter-full-screen', () => {
|
||||
w.fullScreen = false;
|
||||
@@ -1056,7 +1056,7 @@ describe('BrowserWindow module', () => {
|
||||
expect(w.isFullScreen()).to.be.true();
|
||||
});
|
||||
|
||||
it(`checks normal bounds when fullscreen'ed`, async () => {
|
||||
it('checks normal bounds when fullscreen\'ed', async () => {
|
||||
const bounds = w.getBounds();
|
||||
w.show();
|
||||
|
||||
@@ -1067,7 +1067,7 @@ describe('BrowserWindow module', () => {
|
||||
expectBoundsEqual(w.getNormalBounds(), bounds);
|
||||
});
|
||||
|
||||
it(`checks normal bounds when unfullscreen'ed`, async () => {
|
||||
it('checks normal bounds when unfullscreen\'ed', async () => {
|
||||
const bounds = w.getBounds();
|
||||
w.show();
|
||||
|
||||
@@ -1518,16 +1518,19 @@ describe('BrowserWindow module', () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
const bv = new BrowserView();
|
||||
w.setBrowserView(bv);
|
||||
defer(() => {
|
||||
w.removeBrowserView(bv);
|
||||
(bv.webContents as any).destroy();
|
||||
});
|
||||
expect(BrowserWindow.fromBrowserView(bv)!.id).to.equal(w.id);
|
||||
// if BrowserView isn't explicitly destroyed, it will crash in GC later
|
||||
bv.destroy();
|
||||
});
|
||||
|
||||
it('returns undefined if not attached', () => {
|
||||
const bv = new BrowserView();
|
||||
defer(() => {
|
||||
(bv.webContents as any).destroy();
|
||||
});
|
||||
expect(BrowserWindow.fromBrowserView(bv)).to.be.null('BrowserWindow associated with bv');
|
||||
// if BrowserView isn't explicitly destroyed, it will crash in GC later
|
||||
bv.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@ ifdescribe(!isLinuxOnArm && !process.mas && !process.env.DISABLE_CRASH_REPORTER_
|
||||
require('electron').crashReporter.start({
|
||||
submitURL: `http://127.0.0.1:${port}`,
|
||||
ignoreSystemCrashHandler: true,
|
||||
extra: { 'longParam': 'a'.repeat(130) }
|
||||
extra: { longParam: 'a'.repeat(130) }
|
||||
});
|
||||
setTimeout(() => process.crash());
|
||||
}, port);
|
||||
@@ -381,7 +381,7 @@ ifdescribe(!isLinuxOnArm && !process.mas && !process.env.DISABLE_CRASH_REPORTER_
|
||||
await remotely(() => {
|
||||
require('electron').crashReporter.start({
|
||||
submitURL: 'http://127.0.0.1',
|
||||
extra: { 'extra1': 'hi' }
|
||||
extra: { extra1: 'hi' }
|
||||
});
|
||||
});
|
||||
const parameters = await remotely(() => require('electron').crashReporter.getParameters());
|
||||
@@ -414,8 +414,8 @@ ifdescribe(!isLinuxOnArm && !process.mas && !process.env.DISABLE_CRASH_REPORTER_
|
||||
crashReporter.start({ submitURL: 'http://' });
|
||||
const bw = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } });
|
||||
bw.loadURL('about:blank');
|
||||
await bw.webContents.executeJavaScript(`require('electron').crashReporter.addExtraParameter('hello', 'world')`);
|
||||
return bw.webContents.executeJavaScript(`require('electron').crashReporter.getParameters()`);
|
||||
await bw.webContents.executeJavaScript('require(\'electron\').crashReporter.addExtraParameter(\'hello\', \'world\')');
|
||||
return bw.webContents.executeJavaScript('require(\'electron\').crashReporter.getParameters()');
|
||||
});
|
||||
if (process.platform === 'linux') {
|
||||
// On Linux, 'getParameters' will also include the global parameters,
|
||||
|
||||
@@ -523,7 +523,7 @@ describe('net module', () => {
|
||||
session: sess
|
||||
});
|
||||
const response = await getResponse(urlRequest);
|
||||
expect(response.headers['x-cookie']).to.equal(`undefined`);
|
||||
expect(response.headers['x-cookie']).to.equal('undefined');
|
||||
});
|
||||
|
||||
it('should be able to use the sessions cookie store', async () => {
|
||||
|
||||
@@ -105,7 +105,7 @@ describe('session module', () => {
|
||||
});
|
||||
}
|
||||
|
||||
it(`fails to set cookies with samesite=garbage`, async () => {
|
||||
it('fails to set cookies with samesite=garbage', async () => {
|
||||
const { cookies } = session.defaultSession;
|
||||
const value = 'hithere';
|
||||
await expect(cookies.set({ url, value, sameSite: 'garbage' as any })).to.eventually.be.rejectedWith('Failed to convert \'garbage\' to an appropriate cookie same site value');
|
||||
|
||||
@@ -141,6 +141,17 @@ describe('webContents module', () => {
|
||||
}).to.throw('Unsupported pageSize: i-am-a-bad-pagesize');
|
||||
});
|
||||
|
||||
it('throws when an invalid custom pageSize is passed', () => {
|
||||
expect(() => {
|
||||
w.webContents.print({
|
||||
pageSize: {
|
||||
width: 100,
|
||||
height: 200
|
||||
}
|
||||
});
|
||||
}).to.throw('height and width properties must be minimum 352 microns.');
|
||||
});
|
||||
|
||||
it('does not crash with custom margins', () => {
|
||||
expect(() => {
|
||||
w.webContents.print({
|
||||
@@ -1905,7 +1916,7 @@ describe('webContents module', () => {
|
||||
wasCalled = true;
|
||||
});
|
||||
await w.loadURL('about:blank');
|
||||
await w.webContents.executeJavaScript(`window.open('about:blank')`);
|
||||
await w.webContents.executeJavaScript('window.open(\'about:blank\')');
|
||||
await new Promise((resolve) => { process.nextTick(resolve); });
|
||||
expect(wasCalled).to.equal(false);
|
||||
await closeAllWindows();
|
||||
|
||||
@@ -274,7 +274,7 @@ describe('chrome extensions', () => {
|
||||
await customSession.loadExtension(path.join(fixtures, 'extensions', 'persistent-background-page'));
|
||||
const w = new BrowserWindow({ show: false, webPreferences: { session: customSession } });
|
||||
const promise = emittedOnce(app, 'web-contents-created');
|
||||
await w.loadURL(`about:blank`);
|
||||
await w.loadURL('about:blank');
|
||||
const [, bgPageContents] = await promise;
|
||||
expect(bgPageContents.session).to.not.equal(undefined);
|
||||
});
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
const { BrowserView, app } = require('electron');
|
||||
app.whenReady().then(function () {
|
||||
new BrowserView({}) // eslint-disable-line
|
||||
|
||||
app.quit();
|
||||
});
|
||||
@@ -1,22 +1,25 @@
|
||||
const { app } = require('electron');
|
||||
const http = require('http');
|
||||
const v8 = require('v8');
|
||||
|
||||
const server = http.createServer((req, res) => {
|
||||
const chunks = [];
|
||||
req.on('data', chunk => { chunks.push(chunk); });
|
||||
req.on('end', () => {
|
||||
const js = Buffer.concat(chunks).toString('utf8');
|
||||
(async () => {
|
||||
try {
|
||||
const result = await Promise.resolve(eval(js)); // eslint-disable-line no-eval
|
||||
res.end(v8.serialize({ result }));
|
||||
} catch (e) {
|
||||
res.end(v8.serialize({ error: e.stack }));
|
||||
}
|
||||
})();
|
||||
app.whenReady().then(() => {
|
||||
const server = http.createServer((req, res) => {
|
||||
const chunks = [];
|
||||
req.on('data', chunk => { chunks.push(chunk); });
|
||||
req.on('end', () => {
|
||||
const js = Buffer.concat(chunks).toString('utf8');
|
||||
(async () => {
|
||||
try {
|
||||
const result = await Promise.resolve(eval(js)); // eslint-disable-line no-eval
|
||||
res.end(v8.serialize({ result }));
|
||||
} catch (e) {
|
||||
res.end(v8.serialize({ error: e.stack }));
|
||||
}
|
||||
})();
|
||||
});
|
||||
}).listen(0, '127.0.0.1', () => {
|
||||
process.stdout.write(`Listening: ${server.address().port}\n`);
|
||||
});
|
||||
}).listen(0, '127.0.0.1', () => {
|
||||
process.stdout.write(`Listening: ${server.address().port}\n`);
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const { BrowserWindow } = require('electron');
|
||||
|
||||
class Foo {
|
||||
set bar (value) {
|
||||
set bar (value) { // eslint-disable-line accessor-pairs
|
||||
if (!(value instanceof BrowserWindow)) {
|
||||
throw new Error('setting error');
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class GitFake {
|
||||
|
||||
// find the newest shared commit between branches a and b
|
||||
mergeBase (a: string, b:string): string {
|
||||
for (const commit of [ ...this.branches[a].reverse() ]) {
|
||||
for (const commit of [...this.branches[a].reverse()]) {
|
||||
if (this.branches[b].map((commit: Commit) => commit.sha1).includes(commit.sha1)) {
|
||||
return commit.sha1;
|
||||
}
|
||||
@@ -57,7 +57,7 @@ class GitFake {
|
||||
stdout = this.branches[branch].map((commit: Commit) => commit.sha1).join('\n');
|
||||
} else if (args.length > 1 && args[0] === 'log' && args.includes('--format=%H,%s')) {
|
||||
// expected form: `git log --format=%H,%s sha1..branchName
|
||||
const [ start, branch ] = args[args.length - 1].split('..');
|
||||
const [start, branch] = args[args.length - 1].split('..');
|
||||
const lines : string[] = [];
|
||||
let started = false;
|
||||
for (const commit of this.branches[branch]) {
|
||||
@@ -108,7 +108,7 @@ describe('release notes', () => {
|
||||
const wrapper = (args: string[], path: string, options?: IGitExecutionOptions | undefined) => gitFake.exec(args, path, options);
|
||||
sandbox.replace(GitProcess, 'exec', wrapper);
|
||||
|
||||
gitFake.setBranch(oldBranch, [ ...sharedHistory, oldFix ]);
|
||||
gitFake.setBranch(oldBranch, [...sharedHistory, oldFix]);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -120,8 +120,8 @@ describe('release notes', () => {
|
||||
// while oldBranch was the latest stable release
|
||||
it('are skipped if the target version is a new major line (x.0.0)', async function () {
|
||||
const version = 'v9.0.0';
|
||||
gitFake.setBranch(oldBranch, [ ...sharedHistory, oldTropFix ]);
|
||||
gitFake.setBranch(newBranch, [ ...sharedHistory, newTropFix ]);
|
||||
gitFake.setBranch(oldBranch, [...sharedHistory, oldTropFix]);
|
||||
gitFake.setBranch(newBranch, [...sharedHistory, newTropFix]);
|
||||
const results: any = await notes.get(oldBranch, newBranch, version);
|
||||
expect(results.fix).to.have.lengthOf(0);
|
||||
});
|
||||
@@ -130,8 +130,8 @@ describe('release notes', () => {
|
||||
// multiple stable branches at once, including newBranch.
|
||||
it('are included if the target version is a minor or patch bump', async function () {
|
||||
const version = 'v9.0.1';
|
||||
gitFake.setBranch(oldBranch, [ ...sharedHistory, oldTropFix ]);
|
||||
gitFake.setBranch(newBranch, [ ...sharedHistory, newTropFix ]);
|
||||
gitFake.setBranch(oldBranch, [...sharedHistory, oldTropFix]);
|
||||
gitFake.setBranch(newBranch, [...sharedHistory, newTropFix]);
|
||||
const results: any = await notes.get(oldBranch, newBranch, version);
|
||||
expect(results.fix).to.have.lengthOf(1);
|
||||
});
|
||||
@@ -146,7 +146,7 @@ describe('release notes', () => {
|
||||
const testCommit = new Commit('89eb309d0b22bd4aec058ffaf983e81e56a5c378', 'feat: lole u got troled hard (#21891)');
|
||||
const version = 'v9.0.0';
|
||||
|
||||
gitFake.setBranch(newBranch, [ ...sharedHistory, testCommit ]);
|
||||
gitFake.setBranch(newBranch, [...sharedHistory, testCommit]);
|
||||
const results: any = await notes.get(oldBranch, newBranch, version);
|
||||
expect(results.feat).to.have.lengthOf(1);
|
||||
expect(results.feat[0].hash).to.equal(testCommit.sha1);
|
||||
@@ -160,7 +160,7 @@ describe('release notes', () => {
|
||||
|
||||
it("honors 'feat' type", async function () {
|
||||
const testCommit = newFeat;
|
||||
gitFake.setBranch(newBranch, [ ...sharedHistory, testCommit ]);
|
||||
gitFake.setBranch(newBranch, [...sharedHistory, testCommit]);
|
||||
const results: any = await notes.get(oldBranch, newBranch, version);
|
||||
expect(results.feat).to.have.lengthOf(1);
|
||||
expect(results.feat[0].hash).to.equal(testCommit.sha1);
|
||||
@@ -168,7 +168,7 @@ describe('release notes', () => {
|
||||
|
||||
it("honors 'fix' type", async function () {
|
||||
const testCommit = newFix;
|
||||
gitFake.setBranch(newBranch, [ ...sharedHistory, testCommit ]);
|
||||
gitFake.setBranch(newBranch, [...sharedHistory, testCommit]);
|
||||
const results: any = await notes.get(oldBranch, newBranch, version);
|
||||
expect(results.fix).to.have.lengthOf(1);
|
||||
expect(results.fix[0].hash).to.equal(testCommit.sha1);
|
||||
@@ -176,7 +176,7 @@ describe('release notes', () => {
|
||||
|
||||
it("honors 'BREAKING CHANGE' message", async function () {
|
||||
const testCommit = newBreaking;
|
||||
gitFake.setBranch(newBranch, [ ...sharedHistory, testCommit ]);
|
||||
gitFake.setBranch(newBranch, [...sharedHistory, testCommit]);
|
||||
const results: any = await notes.get(oldBranch, newBranch, version);
|
||||
expect(results.breaking).to.have.lengthOf(1);
|
||||
expect(results.breaking[0].hash).to.equal(testCommit.sha1);
|
||||
|
||||
@@ -38,106 +38,106 @@ function ToWebM (frames, outputAsArray) {
|
||||
|
||||
const EBML = [
|
||||
{
|
||||
'id': 0x1a45dfa3, // EBML
|
||||
'data': [
|
||||
id: 0x1a45dfa3, // EBML
|
||||
data: [
|
||||
{
|
||||
'data': 1,
|
||||
'id': 0x4286 // EBMLVersion
|
||||
data: 1,
|
||||
id: 0x4286 // EBMLVersion
|
||||
},
|
||||
{
|
||||
'data': 1,
|
||||
'id': 0x42f7 // EBMLReadVersion
|
||||
data: 1,
|
||||
id: 0x42f7 // EBMLReadVersion
|
||||
},
|
||||
{
|
||||
'data': 4,
|
||||
'id': 0x42f2 // EBMLMaxIDLength
|
||||
data: 4,
|
||||
id: 0x42f2 // EBMLMaxIDLength
|
||||
},
|
||||
{
|
||||
'data': 8,
|
||||
'id': 0x42f3 // EBMLMaxSizeLength
|
||||
data: 8,
|
||||
id: 0x42f3 // EBMLMaxSizeLength
|
||||
},
|
||||
{
|
||||
'data': 'webm',
|
||||
'id': 0x4282 // DocType
|
||||
data: 'webm',
|
||||
id: 0x4282 // DocType
|
||||
},
|
||||
{
|
||||
'data': 2,
|
||||
'id': 0x4287 // DocTypeVersion
|
||||
data: 2,
|
||||
id: 0x4287 // DocTypeVersion
|
||||
},
|
||||
{
|
||||
'data': 2,
|
||||
'id': 0x4285 // DocTypeReadVersion
|
||||
data: 2,
|
||||
id: 0x4285 // DocTypeReadVersion
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'id': 0x18538067, // Segment
|
||||
'data': [
|
||||
id: 0x18538067, // Segment
|
||||
data: [
|
||||
{
|
||||
'id': 0x1549a966, // Info
|
||||
'data': [
|
||||
id: 0x1549a966, // Info
|
||||
data: [
|
||||
{
|
||||
'data': 1e6, // do things in millisecs (num of nanosecs for duration scale)
|
||||
'id': 0x2ad7b1 // TimecodeScale
|
||||
data: 1e6, // do things in millisecs (num of nanosecs for duration scale)
|
||||
id: 0x2ad7b1 // TimecodeScale
|
||||
},
|
||||
{
|
||||
'data': 'whammy',
|
||||
'id': 0x4d80 // MuxingApp
|
||||
data: 'whammy',
|
||||
id: 0x4d80 // MuxingApp
|
||||
},
|
||||
{
|
||||
'data': 'whammy',
|
||||
'id': 0x5741 // WritingApp
|
||||
data: 'whammy',
|
||||
id: 0x5741 // WritingApp
|
||||
},
|
||||
{
|
||||
'data': doubleToString(info.duration),
|
||||
'id': 0x4489 // Duration
|
||||
data: doubleToString(info.duration),
|
||||
id: 0x4489 // Duration
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'id': 0x1654ae6b, // Tracks
|
||||
'data': [
|
||||
id: 0x1654ae6b, // Tracks
|
||||
data: [
|
||||
{
|
||||
'id': 0xae, // TrackEntry
|
||||
'data': [
|
||||
id: 0xae, // TrackEntry
|
||||
data: [
|
||||
{
|
||||
'data': 1,
|
||||
'id': 0xd7 // TrackNumber
|
||||
data: 1,
|
||||
id: 0xd7 // TrackNumber
|
||||
},
|
||||
{
|
||||
'data': 1,
|
||||
'id': 0x73c5 // TrackUID
|
||||
data: 1,
|
||||
id: 0x73c5 // TrackUID
|
||||
},
|
||||
{
|
||||
'data': 0,
|
||||
'id': 0x9c // FlagLacing
|
||||
data: 0,
|
||||
id: 0x9c // FlagLacing
|
||||
},
|
||||
{
|
||||
'data': 'und',
|
||||
'id': 0x22b59c // Language
|
||||
data: 'und',
|
||||
id: 0x22b59c // Language
|
||||
},
|
||||
{
|
||||
'data': 'V_VP8',
|
||||
'id': 0x86 // CodecID
|
||||
data: 'V_VP8',
|
||||
id: 0x86 // CodecID
|
||||
},
|
||||
{
|
||||
'data': 'VP8',
|
||||
'id': 0x258688 // CodecName
|
||||
data: 'VP8',
|
||||
id: 0x258688 // CodecName
|
||||
},
|
||||
{
|
||||
'data': 1,
|
||||
'id': 0x83 // TrackType
|
||||
data: 1,
|
||||
id: 0x83 // TrackType
|
||||
},
|
||||
{
|
||||
'id': 0xe0, // Video
|
||||
'data': [
|
||||
id: 0xe0, // Video
|
||||
data: [
|
||||
{
|
||||
'data': info.width,
|
||||
'id': 0xb0 // PixelWidth
|
||||
data: info.width,
|
||||
id: 0xb0 // PixelWidth
|
||||
},
|
||||
{
|
||||
'data': info.height,
|
||||
'id': 0xba // PixelHeight
|
||||
data: info.height,
|
||||
id: 0xba // PixelHeight
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -146,8 +146,8 @@ function ToWebM (frames, outputAsArray) {
|
||||
]
|
||||
},
|
||||
{
|
||||
'id': 0x1c53bb6b, // Cues
|
||||
'data': [
|
||||
id: 0x1c53bb6b, // Cues
|
||||
data: [
|
||||
// cue insertion point
|
||||
]
|
||||
}
|
||||
@@ -165,23 +165,23 @@ function ToWebM (frames, outputAsArray) {
|
||||
let clusterTimecode = 0;
|
||||
while (frameNumber < frames.length) {
|
||||
const cuePoint = {
|
||||
'id': 0xbb, // CuePoint
|
||||
'data': [
|
||||
id: 0xbb, // CuePoint
|
||||
data: [
|
||||
{
|
||||
'data': Math.round(clusterTimecode),
|
||||
'id': 0xb3 // CueTime
|
||||
data: Math.round(clusterTimecode),
|
||||
id: 0xb3 // CueTime
|
||||
},
|
||||
{
|
||||
'id': 0xb7, // CueTrackPositions
|
||||
'data': [
|
||||
id: 0xb7, // CueTrackPositions
|
||||
data: [
|
||||
{
|
||||
'data': 1,
|
||||
'id': 0xf7 // CueTrack
|
||||
data: 1,
|
||||
id: 0xf7 // CueTrack
|
||||
},
|
||||
{
|
||||
'data': 0, // to be filled in when we know it
|
||||
'size': 8,
|
||||
'id': 0xf1 // CueClusterPosition
|
||||
data: 0, // to be filled in when we know it
|
||||
size: 8,
|
||||
id: 0xf1 // CueClusterPosition
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -200,11 +200,11 @@ function ToWebM (frames, outputAsArray) {
|
||||
|
||||
let clusterCounter = 0;
|
||||
const cluster = {
|
||||
'id': 0x1f43b675, // Cluster
|
||||
'data': [
|
||||
id: 0x1f43b675, // Cluster
|
||||
data: [
|
||||
{
|
||||
'data': Math.round(clusterTimecode),
|
||||
'id': 0xe7 // Timecode
|
||||
data: Math.round(clusterTimecode),
|
||||
id: 0xe7 // Timecode
|
||||
}
|
||||
].concat(clusterFrames.map(function (webp) {
|
||||
const block = makeSimpleBlock({
|
||||
@@ -453,12 +453,17 @@ function doubleToString (num) {
|
||||
.join(''); // join the bytes in holy matrimony as a string
|
||||
}
|
||||
|
||||
function WhammyVideo (speed, quality) { // a more abstract-ish API
|
||||
function WhammyVideo (speed, quality = 0.8) { // a more abstract-ish API
|
||||
this.frames = [];
|
||||
this.duration = 1000 / speed;
|
||||
this.quality = quality || 0.8;
|
||||
this.quality = quality;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} frame
|
||||
* @param {number} [duration]
|
||||
*/
|
||||
WhammyVideo.prototype.add = function (frame, duration) {
|
||||
if (typeof duration !== 'undefined' && this.duration) throw new Error("you can't pass a duration if the fps is set");
|
||||
if (typeof duration === 'undefined' && !this.duration) throw new Error("if you don't have the fps set, you need to have durations here.");
|
||||
|
||||
@@ -112,17 +112,11 @@ describe('clipboard module', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('clipboard.writeBuffer(format, buffer)', () => {
|
||||
describe('clipboard.readBuffer(format)', () => {
|
||||
it('writes a Buffer for the specified format', function () {
|
||||
if (process.platform !== 'darwin') {
|
||||
// FIXME(alexeykuzmin): Skip the test.
|
||||
// this.skip()
|
||||
return;
|
||||
}
|
||||
|
||||
const buffer = Buffer.from('writeBuffer', 'utf8');
|
||||
clipboard.writeBuffer('public.utf8-plain-text', buffer);
|
||||
expect(clipboard.readText()).to.equal('writeBuffer');
|
||||
expect(buffer.equals(clipboard.readBuffer('public.utf8-plain-text'))).to.equal(true);
|
||||
});
|
||||
|
||||
it('throws an error when a non-Buffer is specified', () => {
|
||||
@@ -131,18 +125,4 @@ describe('clipboard module', () => {
|
||||
}).to.throw(/buffer must be a node Buffer/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('clipboard.readBuffer(format)', () => {
|
||||
before(function () {
|
||||
if (process.platform !== 'darwin') {
|
||||
this.skip();
|
||||
}
|
||||
});
|
||||
|
||||
it('returns a Buffer of the content for the specified format', () => {
|
||||
const buffer = Buffer.from('this is binary', 'utf8');
|
||||
clipboard.writeText(buffer.toString());
|
||||
expect(buffer.equals(clipboard.readBuffer('public.utf8-plain-text'))).to.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
2
typings/internal-ambient.d.ts
vendored
2
typings/internal-ambient.d.ts
vendored
@@ -1,4 +1,6 @@
|
||||
declare var internalBinding: any;
|
||||
declare var nodeProcess: any;
|
||||
declare var isolatedWorld: any;
|
||||
declare var binding: { get: (name: string) => any; process: NodeJS.Process; createPreloadScript: (src: string) => Function };
|
||||
|
||||
declare const BUILDFLAG: (flag: boolean) => boolean;
|
||||
|
||||
Reference in New Issue
Block a user