Compare commits
57 Commits
v12.0.0-ni
...
v12.0.0-ni
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93e786d1b5 | ||
|
|
6a0c5a8a65 | ||
|
|
ecb758dae5 | ||
|
|
d4191c4a26 | ||
|
|
aa157c3f05 | ||
|
|
30b5e15ddc | ||
|
|
4379a14335 | ||
|
|
e89abed924 | ||
|
|
c89ce5eecf | ||
|
|
9d18f9d54f | ||
|
|
6181c03df0 | ||
|
|
2d49d82072 | ||
|
|
722903f068 | ||
|
|
554ad93d45 | ||
|
|
d9db9873fd | ||
|
|
c934d1386b | ||
|
|
7f0c6ea47a | ||
|
|
e3c4bbd21f | ||
|
|
f93e33528e | ||
|
|
35455c725d | ||
|
|
10a209ecba | ||
|
|
2aa5a1f494 | ||
|
|
22cb3cd18b | ||
|
|
f6a27973d1 | ||
|
|
939be5eb8a | ||
|
|
a631a8a8b0 | ||
|
|
5c6fa7e420 | ||
|
|
df1432a315 | ||
|
|
1ef803d2ea | ||
|
|
56d1fafe66 | ||
|
|
f7945ade07 | ||
|
|
c4525b4ea6 | ||
|
|
d38c47e748 | ||
|
|
aebb56cb33 | ||
|
|
e6f570d191 | ||
|
|
042ebdd5b0 | ||
|
|
6b6ffbdd10 | ||
|
|
89c04b3c6c | ||
|
|
ae5de3d9c5 | ||
|
|
12e3c85081 | ||
|
|
4ce7ca6cfb | ||
|
|
c6a6f53c8d | ||
|
|
3219812c02 | ||
|
|
e895353f7a | ||
|
|
88508d5166 | ||
|
|
64504536fa | ||
|
|
16caa54248 | ||
|
|
11ce55628e | ||
|
|
87d3f3584c | ||
|
|
6a0221297e | ||
|
|
decb1eb87b | ||
|
|
c27e5fdbb6 | ||
|
|
05b5c197ae | ||
|
|
321395d96e | ||
|
|
eca53aaaf1 | ||
|
|
708cf44d19 | ||
|
|
44221d7452 |
@@ -26,15 +26,6 @@
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"globals": {
|
||||
"standardScheme": "readonly",
|
||||
"globalThis": "readonly",
|
||||
"BUILDFLAG": "readonly",
|
||||
"ENABLE_DESKTOP_CAPTURER": "readonly",
|
||||
"ENABLE_REMOTE_MODULE": "readonly",
|
||||
"ENABLE_VIEWS_API": "readonly",
|
||||
"BigInt": "readonly"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.js",
|
||||
@@ -42,6 +33,15 @@
|
||||
"@typescript-eslint/no-unused-vars": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": "*.ts",
|
||||
"rules": {
|
||||
"no-undef": "off",
|
||||
"no-redeclare": "off",
|
||||
"@typescript-eslint/no-redeclare": ["error"],
|
||||
"no-use-before-define": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": "*.d.ts",
|
||||
"rules": {
|
||||
|
||||
5
.gitignore
vendored
@@ -65,4 +65,7 @@ ts-gen
|
||||
|
||||
# Used to accelerate CI builds
|
||||
.depshash
|
||||
.depshash-target
|
||||
.depshash-target
|
||||
|
||||
# Used to accelerate builds after sync
|
||||
patches/mtime-cache.json
|
||||
34
DEPS
@@ -16,7 +16,7 @@ vars = {
|
||||
'chromium_version':
|
||||
'9269f9eb1d98d29564c2b2ab97f30c6e148c4e11',
|
||||
'node_version':
|
||||
'v14.13.1',
|
||||
'v14.14.0',
|
||||
'nan_version':
|
||||
'2c4ee8a32a299eada3cd6e468bbd0a473bfea96d',
|
||||
'squirrel.mac_version':
|
||||
@@ -38,6 +38,9 @@ vars = {
|
||||
# To be able to build clean Chromium from sources.
|
||||
'apply_patches': True,
|
||||
|
||||
# To use an mtime cache for patched files to speed up builds.
|
||||
'use_mtime_cache': True,
|
||||
|
||||
# To allow in-house builds to checkout those manually.
|
||||
'checkout_chromium': True,
|
||||
'checkout_node': True,
|
||||
@@ -112,6 +115,23 @@ deps = {
|
||||
}
|
||||
}
|
||||
|
||||
pre_deps_hooks = [
|
||||
{
|
||||
'name': 'generate_mtime_cache',
|
||||
'condition': '(checkout_chromium and apply_patches and use_mtime_cache) and process_deps',
|
||||
'pattern': 'src/electron',
|
||||
'action': [
|
||||
'python3',
|
||||
'src/electron/script/patches-mtime-cache.py',
|
||||
'generate',
|
||||
'--cache-file',
|
||||
'src/electron/patches/mtime-cache.json',
|
||||
'--patches-config',
|
||||
'src/electron/patches/config.json',
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
hooks = [
|
||||
{
|
||||
'name': 'patch_chromium',
|
||||
@@ -123,6 +143,18 @@ hooks = [
|
||||
'src/electron/patches/config.json',
|
||||
],
|
||||
},
|
||||
{
|
||||
'name': 'apply_mtime_cache',
|
||||
'condition': '(checkout_chromium and apply_patches and use_mtime_cache) and process_deps',
|
||||
'pattern': 'src/electron',
|
||||
'action': [
|
||||
'python3',
|
||||
'src/electron/script/patches-mtime-cache.py',
|
||||
'apply',
|
||||
'--cache-file',
|
||||
'src/electron/patches/mtime-cache.json',
|
||||
],
|
||||
},
|
||||
{
|
||||
'name': 'electron_external_binaries',
|
||||
'pattern': 'src/electron/script/update-external-binaries.py',
|
||||
|
||||
@@ -1 +1 @@
|
||||
12.0.0-nightly.20201016
|
||||
12.0.0-nightly.20201026
|
||||
@@ -63,7 +63,8 @@ steps:
|
||||
set npm_config_nodedir=%cd%\out\Default\gen\node_headers
|
||||
set npm_config_arch=arm64
|
||||
cd electron
|
||||
node script/yarn test -- --enable-logging --verbose
|
||||
# CalculateNativeWinOcclusion is disabled due to https://bugs.chromium.org/p/chromium/issues/detail?id=1139022
|
||||
node script/yarn test -- --enable-logging --verbose --disable-features=CalculateNativeWinOcclusion
|
||||
displayName: 'Run Electron tests'
|
||||
env:
|
||||
ELECTRON_OUT_DIR: Default
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
process.env.PRINT_WEBPACK_GRAPH = true;
|
||||
require('./run-compiler');
|
||||
@@ -1,45 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
|
||||
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, wrapInitWithTryCatch, ...webpackConfig } = config;
|
||||
|
||||
webpack(webpackConfig, (err, stats) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
} else if (stats.hasErrors()) {
|
||||
console.error(stats.toString('normal'));
|
||||
process.exit(1);
|
||||
} else {
|
||||
let contents = fs.readFileSync(outPath, 'utf8');
|
||||
if (wrapInitWithTryCatch) {
|
||||
contents = `try {
|
||||
${contents}
|
||||
} catch (err) {
|
||||
console.error('Electron ${webpackConfig.output.filename} script failed to run');
|
||||
console.error(err);
|
||||
}`;
|
||||
}
|
||||
if (wrapInitWithProfilingTimeout) {
|
||||
contents = `function ___electron_webpack_init__() {
|
||||
${contents}
|
||||
};
|
||||
if ((globalThis.process || binding.process).argv.includes("--profile-electron-init")) {
|
||||
setTimeout(___electron_webpack_init__, 0);
|
||||
} else {
|
||||
___electron_webpack_init__();
|
||||
}`;
|
||||
}
|
||||
fs.writeFileSync(outPath, contents);
|
||||
process.exit(0);
|
||||
}
|
||||
});
|
||||
@@ -2,16 +2,12 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const WrapperPlugin = require('wrapper-webpack-plugin');
|
||||
|
||||
const electronRoot = path.resolve(__dirname, '../..');
|
||||
|
||||
const onlyPrintingGraph = !!process.env.PRINT_WEBPACK_GRAPH;
|
||||
|
||||
class AccessDependenciesPlugin {
|
||||
apply (compiler) {
|
||||
// Only hook into webpack when we are printing the dependency graph
|
||||
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));
|
||||
@@ -21,49 +17,6 @@ class AccessDependenciesPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
const defines = {
|
||||
BUILDFLAG: onlyPrintingGraph ? '(a => a)' : ''
|
||||
};
|
||||
|
||||
const buildFlagsPrefix = '--buildflags=';
|
||||
const buildFlagArg = process.argv.find(arg => arg.startsWith(buildFlagsPrefix));
|
||||
|
||||
if (buildFlagArg) {
|
||||
const buildFlagPath = buildFlagArg.substr(buildFlagsPrefix.length);
|
||||
|
||||
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])\)/);
|
||||
if (flagMatch) {
|
||||
const [, flagName, flagValue] = flagMatch;
|
||||
defines[flagName] = JSON.stringify(Boolean(parseInt(flagValue, 10)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ignoredModules = [];
|
||||
|
||||
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') {
|
||||
ignoredModules.push(
|
||||
'@electron/internal/browser/remote/server',
|
||||
'@electron/internal/renderer/api/remote'
|
||||
);
|
||||
}
|
||||
|
||||
if (defines.ENABLE_VIEWS_API === 'false') {
|
||||
ignoredModules.push(
|
||||
'@electron/internal/browser/api/views/image-view.js'
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = ({
|
||||
alwaysHasNode,
|
||||
loadElectronFromAlternateTarget,
|
||||
@@ -79,76 +32,148 @@ module.exports = ({
|
||||
|
||||
const electronAPIFile = path.resolve(electronRoot, 'lib', loadElectronFromAlternateTarget || target, 'api', 'exports', 'electron.ts');
|
||||
|
||||
return ({
|
||||
mode: 'development',
|
||||
devtool: false,
|
||||
entry,
|
||||
target: alwaysHasNode ? 'node' : 'web',
|
||||
output: {
|
||||
filename: `${target}.bundle.js`
|
||||
},
|
||||
wrapInitWithProfilingTimeout,
|
||||
wrapInitWithTryCatch,
|
||||
resolve: {
|
||||
alias: {
|
||||
'@electron/internal': path.resolve(electronRoot, 'lib'),
|
||||
electron$: electronAPIFile,
|
||||
'electron/main$': electronAPIFile,
|
||||
'electron/renderer$': electronAPIFile,
|
||||
'electron/common$': electronAPIFile,
|
||||
// Force timers to resolve to our dependency that doesn't use window.postMessage
|
||||
timers: path.resolve(electronRoot, 'node_modules', 'timers-browserify', 'main.js')
|
||||
},
|
||||
extensions: ['.ts', '.js']
|
||||
},
|
||||
module: {
|
||||
rules: [{
|
||||
test: (moduleName) => !onlyPrintingGraph && ignoredModules.includes(moduleName),
|
||||
loader: 'null-loader'
|
||||
}, {
|
||||
test: /\.ts$/,
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
configFile: path.resolve(electronRoot, 'tsconfig.electron.json'),
|
||||
transpileOnly: onlyPrintingGraph,
|
||||
ignoreDiagnostics: [
|
||||
// File '{0}' is not under 'rootDir' '{1}'.
|
||||
6059
|
||||
]
|
||||
return (env = {}, argv = {}) => {
|
||||
const onlyPrintingGraph = !!env.PRINT_WEBPACK_GRAPH;
|
||||
const outputFilename = argv['output-filename'] || `${target}.bundle.js`;
|
||||
|
||||
const defines = {
|
||||
BUILDFLAG: onlyPrintingGraph ? '(a => a)' : ''
|
||||
};
|
||||
|
||||
if (env.buildflags) {
|
||||
const flagFile = fs.readFileSync(env.buildflags, 'utf8');
|
||||
for (const line of flagFile.split(/(\r\n|\r|\n)/g)) {
|
||||
const flagMatch = line.match(/#define BUILDFLAG_INTERNAL_(.+?)\(\) \(([01])\)/);
|
||||
if (flagMatch) {
|
||||
const [, flagName, flagValue] = flagMatch;
|
||||
defines[flagName] = JSON.stringify(Boolean(parseInt(flagValue, 10)));
|
||||
}
|
||||
}]
|
||||
},
|
||||
node: {
|
||||
__dirname: false,
|
||||
__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
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
terserOptions: {
|
||||
keep_classnames: true,
|
||||
keep_fnames: true
|
||||
}
|
||||
})
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new AccessDependenciesPlugin(),
|
||||
...(targetDeletesNodeGlobals ? [
|
||||
new webpack.ProvidePlugin({
|
||||
process: ['@electron/internal/common/webpack-provider', 'process'],
|
||||
global: ['@electron/internal/common/webpack-provider', '_global'],
|
||||
Buffer: ['@electron/internal/common/webpack-provider', 'Buffer']
|
||||
})
|
||||
] : []),
|
||||
new webpack.ProvidePlugin({
|
||||
Promise: ['@electron/internal/common/webpack-globals-provider', 'Promise']
|
||||
}),
|
||||
new webpack.DefinePlugin(defines)
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const ignoredModules = [];
|
||||
|
||||
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') {
|
||||
ignoredModules.push(
|
||||
'@electron/internal/browser/remote/server',
|
||||
'@electron/internal/renderer/api/remote'
|
||||
);
|
||||
}
|
||||
|
||||
if (defines.ENABLE_VIEWS_API === 'false') {
|
||||
ignoredModules.push(
|
||||
'@electron/internal/browser/api/views/image-view.js'
|
||||
);
|
||||
}
|
||||
|
||||
const plugins = [];
|
||||
|
||||
if (onlyPrintingGraph) {
|
||||
plugins.push(new AccessDependenciesPlugin());
|
||||
}
|
||||
|
||||
if (targetDeletesNodeGlobals) {
|
||||
plugins.push(new webpack.ProvidePlugin({
|
||||
process: ['@electron/internal/common/webpack-provider', 'process'],
|
||||
global: ['@electron/internal/common/webpack-provider', '_global'],
|
||||
Buffer: ['@electron/internal/common/webpack-provider', 'Buffer']
|
||||
}));
|
||||
}
|
||||
|
||||
plugins.push(new webpack.ProvidePlugin({
|
||||
Promise: ['@electron/internal/common/webpack-globals-provider', 'Promise']
|
||||
}));
|
||||
|
||||
plugins.push(new webpack.DefinePlugin(defines));
|
||||
|
||||
if (wrapInitWithProfilingTimeout) {
|
||||
plugins.push(new WrapperPlugin({
|
||||
header: 'function ___electron_webpack_init__() {',
|
||||
footer: `
|
||||
};
|
||||
if ((globalThis.process || binding.process).argv.includes("--profile-electron-init")) {
|
||||
setTimeout(___electron_webpack_init__, 0);
|
||||
} else {
|
||||
___electron_webpack_init__();
|
||||
}`
|
||||
}));
|
||||
}
|
||||
|
||||
if (wrapInitWithTryCatch) {
|
||||
plugins.push(new WrapperPlugin({
|
||||
header: 'try {',
|
||||
footer: `
|
||||
} catch (err) {
|
||||
console.error('Electron ${outputFilename} script failed to run');
|
||||
console.error(err);
|
||||
}`
|
||||
}));
|
||||
}
|
||||
|
||||
return {
|
||||
mode: 'development',
|
||||
devtool: false,
|
||||
entry,
|
||||
target: alwaysHasNode ? 'node' : 'web',
|
||||
output: {
|
||||
filename: outputFilename
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@electron/internal': path.resolve(electronRoot, 'lib'),
|
||||
electron$: electronAPIFile,
|
||||
'electron/main$': electronAPIFile,
|
||||
'electron/renderer$': electronAPIFile,
|
||||
'electron/common$': electronAPIFile,
|
||||
// Force timers to resolve to our dependency that doesn't use window.postMessage
|
||||
timers: path.resolve(electronRoot, 'node_modules', 'timers-browserify', 'main.js')
|
||||
},
|
||||
extensions: ['.ts', '.js']
|
||||
},
|
||||
module: {
|
||||
rules: [{
|
||||
test: (moduleName) => !onlyPrintingGraph && ignoredModules.includes(moduleName),
|
||||
loader: 'null-loader'
|
||||
}, {
|
||||
test: /\.ts$/,
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
configFile: path.resolve(electronRoot, 'tsconfig.electron.json'),
|
||||
transpileOnly: onlyPrintingGraph,
|
||||
ignoreDiagnostics: [
|
||||
// File '{0}' is not under 'rootDir' '{1}'.
|
||||
6059
|
||||
]
|
||||
}
|
||||
}]
|
||||
},
|
||||
node: {
|
||||
__dirname: false,
|
||||
__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
|
||||
},
|
||||
optimization: {
|
||||
minimize: true,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
terserOptions: {
|
||||
keep_classnames: true,
|
||||
keep_fnames: true
|
||||
}
|
||||
})
|
||||
]
|
||||
},
|
||||
plugins
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -16,7 +16,6 @@ template("webpack_build") {
|
||||
inputs = [
|
||||
invoker.config_file,
|
||||
"//electron/build/webpack/webpack.config.base.js",
|
||||
"//electron/build/webpack/run-compiler.js",
|
||||
"//electron/tsconfig.json",
|
||||
"//electron/yarn.lock",
|
||||
"//electron/typings/internal-ambient.d.ts",
|
||||
@@ -24,9 +23,12 @@ template("webpack_build") {
|
||||
] + invoker.inputs
|
||||
|
||||
args = [
|
||||
"--config",
|
||||
rebase_path(invoker.config_file),
|
||||
rebase_path(invoker.out_file),
|
||||
"--buildflags=" + rebase_path("$target_gen_dir/buildflags/buildflags.h"),
|
||||
"--output-filename=" + get_path_info(invoker.out_file, "file"),
|
||||
"--output-path=" + rebase_path(get_path_info(invoker.out_file, "dir")),
|
||||
"--env.buildflags=" +
|
||||
rebase_path("$target_gen_dir/buildflags/buildflags.h"),
|
||||
]
|
||||
deps += [ "buildflags" ]
|
||||
|
||||
|
||||
@@ -93,9 +93,18 @@ static_library("chrome") {
|
||||
|
||||
if (is_linux) {
|
||||
sources += [ "//chrome/browser/icon_loader_auralinux.cc" ]
|
||||
if (use_x11) {
|
||||
sources += [
|
||||
"//chrome/browser/extensions/global_shortcut_listener_x11.cc",
|
||||
"//chrome/browser/extensions/global_shortcut_listener_x11.h",
|
||||
]
|
||||
} else if (use_ozone) {
|
||||
sources += [
|
||||
"//chrome/browser/extensions/global_shortcut_listener_ozone.cc",
|
||||
"//chrome/browser/extensions/global_shortcut_listener_ozone.h",
|
||||
]
|
||||
}
|
||||
sources += [
|
||||
"//chrome/browser/extensions/global_shortcut_listener_x11.cc",
|
||||
"//chrome/browser/extensions/global_shortcut_listener_x11.h",
|
||||
"//chrome/browser/ui/views/status_icons/concat_menu_model.cc",
|
||||
"//chrome/browser/ui/views/status_icons/concat_menu_model.h",
|
||||
"//chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc",
|
||||
|
||||
@@ -432,6 +432,7 @@ Returns:
|
||||
* `integrity-failure` - Windows code integrity checks failed
|
||||
* `exitCode` Number - The exit code for the process
|
||||
(e.g. status from waitpid if on posix, from GetExitCodeProcess on Windows).
|
||||
* `serviceName` String (optional) - The non-localized name of the process.
|
||||
* `name` String (optional) - The name of the process.
|
||||
Examples for utility: `Audio Service`, `Content Decryption Module Service`, `Network Service`, `Video Capture`, etc.
|
||||
|
||||
|
||||
@@ -398,6 +398,11 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
* `bypassHeatCheck` - Bypass code caching heuristics but with lazy compilation
|
||||
* `bypassHeatCheckAndEagerCompile` - Same as above except compilation is eager.
|
||||
Default policy is `code`.
|
||||
* `enablePreferredSizeMode` Boolean (optional) - Whether to enable
|
||||
preferred size mode. The preferred size is the minimum size needed to
|
||||
contain the layout of the document—without requiring scrolling. Enabling
|
||||
this will cause the `preferred-size-changed` event to be emitted on the
|
||||
`WebContents` when the preferred size changes. Default is `false`.
|
||||
|
||||
When setting minimum or maximum window size with `minWidth`/`maxWidth`/
|
||||
`minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from
|
||||
|
||||
@@ -232,7 +232,7 @@ Specify ways of the inspector web socket url exposure.
|
||||
By default inspector websocket url is available in stderr and under /json/list endpoint on http://host:port/json/list.
|
||||
|
||||
[app]: app.md
|
||||
[append-switch]: app.md#appcommandlineappendswitchswitch-value
|
||||
[append-switch]: command-line.md#commandlineappendswitchswitch-value
|
||||
[ready]: app.md#event-ready
|
||||
[play-silent-audio]: https://github.com/atom/atom/pull/9485/files
|
||||
[debugging-main-process]: ../tutorial/debugging-main-process.md
|
||||
|
||||
@@ -95,7 +95,7 @@ Returns `Promise<DesktopCapturerSource[]>` - Resolves with an array of [`Desktop
|
||||
which can detected by [`systemPreferences.getMediaAccessStatus`].
|
||||
|
||||
[`navigator.mediaDevices.getUserMedia`]: https://developer.mozilla.org/en/docs/Web/API/MediaDevices/getUserMedia
|
||||
[`systemPreferences.getMediaAccessStatus`]: system-preferences.md#systempreferencesgetmediaaccessstatusmediatype-macos
|
||||
[`systemPreferences.getMediaAccessStatus`]: system-preferences.md#systempreferencesgetmediaaccessstatusmediatype-windows-macos
|
||||
|
||||
## Caveats
|
||||
|
||||
|
||||
@@ -221,6 +221,7 @@ expanding and collapsing the dialog.
|
||||
|
||||
* `browserWindow` [BrowserWindow](browser-window.md) (optional)
|
||||
* `options` Object
|
||||
* `message` String - Content of the message box.
|
||||
* `type` String (optional) - Can be `"none"`, `"info"`, `"error"`, `"question"` or
|
||||
`"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless
|
||||
you set an icon using the `"icon"` option. On macOS, both `"warning"` and
|
||||
@@ -230,7 +231,6 @@ expanding and collapsing the dialog.
|
||||
* `defaultId` Integer (optional) - Index of the button in the buttons array which will
|
||||
be selected by default when the message box opens.
|
||||
* `title` String (optional) - Title of the message box, some platforms will not show it.
|
||||
* `message` String - Content of the message box.
|
||||
* `detail` String (optional) - Extra information of the message.
|
||||
* `checkboxLabel` String (optional) - If provided, the message box will
|
||||
include a checkbox with the given label.
|
||||
@@ -267,6 +267,7 @@ If `browserWindow` is not shown dialog will not be attached to it. In such case
|
||||
|
||||
* `browserWindow` [BrowserWindow](browser-window.md) (optional)
|
||||
* `options` Object
|
||||
* `message` String - Content of the message box.
|
||||
* `type` String (optional) - Can be `"none"`, `"info"`, `"error"`, `"question"` or
|
||||
`"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless
|
||||
you set an icon using the `"icon"` option. On macOS, both `"warning"` and
|
||||
@@ -276,7 +277,6 @@ If `browserWindow` is not shown dialog will not be attached to it. In such case
|
||||
* `defaultId` Integer (optional) - Index of the button in the buttons array which will
|
||||
be selected by default when the message box opens.
|
||||
* `title` String (optional) - Title of the message box, some platforms will not show it.
|
||||
* `message` String - Content of the message box.
|
||||
* `detail` String (optional) - Extra information of the message.
|
||||
* `checkboxLabel` String (optional) - If provided, the message box will
|
||||
include a checkbox with the given label.
|
||||
|
||||
@@ -14,7 +14,7 @@ See [`Menu`](menu.md) for examples.
|
||||
* `menuItem` MenuItem
|
||||
* `browserWindow` [BrowserWindow](browser-window.md) | undefined - This will not be defined if no window is open.
|
||||
* `event` [KeyboardEvent](structures/keyboard-event.md)
|
||||
* `role` String (optional) - Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteAndMatchStyle`, `delete`, `selectAll`, `reload`, `forceReload`, `toggleDevTools`, `resetZoom`, `zoomIn`, `zoomOut`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideOthers`, `unhide`, `quit`, `startSpeaking`, `stopSpeaking`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu`, `recentDocuments`, `toggleTabBar`, `selectNextTab`, `selectPreviousTab`, `mergeAllWindows`, `clearRecentDocuments`, `moveTabToNewWindow` or `windowMenu` - Define the action of the menu item, when specified the
|
||||
* `role` String (optional) - Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteAndMatchStyle`, `delete`, `selectAll`, `reload`, `forceReload`, `toggleDevTools`, `resetZoom`, `zoomIn`, `zoomOut`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideOthers`, `unhide`, `quit`, `startSpeaking`, `stopSpeaking`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu`, `shareMenu`, `recentDocuments`, `toggleTabBar`, `selectNextTab`, `selectPreviousTab`, `mergeAllWindows`, `clearRecentDocuments`, `moveTabToNewWindow` or `windowMenu` - Define the action of the menu item, when specified the
|
||||
`click` property will be ignored. See [roles](#roles).
|
||||
* `type` String (optional) - Can be `normal`, `separator`, `submenu`, `checkbox` or
|
||||
`radio`.
|
||||
@@ -31,6 +31,7 @@ See [`Menu`](menu.md) for examples.
|
||||
menu items.
|
||||
* `registerAccelerator` Boolean (optional) _Linux_ _Windows_ - If false, the accelerator won't be registered
|
||||
with the system, but it will still be displayed. Defaults to true.
|
||||
* `sharingItem` SharingItem (optional) _macOS_ - The item to share when the `role` is `shareMenu`.
|
||||
* `submenu` (MenuItemConstructorOptions[] | [Menu](menu.md)) (optional) - Should be specified
|
||||
for `submenu` type menu items. If `submenu` is specified, the `type: 'submenu'` can be omitted.
|
||||
If the value is not a [`Menu`](menu.md) then it will be automatically converted to one using
|
||||
@@ -112,6 +113,7 @@ The following additional roles are available on _macOS_:
|
||||
* `services` - The submenu is a ["Services"](https://developer.apple.com/documentation/appkit/nsapplication/1428608-servicesmenu?language=objc) menu. This is only intended for use in the Application Menu and is *not* the same as the "Services" submenu used in context menus in macOS apps, which is not implemented in Electron.
|
||||
* `recentDocuments` - The submenu is an "Open Recent" menu.
|
||||
* `clearRecentDocuments` - Map to the `clearRecentDocuments` action.
|
||||
* `shareMenu` - The submenu is [share menu][ShareMenu]. The `sharingItem` property must also be set to indicate the item to share.
|
||||
|
||||
When specifying a `role` on macOS, `label` and `accelerator` are the only
|
||||
options that will affect the menu item. All other options will be ignored.
|
||||
@@ -200,6 +202,12 @@ system or just displayed.
|
||||
|
||||
This property can be dynamically changed.
|
||||
|
||||
#### `menuItem.sharingItem` _macOS_
|
||||
|
||||
A `SharingItem` indicating the item to share when the `role` is `shareMenu`.
|
||||
|
||||
This property can be dynamically changed.
|
||||
|
||||
#### `menuItem.commandId`
|
||||
|
||||
A `Number` indicating an item's sequential unique id.
|
||||
@@ -207,3 +215,5 @@ A `Number` indicating an item's sequential unique id.
|
||||
#### `menuItem.menu`
|
||||
|
||||
A `Menu` that the item is a part of.
|
||||
|
||||
[ShareMenu]: https://developer.apple.com/design/human-interface-guidelines/macos/extensions/share-extensions/
|
||||
|
||||
@@ -8,7 +8,7 @@ The `net` module is a client-side API for issuing HTTP(S) requests. It is
|
||||
similar to the [HTTP](https://nodejs.org/api/http.html) and
|
||||
[HTTPS](https://nodejs.org/api/https.html) modules of Node.js but uses
|
||||
Chromium's native networking library instead of the Node.js implementation,
|
||||
offering better support for web proxies.
|
||||
offering better support for web proxies. It also supports checking network status.
|
||||
|
||||
The following is a non-exhaustive list of why you may consider using the `net`
|
||||
module instead of the native Node.js modules:
|
||||
@@ -62,3 +62,25 @@ Creates a [`ClientRequest`](./client-request.md) instance using the provided
|
||||
`options` which are directly forwarded to the `ClientRequest` constructor.
|
||||
The `net.request` method would be used to issue both secure and insecure HTTP
|
||||
requests according to the specified protocol scheme in the `options` object.
|
||||
|
||||
### `net.isOnline()`
|
||||
|
||||
Returns `Boolean` - Whether there is currently internet connection.
|
||||
|
||||
A return value of `false` is a pretty strong indicator that the user
|
||||
won't be able to connect to remote sites. However, a return value of
|
||||
`true` is inconclusive; even if some link is up, it is uncertain
|
||||
whether a particular connection attempt to a particular remote site
|
||||
will be successful.
|
||||
|
||||
## Properties
|
||||
|
||||
### `net.online` _Readonly_
|
||||
|
||||
A `Boolean` property. Whether there is currently internet connection.
|
||||
|
||||
A return value of `false` is a pretty strong indicator that the user
|
||||
won't be able to connect to remote sites. However, a return value of
|
||||
`true` is inconclusive; even if some link is up, it is uncertain
|
||||
whether a particular connection attempt to a particular remote site
|
||||
will be successful.
|
||||
|
||||
@@ -574,11 +574,20 @@ Returns `String` - The user agent for this session.
|
||||
#### `ses.setSSLConfig(config)`
|
||||
|
||||
* `config` Object
|
||||
* `minVersion` String - Can be `tls1`, `tls1.1`, `tls1.2` or `tls1.3`. The
|
||||
* `minVersion` String (optional) - Can be `tls1`, `tls1.1`, `tls1.2` or `tls1.3`. The
|
||||
minimum SSL version to allow when connecting to remote servers. Defaults to
|
||||
`tls1`.
|
||||
* `maxVersion` String - Can be `tls1.2` or `tls1.3`. The maximum SSL version
|
||||
* `maxVersion` String (optional) - Can be `tls1.2` or `tls1.3`. The maximum SSL version
|
||||
to allow when connecting to remote servers. Defaults to `tls1.3`.
|
||||
* `disabledCipherSuites` Integer[] (optional) - List of cipher suites which
|
||||
should be explicitly prevented from being used in addition to those
|
||||
disabled by the net built-in policy.
|
||||
Supported literal forms: 0xAABB, where AA is `cipher_suite[0]` and BB is
|
||||
`cipher_suite[1]`, as defined in RFC 2246, Section 7.4.1.2. Unrecognized but
|
||||
parsable cipher suites in this form will not return an error.
|
||||
Ex: To disable TLS_RSA_WITH_RC4_128_MD5, specify 0x0004, while to
|
||||
disable TLS_ECDH_ECDSA_WITH_RC4_128_SHA, specify 0xC002.
|
||||
Note that TLSv1.3 ciphers cannot be disabled using this mechanism.
|
||||
|
||||
Sets the SSL configuration for the session. All subsequent network requests
|
||||
will use the new configuration. Existing network connections (such as WebSocket
|
||||
|
||||
45
docs/api/share-menu.md
Normal file
@@ -0,0 +1,45 @@
|
||||
## Class: ShareMenu
|
||||
|
||||
> Create share menu on macOS.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
The `ShareMenu` class creates [Share Menu][share-menu] on macOS, which can be
|
||||
used to share information from the current context to apps, social media
|
||||
accounts, and other services.
|
||||
|
||||
For including the share menu as a submenu of other menus, please use the
|
||||
`shareMenu` role of [`MenuItem`](menu-item.md).
|
||||
|
||||
### `new ShareMenu(sharingItem)`
|
||||
|
||||
* `sharingItem` SharingItem - The item to share.
|
||||
|
||||
Creates a new share menu.
|
||||
|
||||
### Instance Methods
|
||||
|
||||
The `shareMenu` object has the following instance methods:
|
||||
|
||||
#### `shareMenu.popup([options])`
|
||||
|
||||
* `options` PopupOptions (optional)
|
||||
* `browserWindow` [BrowserWindow](browser-window.md) (optional) - Default is the focused window.
|
||||
* `x` Number (optional) - Default is the current mouse cursor position.
|
||||
Must be declared if `y` is declared.
|
||||
* `y` Number (optional) - Default is the current mouse cursor position.
|
||||
Must be declared if `x` is declared.
|
||||
* `positioningItem` Number (optional) _macOS_ - The index of the menu item to
|
||||
be positioned under the mouse cursor at the specified coordinates. Default
|
||||
is -1.
|
||||
* `callback` Function (optional) - Called when menu is closed.
|
||||
|
||||
Pops up this menu as a context menu in the [`BrowserWindow`](browser-window.md).
|
||||
|
||||
#### `shareMenu.closePopup([browserWindow])`
|
||||
|
||||
* `browserWindow` [BrowserWindow](browser-window.md) (optional) - Default is the focused window.
|
||||
|
||||
Closes the context menu in the `browserWindow`.
|
||||
|
||||
[share-menu]: https://developer.apple.com/design/human-interface-guidelines/macos/extensions/share-extensions/
|
||||
@@ -4,4 +4,4 @@
|
||||
* `senderId` Integer - The `webContents.id` that sent the message, you can call `event.sender.sendTo(event.senderId, ...)` to reply to the message, see [ipcRenderer.sendTo][ipc-renderer-sendto] for more information. This only applies to messages sent from a different renderer. Messages sent directly from the main process set `event.senderId` to `0`.
|
||||
* `ports` MessagePort[] - A list of MessagePorts that were transferred with this message
|
||||
|
||||
[ipc-renderer-sendto]: #ipcrenderersendtowindowid-channel--arg1-arg2-
|
||||
[ipc-renderer-sendto]: ../ipc-renderer.md#ipcrenderersendtowebcontentsid-channel-args
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
* `Pepper Plugin`
|
||||
* `Pepper Plugin Broker`
|
||||
* `Unknown`
|
||||
* `name` String (optional) - The name of the process. i.e. for plugins it might be Flash.
|
||||
* `serviceName` String (optional) - The non-localized name of the process.
|
||||
* `name` String (optional) - The name of the process.
|
||||
Examples for utility: `Audio Service`, `Content Decryption Module Service`, `Network Service`, `Video Capture`, etc.
|
||||
* `cpu` [CPUUsage](cpu-usage.md) - CPU usage of the process.
|
||||
* `creationTime` Number - Creation time for this process.
|
||||
|
||||
5
docs/api/structures/sharing-item.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# SharingItem Object
|
||||
|
||||
* `texts` String[] (optional) - An array of text to share.
|
||||
* `filePaths` String[] (optional) - An array of files to share.
|
||||
* `urls` String[] (optional) - An array of URLs to share.
|
||||
@@ -837,6 +837,19 @@ Emitted when `remote.getCurrentWebContents()` is called in the renderer process.
|
||||
Calling `event.preventDefault()` will prevent the object from being returned.
|
||||
Custom value can be returned by setting `event.returnValue`.
|
||||
|
||||
#### Event: 'preferred-size-changed'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `preferredSize` [Size](structures/size.md) - The minimum size needed to
|
||||
contain the layout of the document—without requiring scrolling.
|
||||
|
||||
Emitted when the `WebContents` preferred size has changed.
|
||||
|
||||
This event will only be emitted when `enablePreferredSizeMode` is set to `true`
|
||||
in `webPreferences`.
|
||||
|
||||
### Instance Methods
|
||||
|
||||
#### `contents.loadURL(url[, options])`
|
||||
|
||||
@@ -122,9 +122,18 @@ content. The identifier is fixed at the creation of the frame and stays
|
||||
constant for the lifetime of the frame. When the frame is removed, the id is
|
||||
not used again.
|
||||
|
||||
#### `frame.name` _Readonly_
|
||||
|
||||
A `String` representing the frame name.
|
||||
|
||||
#### `frame.osProcessId` _Readonly_
|
||||
|
||||
An `Integer` representing the operating system `pid` of the process which owns this frame.
|
||||
|
||||
#### `frame.processId` _Readonly_
|
||||
|
||||
An `Integer` representing the id of the process which owns this frame.
|
||||
An `Integer` representing the Chromium internal `pid` of the process which owns this frame.
|
||||
This is not the same as the OS process ID; to read that use `frame.osProcessId`.
|
||||
|
||||
#### `frame.routingId` _Readonly_
|
||||
|
||||
|
||||
@@ -257,6 +257,20 @@ renderer process.
|
||||
|
||||
Returns `WebFrame` - that has the supplied `routingId`, `null` if not found.
|
||||
|
||||
### `webFrame.isWordMisspelled(word)`
|
||||
|
||||
* `word` String - The word to be spellchecked.
|
||||
|
||||
Returns `Boolean` - True if the word is misspelled according to the built in
|
||||
spellchecker, false otherwise. If no dictionary is loaded, always return false.
|
||||
|
||||
### `webFrame.getWordSuggestions(word)`
|
||||
|
||||
* `word` String - The misspelled word.
|
||||
|
||||
Returns `String[]` - A list of suggested words for a given word. If the word
|
||||
is spelled correctly, the result will be empty.
|
||||
|
||||
## Properties
|
||||
|
||||
### `webFrame.top` _Readonly_
|
||||
|
||||
BIN
docs/images/dock-progress-bar.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
docs/images/linux-progress-bar.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
docs/images/macos-dock-menu.png
Normal file
|
After Width: | Height: | Size: 100 KiB |
BIN
docs/images/macos-progress-bar.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
docs/images/message-notification-renderer.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
docs/images/mission-control-progress-bar.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
docs/images/notification-main.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
docs/images/notification-renderer.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
docs/images/online-event-detection.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
docs/images/recent-documents.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
docs/images/represented-file.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
@@ -1,10 +1,11 @@
|
||||
# macOS Dock
|
||||
|
||||
## Overview
|
||||
|
||||
Electron has APIs to configure the app's icon in the macOS Dock. A macOS-only
|
||||
API exists to create a custom dock menu, but
|
||||
Electron also uses the app's dock icon to implement cross-platform features
|
||||
like [recent documents][recent-documents] and
|
||||
[application progress][progress-bar].
|
||||
API exists to create a custom dock menu, but Electron also uses the app dock
|
||||
icon as the entry point for cross-platform features like
|
||||
[recent documents][recent-documents] and [application progress][progress-bar].
|
||||
|
||||
The custom dock is commonly used to add shortcuts to tasks the user wouldn't
|
||||
want to open the whole app window for.
|
||||
@@ -13,8 +14,15 @@ __Dock menu of Terminal.app:__
|
||||
|
||||
![Dock Menu][dock-menu-image]
|
||||
|
||||
To set your custom dock menu, you can use the `app.dock.setMenu` API, which is
|
||||
only available on macOS:
|
||||
To set your custom dock menu, you need to use the
|
||||
[`app.dock.setMenu`](../api/dock.md#docksetmenumenu-macos) API,
|
||||
which is only available on macOS.
|
||||
|
||||
## Example
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` file with the
|
||||
following lines:
|
||||
|
||||
```javascript
|
||||
const { app, Menu } = require('electron')
|
||||
@@ -33,9 +41,16 @@ const dockMenu = Menu.buildFromTemplate([
|
||||
{ label: 'New Command...' }
|
||||
])
|
||||
|
||||
app.dock.setMenu(dockMenu)
|
||||
app.whenReady().then(() => {
|
||||
app.dock.setMenu(dockMenu)
|
||||
})
|
||||
```
|
||||
|
||||
After launching the Electron application, right click the application icon.
|
||||
You should see the custom menu you just defined:
|
||||
|
||||

|
||||
|
||||
[dock-menu-image]: https://cloud.githubusercontent.com/assets/639601/5069962/6032658a-6e9c-11e4-9953-aa84006bdfff.png
|
||||
[recent-documents]: ./recent-documents.md
|
||||
[progress-bar]: ./progress-bar.md
|
||||
|
||||
@@ -51,7 +51,7 @@ ipcMain.on('ondragstart', (event, filePath) => {
|
||||
})
|
||||
```
|
||||
|
||||
After launching the Electron application, try to dragging and dropping
|
||||
After launching the Electron application, try dragging and dropping
|
||||
the item from the BroswerWindow onto your desktop. In this guide,
|
||||
the item is a Markdown file located in the root of the project:
|
||||
|
||||
|
||||
@@ -1,17 +1,36 @@
|
||||
# Notifications (Windows, Linux, macOS)
|
||||
|
||||
All three operating systems provide means for applications to send notifications
|
||||
to the user. Electron conveniently allows developers to send notifications with
|
||||
the [HTML5 Notification API](https://notifications.spec.whatwg.org/), using
|
||||
the currently running operating system's native notification APIs to display it.
|
||||
## Overview
|
||||
|
||||
**Note:** Since this is an HTML5 API it is only available in the renderer process. If
|
||||
you want to show Notifications in the main process please check out the
|
||||
All three operating systems provide means for applications to send
|
||||
notifications to the user. The technique of showing notifications is different
|
||||
for the Main and Renderer processes.
|
||||
|
||||
For the Renderer process, Electron conveniently allows developers to send
|
||||
notifications with the [HTML5 Notification API](https://notifications.spec.whatwg.org/),
|
||||
using the currently running operating system's native notification APIs
|
||||
to display it.
|
||||
|
||||
To show notifications in the Main process, you need to use the
|
||||
[Notification](../api/notification.md) module.
|
||||
|
||||
```javascript
|
||||
## Example
|
||||
|
||||
### Show notifications in the Renderer process
|
||||
|
||||
Assuming you have a working Electron application from the
|
||||
[Quick Start Guide](quick-start.md), add the following line to the
|
||||
`index.html` file before the closing `</body>` tag:
|
||||
|
||||
```html
|
||||
<script src="renderer.js"></script>
|
||||
```
|
||||
|
||||
and add the `renderer.js` file:
|
||||
|
||||
```js
|
||||
const myNotification = new Notification('Title', {
|
||||
body: 'Lorem Ipsum Dolor Sit Amet'
|
||||
body: 'Notification from the Renderer process'
|
||||
})
|
||||
|
||||
myNotification.onclick = () => {
|
||||
@@ -19,12 +38,52 @@ myNotification.onclick = () => {
|
||||
}
|
||||
```
|
||||
|
||||
After launching the Electron application, you should see the notification:
|
||||
|
||||

|
||||
|
||||
If you open the Console and then click the notification, you will see the
|
||||
message that was generated after triggering the `onclick` event:
|
||||
|
||||

|
||||
|
||||
### Show notifications in the Main process
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` file with the following lines:
|
||||
|
||||
```js
|
||||
const { Notification } = require('electron')
|
||||
|
||||
function showNotification () {
|
||||
const notification = {
|
||||
title: 'Basic Notification',
|
||||
body: 'Notification from the Main process'
|
||||
}
|
||||
new Notification(notification).show()
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow).then(showNotification)
|
||||
```
|
||||
|
||||
After launching the Electron application, you should see the notification:
|
||||
|
||||

|
||||
|
||||
## Additional information
|
||||
|
||||
While code and user experience across operating systems are similar, there
|
||||
are subtle differences.
|
||||
|
||||
## Windows
|
||||
* On Windows 10, a shortcut to your app with an [Application User
|
||||
Model ID][app-user-model-id] must be installed to the Start Menu. This can be overkill during development, so adding `node_modules\electron\dist\electron.exe` to your Start Menu also does the trick. Navigate to the file in Explorer, right-click and 'Pin to Start Menu'. You will then need to add the line `app.setAppUserModelId(process.execPath)` to your main process to see notifications.
|
||||
### Windows
|
||||
|
||||
* On Windows 10, a shortcut to your app with an
|
||||
[Application User Model ID][app-user-model-id] must be installed to the
|
||||
Start Menu. This can be overkill during development, so adding
|
||||
`node_modules\electron\dist\electron.exe` to your Start Menu also does the
|
||||
trick. Navigate to the file in Explorer, right-click and 'Pin to Start Menu'.
|
||||
You will then need to add the line `app.setAppUserModelId(process.execPath)` to
|
||||
your main process to see notifications.
|
||||
* On Windows 8.1 and Windows 8, a shortcut to your app with an [Application User
|
||||
Model ID][app-user-model-id] must be installed to the Start screen. Note,
|
||||
however, that it does not need to be pinned to the Start screen.
|
||||
@@ -44,7 +103,7 @@ to 200 characters. That said, that limitation has been removed in Windows 10, wi
|
||||
the Windows team asking developers to be reasonable. Attempting to send gigantic
|
||||
amounts of text to the API (thousands of characters) might result in instability.
|
||||
|
||||
### Advanced Notifications
|
||||
#### Advanced Notifications
|
||||
|
||||
Later versions of Windows allow for advanced notifications, with custom templates,
|
||||
images, and other flexible elements. To send those notifications (from either the
|
||||
@@ -53,40 +112,47 @@ main process or the renderer process), use the userland module
|
||||
which uses native Node addons to send `ToastNotification` and `TileNotification` objects.
|
||||
|
||||
While notifications including buttons work with `electron-windows-notifications`,
|
||||
handling replies requires the use of [`electron-windows-interactive-notifications`](https://github.com/felixrieseberg/electron-windows-interactive-notifications), which
|
||||
helps with registering the required COM components and calling your Electron app with
|
||||
the entered user data.
|
||||
handling replies requires the use of
|
||||
[`electron-windows-interactive-notifications`](https://github.com/felixrieseberg/electron-windows-interactive-notifications),
|
||||
which helps with registering the required COM components and calling your
|
||||
Electron app with the entered user data.
|
||||
|
||||
### Quiet Hours / Presentation Mode
|
||||
#### Quiet Hours / Presentation Mode
|
||||
|
||||
To detect whether or not you're allowed to send a notification, use the userland module
|
||||
[electron-notification-state](https://github.com/felixrieseberg/electron-notification-state).
|
||||
To detect whether or not you're allowed to send a notification, use the
|
||||
userland module [electron-notification-state](https://github.com/felixrieseberg/electron-notification-state).
|
||||
|
||||
This allows you to determine ahead of time whether or not Windows will silently throw
|
||||
the notification away.
|
||||
This allows you to determine ahead of time whether or not Windows will
|
||||
silently throw the notification away.
|
||||
|
||||
## macOS
|
||||
### macOS
|
||||
|
||||
Notifications are straight-forward on macOS, but you should be aware of
|
||||
[Apple's Human Interface guidelines regarding notifications](https://developer.apple.com/macos/human-interface-guidelines/system-capabilities/notifications/).
|
||||
[Apple's Human Interface guidelines regarding notifications][apple-notification-guidelines].
|
||||
|
||||
Note that notifications are limited to 256 bytes in size and will be truncated
|
||||
if you exceed that limit.
|
||||
|
||||
### Advanced Notifications
|
||||
[apple-notification-guidelines]: https://developer.apple.com/macos/human-interface-guidelines/system-capabilities/notifications/
|
||||
|
||||
#### Advanced Notifications
|
||||
|
||||
Later versions of macOS allow for notifications with an input field, allowing the user
|
||||
to quickly reply to a notification. In order to send notifications with an input field,
|
||||
use the userland module [node-mac-notifier](https://github.com/CharlieHess/node-mac-notifier).
|
||||
use the userland module [node-mac-notifier][node-mac-notifier].
|
||||
|
||||
### Do not disturb / Session State
|
||||
[node-mac-notifier]: https://github.com/CharlieHess/node-mac-notifier
|
||||
|
||||
#### Do not disturb / Session State
|
||||
|
||||
To detect whether or not you're allowed to send a notification, use the userland module
|
||||
[electron-notification-state](https://github.com/felixrieseberg/electron-notification-state).
|
||||
[electron-notification-state][electron-notification-state].
|
||||
|
||||
This will allow you to detect ahead of time whether or not the notification will be displayed.
|
||||
|
||||
## Linux
|
||||
[electron-notification-state]: https://github.com/felixrieseberg/electron-notification-state
|
||||
|
||||
### Linux
|
||||
|
||||
Notifications are sent using `libnotify` which can show notifications on any
|
||||
desktop environment that follows [Desktop Notifications
|
||||
|
||||
@@ -1,14 +1,30 @@
|
||||
# Online/Offline Event Detection
|
||||
|
||||
[Online and offline event](https://developer.mozilla.org/en-US/docs/Online_and_offline_events) detection can be implemented in the renderer process using the [`navigator.onLine`](http://html5index.org/Offline%20-%20NavigatorOnLine.html) attribute, part of standard HTML5 API.
|
||||
The `navigator.onLine` attribute returns `false` if any network requests are guaranteed to fail i.e. definitely offline (disconnected from the network). It returns `true` in all other cases.
|
||||
Since all other conditions return `true`, one has to be mindful of getting false positives, as we cannot assume `true` value necessarily means that Electron can access the internet. Such as in cases where the computer is running a virtualization software that has virtual ethernet adapters that are always “connected.”
|
||||
Therefore, if you really want to determine the internet access status of Electron,
|
||||
you should develop additional means for checking.
|
||||
## Overview
|
||||
|
||||
Example:
|
||||
[Online and offline event](https://developer.mozilla.org/en-US/docs/Online_and_offline_events)
|
||||
detection can be implemented in the Renderer process using the
|
||||
[`navigator.onLine`](http://html5index.org/Offline%20-%20NavigatorOnLine.html)
|
||||
attribute, part of standard HTML5 API.
|
||||
|
||||
_main.js_
|
||||
The `navigator.onLine` attribute returns:
|
||||
* `false` if all network requests are guaranteed to fail (e.g. when disconnected from the network).
|
||||
* `true` in all other cases.
|
||||
|
||||
Since many cases return `true`, you should treat with care situations of
|
||||
getting false positives, as we cannot always assume that `true` value means
|
||||
that Electron can access the Internet. For example, in cases when the computer
|
||||
is running a virtualization software that has virtual Ethernet adapters in "always
|
||||
connected" state. Therefore, if you want to determine the Internet access
|
||||
status of Electron, you should develop additional means for this check.
|
||||
|
||||
## Example
|
||||
|
||||
### Event detection in the Renderer process
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` file
|
||||
with the following lines:
|
||||
|
||||
```javascript
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
@@ -21,33 +37,39 @@ app.whenReady().then(() => {
|
||||
})
|
||||
```
|
||||
|
||||
_online-status.html_
|
||||
create the `online-status.html` file and add the following line before the
|
||||
closing `</body>` tag:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
const alertOnlineStatus = () => {
|
||||
window.alert(navigator.onLine ? 'online' : 'offline')
|
||||
}
|
||||
|
||||
window.addEventListener('online', alertOnlineStatus)
|
||||
window.addEventListener('offline', alertOnlineStatus)
|
||||
|
||||
alertOnlineStatus()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
<script src="renderer.js"></script>
|
||||
```
|
||||
|
||||
There may be instances where you want to respond to these events in the
|
||||
main process as well. The main process however does not have a
|
||||
`navigator` object and thus cannot detect these events directly. Using
|
||||
Electron's inter-process communication utilities, the events can be forwarded
|
||||
to the main process and handled as needed, as shown in the following example.
|
||||
and add the `renderer.js` file:
|
||||
|
||||
_main.js_
|
||||
```javascript
|
||||
const alertOnlineStatus = () => { window.alert(navigator.onLine ? 'online' : 'offline') }
|
||||
|
||||
window.addEventListener('online', alertOnlineStatus)
|
||||
window.addEventListener('offline', alertOnlineStatus)
|
||||
|
||||
alertOnlineStatus()
|
||||
```
|
||||
|
||||
After launching the Electron application, you should see the notification:
|
||||
|
||||

|
||||
|
||||
### Event detection in the Main process
|
||||
|
||||
There may be situations when you want to respond to online/offline events in
|
||||
the Main process as well. The Main process, however, does not have a
|
||||
`navigator` object and cannot detect these events directly. In this case, you
|
||||
need to forward the events to the Main process using Electron's inter-process
|
||||
communication (IPC) utilities.
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` file
|
||||
with the following lines:
|
||||
|
||||
```javascript
|
||||
const { app, BrowserWindow, ipcMain } = require('electron')
|
||||
@@ -63,23 +85,33 @@ ipcMain.on('online-status-changed', (event, status) => {
|
||||
})
|
||||
```
|
||||
|
||||
_online-status.html_
|
||||
create the `online-status.html` file and add the following line before the
|
||||
closing `</body>` tag:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
const { ipcRenderer } = require('electron')
|
||||
const updateOnlineStatus = () => {
|
||||
ipcRenderer.send('online-status-changed', navigator.onLine ? 'online' : 'offline')
|
||||
}
|
||||
|
||||
window.addEventListener('online', updateOnlineStatus)
|
||||
window.addEventListener('offline', updateOnlineStatus)
|
||||
|
||||
updateOnlineStatus()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
<script src="renderer.js"></script>
|
||||
```
|
||||
|
||||
and add the `renderer.js` file:
|
||||
|
||||
```javascript
|
||||
const { ipcRenderer } = require('electron')
|
||||
const updateOnlineStatus = () => { ipcRenderer.send('online-status-changed', navigator.onLine ? 'online' : 'offline') }
|
||||
|
||||
window.addEventListener('online', updateOnlineStatus)
|
||||
window.addEventListener('offline', updateOnlineStatus)
|
||||
|
||||
updateOnlineStatus()
|
||||
```
|
||||
|
||||
After launching the Electron application, you should see the notification in the
|
||||
Console:
|
||||
|
||||
```sh
|
||||
npm start
|
||||
|
||||
> electron@1.0.0 start /electron
|
||||
> electron .
|
||||
|
||||
online
|
||||
```
|
||||
|
||||
@@ -1,29 +1,50 @@
|
||||
# Progress Bar in Taskbar (Windows, macOS, Unity)
|
||||
|
||||
On Windows a taskbar button can be used to display a progress bar. This enables
|
||||
a window to provide progress information to the user without the user having to
|
||||
switch to the window itself.
|
||||
## Overview
|
||||
|
||||
On macOS the progress bar will be displayed as a part of the dock icon.
|
||||
A progress bar enables a window to provide progress information to the user
|
||||
without the need of switching to the window itself.
|
||||
|
||||
The Unity DE also has a similar feature that allows you to specify the progress
|
||||
bar in the launcher.
|
||||
On Windows, you can use a taskbar button to display a progress bar.
|
||||
|
||||
__Progress bar in taskbar button:__
|
||||
![Windows Progress Bar][windows-progress-bar]
|
||||
|
||||
![Taskbar Progress Bar][taskbar-progress-image]
|
||||
On macOS, the progress bar will be displayed as a part of the dock icon.
|
||||
|
||||
All three cases are covered by the same API - the `setProgressBar()` method
|
||||
available on instances of `BrowserWindows`. Call it with a number between `0`
|
||||
and `1` to indicate your progress. If you have a long-running task that's
|
||||
currently at 63% towards completion, you'd call it with `setProgressBar(0.63)`.
|
||||
![macOS Progress Bar][macos-progress-bar]
|
||||
|
||||
Generally speaking, setting the parameter to a value below zero (like `-1`)
|
||||
will remove the progress bar while setting it to a value higher than one
|
||||
(like `2`) will switch the progress bar to intermediate mode.
|
||||
On Linux, the Unity graphical interface also has a similar feature that allows
|
||||
you to specify the progress bar in the launcher.
|
||||
|
||||
![Linux Progress Bar][linux-progress-bar]
|
||||
|
||||
> NOTE: on Windows, each window can have its own progress bar, whereas on macOS
|
||||
and Linux (Unity) there can be only one progress bar for the application.
|
||||
|
||||
----
|
||||
|
||||
All three cases are covered by the same API - the
|
||||
[`setProgressBar()`][setprogressbar] method available on an instance of
|
||||
`BrowserWindow`. To indicate your progress, call this method with a number
|
||||
between `0` and `1`. For example, if you have a long-running task that is
|
||||
currently at 63% towards completion, you would call it as
|
||||
`setProgressBar(0.63)`.
|
||||
|
||||
Setting the parameter to negative values (e.g. `-1`) will remove the progress
|
||||
bar, whereas setting it to values greater than `1` (e.g. `2`) will switch the
|
||||
progress bar to indeterminate mode (Windows-only -- it will clamp to 100%
|
||||
otherwise). In this mode, a progress bar remains active but does not show an
|
||||
actual percentage. Use this mode for situations when you do not know how long
|
||||
an operation will take to complete.
|
||||
|
||||
See the [API documentation for more options and modes][setprogressbar].
|
||||
|
||||
## Example
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), add the following lines to the
|
||||
`main.js` file:
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow()
|
||||
@@ -31,5 +52,18 @@ const win = new BrowserWindow()
|
||||
win.setProgressBar(0.5)
|
||||
```
|
||||
|
||||
[taskbar-progress-image]: https://cloud.githubusercontent.com/assets/639601/5081682/16691fda-6f0e-11e4-9676-49b6418f1264.png
|
||||
[setprogressbar]: ../api/browser-window.md#winsetprogressbarprogress
|
||||
After launching the Electron application, you should see the bar in
|
||||
the dock (macOS) or taskbar (Windows, Unity), indicating the progress
|
||||
percentage you just defined.
|
||||
|
||||

|
||||
|
||||
For macOS, the progress bar will also be indicated for your application
|
||||
when using [Mission Control](https://support.apple.com/en-us/HT204100):
|
||||
|
||||

|
||||
|
||||
[windows-progress-bar]: https://cloud.githubusercontent.com/assets/639601/5081682/16691fda-6f0e-11e4-9676-49b6418f1264.png
|
||||
[macos-progress-bar]: ../images/macos-progress-bar.png
|
||||
[linux-progress-bar]: ../images/linux-progress-bar.png
|
||||
[setprogressbar]: ../api/browser-window.md#winsetprogressbarprogress-options
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# Recent Documents (Windows & macOS)
|
||||
|
||||
## Overview
|
||||
|
||||
Windows and macOS provide access to a list of recent documents opened by
|
||||
the application via JumpList or dock menu, respectively.
|
||||
|
||||
@@ -11,39 +13,58 @@ __Application dock menu:__
|
||||
|
||||
![macOS Dock Menu][dock-menu-image]
|
||||
|
||||
To add a file to recent documents, you can use the
|
||||
[app.addRecentDocument][addrecentdocument] API:
|
||||
To add a file to recent documents, you need to use the
|
||||
[app.addRecentDocument][addrecentdocument] API.
|
||||
|
||||
## Example
|
||||
|
||||
### Add an item to recent documents
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), add the following lines to the
|
||||
`main.js` file:
|
||||
|
||||
```javascript
|
||||
const { app } = require('electron')
|
||||
|
||||
app.addRecentDocument('/Users/USERNAME/Desktop/work.type')
|
||||
```
|
||||
|
||||
And you can use [app.clearRecentDocuments][clearrecentdocuments] API to empty
|
||||
the recent documents list:
|
||||
After launching the Electron application, right click the application icon.
|
||||
You should see the item you just added. In this guide, the item is a Markdown
|
||||
file located in the root of the project:
|
||||
|
||||

|
||||
|
||||
### Clear the list of recent documents
|
||||
|
||||
To clear the list of recent documents, you need to use
|
||||
[app.clearRecentDocuments][clearrecentdocuments] API in the `main.js` file:
|
||||
|
||||
```javascript
|
||||
const { app } = require('electron')
|
||||
|
||||
app.clearRecentDocuments()
|
||||
```
|
||||
|
||||
## Windows Notes
|
||||
## Additional information
|
||||
|
||||
In order to be able to use this feature on Windows, your application has to be
|
||||
registered as a handler of the file type of the document, otherwise the file
|
||||
won't appear in JumpList even after you have added it. You can find everything
|
||||
### Windows Notes
|
||||
|
||||
To use this feature on Windows, your application has to be registered as
|
||||
a handler of the file type of the document, otherwise the file won't appear
|
||||
in JumpList even after you have added it. You can find everything
|
||||
on registering your application in [Application Registration][app-registration].
|
||||
|
||||
When a user clicks a file from the JumpList, a new instance of your application
|
||||
will be started with the path of the file added as a command line argument.
|
||||
|
||||
## macOS Notes
|
||||
### macOS Notes
|
||||
|
||||
### Adding the Recent Documents list to the application menu:
|
||||
#### Add the Recent Documents list to the application menu
|
||||
|
||||
![macOS Recent Documents menu item][menu-item-image]
|
||||
|
||||
You can add menu items to access and clear recent documents by adding the following code snippet to your menu's template.
|
||||
You can add menu items to access and clear recent documents by adding the
|
||||
following code snippet to your menu template:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -62,6 +83,8 @@ You can add menu items to access and clear recent documents by adding the follow
|
||||
}
|
||||
```
|
||||
|
||||
![macOS Recent Documents menu item][menu-item-image]
|
||||
|
||||
When a file is requested from the recent documents menu, the `open-file` event
|
||||
of `app` module will be emitted for it.
|
||||
|
||||
|
||||
@@ -1,28 +1,45 @@
|
||||
# Represented File for macOS BrowserWindows
|
||||
|
||||
On macOS a window can set its represented file, so the file's icon can show in
|
||||
the title bar and when users Command-Click or Control-Click on the title a path
|
||||
popup will show.
|
||||
## Overview
|
||||
|
||||
You can also set the edited state of a window so that the file icon can indicate
|
||||
whether the document in this window has been modified.
|
||||
|
||||
__Represented file popup menu:__
|
||||
On macOS, you can set a represented file for any window in your application.
|
||||
The represented file's icon will be shown in the title bar, and when users
|
||||
`Command-Click` or `Control-Click`, a popup with a path to the file will be
|
||||
shown.
|
||||
|
||||
![Represented File][represented-image]
|
||||
|
||||
> NOTE: The screenshot above is an example where this feature is used to indicate the currently opened file in the Atom text editor.
|
||||
|
||||
You can also set the edited state for a window so that the file icon can
|
||||
indicate whether the document in this window has been modified.
|
||||
|
||||
To set the represented file of window, you can use the
|
||||
[BrowserWindow.setRepresentedFilename][setrepresentedfilename] and
|
||||
[BrowserWindow.setDocumentEdited][setdocumentedited] APIs:
|
||||
[BrowserWindow.setDocumentEdited][setdocumentedited] APIs.
|
||||
|
||||
## Example
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), add the following lines to the
|
||||
`main.js` file:
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
const win = new BrowserWindow()
|
||||
win.setRepresentedFilename('/etc/passwd')
|
||||
win.setDocumentEdited(true)
|
||||
app.whenReady().then(() => {
|
||||
const win = new BrowserWindow()
|
||||
|
||||
win.setRepresentedFilename('/etc/passwd')
|
||||
win.setDocumentEdited(true)
|
||||
})
|
||||
```
|
||||
|
||||
After launching the Electron application, click on the title with `Command` or
|
||||
`Control` key pressed. You should see a popup with the file you just defined:
|
||||
|
||||

|
||||
|
||||
[represented-image]: https://cloud.githubusercontent.com/assets/639601/5082061/670a949a-6f14-11e4-987a-9aaa04b23c1d.png
|
||||
[setrepresentedfilename]: ../api/browser-window.md#winsetrepresentedfilenamefilename-macos
|
||||
[setdocumentedited]: ../api/browser-window.md#winsetdocumenteditededited-macos
|
||||
|
||||
@@ -814,6 +814,6 @@ which potential security issues are not as widely known.
|
||||
[web-contents]: ../api/web-contents.md
|
||||
[new-window]: ../api/web-contents.md#event-new-window
|
||||
[will-navigate]: ../api/web-contents.md#event-will-navigate
|
||||
[open-external]: ../api/shell.md#shellopenexternalurl-options-callback
|
||||
[open-external]: ../api/shell.md#shellopenexternalurl-options
|
||||
[sandbox]: ../api/sandbox-option.md
|
||||
[responsible-disclosure]: https://en.wikipedia.org/wiki/Responsible_disclosure
|
||||
|
||||
@@ -79,6 +79,78 @@ snap(options)
|
||||
.then(snapPath => console.log(`Created snap at ${snapPath}!`))
|
||||
```
|
||||
|
||||
## Using `snapcraft` with `electron-packager`
|
||||
|
||||
### Step 1: Create Sample Snapcraft Project
|
||||
|
||||
Create your project directory and add add the following to `snap/snapcraft.yaml`:
|
||||
|
||||
```yaml
|
||||
name: electron-packager-hello-world
|
||||
version: '0.1'
|
||||
summary: Hello World Electron app
|
||||
description: |
|
||||
Simple Hello World Electron app as an example
|
||||
base: core18
|
||||
confinement: strict
|
||||
grade: stable
|
||||
|
||||
apps:
|
||||
electron-packager-hello-world:
|
||||
command: electron-quick-start/electron-quick-start --no-sandbox
|
||||
extensions: [gnome-3-34]
|
||||
plugs:
|
||||
- browser-support
|
||||
- network
|
||||
- network-bind
|
||||
environment:
|
||||
# Correct the TMPDIR path for Chromium Framework/Electron to ensure
|
||||
# libappindicator has readable resources.
|
||||
TMPDIR: $XDG_RUNTIME_DIR
|
||||
|
||||
parts:
|
||||
electron-quick-start:
|
||||
plugin: nil
|
||||
source: https://github.com/electron/electron-quick-start.git
|
||||
override-build: |
|
||||
npm install electron electron-packager
|
||||
npx electron-packager . --overwrite --platform=linux --output=release-build --prune=true
|
||||
cp -rv ./electron-quick-start-linux-* $SNAPCRAFT_PART_INSTALL/electron-quick-start
|
||||
build-snaps:
|
||||
- node/14/stable
|
||||
build-packages:
|
||||
- unzip
|
||||
stage-packages:
|
||||
- libnss3
|
||||
- libnspr4
|
||||
```
|
||||
|
||||
If you want to apply this example to an existing project:
|
||||
|
||||
- Replace `source: https://github.com/electron/electron-quick-start.git` with `source: .`.
|
||||
- Replace all instances of `electron-quick-start` with your project's name.
|
||||
|
||||
### Step 2: Build the snap
|
||||
|
||||
```sh
|
||||
$ snapcraft
|
||||
|
||||
<output snipped>
|
||||
Snapped electron-packager-hello-world_0.1_amd64.snap
|
||||
```
|
||||
|
||||
### Step 3: Install the snap
|
||||
|
||||
```sh
|
||||
sudo snap install electron-packager-hello-world_0.1_amd64.snap --dangerous
|
||||
```
|
||||
|
||||
### Step 4: Run the snap
|
||||
|
||||
```sh
|
||||
electron-packager-hello-world
|
||||
```
|
||||
|
||||
## Using an Existing Debian Package
|
||||
|
||||
Snapcraft is capable of taking an existing `.deb` file and turning it into
|
||||
|
||||
@@ -9,8 +9,12 @@ If you're looking for programming help,
|
||||
for answers to questions,
|
||||
or to join in discussion with other developers who use Electron,
|
||||
you can interact with the community in these locations:
|
||||
- [`electron`](https://discuss.atom.io/c/electron) category on the Atom
|
||||
forums
|
||||
- [`Electron's Discord`](https://discord.com/invite/electron) has channels for:
|
||||
- Getting help
|
||||
- Ecosystem apps like [Electron Forge](https://github.com/electron-userland/electron-forge) and [Electron Fiddle](https://github.com/electron/fiddle)
|
||||
- Sharing ideas with other Electron app developers
|
||||
- And more!
|
||||
- [`electron`](https://discuss.atom.io/c/electron) category on the Atom forums
|
||||
- `#atom-shell` channel on Freenode
|
||||
- `#electron` channel on [Atom's Slack](https://discuss.atom.io/t/join-us-on-slack/16638?source_topic_id=25406)
|
||||
- [`electron-ru`](https://telegram.me/electron_ru) *(Russian)*
|
||||
|
||||
@@ -1,22 +1,57 @@
|
||||
# Web embeds in Electron
|
||||
# Web embeds
|
||||
|
||||
If you want to embed (third party) web content in an Electron `BrowserWindow`, there are three options available to you: `<iframe>` tags, `<webview>` tags, and `BrowserViews`. Each one offers slightly different functionality and is useful in different situations. To help you choose between these, this guide will explain the differences and capabilities of each.
|
||||
## Overview
|
||||
|
||||
## Iframes
|
||||
If you want to embed (third-party) web content in an Electron `BrowserWindow`,
|
||||
there are three options available to you: `<iframe>` tags, `<webview>` tags,
|
||||
and `BrowserViews`. Each one offers slightly different functionality and is
|
||||
useful in different situations. To help you choose between these, this guide
|
||||
explains the differences and capabilities of each option.
|
||||
|
||||
Iframes in Electron behave like iframes in regular browsers. An `<iframe>` element in your page can show external web pages, provided that their [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) allows it. To limit the amount of capabilities a site in an `<iframe>` tag, it's recommended to use the [`sandbox` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox) and only allow the capabilities you want to support.
|
||||
### Iframes
|
||||
|
||||
## WebViews
|
||||
Iframes in Electron behave like iframes in regular browsers. An `<iframe>`
|
||||
element in your page can show external web pages, provided that their
|
||||
[Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)
|
||||
allows it. To limit the number of capabilities of a site in an `<iframe>` tag,
|
||||
it is recommended to use the [`sandbox` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox)
|
||||
and only allow the capabilities you want to support.
|
||||
|
||||
[WebViews](../api/webview-tag.md) are based on Chromium's WebViews and are not explicitly supported by Electron. We do not guarantee that the WebView API will remain available in future versions of Electron. This is why, if you want to use `<webview>` tags, you will need to set `webviewTag` to `true` in the `webPreferences` of your `BrowserWindow`.
|
||||
### WebViews
|
||||
|
||||
WebViews are a custom element (`<webview>`) that will only work inside Electron.
|
||||
They are implemented as an "out-of-process iframe". This means that all communication with the `<webview>` is done asynchronously using IPC. The `<webview>` element has many custom methods and events, similar to `webContents`, that allow you much greater control over the contents.
|
||||
> Important Note:
|
||||
[we do not recommend you to use use WebViews](https://www.electronjs.org/docs/api/webview-tag#warning),
|
||||
as this tag undergoes dramatic architectural changes that may affect stability
|
||||
of your application. Consider switching to alternatives, like `iframe` and
|
||||
Electron's `BrowserView`, or an architecture that avoids embedded content
|
||||
by design.
|
||||
|
||||
Compared to an `<iframe>`, `<webview>` tends to be slightly slower but offers much greater control in loading and communicating with the third party content and handling various events.
|
||||
[WebViews](../api/webview-tag.md) are based on Chromium's WebViews and are not
|
||||
explicitly supported by Electron. We do not guarantee that the WebView API will
|
||||
remain available in future versions of Electron. To use `<webview>` tags, you
|
||||
will need to set `webviewTag` to `true` in the `webPreferences` of your
|
||||
`BrowserWindow`.
|
||||
|
||||
## BrowserViews
|
||||
WebView is a custom element (`<webview>`) that will only work inside Electron.
|
||||
They are implemented as an "out-of-process iframe". This means that all
|
||||
communication with the `<webview>` is done asynchronously using IPC. The
|
||||
`<webview>` element has many custom methods and events, similar to
|
||||
`webContents`, that provide you with greater control over the content.
|
||||
|
||||
[BrowserViews](../api/browser-view.md) are not part of the DOM - instead, they are created in and controlled by your main process. They are simply another layer of web content on top of your existing window. This means that they are completely separate from your own `BrowserWindow` content and that their position is not controlled by the DOM or CSS but by setting the bounds in the main process.
|
||||
Compared to an `<iframe>`, `<webview>` tends to be slightly slower but offers
|
||||
much greater control in loading and communicating with the third-party content
|
||||
and handling various events.
|
||||
|
||||
BrowserViews offer the greatest control over their contents, since they implement the `webContents` similarly to how a `BrowserWindow` implements it. However, they are not part of your DOM but are overlaid on top of them, which means you will have to manage their position manually.
|
||||
### BrowserViews
|
||||
|
||||
[BrowserViews](../api/browser-view.md) are not a part of the DOM - instead,
|
||||
they are created in and controlled by your Main process. They are simply
|
||||
another layer of web content on top of your existing window. This means
|
||||
that they are completely separate from your own `BrowserWindow` content and
|
||||
their position is not controlled by the DOM or CSS. Instead, it is controlled
|
||||
by setting the bounds in the Main process.
|
||||
|
||||
`BrowserViews` offer the greatest control over their contents, since they
|
||||
implement the `webContents` similarly to how the `BrowserWindow` does it.
|
||||
However, as `BrowserViews` are not a part of your DOM, but are rather overlaid
|
||||
on top of them, you will have to manage their position manually.
|
||||
|
||||
@@ -49,6 +49,7 @@ auto_filenames = {
|
||||
"docs/api/screen.md",
|
||||
"docs/api/service-workers.md",
|
||||
"docs/api/session.md",
|
||||
"docs/api/share-menu.md",
|
||||
"docs/api/shell.md",
|
||||
"docs/api/structures",
|
||||
"docs/api/synopsis.md",
|
||||
@@ -119,6 +120,7 @@ auto_filenames = {
|
||||
"docs/api/structures/serial-port.md",
|
||||
"docs/api/structures/service-worker-info.md",
|
||||
"docs/api/structures/shared-worker-info.md",
|
||||
"docs/api/structures/sharing-item.md",
|
||||
"docs/api/structures/shortcut-details.md",
|
||||
"docs/api/structures/size.md",
|
||||
"docs/api/structures/task.md",
|
||||
@@ -219,6 +221,7 @@ auto_filenames = {
|
||||
"lib/browser/api/protocol.ts",
|
||||
"lib/browser/api/screen.ts",
|
||||
"lib/browser/api/session.ts",
|
||||
"lib/browser/api/share-menu.ts",
|
||||
"lib/browser/api/system-preferences.ts",
|
||||
"lib/browser/api/touch-bar.ts",
|
||||
"lib/browser/api/tray.ts",
|
||||
|
||||
197
filenames.gni
@@ -1,3 +1,5 @@
|
||||
import("//build/config/ui.gni")
|
||||
|
||||
filenames = {
|
||||
default_app_ts_sources = [
|
||||
"default_app/default_app.ts",
|
||||
@@ -22,35 +24,25 @@ filenames = {
|
||||
]
|
||||
|
||||
lib_sources_linux = [
|
||||
"chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc",
|
||||
"chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h",
|
||||
"shell/browser/browser_linux.cc",
|
||||
"shell/browser/lib/power_observer_linux.cc",
|
||||
"shell/browser/lib/power_observer_linux.h",
|
||||
"shell/browser/linux/unity_service.cc",
|
||||
"shell/browser/linux/unity_service.h",
|
||||
"shell/browser/notifications/linux/libnotify_notification.cc",
|
||||
"shell/browser/notifications/linux/libnotify_notification.h",
|
||||
"shell/browser/notifications/linux/notification_presenter_linux.cc",
|
||||
"shell/browser/notifications/linux/notification_presenter_linux.h",
|
||||
"shell/browser/relauncher_linux.cc",
|
||||
"shell/browser/ui/file_dialog_gtk.cc",
|
||||
"shell/browser/ui/message_box_gtk.cc",
|
||||
"shell/browser/ui/tray_icon_gtk.cc",
|
||||
"shell/browser/ui/tray_icon_gtk.h",
|
||||
"shell/browser/ui/views/global_menu_bar_x11.cc",
|
||||
"shell/browser/ui/views/global_menu_bar_x11.h",
|
||||
"shell/browser/ui/x/event_disabler.cc",
|
||||
"shell/browser/ui/x/event_disabler.h",
|
||||
"shell/browser/ui/x/window_state_watcher.cc",
|
||||
"shell/browser/ui/x/window_state_watcher.h",
|
||||
"shell/browser/ui/x/x_window_utils.cc",
|
||||
"shell/browser/ui/x/x_window_utils.h",
|
||||
"shell/browser/browser_linux.cc",
|
||||
"shell/browser/lib/power_observer_linux.cc",
|
||||
"shell/browser/lib/power_observer_linux.h",
|
||||
"shell/browser/notifications/linux/notification_presenter_linux.cc",
|
||||
"shell/browser/notifications/linux/notification_presenter_linux.h",
|
||||
"shell/browser/relauncher_linux.cc",
|
||||
"shell/common/application_info_linux.cc",
|
||||
"shell/common/language_util_linux.cc",
|
||||
"shell/common/node_bindings_linux.cc",
|
||||
"shell/common/node_bindings_linux.h",
|
||||
"shell/common/platform_util_linux.cc",
|
||||
"shell/browser/linux/unity_service.h",
|
||||
"shell/browser/notifications/linux/libnotify_notification.cc",
|
||||
"shell/browser/notifications/linux/libnotify_notification.h",
|
||||
"shell/browser/linux/unity_service.cc",
|
||||
]
|
||||
|
||||
lib_sources_posix = [
|
||||
@@ -68,6 +60,17 @@ filenames = {
|
||||
"shell/browser/notifications/win/notification_presenter_win.h",
|
||||
"shell/browser/notifications/win/notification_presenter_win7.cc",
|
||||
"shell/browser/notifications/win/notification_presenter_win7.h",
|
||||
"shell/browser/notifications/win/win32_desktop_notifications/common.h",
|
||||
"shell/browser/notifications/win/win32_desktop_notifications/desktop_notification_controller.cc",
|
||||
"shell/browser/notifications/win/win32_desktop_notifications/desktop_notification_controller.h",
|
||||
"shell/browser/notifications/win/win32_desktop_notifications/toast_uia.cc",
|
||||
"shell/browser/notifications/win/win32_desktop_notifications/toast_uia.h",
|
||||
"shell/browser/notifications/win/win32_desktop_notifications/toast.cc",
|
||||
"shell/browser/notifications/win/win32_desktop_notifications/toast.h",
|
||||
"shell/browser/notifications/win/win32_notification.cc",
|
||||
"shell/browser/notifications/win/win32_notification.h",
|
||||
"shell/browser/notifications/win/windows_toast_notification.cc",
|
||||
"shell/browser/notifications/win/windows_toast_notification.h",
|
||||
"shell/browser/relauncher_win.cc",
|
||||
"shell/browser/ui/certificate_trust_win.cc",
|
||||
"shell/browser/ui/file_dialog_win.cc",
|
||||
@@ -76,39 +79,28 @@ filenames = {
|
||||
"shell/browser/ui/views/electron_views_delegate_win.cc",
|
||||
"shell/browser/ui/views/win_frame_view.cc",
|
||||
"shell/browser/ui/views/win_frame_view.h",
|
||||
"shell/browser/ui/win/dialog_thread.cc",
|
||||
"shell/browser/ui/win/dialog_thread.h",
|
||||
"shell/browser/ui/win/electron_desktop_native_widget_aura.cc",
|
||||
"shell/browser/ui/win/electron_desktop_native_widget_aura.h",
|
||||
"shell/browser/ui/win/electron_desktop_window_tree_host_win.cc",
|
||||
"shell/browser/ui/win/electron_desktop_window_tree_host_win.h",
|
||||
"shell/browser/ui/win/jump_list.cc",
|
||||
"shell/browser/ui/win/jump_list.h",
|
||||
"shell/browser/ui/win/notify_icon_host.cc",
|
||||
"shell/browser/ui/win/notify_icon_host.h",
|
||||
"shell/browser/ui/win/notify_icon.cc",
|
||||
"shell/browser/ui/win/notify_icon.h",
|
||||
"shell/browser/ui/win/taskbar_host.cc",
|
||||
"shell/browser/ui/win/taskbar_host.h",
|
||||
"shell/browser/win/scoped_hstring.cc",
|
||||
"shell/browser/win/scoped_hstring.h",
|
||||
"shell/common/api/electron_api_native_image_win.cc",
|
||||
"shell/common/application_info_win.cc",
|
||||
"shell/common/language_util_win.cc",
|
||||
"shell/common/node_bindings_win.cc",
|
||||
"shell/common/node_bindings_win.h",
|
||||
"shell/common/platform_util_win.cc",
|
||||
"shell/browser/notifications/win/win32_desktop_notifications/common.h",
|
||||
"shell/browser/notifications/win/win32_desktop_notifications/desktop_notification_controller.cc",
|
||||
"shell/browser/notifications/win/win32_desktop_notifications/desktop_notification_controller.h",
|
||||
"shell/browser/notifications/win/win32_desktop_notifications/toast.cc",
|
||||
"shell/browser/notifications/win/win32_desktop_notifications/toast.h",
|
||||
"shell/browser/notifications/win/win32_desktop_notifications/toast_uia.cc",
|
||||
"shell/browser/notifications/win/win32_desktop_notifications/toast_uia.h",
|
||||
"shell/browser/notifications/win/win32_notification.cc",
|
||||
"shell/browser/notifications/win/win32_notification.h",
|
||||
"shell/browser/notifications/win/windows_toast_notification.cc",
|
||||
"shell/browser/notifications/win/windows_toast_notification.h",
|
||||
"shell/browser/ui/win/dialog_thread.cc",
|
||||
"shell/browser/ui/win/dialog_thread.h",
|
||||
"shell/browser/ui/win/electron_desktop_native_widget_aura.cc",
|
||||
"shell/browser/ui/win/electron_desktop_native_widget_aura.h",
|
||||
"shell/browser/ui/win/jump_list.cc",
|
||||
"shell/browser/ui/win/jump_list.h",
|
||||
"shell/browser/ui/win/notify_icon.cc",
|
||||
"shell/browser/ui/win/notify_icon.h",
|
||||
"shell/browser/ui/win/notify_icon_host.cc",
|
||||
"shell/browser/ui/win/notify_icon_host.h",
|
||||
"shell/browser/ui/win/taskbar_host.cc",
|
||||
"shell/browser/ui/win/taskbar_host.h",
|
||||
"shell/browser/win/scoped_hstring.cc",
|
||||
"shell/browser/win/scoped_hstring.h",
|
||||
]
|
||||
|
||||
lib_sources_mac = [
|
||||
@@ -124,22 +116,56 @@ filenames = {
|
||||
"shell/browser/api/electron_api_web_contents_mac.mm",
|
||||
"shell/browser/auto_updater_mac.mm",
|
||||
"shell/browser/browser_mac.mm",
|
||||
"shell/browser/notifications/mac/notification_center_delegate.h",
|
||||
"shell/browser/notifications/mac/notification_center_delegate.mm",
|
||||
"shell/common/mac/main_application_bundle.h",
|
||||
"shell/common/mac/main_application_bundle.mm",
|
||||
"shell/browser/common_web_contents_delegate_mac.mm",
|
||||
"shell/browser/electron_browser_main_parts_mac.mm",
|
||||
"shell/browser/mac/dict_util.h",
|
||||
"shell/browser/mac/dict_util.mm",
|
||||
"shell/browser/mac/electron_application_delegate.h",
|
||||
"shell/browser/mac/electron_application_delegate.mm",
|
||||
"shell/browser/mac/electron_application.h",
|
||||
"shell/browser/mac/electron_application.mm",
|
||||
"shell/browser/mac/in_app_purchase_observer.h",
|
||||
"shell/browser/mac/in_app_purchase_observer.mm",
|
||||
"shell/browser/mac/in_app_purchase_product.h",
|
||||
"shell/browser/mac/in_app_purchase_product.mm",
|
||||
"shell/browser/mac/in_app_purchase.h",
|
||||
"shell/browser/mac/in_app_purchase.mm",
|
||||
"shell/browser/native_browser_view_mac.h",
|
||||
"shell/browser/native_browser_view_mac.mm",
|
||||
"shell/browser/native_window_mac.h",
|
||||
"shell/browser/native_window_mac.mm",
|
||||
"shell/browser/notifications/mac/cocoa_notification.h",
|
||||
"shell/browser/notifications/mac/cocoa_notification.mm",
|
||||
"shell/browser/notifications/mac/notification_center_delegate.h",
|
||||
"shell/browser/notifications/mac/notification_center_delegate.mm",
|
||||
"shell/browser/notifications/mac/notification_presenter_mac.h",
|
||||
"shell/browser/notifications/mac/notification_presenter_mac.mm",
|
||||
"shell/browser/relauncher_mac.cc",
|
||||
"shell/browser/ui/certificate_trust_mac.mm",
|
||||
"shell/browser/ui/cocoa/delayed_native_view_host.cc",
|
||||
"shell/browser/ui/cocoa/delayed_native_view_host.h",
|
||||
"shell/browser/ui/cocoa/electron_bundle_mover.h",
|
||||
"shell/browser/ui/cocoa/electron_bundle_mover.mm",
|
||||
"shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h",
|
||||
"shell/browser/ui/cocoa/electron_inspectable_web_contents_view.mm",
|
||||
"shell/browser/ui/cocoa/electron_menu_controller.h",
|
||||
"shell/browser/ui/cocoa/electron_menu_controller.mm",
|
||||
"shell/browser/ui/cocoa/electron_native_widget_mac.h",
|
||||
"shell/browser/ui/cocoa/electron_native_widget_mac.mm",
|
||||
"shell/browser/ui/cocoa/electron_ns_window_delegate.h",
|
||||
"shell/browser/ui/cocoa/electron_ns_window_delegate.mm",
|
||||
"shell/browser/ui/cocoa/electron_ns_window.h",
|
||||
"shell/browser/ui/cocoa/electron_ns_window.mm",
|
||||
"shell/browser/ui/cocoa/electron_preview_item.h",
|
||||
"shell/browser/ui/cocoa/electron_preview_item.mm",
|
||||
"shell/browser/ui/cocoa/electron_touch_bar.h",
|
||||
"shell/browser/ui/cocoa/electron_touch_bar.mm",
|
||||
"shell/browser/ui/cocoa/event_dispatching_window.h",
|
||||
"shell/browser/ui/cocoa/event_dispatching_window.mm",
|
||||
"shell/browser/ui/cocoa/NSColor+Hex.h",
|
||||
"shell/browser/ui/cocoa/NSColor+Hex.mm",
|
||||
"shell/browser/ui/cocoa/NSString+ANSI.h",
|
||||
"shell/browser/ui/cocoa/NSString+ANSI.mm",
|
||||
"shell/browser/ui/cocoa/root_view_mac.h",
|
||||
"shell/browser/ui/cocoa/root_view_mac.mm",
|
||||
"shell/browser/ui/cocoa/views_delegate_mac.h",
|
||||
@@ -149,51 +175,17 @@ filenames = {
|
||||
"shell/browser/ui/inspectable_web_contents_view_mac.h",
|
||||
"shell/browser/ui/inspectable_web_contents_view_mac.mm",
|
||||
"shell/browser/ui/message_box_mac.mm",
|
||||
"shell/browser/ui/tray_icon_cocoa.h",
|
||||
"shell/browser/ui/tray_icon_cocoa.mm",
|
||||
"shell/common/api/electron_api_clipboard_mac.mm",
|
||||
"shell/common/api/electron_api_native_image_mac.mm",
|
||||
"shell/common/application_info_mac.mm",
|
||||
"shell/common/language_util_mac.mm",
|
||||
"shell/common/mac/main_application_bundle.h",
|
||||
"shell/common/mac/main_application_bundle.mm",
|
||||
"shell/common/node_bindings_mac.cc",
|
||||
"shell/common/node_bindings_mac.h",
|
||||
"shell/common/platform_util_mac.mm",
|
||||
"shell/browser/notifications/mac/cocoa_notification.h",
|
||||
"shell/browser/notifications/mac/cocoa_notification.mm",
|
||||
"shell/browser/ui/cocoa/NSColor+Hex.h",
|
||||
"shell/browser/ui/cocoa/NSColor+Hex.mm",
|
||||
"shell/browser/ui/cocoa/NSString+ANSI.h",
|
||||
"shell/browser/ui/cocoa/NSString+ANSI.mm",
|
||||
"shell/browser/ui/cocoa/delayed_native_view_host.cc",
|
||||
"shell/browser/ui/cocoa/delayed_native_view_host.h",
|
||||
"shell/browser/ui/cocoa/electron_bundle_mover.h",
|
||||
"shell/browser/ui/cocoa/electron_bundle_mover.mm",
|
||||
"shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h",
|
||||
"shell/browser/ui/cocoa/electron_inspectable_web_contents_view.mm",
|
||||
"shell/browser/ui/cocoa/electron_menu_controller.h",
|
||||
"shell/browser/ui/cocoa/electron_menu_controller.mm",
|
||||
"shell/browser/ui/cocoa/electron_ns_window.h",
|
||||
"shell/browser/ui/cocoa/electron_ns_window.mm",
|
||||
"shell/browser/ui/cocoa/electron_ns_window_delegate.h",
|
||||
"shell/browser/ui/cocoa/electron_ns_window_delegate.mm",
|
||||
"shell/browser/ui/cocoa/electron_preview_item.h",
|
||||
"shell/browser/ui/cocoa/electron_preview_item.mm",
|
||||
"shell/browser/ui/cocoa/electron_touch_bar.h",
|
||||
"shell/browser/ui/cocoa/electron_touch_bar.mm",
|
||||
"shell/browser/ui/cocoa/event_dispatching_window.h",
|
||||
"shell/browser/ui/cocoa/event_dispatching_window.mm",
|
||||
"shell/browser/ui/tray_icon_cocoa.h",
|
||||
"shell/browser/ui/tray_icon_cocoa.mm",
|
||||
"shell/browser/mac/dict_util.h",
|
||||
"shell/browser/mac/dict_util.mm",
|
||||
"shell/browser/mac/electron_application.h",
|
||||
"shell/browser/mac/electron_application.mm",
|
||||
"shell/browser/mac/electron_application_delegate.h",
|
||||
"shell/browser/mac/electron_application_delegate.mm",
|
||||
"shell/browser/mac/in_app_purchase.h",
|
||||
"shell/browser/mac/in_app_purchase.mm",
|
||||
"shell/browser/mac/in_app_purchase_observer.h",
|
||||
"shell/browser/mac/in_app_purchase_observer.mm",
|
||||
"shell/browser/mac/in_app_purchase_product.h",
|
||||
"shell/browser/mac/in_app_purchase_product.mm",
|
||||
]
|
||||
|
||||
lib_sources_views = [
|
||||
@@ -206,14 +198,14 @@ filenames = {
|
||||
"shell/browser/native_window_views.cc",
|
||||
"shell/browser/native_window_views.h",
|
||||
"shell/browser/ui/drag_util_views.cc",
|
||||
"shell/browser/ui/views/inspectable_web_contents_view_views.cc",
|
||||
"shell/browser/ui/views/inspectable_web_contents_view_views.h",
|
||||
"shell/browser/ui/views/autofill_popup_view.cc",
|
||||
"shell/browser/ui/views/autofill_popup_view.h",
|
||||
"shell/browser/ui/views/electron_views_delegate.cc",
|
||||
"shell/browser/ui/views/electron_views_delegate.h",
|
||||
"shell/browser/ui/views/frameless_view.cc",
|
||||
"shell/browser/ui/views/frameless_view.h",
|
||||
"shell/browser/ui/views/inspectable_web_contents_view_views.cc",
|
||||
"shell/browser/ui/views/inspectable_web_contents_view_views.h",
|
||||
"shell/browser/ui/views/menu_bar.cc",
|
||||
"shell/browser/ui/views/menu_bar.h",
|
||||
"shell/browser/ui/views/menu_delegate.cc",
|
||||
@@ -642,6 +634,21 @@ filenames = {
|
||||
"shell/utility/electron_content_utility_client.h",
|
||||
]
|
||||
|
||||
if (use_x11) {
|
||||
lib_sources_linux += [
|
||||
"chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.cc",
|
||||
"chromium_src/chrome/browser/ui/views/frame/global_menu_bar_registrar_x11.h",
|
||||
"shell/browser/ui/views/global_menu_bar_x11.cc",
|
||||
"shell/browser/ui/views/global_menu_bar_x11.h",
|
||||
"shell/browser/ui/x/event_disabler.cc",
|
||||
"shell/browser/ui/x/event_disabler.h",
|
||||
"shell/browser/ui/x/window_state_watcher.cc",
|
||||
"shell/browser/ui/x/window_state_watcher.h",
|
||||
"shell/browser/ui/x/x_window_utils.cc",
|
||||
"shell/browser/ui/x/x_window_utils.h",
|
||||
]
|
||||
}
|
||||
|
||||
lib_sources_nss = [
|
||||
"chromium_src/chrome/browser/certificate_manager_model.cc",
|
||||
"chromium_src/chrome/browser/certificate_manager_model.h",
|
||||
@@ -650,16 +657,16 @@ filenames = {
|
||||
lib_sources_extensions = [
|
||||
"shell/browser/extensions/api/i18n/i18n_api.cc",
|
||||
"shell/browser/extensions/api/i18n/i18n_api.h",
|
||||
"shell/browser/extensions/api/management/electron_management_api_delegate.cc",
|
||||
"shell/browser/extensions/api/management/electron_management_api_delegate.h",
|
||||
"shell/browser/extensions/api/resources_private/resources_private_api.cc",
|
||||
"shell/browser/extensions/api/resources_private/resources_private_api.h",
|
||||
"shell/browser/extensions/api/runtime/electron_runtime_api_delegate.cc",
|
||||
"shell/browser/extensions/api/runtime/electron_runtime_api_delegate.h",
|
||||
"shell/browser/extensions/api/management/electron_management_api_delegate.cc",
|
||||
"shell/browser/extensions/api/management/electron_management_api_delegate.h",
|
||||
"shell/browser/extensions/api/tabs/tabs_api.cc",
|
||||
"shell/browser/extensions/api/tabs/tabs_api.h",
|
||||
"shell/browser/extensions/api/streams_private/streams_private_api.cc",
|
||||
"shell/browser/extensions/api/streams_private/streams_private_api.h",
|
||||
"shell/browser/extensions/api/tabs/tabs_api.cc",
|
||||
"shell/browser/extensions/api/tabs/tabs_api.h",
|
||||
"shell/browser/extensions/electron_browser_context_keyed_service_factories.cc",
|
||||
"shell/browser/extensions/electron_browser_context_keyed_service_factories.h",
|
||||
"shell/browser/extensions/electron_component_extension_resource_manager.cc",
|
||||
@@ -672,10 +679,10 @@ filenames = {
|
||||
"shell/browser/extensions/electron_extension_loader.h",
|
||||
"shell/browser/extensions/electron_extension_message_filter.cc",
|
||||
"shell/browser/extensions/electron_extension_message_filter.h",
|
||||
"shell/browser/extensions/electron_extension_system.cc",
|
||||
"shell/browser/extensions/electron_extension_system.h",
|
||||
"shell/browser/extensions/electron_extension_system_factory.cc",
|
||||
"shell/browser/extensions/electron_extension_system_factory.h",
|
||||
"shell/browser/extensions/electron_extension_system.cc",
|
||||
"shell/browser/extensions/electron_extension_system.h",
|
||||
"shell/browser/extensions/electron_extension_web_contents_observer.cc",
|
||||
"shell/browser/extensions/electron_extension_web_contents_observer.h",
|
||||
"shell/browser/extensions/electron_extensions_api_client.cc",
|
||||
|
||||
@@ -37,6 +37,8 @@ const getOrCreateArchive = (archivePath: string) => {
|
||||
return newArchive;
|
||||
};
|
||||
|
||||
const asarRe = /\.asar/i;
|
||||
|
||||
// Separate asar package's path from full path.
|
||||
const splitPath = (archivePathOrBuffer: string | Buffer) => {
|
||||
// Shortcut for disabled asar.
|
||||
@@ -48,6 +50,7 @@ const splitPath = (archivePathOrBuffer: string | Buffer) => {
|
||||
archivePath = archivePathOrBuffer.toString();
|
||||
}
|
||||
if (typeof archivePath !== 'string') return { isAsar: <const>false };
|
||||
if (!asarRe.test(archivePath)) return { isAsar: <const>false };
|
||||
|
||||
return asar.splitPath(path.normalize(archivePath));
|
||||
};
|
||||
@@ -216,16 +219,16 @@ const makePromiseFunction = function (orig: Function, pathArgumentIndex: number)
|
||||
|
||||
// Override fs APIs.
|
||||
export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
const logFDs: Record<string, number> = {};
|
||||
const logFDs = new Map<string, number>();
|
||||
const logASARAccess = (asarPath: string, filePath: string, offset: number) => {
|
||||
if (!process.env.ELECTRON_LOG_ASAR_READS) return;
|
||||
if (!logFDs[asarPath]) {
|
||||
if (!logFDs.has(asarPath)) {
|
||||
const path = require('path');
|
||||
const logFilename = `${path.basename(asarPath, '.asar')}-access-log.txt`;
|
||||
const logPath = path.join(require('os').tmpdir(), logFilename);
|
||||
logFDs[asarPath] = fs.openSync(logPath, 'a');
|
||||
logFDs.set(asarPath, fs.openSync(logPath, 'a'));
|
||||
}
|
||||
fs.writeSync(logFDs[asarPath], `${offset}: ${filePath}\n`);
|
||||
fs.writeSync(logFDs.get(asarPath), `${offset}: ${filePath}\n`);
|
||||
};
|
||||
|
||||
const { lstatSync } = fs;
|
||||
|
||||
@@ -6,7 +6,7 @@ const isLinux = process.platform === 'linux';
|
||||
|
||||
type RoleId = 'about' | 'close' | 'copy' | 'cut' | 'delete' | 'forcereload' | 'front' | 'help' | 'hide' | 'hideothers' | 'minimize' |
|
||||
'paste' | 'pasteandmatchstyle' | 'quit' | 'redo' | 'reload' | 'resetzoom' | 'selectall' | 'services' | 'recentdocuments' | 'clearrecentdocuments' | 'startspeaking' | 'stopspeaking' |
|
||||
'toggledevtools' | 'togglefullscreen' | 'undo' | 'unhide' | 'window' | 'zoom' | 'zoomin' | 'zoomout' | 'appmenu' | 'filemenu' | 'editmenu' | 'viewmenu' | 'windowmenu'
|
||||
'toggledevtools' | 'togglefullscreen' | 'undo' | 'unhide' | 'window' | 'zoom' | 'zoomin' | 'zoomout' | 'appmenu' | 'filemenu' | 'editmenu' | 'viewmenu' | 'windowmenu' | 'sharemenu'
|
||||
interface Role {
|
||||
label: string;
|
||||
accelerator?: string;
|
||||
@@ -261,6 +261,11 @@ export const roleList: Record<RoleId, Role> = {
|
||||
{ role: 'close' }
|
||||
] as MenuItemConstructorOptions[])
|
||||
]
|
||||
},
|
||||
// Share submenu
|
||||
sharemenu: {
|
||||
label: 'Share',
|
||||
submenu: []
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -41,6 +41,12 @@ Menu.prototype._shouldRegisterAcceleratorForCommandId = function (id) {
|
||||
return this.commandsMap[id] ? this.commandsMap[id].registerAccelerator : false;
|
||||
};
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
Menu.prototype._getSharingItemForCommandId = function (id) {
|
||||
return this.commandsMap[id] ? this.commandsMap[id].sharingItem : null;
|
||||
};
|
||||
}
|
||||
|
||||
Menu.prototype._executeCommand = function (event, id) {
|
||||
const command = this.commandsMap[id];
|
||||
if (!command) return;
|
||||
|
||||
@@ -26,6 +26,7 @@ export const browserModuleList: ElectronInternal.ModuleEntry[] = [
|
||||
{ name: 'protocol', loader: () => require('./protocol') },
|
||||
{ name: 'screen', loader: () => require('./screen') },
|
||||
{ name: 'session', loader: () => require('./session') },
|
||||
{ name: 'ShareMenu', loader: () => require('./share-menu') },
|
||||
{ name: 'systemPreferences', loader: () => require('./system-preferences') },
|
||||
{ name: 'TouchBar', loader: () => require('./touch-bar') },
|
||||
{ name: 'Tray', loader: () => require('./tray') },
|
||||
|
||||
@@ -29,6 +29,7 @@ export const browserModuleNames = [
|
||||
'protocol',
|
||||
'screen',
|
||||
'session',
|
||||
'ShareMenu',
|
||||
'systemPreferences',
|
||||
'TouchBar',
|
||||
'Tray',
|
||||
|
||||
@@ -4,6 +4,7 @@ import { app } from 'electron/main';
|
||||
import type { ClientRequestConstructorOptions, UploadProgress } from 'electron/main';
|
||||
|
||||
const {
|
||||
isOnline,
|
||||
isValidHeaderName,
|
||||
isValidHeaderValue,
|
||||
createURLLoader
|
||||
@@ -516,3 +517,9 @@ export class ClientRequest extends Writable implements Electron.ClientRequest {
|
||||
export function request (options: ClientRequestConstructorOptions | string, callback?: (message: IncomingMessage) => void) {
|
||||
return new ClientRequest(options, callback);
|
||||
}
|
||||
|
||||
exports.isOnline = isOnline;
|
||||
|
||||
Object.defineProperty(exports, 'online', {
|
||||
get: () => isOnline()
|
||||
});
|
||||
|
||||
19
lib/browser/api/share-menu.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { BrowserWindow, Menu, SharingItem, PopupOptions } from 'electron/main';
|
||||
|
||||
class ShareMenu {
|
||||
private menu: Menu;
|
||||
|
||||
constructor (sharingItem: SharingItem) {
|
||||
this.menu = new (Menu as any)({ sharingItem });
|
||||
}
|
||||
|
||||
popup (options?: PopupOptions) {
|
||||
this.menu.popup(options);
|
||||
}
|
||||
|
||||
closePopup (browserWindow?: BrowserWindow) {
|
||||
this.menu.closePopup(browserWindow);
|
||||
}
|
||||
}
|
||||
|
||||
export default ShareMenu;
|
||||
@@ -300,8 +300,8 @@ class TouchBar extends EventEmitter implements Electron.TouchBar {
|
||||
touchBar._addToWindow(window);
|
||||
}
|
||||
|
||||
private windowListeners: Record<number, Function> = {};
|
||||
private items: Record<string, TouchBarItem<any>> = {};
|
||||
private windowListeners = new Map<number, Function>();
|
||||
private items = new Map<string, TouchBarItem<any>>();
|
||||
orderedItems: TouchBarItem<any>[] = [];
|
||||
|
||||
constructor (options: Electron.TouchBarConstructorOptions) {
|
||||
@@ -317,12 +317,10 @@ class TouchBar extends EventEmitter implements Electron.TouchBar {
|
||||
items = [];
|
||||
}
|
||||
|
||||
this.windowListeners = {};
|
||||
this.items = {};
|
||||
this.escapeItem = (escapeItem as any) || null;
|
||||
|
||||
const registerItem = (item: TouchBarItem<any>) => {
|
||||
this.items[item.id] = item;
|
||||
this.items.set(item.id, item);
|
||||
item.on('change', this.changeListener);
|
||||
if (item.child instanceof TouchBar) {
|
||||
item.child.orderedItems.forEach(registerItem);
|
||||
@@ -387,7 +385,7 @@ class TouchBar extends EventEmitter implements Electron.TouchBar {
|
||||
const { id } = window;
|
||||
|
||||
// Already added to window
|
||||
if (Object.prototype.hasOwnProperty.call(this.windowListeners, id)) return;
|
||||
if (this.windowListeners.has(id)) return;
|
||||
|
||||
window._touchBar = this;
|
||||
|
||||
@@ -402,7 +400,7 @@ class TouchBar extends EventEmitter implements Electron.TouchBar {
|
||||
this.on('escape-item-change', escapeItemListener);
|
||||
|
||||
const interactionListener = (_: any, itemID: string, details: any) => {
|
||||
let item = this.items[itemID];
|
||||
let item = this.items.get(itemID);
|
||||
if (item == null && this.escapeItem != null && this.escapeItem.id === itemID) {
|
||||
item = this.escapeItem;
|
||||
}
|
||||
@@ -418,7 +416,7 @@ class TouchBar extends EventEmitter implements Electron.TouchBar {
|
||||
window.removeListener('-touch-bar-interaction', interactionListener);
|
||||
window.removeListener('closed', removeListeners);
|
||||
window._touchBar = null;
|
||||
delete this.windowListeners[id];
|
||||
this.windowListeners.delete(id);
|
||||
const unregisterItems = (items: TouchBarItem<any>[]) => {
|
||||
for (const item of items) {
|
||||
item.removeListener('change', this.changeListener);
|
||||
@@ -433,14 +431,14 @@ class TouchBar extends EventEmitter implements Electron.TouchBar {
|
||||
}
|
||||
};
|
||||
window.once('closed', removeListeners);
|
||||
this.windowListeners[id] = removeListeners;
|
||||
this.windowListeners.set(id, removeListeners);
|
||||
|
||||
window._setTouchBarItems(this.orderedItems);
|
||||
escapeItemListener(this.escapeItem);
|
||||
}
|
||||
|
||||
_removeFromWindow (window: Electron.BrowserWindow) {
|
||||
const removeListeners = this.windowListeners[window.id];
|
||||
const removeListeners = this.windowListeners.get(window.id);
|
||||
if (removeListeners != null) removeListeners();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ const webViewManager = process._linkedBinding('electron_browser_web_view_manager
|
||||
|
||||
const supportedWebViewEvents = Object.keys(webViewEvents);
|
||||
|
||||
const guestInstances: Record<string, GuestInstance> = {};
|
||||
const embedderElementsMap: Record<string, number> = {};
|
||||
const guestInstances = new Map<number, GuestInstance>();
|
||||
const embedderElementsMap = new Map<string, number>();
|
||||
|
||||
function sanitizeOptionsForGuest (options: Record<string, any>) {
|
||||
const ret = { ...options };
|
||||
@@ -37,14 +37,14 @@ const createGuest = function (embedder: Electron.WebContents, params: Record<str
|
||||
embedder: embedder
|
||||
});
|
||||
const guestInstanceId = guest.id;
|
||||
guestInstances[guestInstanceId] = {
|
||||
guestInstances.set(guestInstanceId, {
|
||||
guest: guest,
|
||||
embedder: embedder
|
||||
};
|
||||
});
|
||||
|
||||
// Clear the guest from map when it is destroyed.
|
||||
guest.once('destroyed', () => {
|
||||
if (Object.prototype.hasOwnProperty.call(guestInstances, guestInstanceId)) {
|
||||
if (guestInstances.has(guestInstanceId)) {
|
||||
detachGuest(embedder, guestInstanceId);
|
||||
}
|
||||
});
|
||||
@@ -107,7 +107,7 @@ const createGuest = function (embedder: Electron.WebContents, params: Record<str
|
||||
// Notify guest of embedder window visibility when it is ready
|
||||
// FIXME Remove once https://github.com/electron/electron/issues/6828 is fixed
|
||||
guest.on('dom-ready', function () {
|
||||
const guestInstance = guestInstances[guestInstanceId];
|
||||
const guestInstance = guestInstances.get(guestInstanceId);
|
||||
if (guestInstance != null && guestInstance.visibilityState != null) {
|
||||
guest._sendInternal(IPC_MESSAGES.GUEST_INSTANCE_VISIBILITY_CHANGE, guestInstance.visibilityState);
|
||||
}
|
||||
@@ -122,20 +122,20 @@ const attachGuest = function (event: Electron.IpcMainInvokeEvent,
|
||||
const embedder = event.sender;
|
||||
// Destroy the old guest when attaching.
|
||||
const key = `${embedder.id}-${elementInstanceId}`;
|
||||
const oldGuestInstanceId = embedderElementsMap[key];
|
||||
const oldGuestInstanceId = embedderElementsMap.get(key);
|
||||
if (oldGuestInstanceId != null) {
|
||||
// Reattachment to the same guest is just a no-op.
|
||||
if (oldGuestInstanceId === guestInstanceId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldGuestInstance = guestInstances[oldGuestInstanceId];
|
||||
const oldGuestInstance = guestInstances.get(oldGuestInstanceId);
|
||||
if (oldGuestInstance) {
|
||||
oldGuestInstance.guest.detachFromOuterFrame();
|
||||
}
|
||||
}
|
||||
|
||||
const guestInstance = guestInstances[guestInstanceId];
|
||||
const guestInstance = guestInstances.get(guestInstanceId);
|
||||
// If this isn't a valid guest instance then do nothing.
|
||||
if (!guestInstance) {
|
||||
throw new Error(`Invalid guestInstanceId: ${guestInstanceId}`);
|
||||
@@ -148,7 +148,7 @@ const attachGuest = function (event: Electron.IpcMainInvokeEvent,
|
||||
// If this guest is already attached to an element then remove it
|
||||
if (guestInstance.elementInstanceId) {
|
||||
const oldKey = `${guestInstance.embedder.id}-${guestInstance.elementInstanceId}`;
|
||||
delete embedderElementsMap[oldKey];
|
||||
embedderElementsMap.delete(oldKey);
|
||||
|
||||
// Remove guest from embedder if moving across web views
|
||||
if (guest.viewInstanceId !== params.instanceId) {
|
||||
@@ -210,7 +210,7 @@ const attachGuest = function (event: Electron.IpcMainInvokeEvent,
|
||||
}
|
||||
|
||||
guest.attachParams = params;
|
||||
embedderElementsMap[key] = guestInstanceId;
|
||||
embedderElementsMap.set(key, guestInstanceId);
|
||||
|
||||
guest.setEmbedder(embedder);
|
||||
guestInstance.embedder = embedder;
|
||||
@@ -224,7 +224,7 @@ const attachGuest = function (event: Electron.IpcMainInvokeEvent,
|
||||
|
||||
// Remove an guest-embedder relationship.
|
||||
const detachGuest = function (embedder: Electron.WebContents, guestInstanceId: number) {
|
||||
const guestInstance = guestInstances[guestInstanceId];
|
||||
const guestInstance = guestInstances.get(guestInstanceId);
|
||||
|
||||
if (!guestInstance) return;
|
||||
|
||||
@@ -233,10 +233,10 @@ const detachGuest = function (embedder: Electron.WebContents, guestInstanceId: n
|
||||
}
|
||||
|
||||
webViewManager.removeGuest(embedder, guestInstanceId);
|
||||
delete guestInstances[guestInstanceId];
|
||||
guestInstances.delete(guestInstanceId);
|
||||
|
||||
const key = `${embedder.id}-${guestInstance.elementInstanceId}`;
|
||||
delete embedderElementsMap[key];
|
||||
embedderElementsMap.delete(key);
|
||||
};
|
||||
|
||||
// Once an embedder has had a guest attached we watch it for destruction to
|
||||
@@ -250,8 +250,7 @@ const watchEmbedder = function (embedder: Electron.WebContents) {
|
||||
|
||||
// Forward embedder window visibility change events to guest
|
||||
const onVisibilityChange = function (visibilityState: VisibilityState) {
|
||||
for (const guestInstanceId of Object.keys(guestInstances)) {
|
||||
const guestInstance = guestInstances[guestInstanceId];
|
||||
for (const guestInstance of guestInstances.values()) {
|
||||
guestInstance.visibilityState = visibilityState;
|
||||
if (guestInstance.embedder === embedder) {
|
||||
guestInstance.guest._sendInternal(IPC_MESSAGES.GUEST_INSTANCE_VISIBILITY_CHANGE, visibilityState);
|
||||
@@ -264,10 +263,9 @@ const watchEmbedder = function (embedder: Electron.WebContents) {
|
||||
// Usually the guestInstances is cleared when guest is destroyed, but it
|
||||
// may happen that the embedder gets manually destroyed earlier than guest,
|
||||
// and the embedder will be invalid in the usual code path.
|
||||
for (const guestInstanceId of Object.keys(guestInstances)) {
|
||||
const guestInstance = guestInstances[guestInstanceId];
|
||||
for (const [guestInstanceId, guestInstance] of guestInstances) {
|
||||
if (guestInstance.embedder === embedder) {
|
||||
detachGuest(embedder, parseInt(guestInstanceId));
|
||||
detachGuest(embedder, guestInstanceId);
|
||||
}
|
||||
}
|
||||
// Clear the listeners.
|
||||
@@ -388,6 +386,6 @@ const getGuestForWebContents = function (guestInstanceId: number, contents: Elec
|
||||
|
||||
// Returns WebContents from its guest id.
|
||||
const getGuest = function (guestInstanceId: number) {
|
||||
const guestInstance = guestInstances[guestInstanceId];
|
||||
const guestInstance = guestInstances.get(guestInstanceId);
|
||||
if (guestInstance != null) return guestInstance.guest;
|
||||
};
|
||||
|
||||
@@ -5,6 +5,18 @@ const Module = require('module');
|
||||
// Clear Node's global search paths.
|
||||
Module.globalPaths.length = 0;
|
||||
|
||||
// We do not want to allow use of the VM module in the renderer process as
|
||||
// it conflicts with Blink's V8::Context internal logic.
|
||||
if (process.type === 'renderer') {
|
||||
const _load = Module._load;
|
||||
Module._load = function (request: string) {
|
||||
if (request === 'vm') {
|
||||
console.warn('The vm module of Node.js is deprecated in the renderer process and will be removed.');
|
||||
}
|
||||
return _load.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
// Prevent Node from adding paths outside this app to search paths.
|
||||
const resourcesPathWithTrailingSlash = process.resourcesPath + path.sep;
|
||||
const originalNodeModulePaths = Module._nodeModulePaths;
|
||||
|
||||
24
npm/cli.js
@@ -1,25 +1,25 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var electron = require('./')
|
||||
const electron = require('./');
|
||||
|
||||
var proc = require('child_process')
|
||||
const proc = require('child_process');
|
||||
|
||||
var child = proc.spawn(electron, process.argv.slice(2), { stdio: 'inherit', windowsHide: false })
|
||||
const child = proc.spawn(electron, process.argv.slice(2), { stdio: 'inherit', windowsHide: false });
|
||||
child.on('close', function (code, signal) {
|
||||
if (code === null) {
|
||||
console.error(electron, 'exited with signal', signal)
|
||||
process.exit(1)
|
||||
console.error(electron, 'exited with signal', signal);
|
||||
process.exit(1);
|
||||
}
|
||||
process.exit(code)
|
||||
})
|
||||
process.exit(code);
|
||||
});
|
||||
|
||||
const handleTerminationSignal = function (signal) {
|
||||
process.on(signal, function signalHandler () {
|
||||
if (!child.killed) {
|
||||
child.kill(signal)
|
||||
child.kill(signal);
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleTerminationSignal('SIGINT')
|
||||
handleTerminationSignal('SIGTERM')
|
||||
handleTerminationSignal('SIGINT');
|
||||
handleTerminationSignal('SIGTERM');
|
||||
|
||||
16
npm/index.js
@@ -1,18 +1,18 @@
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
var pathFile = path.join(__dirname, 'path.txt')
|
||||
const pathFile = path.join(__dirname, 'path.txt');
|
||||
|
||||
function getElectronPath () {
|
||||
if (fs.existsSync(pathFile)) {
|
||||
var executablePath = fs.readFileSync(pathFile, 'utf-8')
|
||||
const executablePath = fs.readFileSync(pathFile, 'utf-8');
|
||||
if (process.env.ELECTRON_OVERRIDE_DIST_PATH) {
|
||||
return path.join(process.env.ELECTRON_OVERRIDE_DIST_PATH, executablePath)
|
||||
return path.join(process.env.ELECTRON_OVERRIDE_DIST_PATH, executablePath);
|
||||
}
|
||||
return path.join(__dirname, 'dist', executablePath)
|
||||
return path.join(__dirname, 'dist', executablePath);
|
||||
} else {
|
||||
throw new Error('Electron failed to install correctly, please delete node_modules/electron and try installing again')
|
||||
throw new Error('Electron failed to install correctly, please delete node_modules/electron and try installing again');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = getElectronPath()
|
||||
module.exports = getElectronPath();
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {version} = require('./package')
|
||||
const { version } = require('./package');
|
||||
|
||||
const fs = require('fs')
|
||||
const os = require('os')
|
||||
const path = require('path')
|
||||
const extract = require('extract-zip')
|
||||
const { downloadArtifact } = require('@electron/get')
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const extract = require('extract-zip');
|
||||
const { downloadArtifact } = require('@electron/get');
|
||||
|
||||
if (process.env.ELECTRON_SKIP_BINARY_DOWNLOAD) {
|
||||
process.exit(0)
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const platformPath = getPlatformPath()
|
||||
const platformPath = getPlatformPath();
|
||||
|
||||
if (isInstalled()) {
|
||||
process.exit(0)
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// downloads if not cached
|
||||
@@ -27,57 +27,57 @@ downloadArtifact({
|
||||
platform: process.env.npm_config_platform || process.platform,
|
||||
arch: process.env.npm_config_arch || process.arch
|
||||
}).then(extractFile).catch(err => {
|
||||
console.error(err.stack)
|
||||
process.exit(1)
|
||||
})
|
||||
console.error(err.stack);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
function isInstalled () {
|
||||
try {
|
||||
if (fs.readFileSync(path.join(__dirname, 'dist', 'version'), 'utf-8').replace(/^v/, '') !== version) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fs.readFileSync(path.join(__dirname, 'path.txt'), 'utf-8') !== platformPath) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
} catch (ignored) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
const electronPath = process.env.ELECTRON_OVERRIDE_DIST_PATH || path.join(__dirname, 'dist', platformPath)
|
||||
|
||||
return fs.existsSync(electronPath)
|
||||
|
||||
const electronPath = process.env.ELECTRON_OVERRIDE_DIST_PATH || path.join(__dirname, 'dist', platformPath);
|
||||
|
||||
return fs.existsSync(electronPath);
|
||||
}
|
||||
|
||||
// unzips and makes path.txt point at the correct executable
|
||||
function extractFile (zipPath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
extract(zipPath, { dir: path.join(__dirname, 'dist') }, err => {
|
||||
if (err) return reject(err)
|
||||
if (err) return reject(err);
|
||||
|
||||
fs.writeFile(path.join(__dirname, 'path.txt'), platformPath, err => {
|
||||
if (err) return reject(err)
|
||||
if (err) return reject(err);
|
||||
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
})
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getPlatformPath () {
|
||||
const platform = process.env.npm_config_platform || os.platform()
|
||||
const platform = process.env.npm_config_platform || os.platform();
|
||||
|
||||
switch (platform) {
|
||||
case 'mas':
|
||||
case 'darwin':
|
||||
return 'Electron.app/Contents/MacOS/Electron'
|
||||
return 'Electron.app/Contents/MacOS/Electron';
|
||||
case 'freebsd':
|
||||
case 'openbsd':
|
||||
case 'linux':
|
||||
return 'electron'
|
||||
return 'electron';
|
||||
case 'win32':
|
||||
return 'electron.exe'
|
||||
return 'electron.exe';
|
||||
default:
|
||||
throw new Error('Electron builds are not available on platform: ' + platform)
|
||||
throw new Error('Electron builds are not available on platform: ' + platform);
|
||||
}
|
||||
}
|
||||
|
||||
13
package.json
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "12.0.0-nightly.20201016",
|
||||
"version": "12.0.0-nightly.20201026",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
"@electron/docs-parser": "^0.9.1",
|
||||
"@electron/docs-parser": "^0.10.0",
|
||||
"@electron/typescript-definitions": "^8.8.0",
|
||||
"@octokit/rest": "^18.0.3",
|
||||
"@primer/octicons": "^10.0.0",
|
||||
@@ -23,8 +23,8 @@
|
||||
"@types/uuid": "^3.4.6",
|
||||
"@types/webpack": "^4.41.21",
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"@typescript-eslint/eslint-plugin": "^3.9.1",
|
||||
"@typescript-eslint/parser": "^3.9.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.4.1",
|
||||
"@typescript-eslint/parser": "^4.4.1",
|
||||
"asar": "^3.0.3",
|
||||
"check-for-leaks": "^1.2.1",
|
||||
"colors": "^1.4.0",
|
||||
@@ -63,7 +63,8 @@
|
||||
"ts-node": "6.2.0",
|
||||
"typescript": "^4.0.2",
|
||||
"webpack": "^4.43.0",
|
||||
"webpack-cli": "^3.3.12"
|
||||
"webpack-cli": "^3.3.12",
|
||||
"wrapper-webpack-plugin": "^2.1.0"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@@ -91,7 +92,7 @@
|
||||
"start": "node ./script/start.js",
|
||||
"test": "node ./script/spec-runner.js",
|
||||
"tsc": "tsc",
|
||||
"webpack": "node build/webpack/run-compiler"
|
||||
"webpack": "webpack"
|
||||
},
|
||||
"license": "MIT",
|
||||
"author": "Electron Community",
|
||||
|
||||
@@ -9,10 +9,10 @@ we're running with contextIsolation enabled, we should be falling back
|
||||
to Blink's logic. This will be upstreamed in some form.
|
||||
|
||||
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
|
||||
index 7c2ae147254dad017214d2535203a18719294768..3313d6aff572307777f02801b09fc3d29318050e 100644
|
||||
index 85ac9d5d95856470707d320d382743673cd1451a..398095d8890cee3f8838170a86ccb48010ff74a0 100644
|
||||
--- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
|
||||
+++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
|
||||
@@ -442,7 +442,7 @@ CodeGenerationCheckCallbackInMainThread(v8::Local<v8::Context> context,
|
||||
@@ -438,7 +438,7 @@ CodeGenerationCheckCallbackInMainThread(v8::Local<v8::Context> context,
|
||||
return {true, std::move(stringified_source)};
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ index 5575c90cf05ec43bc787711f1d44b8dd58ead99c..a544d836159522751c1262370d8c1562
|
||||
!command_line->HasSwitch(switches::kUIDisablePartialSwap);
|
||||
#if defined(OS_APPLE)
|
||||
diff --git a/components/viz/service/display/gl_renderer.cc b/components/viz/service/display/gl_renderer.cc
|
||||
index 31fa3d22a28cb673a1eac983acafb7bcd484e6ca..58d52c207f12dd329a0cb8593af5f76ab5ba70f1 100644
|
||||
index 31fa3d22a28cb673a1eac983acafb7bcd484e6ca..e1bfab6b716fa5d2f552b7af149748b3b0dc0a23 100644
|
||||
--- a/components/viz/service/display/gl_renderer.cc
|
||||
+++ b/components/viz/service/display/gl_renderer.cc
|
||||
@@ -88,6 +88,9 @@
|
||||
@@ -121,7 +121,7 @@ index 31fa3d22a28cb673a1eac983acafb7bcd484e6ca..58d52c207f12dd329a0cb8593af5f76a
|
||||
tint_gl_composited_content_,
|
||||
ShouldApplyRoundedCorner(quad)),
|
||||
- CurrentRenderPassColorSpace(), CurrentRenderPassColorSpace());
|
||||
+ PATCH_CS(CurrentRenderPassColorSpace()),
|
||||
+ PATCH_CS(CurrentRenderPassColorSpace()),
|
||||
+ PATCH_CS(CurrentRenderPassColorSpace()));
|
||||
|
||||
gfx::ColorSpace quad_color_space = gfx::ColorSpace::CreateSRGB();
|
||||
|
||||
@@ -7,7 +7,7 @@ This tweaks Chrome's Accessibility support at chrome://accessibility
|
||||
to make it usable from Electron by removing Profile references.
|
||||
|
||||
diff --git a/chrome/browser/accessibility/accessibility_ui.cc b/chrome/browser/accessibility/accessibility_ui.cc
|
||||
index 42d79b5651e204dc8014489f8feb6b6ad7994d8c..77ca7e88b9e5c2f1dd80d28452588f85a1120169 100644
|
||||
index 42d79b5651e204dc8014489f8feb6b6ad7994d8c..bed9a4f98f566d368a891a8247f3e528f9db910d 100644
|
||||
--- a/chrome/browser/accessibility/accessibility_ui.cc
|
||||
+++ b/chrome/browser/accessibility/accessibility_ui.cc
|
||||
@@ -19,7 +19,10 @@
|
||||
@@ -101,7 +101,7 @@ index 42d79b5651e204dc8014489f8feb6b6ad7994d8c..77ca7e88b9e5c2f1dd80d28452588f85
|
||||
+#if 0
|
||||
PrefService* pref = Profile::FromWebUI(web_ui())->GetPrefs();
|
||||
bool internal = pref->GetBoolean(prefs::kShowInternalAccessibilityTree);
|
||||
+#endif
|
||||
+#endif
|
||||
std::string accessibility_contents =
|
||||
- web_contents->DumpAccessibilityTree(internal, property_filters);
|
||||
+ web_contents->DumpAccessibilityTree(true, property_filters);
|
||||
|
||||
@@ -25,7 +25,7 @@ index f63f7f2674d9562f57dea4f9c9f473aa595a0c5f..78a46dbea7ff31209748ef47d5417253
|
||||
// Returns true if duplex mode is set.
|
||||
bool SetDuplexModeInPrintSettings(mojom::DuplexMode mode);
|
||||
diff --git a/printing/printing_context_mac.mm b/printing/printing_context_mac.mm
|
||||
index aa950b59390fdae9a5152affb7a7438cb78eb6f4..3ec9ee0ee464960a48d23f5000137cc44027e9b1 100644
|
||||
index aa950b59390fdae9a5152affb7a7438cb78eb6f4..9b5307bda7b73cb502fe185be2a7c02e23a7722c 100644
|
||||
--- a/printing/printing_context_mac.mm
|
||||
+++ b/printing/printing_context_mac.mm
|
||||
@@ -189,7 +189,8 @@ PMPaper MatchPaper(CFArrayRef paper_list,
|
||||
@@ -45,7 +45,7 @@ index aa950b59390fdae9a5152affb7a7438cb78eb6f4..3ec9ee0ee464960a48d23f5000137cc4
|
||||
+bool PrintingContextMac::SetPrintRangeInPrintSettings(const PageRanges& ranges) {
|
||||
+ // Default is already NSPrintAllPages - we can safely bail.
|
||||
+ if (ranges.empty())
|
||||
+ return true;
|
||||
+ return true;
|
||||
+
|
||||
+ auto* print_settings =
|
||||
+ static_cast<PMPrintSettings>([print_info_.get() PMPrintSettings]);
|
||||
@@ -100,14 +100,14 @@ index d3c8677f30d72efc49b28f293260c74c7b8d8b4e..f6e66aaa58ab1881d64dcbb320ae8b5a
|
||||
} else {
|
||||
// No need to bother, we don't know how many pages are available.
|
||||
diff --git a/ui/gtk/printing/print_dialog_gtk.cc b/ui/gtk/printing/print_dialog_gtk.cc
|
||||
index f2ed36e1258f4f3ef1bfce972e215e3d5d7335b6..405839e9f944f70106c1c203652044c3abfade3d 100644
|
||||
index f2ed36e1258f4f3ef1bfce972e215e3d5d7335b6..5b38bf1369a68546f0aeea8948abba995c65e7f7 100644
|
||||
--- a/ui/gtk/printing/print_dialog_gtk.cc
|
||||
+++ b/ui/gtk/printing/print_dialog_gtk.cc
|
||||
@@ -239,6 +239,24 @@ void PrintDialogGtk::UpdateSettings(
|
||||
|
||||
gtk_print_settings_set_n_copies(gtk_settings_, settings->copies());
|
||||
gtk_print_settings_set_collate(gtk_settings_, settings->collate());
|
||||
+
|
||||
+
|
||||
+ auto print_ranges = settings->ranges();
|
||||
+ if (!print_ranges.empty()) {
|
||||
+ // Tell the system that we only intend to print a subset of pages.
|
||||
|
||||
@@ -12,14 +12,14 @@ rendering and there is no signal from browser process on this event
|
||||
to identify it.
|
||||
|
||||
diff --git a/content/browser/gpu/gpu_data_manager_impl.cc b/content/browser/gpu/gpu_data_manager_impl.cc
|
||||
index 694f63ecd2de241fd1a8b7b529bbd4d1bea78337..cc9679eb86f85239f5612d8db8200db5392f5bc5 100644
|
||||
index 694f63ecd2de241fd1a8b7b529bbd4d1bea78337..705d24cb09a2a8b07ac7acd21b18e2e3483856bf 100644
|
||||
--- a/content/browser/gpu/gpu_data_manager_impl.cc
|
||||
+++ b/content/browser/gpu/gpu_data_manager_impl.cc
|
||||
@@ -229,6 +229,11 @@ void GpuDataManagerImpl::TerminateInfoCollectionGpuProcess() {
|
||||
base::AutoLock auto_lock(lock_);
|
||||
private_->TerminateInfoCollectionGpuProcess();
|
||||
}
|
||||
+
|
||||
+
|
||||
+bool GpuDataManagerImpl::DxdiagDx12VulkanRequested() const {
|
||||
+ base::AutoLock auto_lock(lock_);
|
||||
+ return private_->DxdiagDx12VulkanRequested();
|
||||
|
||||
@@ -419,7 +419,7 @@ index 894ac47e596c1c96a7e0659be80ed8a5629d0304..eca797a24df79b8502b9698e6ed8830a
|
||||
|
||||
} // namespace
|
||||
diff --git a/content/renderer/theme_helper_mac.mm b/content/renderer/theme_helper_mac.mm
|
||||
index 1db129740992672a4e8be8100da18b6813f1a4f8..5b1e456020ac859c826dbef2826cacf3bb60108b 100644
|
||||
index 1db129740992672a4e8be8100da18b6813f1a4f8..dc18d623869e815d4d1ef64ad8bceb6948f5cc9e 100644
|
||||
--- a/content/renderer/theme_helper_mac.mm
|
||||
+++ b/content/renderer/theme_helper_mac.mm
|
||||
@@ -7,11 +7,11 @@
|
||||
@@ -445,7 +445,7 @@ index 1db129740992672a4e8be8100da18b6813f1a4f8..5b1e456020ac859c826dbef2826cacf3
|
||||
+#else
|
||||
+ NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
|
||||
+ NSString *default_key = @"CGFontRenderingGetFontSmoothingDisabled";
|
||||
+ // Check that key exists since boolForKey defaults to NO when the
|
||||
+ // Check that key exists since boolForKey defaults to NO when the
|
||||
+ // key is missing and this key in fact defaults to YES;
|
||||
+ if ([defaults objectForKey:default_key] == nil)
|
||||
+ return false;
|
||||
|
||||
@@ -102,7 +102,7 @@ index 89c7798d8ddf21eb74e726c142377afa05b59c26..dd75b8e82552a54868ce86caf90ba175
|
||||
}
|
||||
|
||||
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
|
||||
index ad70dada204132ce44d6613378072a080771148a..02ecf3e77bee365eef4dc8a985cfe092785b8b8e 100644
|
||||
index ad70dada204132ce44d6613378072a080771148a..75908fc9978db020d752e7fc7211d1a075c11ffb 100644
|
||||
--- a/chrome/browser/printing/print_view_manager_base.cc
|
||||
+++ b/chrome/browser/printing/print_view_manager_base.cc
|
||||
@@ -28,10 +28,7 @@
|
||||
@@ -145,7 +145,7 @@ index ad70dada204132ce44d6613378072a080771148a..02ecf3e77bee365eef4dc8a985cfe092
|
||||
: PrintManager(web_contents),
|
||||
queue_(g_browser_process->print_job_manager()->queue()) {
|
||||
DCHECK(queue_);
|
||||
+#if 0
|
||||
+#if 0 // Printing is always enabled.
|
||||
Profile* profile =
|
||||
Profile::FromBrowserContext(web_contents->GetBrowserContext());
|
||||
printing_enabled_.Init(
|
||||
@@ -197,7 +197,22 @@ index ad70dada204132ce44d6613378072a080771148a..02ecf3e77bee365eef4dc8a985cfe092
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::NavigationStopped() {
|
||||
@@ -441,7 +454,7 @@ void PrintViewManagerBase::PrintingFailed(int32_t cookie) {
|
||||
@@ -421,12 +434,13 @@ void PrintViewManagerBase::OnDidPrintDocument(
|
||||
void PrintViewManagerBase::GetDefaultPrintSettings(
|
||||
GetDefaultPrintSettingsCallback callback) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
+#if 0 // Printing is always enabled.
|
||||
if (!printing_enabled_.GetValue()) {
|
||||
auto params = mojom::PrintParams::New();
|
||||
GetDefaultPrintSettingsReply(std::move(callback), std::move(params));
|
||||
return;
|
||||
}
|
||||
-
|
||||
+#endif
|
||||
content::RenderFrameHost* render_frame_host =
|
||||
print_manager_host_receivers_.GetCurrentTargetFrame();
|
||||
|
||||
@@ -441,7 +455,7 @@ void PrintViewManagerBase::PrintingFailed(int32_t cookie) {
|
||||
PrintManager::PrintingFailed(cookie);
|
||||
|
||||
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
|
||||
@@ -206,7 +221,7 @@ index ad70dada204132ce44d6613378072a080771148a..02ecf3e77bee365eef4dc8a985cfe092
|
||||
#endif
|
||||
|
||||
ReleasePrinterQuery();
|
||||
@@ -460,6 +473,11 @@ void PrintViewManagerBase::OnScriptedPrint(
|
||||
@@ -460,6 +474,11 @@ void PrintViewManagerBase::OnScriptedPrint(
|
||||
}
|
||||
|
||||
void PrintViewManagerBase::ShowInvalidPrinterSettingsError() {
|
||||
@@ -218,7 +233,7 @@ index ad70dada204132ce44d6613378072a080771148a..02ecf3e77bee365eef4dc8a985cfe092
|
||||
base::ThreadTaskRunnerHandle::Get()->PostTask(
|
||||
FROM_HERE, base::BindOnce(&ShowWarningMessageBox,
|
||||
l10n_util::GetStringUTF16(
|
||||
@@ -529,9 +547,13 @@ void PrintViewManagerBase::OnNotifyPrintJobEvent(
|
||||
@@ -529,9 +548,13 @@ void PrintViewManagerBase::OnNotifyPrintJobEvent(
|
||||
content::NotificationService::NoDetails());
|
||||
break;
|
||||
}
|
||||
@@ -234,7 +249,7 @@ index ad70dada204132ce44d6613378072a080771148a..02ecf3e77bee365eef4dc8a985cfe092
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
@@ -627,8 +649,10 @@ bool PrintViewManagerBase::CreateNewPrintJob(
|
||||
@@ -627,8 +650,10 @@ bool PrintViewManagerBase::CreateNewPrintJob(
|
||||
DCHECK(!quit_inner_loop_);
|
||||
DCHECK(query);
|
||||
|
||||
@@ -247,7 +262,7 @@ index ad70dada204132ce44d6613378072a080771148a..02ecf3e77bee365eef4dc8a985cfe092
|
||||
|
||||
// We can't print if there is no renderer.
|
||||
if (!web_contents()->GetRenderViewHost() ||
|
||||
@@ -649,8 +673,6 @@ bool PrintViewManagerBase::CreateNewPrintJob(
|
||||
@@ -649,8 +674,6 @@ bool PrintViewManagerBase::CreateNewPrintJob(
|
||||
print_job_->SetSource(source, /*source_id=*/"");
|
||||
#endif
|
||||
|
||||
@@ -256,7 +271,7 @@ index ad70dada204132ce44d6613378072a080771148a..02ecf3e77bee365eef4dc8a985cfe092
|
||||
printing_succeeded_ = false;
|
||||
return true;
|
||||
}
|
||||
@@ -699,14 +721,22 @@ void PrintViewManagerBase::ReleasePrintJob() {
|
||||
@@ -699,14 +722,22 @@ void PrintViewManagerBase::ReleasePrintJob() {
|
||||
content::RenderFrameHost* rfh = printing_rfh_;
|
||||
printing_rfh_ = nullptr;
|
||||
|
||||
@@ -281,7 +296,7 @@ index ad70dada204132ce44d6613378072a080771148a..02ecf3e77bee365eef4dc8a985cfe092
|
||||
// Don't close the worker thread.
|
||||
print_job_ = nullptr;
|
||||
}
|
||||
@@ -742,7 +772,7 @@ bool PrintViewManagerBase::RunInnerMessageLoop() {
|
||||
@@ -742,7 +773,7 @@ bool PrintViewManagerBase::RunInnerMessageLoop() {
|
||||
}
|
||||
|
||||
bool PrintViewManagerBase::OpportunisticallyCreatePrintJob(int cookie) {
|
||||
|
||||
@@ -25,8 +25,6 @@ fix_use_crypto_impls_for_compat.patch
|
||||
fix_comment_out_incompatible_crypto_modules.patch
|
||||
update_tests_after_increasing_typed_array_size.patch
|
||||
feat_add_implementation_of_v8_platform_postjob.patch
|
||||
crypto_update_certdata_to_nss_3_56.patch
|
||||
fix_-wincompatible-pointer-types-discards-qualifiers_error.patch
|
||||
fix_add_v8_enable_reverse_jsargs_defines_in_common_gypi.patch
|
||||
fix_allow_preventing_initializeinspector_in_env.patch
|
||||
chore_expose_v8_initialization_isolate_callbacks.patch
|
||||
|
||||
@@ -846,10 +846,10 @@ index 0000000000000000000000000000000000000000..2c9d2826c85bdd033f1df1d6188df636
|
||||
+}
|
||||
diff --git a/filenames.json b/filenames.json
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..fbf2c13688d52b5ba320eadac42d472f09441e79
|
||||
index 0000000000000000000000000000000000000000..9480edd9b00591e7aad7f764a409b86094e4cd5d
|
||||
--- /dev/null
|
||||
+++ b/filenames.json
|
||||
@@ -0,0 +1,527 @@
|
||||
@@ -0,0 +1,530 @@
|
||||
+// This file is automatically generated by generate_gn_filenames_json.py
|
||||
+// DO NOT EDIT
|
||||
+{
|
||||
@@ -871,6 +871,7 @@ index 0000000000000000000000000000000000000000..fbf2c13688d52b5ba320eadac42d472f
|
||||
+ "files": [
|
||||
+ "//v8/include/cppgc/allocation.h",
|
||||
+ "//v8/include/cppgc/common.h",
|
||||
+ "//v8/include/cppgc/cross-thread-persistent.h",
|
||||
+ "//v8/include/cppgc/custom-space.h",
|
||||
+ "//v8/include/cppgc/default-platform.h",
|
||||
+ "//v8/include/cppgc/garbage-collected.h",
|
||||
@@ -878,6 +879,7 @@ index 0000000000000000000000000000000000000000..fbf2c13688d52b5ba320eadac42d472f
|
||||
+ "//v8/include/cppgc/liveness-broker.h",
|
||||
+ "//v8/include/cppgc/macros.h",
|
||||
+ "//v8/include/cppgc/member.h",
|
||||
+ "//v8/include/cppgc/name-provider.h",
|
||||
+ "//v8/include/cppgc/persistent.h",
|
||||
+ "//v8/include/cppgc/platform.h",
|
||||
+ "//v8/include/cppgc/prefinalizer.h",
|
||||
@@ -897,6 +899,7 @@ index 0000000000000000000000000000000000000000..fbf2c13688d52b5ba320eadac42d472f
|
||||
+ "//v8/include/cppgc/internal/finalizer-trait.h",
|
||||
+ "//v8/include/cppgc/internal/gc-info.h",
|
||||
+ "//v8/include/cppgc/internal/logging.h",
|
||||
+ "//v8/include/cppgc/internal/name-trait.h",
|
||||
+ "//v8/include/cppgc/internal/persistent-node.h",
|
||||
+ "//v8/include/cppgc/internal/pointer-policies.h",
|
||||
+ "//v8/include/cppgc/internal/prefinalizer-handler.h",
|
||||
@@ -1153,7 +1156,6 @@ index 0000000000000000000000000000000000000000..fbf2c13688d52b5ba320eadac42d472f
|
||||
+ "lib/internal/worker/js_transferable.js",
|
||||
+ "lib/internal/watchdog.js",
|
||||
+ "lib/internal/streams/lazy_transform.js",
|
||||
+ "lib/internal/streams/async_iterator.js",
|
||||
+ "lib/internal/streams/buffer_list.js",
|
||||
+ "lib/internal/streams/duplexpair.js",
|
||||
+ "lib/internal/streams/from.js",
|
||||
@@ -1183,7 +1185,8 @@ index 0000000000000000000000000000000000000000..fbf2c13688d52b5ba320eadac42d472f
|
||||
+ "deps/acorn-plugins/acorn-private-class-elements/index.js",
|
||||
+ "deps/acorn-plugins/acorn-private-methods/index.js",
|
||||
+ "deps/acorn-plugins/acorn-static-class-features/index.js",
|
||||
+ "deps/cjs-module-lexer/lexer.js"
|
||||
+ "deps/cjs-module-lexer/lexer.js",
|
||||
+ "deps/cjs-module-lexer/dist/lexer.js"
|
||||
+ ],
|
||||
+ "node_sources": [
|
||||
+ "src/api/async_resource.cc",
|
||||
@@ -1583,7 +1586,7 @@ index 0000000000000000000000000000000000000000..f3c5c798c0aefcb8cf9b1570a7b4817c
|
||||
+ args = rebase_path(inputs + outputs, root_build_dir)
|
||||
+}
|
||||
diff --git a/src/node_version.h b/src/node_version.h
|
||||
index 19fa04ebe755ecd120ef0842a02688e121c4c963..fdbde0397dd4bfaa117ca8e9223510b885511ce6 100644
|
||||
index 7f2f31389637d07fcf0f721daf18b409ade039b4..ffc4ed7085f2b97ce2017245947085e26e7633ac 100644
|
||||
--- a/src/node_version.h
|
||||
+++ b/src/node_version.h
|
||||
@@ -89,7 +89,10 @@
|
||||
|
||||
@@ -10,7 +10,7 @@ THe fix for this should land in node-gyp as discussed in above issue,
|
||||
landing this as temporary patch.
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index 6f309e5cdbf336d27ec88ee5be431a8aebf85d7f..c8618597d8d71b58a46d4aa405536357055edcd3 100644
|
||||
index 81568d5afabd6d80b4df445124ccd7108801769d..463adbfdd8fb3af5d19ed30461eae46fd647de1a 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Mon, 5 Oct 2020 16:05:45 -0700
|
||||
Subject: chore: expose v8 initialization isolate callbacks
|
||||
|
||||
Exposes v8 initializer callbacks to Electron so that we can call them
|
||||
directly. We expand upon and adapt their behavior, so allows us to
|
||||
ensure that we stay in sync with Node.js default behavior.
|
||||
|
||||
This will be upstreamed.
|
||||
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index 274d0481529ace763c997910ce40e2c730a20146..194094e1d5bdda4589c7cc4d99270af3cb3ef5a3 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -30,14 +30,16 @@ using v8::PropertyDescriptor;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
-static bool AllowWasmCodeGenerationCallback(Local<Context> context,
|
||||
+// static
|
||||
+bool Environment::AllowWasmCodeGenerationCallback(Local<Context> context,
|
||||
Local<String>) {
|
||||
Local<Value> wasm_code_gen =
|
||||
context->GetEmbedderData(ContextEmbedderIndex::kAllowWasmCodeGeneration);
|
||||
return wasm_code_gen->IsUndefined() || wasm_code_gen->IsTrue();
|
||||
}
|
||||
|
||||
-static bool ShouldAbortOnUncaughtException(Isolate* isolate) {
|
||||
+// static
|
||||
+bool Environment::ShouldAbortOnUncaughtException(Isolate* isolate) {
|
||||
DebugSealHandleScope scope(isolate);
|
||||
Environment* env = Environment::GetCurrent(isolate);
|
||||
return env != nullptr &&
|
||||
@@ -47,7 +49,8 @@ static bool ShouldAbortOnUncaughtException(Isolate* isolate) {
|
||||
!env->inside_should_not_abort_on_uncaught_scope();
|
||||
}
|
||||
|
||||
-static MaybeLocal<Value> PrepareStackTraceCallback(Local<Context> context,
|
||||
+// static
|
||||
+MaybeLocal<Value> Environment::PrepareStackTraceCallback(Local<Context> context,
|
||||
Local<Value> exception,
|
||||
Local<Array> trace) {
|
||||
Environment* env = Environment::GetCurrent(context);
|
||||
@@ -221,7 +224,7 @@ void SetIsolateErrorHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
|
||||
|
||||
auto* abort_callback = s.should_abort_on_uncaught_exception_callback ?
|
||||
s.should_abort_on_uncaught_exception_callback :
|
||||
- ShouldAbortOnUncaughtException;
|
||||
+ Environment::ShouldAbortOnUncaughtException;
|
||||
isolate->SetAbortOnUncaughtExceptionCallback(abort_callback);
|
||||
|
||||
auto* fatal_error_cb = s.fatal_error_callback ?
|
||||
@@ -229,7 +232,7 @@ void SetIsolateErrorHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
|
||||
isolate->SetFatalErrorHandler(fatal_error_cb);
|
||||
|
||||
auto* prepare_stack_trace_cb = s.prepare_stack_trace_callback ?
|
||||
- s.prepare_stack_trace_callback : PrepareStackTraceCallback;
|
||||
+ s.prepare_stack_trace_callback : Environment::PrepareStackTraceCallback;
|
||||
isolate->SetPrepareStackTraceCallback(prepare_stack_trace_cb);
|
||||
}
|
||||
|
||||
@@ -237,7 +240,7 @@ void SetIsolateMiscHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
|
||||
isolate->SetMicrotasksPolicy(s.policy);
|
||||
|
||||
auto* allow_wasm_codegen_cb = s.allow_wasm_code_generation_callback ?
|
||||
- s.allow_wasm_code_generation_callback : AllowWasmCodeGenerationCallback;
|
||||
+ s.allow_wasm_code_generation_callback : Environment::AllowWasmCodeGenerationCallback;
|
||||
isolate->SetAllowWasmCodeGenerationCallback(allow_wasm_codegen_cb);
|
||||
|
||||
if ((s.flags & SHOULD_NOT_SET_PROMISE_REJECTION_CALLBACK) == 0) {
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index 4fe2eb3b7699efcab87c377743a955effbbfd9de..2bb196d199bd9b6c27d9de8ca7e5a9bffad0c788 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -904,6 +904,13 @@ class Environment : public MemoryRetainer {
|
||||
void Exit(int code);
|
||||
void ExitEnv();
|
||||
|
||||
+ static bool AllowWasmCodeGenerationCallback(v8::Local<v8::Context> context,
|
||||
+ v8::Local<v8::String>);
|
||||
+ static bool ShouldAbortOnUncaughtException(v8::Isolate* isolate);
|
||||
+ static v8::MaybeLocal<v8::Value> PrepareStackTraceCallback(v8::Local<v8::Context> context,
|
||||
+ v8::Local<v8::Value> exception,
|
||||
+ v8::Local<v8::Array> trace);
|
||||
+
|
||||
// Register clean-up cb to be called on environment destruction.
|
||||
inline void RegisterHandleCleanup(uv_handle_t* handle,
|
||||
HandleCleanupCb cb,
|
||||
@@ -8,10 +8,10 @@ once we stop warning and begin to unilaterally prevent non-context aware modules
|
||||
from being loaded.
|
||||
|
||||
diff --git a/lib/internal/bootstrap/pre_execution.js b/lib/internal/bootstrap/pre_execution.js
|
||||
index f947c6bf27e80c534a8f72265d0139a8b5b3f13a..d7e56d9c3fe5a56897989915984cb823d27b9c52 100644
|
||||
index 1b781fb8193002e111d8904e44ca66dbec9daaac..3f80a6e4c03a51d40c25717baab5c690c53abccd 100644
|
||||
--- a/lib/internal/bootstrap/pre_execution.js
|
||||
+++ b/lib/internal/bootstrap/pre_execution.js
|
||||
@@ -92,10 +92,12 @@ function patchProcessObject(expandArgv1) {
|
||||
@@ -93,10 +93,12 @@ function patchProcessObject(expandArgv1) {
|
||||
|
||||
if (expandArgv1 && process.argv[1] && !process.argv[1].startsWith('-')) {
|
||||
// Expand process.argv[1] into a full path.
|
||||
|
||||
@@ -8,7 +8,7 @@ node modules will have different (wrong) ideas about how v8 structs are laid
|
||||
out in memory on 64-bit machines, and will summarily fail to work.
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index c8618597d8d71b58a46d4aa405536357055edcd3..5e209300b5ce85c2a6e15480465623f911053960 100644
|
||||
index 463adbfdd8fb3af5d19ed30461eae46fd647de1a..4d63ac7981edca3f99c05ce08af8ea41628b0387 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -64,7 +64,7 @@
|
||||
|
||||
@@ -65,7 +65,7 @@ index 905afd8c235b7b1a7b45823db486384935a2a52b..102847cd32d03addeb40c9539eafc92b
|
||||
NativeModuleEnv::InitializeCodeCache();
|
||||
|
||||
diff --git a/src/node.h b/src/node.h
|
||||
index 33e11327e487bca9d0d7b5cd5a1c036c7009a359..7340d1a6f0cf2f912aaee15d66ed137fe2870bab 100644
|
||||
index 38e0ef50f9b283b1d7ca8f54412d99b8cd38e524..34a16feaed229a59181e1b2e48b0e111d5b0b2a6 100644
|
||||
--- a/src/node.h
|
||||
+++ b/src/node.h
|
||||
@@ -220,6 +220,8 @@ namespace node {
|
||||
|
||||
@@ -6,10 +6,10 @@ Subject: feat: initialize asar support
|
||||
This patch initializes asar support in Node.js.
|
||||
|
||||
diff --git a/lib/internal/bootstrap/pre_execution.js b/lib/internal/bootstrap/pre_execution.js
|
||||
index dfbefa955cab8adcafc5f46151ac83ed893645e0..f947c6bf27e80c534a8f72265d0139a8b5b3f13a 100644
|
||||
index 9689e2a9edf69530546d5238155f6ea28dd70daf..1b781fb8193002e111d8904e44ca66dbec9daaac 100644
|
||||
--- a/lib/internal/bootstrap/pre_execution.js
|
||||
+++ b/lib/internal/bootstrap/pre_execution.js
|
||||
@@ -73,6 +73,7 @@ function prepareMainThreadExecution(expandArgv1 = false) {
|
||||
@@ -74,6 +74,7 @@ function prepareMainThreadExecution(expandArgv1 = false) {
|
||||
assert(!CJSLoader.hasLoadedAnyUserCJSModule);
|
||||
loadPreloadModules();
|
||||
initializeFrozenIntrinsics();
|
||||
@@ -17,7 +17,7 @@ index dfbefa955cab8adcafc5f46151ac83ed893645e0..f947c6bf27e80c534a8f72265d0139a8
|
||||
}
|
||||
|
||||
function patchProcessObject(expandArgv1) {
|
||||
@@ -447,6 +448,10 @@ function loadPreloadModules() {
|
||||
@@ -448,6 +449,10 @@ function loadPreloadModules() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ common.gypi is a file that's included in the node header bundle, despite
|
||||
the fact that we do not build node with gyp.
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index 33b1325eb513eadfb4b5aba77e52bd63aa1c9980..6f309e5cdbf336d27ec88ee5be431a8aebf85d7f 100644
|
||||
index 4745bb5ac77639a97b30a9730d0ab990fdcca05e..81568d5afabd6d80b4df445124ccd7108801769d 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -81,6 +81,22 @@
|
||||
|
||||
@@ -6,7 +6,7 @@ Subject: fix: add v8_enable_reverse_jsargs defines in common.gypi
|
||||
This can be removed once node upgrades V8 and inevitably has to do this exact same thing. Also hi node people if you are looking at this.
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index 5e209300b5ce85c2a6e15480465623f911053960..27892535631a3e6431bdb3bdea15d0c4ee6e2b59 100644
|
||||
index 4d63ac7981edca3f99c05ce08af8ea41628b0387..42d353c7495ff29a58a942ad72227ada8be662a9 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -65,6 +65,7 @@
|
||||
|
||||
@@ -11,7 +11,7 @@ initialize it in the browser process. This adds a new
|
||||
EnvironmentFlags option which allows preventing that invocation.
|
||||
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index 5110c9f754f7653261f7de6d5f0c35e541880a4d..274d0481529ace763c997910ce40e2c730a20146 100644
|
||||
index 53b07052e43a09f29f863ee1b2287bdebe7b7a7f..c08fe4b32d4155badb572f15529f903c0ec63146 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -358,12 +358,14 @@ Environment* CreateEnvironment(
|
||||
@@ -63,7 +63,7 @@ index 38d17f4e18aa38fde2c2f59a9816c8fb0f65fd51..4fe2eb3b7699efcab87c377743a955ef
|
||||
inline worker::Worker* worker_context() const;
|
||||
Environment* worker_parent_env() const;
|
||||
diff --git a/src/node.h b/src/node.h
|
||||
index b9493d1f3d5b4f192609f1e7529715ec30ab46e2..019620ad0c6a0ca80e6cbcfc5a8322f4e1220bb1 100644
|
||||
index a649f52403659fd18898e1e813f97e32f33784e7..b646fdda58ebcbf2dd92ee4fc9cb0d9c039174d1 100644
|
||||
--- a/src/node.h
|
||||
+++ b/src/node.h
|
||||
@@ -426,7 +426,11 @@ enum Flags : uint64_t {
|
||||
|
||||
@@ -6,10 +6,10 @@ Subject: fix: expose InternalCallbackScope
|
||||
This commit exposes InternalCallbackScope in order to allow us access to its internal flags.
|
||||
|
||||
diff --git a/src/node_internals.h b/src/node_internals.h
|
||||
index c8952e59a2b071c94eaba41393df5b2aa238318e..ab664208076ea776fcb2223dbc228cacd3eb7e58 100644
|
||||
index aa7180e18544cab4004a0ef87ba230bd2e732d28..9a5b2165d5648045ea18d66b0c15d29b4ea1cced 100644
|
||||
--- a/src/node_internals.h
|
||||
+++ b/src/node_internals.h
|
||||
@@ -204,7 +204,7 @@ v8::MaybeLocal<v8::Value> InternalMakeCallback(
|
||||
@@ -200,7 +200,7 @@ v8::MaybeLocal<v8::Value> InternalMakeCallback(
|
||||
v8::Local<v8::Value> argv[],
|
||||
async_context asyncContext);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Subject: fix: expose tracing::Agent and use tracing::TracingController instead
|
||||
of v8::TracingController
|
||||
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index 9a2661ce8b6146a73b910444a49e01e20c8d96e5..5110c9f754f7653261f7de6d5f0c35e541880a4d 100644
|
||||
index 2c4acbc4fa0eca3b7c6d03b997445633646446e7..53b07052e43a09f29f863ee1b2287bdebe7b7a7f 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -472,6 +472,10 @@ MultiIsolatePlatform* GetMultiIsolatePlatform(IsolateData* env) {
|
||||
@@ -20,7 +20,7 @@ index 9a2661ce8b6146a73b910444a49e01e20c8d96e5..5110c9f754f7653261f7de6d5f0c35e5
|
||||
int thread_pool_size,
|
||||
node::tracing::TracingController* tracing_controller) {
|
||||
diff --git a/src/node.h b/src/node.h
|
||||
index 7340d1a6f0cf2f912aaee15d66ed137fe2870bab..b9493d1f3d5b4f192609f1e7529715ec30ab46e2 100644
|
||||
index 34a16feaed229a59181e1b2e48b0e111d5b0b2a6..a649f52403659fd18898e1e813f97e32f33784e7 100644
|
||||
--- a/src/node.h
|
||||
+++ b/src/node.h
|
||||
@@ -125,6 +125,7 @@ namespace node {
|
||||
@@ -31,7 +31,7 @@ index 7340d1a6f0cf2f912aaee15d66ed137fe2870bab..b9493d1f3d5b4f192609f1e7529715ec
|
||||
class TracingController;
|
||||
|
||||
}
|
||||
@@ -512,6 +513,8 @@ NODE_DEPRECATED("Use GetMultiIsolatePlatform(env) instead",
|
||||
@@ -522,6 +523,8 @@ NODE_DEPRECATED("Use GetMultiIsolatePlatform(env) instead",
|
||||
NODE_EXTERN MultiIsolatePlatform* GetMultiIsolatePlatform(Environment* env);
|
||||
NODE_EXTERN MultiIsolatePlatform* GetMultiIsolatePlatform(IsolateData* env);
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ This broke the build at some point. Does it still? We should probably remove
|
||||
this patch and find out!
|
||||
|
||||
diff --git a/src/node_internals.h b/src/node_internals.h
|
||||
index ab664208076ea776fcb2223dbc228cacd3eb7e58..4a1c3392cf53490bcb883e826bf731a4a674ef61 100644
|
||||
index 9a5b2165d5648045ea18d66b0c15d29b4ea1cced..6aff1a4ee7f708437dbf581b9eacc21e5bdd1c43 100644
|
||||
--- a/src/node_internals.h
|
||||
+++ b/src/node_internals.h
|
||||
@@ -372,10 +372,11 @@ class TraceEventScope {
|
||||
@@ -368,10 +368,11 @@ class TraceEventScope {
|
||||
TraceEventScope(const char* category,
|
||||
const char* name,
|
||||
void* id) : category_(category), name_(name), id_(id) {
|
||||
|
||||
@@ -48,14 +48,20 @@ def getBrokenLinks(filepath):
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
regexLink = re.compile('\[(.*?)\]\((?P<links>(.*?))\)')
|
||||
linkRegexLink = re.compile('\[(.*?)\]\((?P<link>(.*?))\)')
|
||||
referenceLinkRegex = re.compile('^\s{0,3}\[.*?\]:\s*(?P<link>[^<\s]+|<[^<>\r\n]+>)')
|
||||
links = []
|
||||
for line in lines:
|
||||
matchLinks = regexLink.search(line)
|
||||
matchLinks = linkRegexLink.search(line)
|
||||
matchReferenceLinks = referenceLinkRegex.search(line)
|
||||
if matchLinks:
|
||||
relativeLink = matchLinks.group('links')
|
||||
relativeLink = matchLinks.group('link')
|
||||
if not str(relativeLink).startswith('http'):
|
||||
links.append(relativeLink)
|
||||
if matchReferenceLinks:
|
||||
referenceLink = matchReferenceLinks.group('link').strip('<>')
|
||||
if not str(referenceLink).startswith('http'):
|
||||
links.append(referenceLink)
|
||||
|
||||
for link in links:
|
||||
sections = link.split('#')
|
||||
|
||||
@@ -46,9 +46,12 @@ const main = async () => {
|
||||
const webpackTargetsWithDeps = await Promise.all(webpackTargets.map(async webpackTarget => {
|
||||
const tmpDir = await fs.mkdtemp(path.resolve(os.tmpdir(), 'electron-filenames-'));
|
||||
const child = cp.spawn('node', [
|
||||
'build/webpack/get-outputs.js',
|
||||
`./${webpackTarget.config}`,
|
||||
path.resolve(tmpDir, `${webpackTarget.name}.measure.js`)
|
||||
'./node_modules/webpack-cli/bin/cli.js',
|
||||
'--config', `./build/webpack/${webpackTarget.config}`,
|
||||
'--display', 'errors-only',
|
||||
`--output-path=${tmpDir}`,
|
||||
`--output-filename=${webpackTarget.name}.measure.js`,
|
||||
'--env.PRINT_WEBPACK_GRAPH'
|
||||
], {
|
||||
cwd: path.resolve(__dirname, '..')
|
||||
});
|
||||
|
||||
@@ -12,7 +12,8 @@ def read_patch(patch_dir, patch_filename):
|
||||
patch_path = os.path.join(patch_dir, patch_filename)
|
||||
with codecs.open(patch_path, encoding='utf-8') as f:
|
||||
for l in f.readlines():
|
||||
if not added_filename_line and (l.startswith('diff -') or l.startswith('---')):
|
||||
line_has_correct_start = l.startswith('diff -') or l.startswith('---')
|
||||
if not added_filename_line and line_has_correct_start:
|
||||
ret.append('Patch-Filename: {}\n'.format(patch_filename))
|
||||
added_filename_line = True
|
||||
ret.append(l)
|
||||
|
||||
@@ -23,6 +23,8 @@ const IGNORELIST = new Set([
|
||||
['spec', 'ts-smoke', 'runner.js']
|
||||
].map(tokens => path.join(SOURCE_ROOT, ...tokens)));
|
||||
|
||||
const IS_WINDOWS = process.platform === 'win32';
|
||||
|
||||
function spawnAndCheckExitCode (cmd, args, opts) {
|
||||
opts = Object.assign({ stdio: 'inherit' }, opts);
|
||||
const status = childProcess.spawnSync(cmd, args, opts).status;
|
||||
@@ -30,7 +32,7 @@ function spawnAndCheckExitCode (cmd, args, opts) {
|
||||
}
|
||||
|
||||
function cpplint (args) {
|
||||
const result = childProcess.spawnSync('cpplint.py', args, { encoding: 'utf8' });
|
||||
const result = childProcess.spawnSync(IS_WINDOWS ? 'cpplint.bat' : 'cpplint.py', args, { encoding: 'utf8', shell: true });
|
||||
// cpplint.py writes EVERYTHING to stderr, including status messages
|
||||
if (result.stderr) {
|
||||
for (const line of result.stderr.split(/[\r\n]+/)) {
|
||||
@@ -39,8 +41,9 @@ function cpplint (args) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result.status) {
|
||||
process.exit(result.status);
|
||||
if (result.status !== 0) {
|
||||
if (result.error) console.error(result.error);
|
||||
process.exit(result.status || 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,14 +93,44 @@ const LINTERS = [{
|
||||
}
|
||||
}, {
|
||||
key: 'javascript',
|
||||
roots: ['lib', 'spec', 'spec-main', 'script', 'default_app', 'build'],
|
||||
roots: ['build', 'default_app', 'lib', 'npm', 'script', 'spec', 'spec-main'],
|
||||
ignoreRoots: ['spec/node_modules', 'spec-main/node_modules'],
|
||||
test: filename => filename.endsWith('.js') || filename.endsWith('.ts'),
|
||||
run: (opts, filenames) => {
|
||||
const cmd = path.join(SOURCE_ROOT, 'node_modules', '.bin', 'eslint');
|
||||
const args = ['--cache', '--ext', '.js,.ts', ...filenames];
|
||||
const args = ['--cache', '--ext', '.js,.ts'];
|
||||
if (opts.fix) args.unshift('--fix');
|
||||
spawnAndCheckExitCode(cmd, args, { cwd: SOURCE_ROOT });
|
||||
// Windows has a max command line length of 2047 characters, so we can't provide
|
||||
// all of the filenames without going over that. To work around it, run eslint
|
||||
// multiple times and chunk the filenames so that each run is under that limit.
|
||||
// Use a much higher limit on other platforms which will effectively be a no-op.
|
||||
const MAX_FILENAME_ARGS_LENGTH = IS_WINDOWS ? 1900 : 100 * 1024;
|
||||
const cmdOpts = { stdio: 'inherit', shell: IS_WINDOWS, cwd: SOURCE_ROOT };
|
||||
if (IS_WINDOWS) {
|
||||
// When running with shell spaces in filenames are problematic
|
||||
filenames = filenames.map(filename => `"${filename}"`);
|
||||
}
|
||||
const chunkedFilenames = filenames.reduce((chunkedFilenames, filename) => {
|
||||
const currentChunk = chunkedFilenames[chunkedFilenames.length - 1];
|
||||
const currentChunkLength = currentChunk.reduce((totalLength, _filename) => totalLength + _filename.length, 0);
|
||||
if (currentChunkLength + filename.length > MAX_FILENAME_ARGS_LENGTH) {
|
||||
chunkedFilenames.push([filename]);
|
||||
} else {
|
||||
currentChunk.push(filename);
|
||||
}
|
||||
return chunkedFilenames;
|
||||
}, [[]]);
|
||||
const allOk = chunkedFilenames.map(filenames => {
|
||||
const result = childProcess.spawnSync(cmd, [...args, ...filenames], cmdOpts);
|
||||
if (result.error) {
|
||||
console.error(result.error);
|
||||
process.exit(result.status || 1);
|
||||
}
|
||||
return result.status === 0;
|
||||
}).every(x => x);
|
||||
if (!allOk) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
key: 'gn',
|
||||
@@ -183,6 +216,11 @@ const LINTERS = [{
|
||||
console.warn(`Patch file '${f}' has no description. Every patch must contain a justification for why the patch exists and the plan for its removal.`);
|
||||
ok = false;
|
||||
}
|
||||
const trailingWhitespace = patchText.split('\n').filter(line => line.startsWith('+')).some(line => /\s+$/.test(line));
|
||||
if (trailingWhitespace) {
|
||||
console.warn(`Patch file '${f}' has trailing whitespace on some lines.`);
|
||||
ok = false;
|
||||
}
|
||||
});
|
||||
if (!ok) {
|
||||
process.exit(1);
|
||||
|
||||
185
script/patches-mtime-cache.py
Normal file
@@ -0,0 +1,185 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import posixpath
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from lib.patches import patch_from_dir
|
||||
|
||||
|
||||
def patched_file_paths(patches_config):
|
||||
for patch_dir, repo in patches_config.items():
|
||||
for line in patch_from_dir(patch_dir).split("\n"):
|
||||
if line.startswith("+++"):
|
||||
yield posixpath.join(repo, line[6:])
|
||||
|
||||
|
||||
def generate_cache(patches_config):
|
||||
mtime_cache = {}
|
||||
|
||||
for file_path in patched_file_paths(patches_config):
|
||||
if file_path in mtime_cache:
|
||||
# File may be patched multiple times, we don't need to
|
||||
# rehash it since we are looking at the final result
|
||||
continue
|
||||
|
||||
if not os.path.exists(file_path):
|
||||
print("Skipping non-existent file:", file_path)
|
||||
continue
|
||||
|
||||
with open(file_path, "rb") as f:
|
||||
mtime_cache[file_path] = {
|
||||
"sha256": hashlib.sha256(f.read()).hexdigest(),
|
||||
"atime": os.path.getatime(file_path),
|
||||
"mtime": os.path.getmtime(file_path),
|
||||
}
|
||||
|
||||
return mtime_cache
|
||||
|
||||
|
||||
def apply_mtimes(mtime_cache):
|
||||
updates = []
|
||||
|
||||
for file_path, metadata in mtime_cache.items():
|
||||
if not os.path.exists(file_path):
|
||||
print("Skipping non-existent file:", file_path)
|
||||
continue
|
||||
|
||||
with open(file_path, "rb") as f:
|
||||
if hashlib.sha256(f.read()).hexdigest() == metadata["sha256"]:
|
||||
updates.append(
|
||||
[file_path, metadata["atime"], metadata["mtime"]]
|
||||
)
|
||||
|
||||
# We can't atomically set the times for all files at once, but by waiting
|
||||
# to update until we've checked all the files we at least have less chance
|
||||
# of only updating some files due to an error on one of the files
|
||||
for [file_path, atime, mtime] in updates:
|
||||
os.utime(file_path, (atime, mtime))
|
||||
|
||||
|
||||
def set_mtimes(patches_config, mtime):
|
||||
mtime_cache = {}
|
||||
|
||||
for file_path in patched_file_paths(patches_config):
|
||||
if file_path in mtime_cache:
|
||||
continue
|
||||
|
||||
if not os.path.exists(file_path):
|
||||
print("Skipping non-existent file:", file_path)
|
||||
continue
|
||||
|
||||
mtime_cache[file_path] = mtime
|
||||
|
||||
for file_path in mtime_cache:
|
||||
os.utime(file_path, (mtime_cache[file_path], mtime_cache[file_path]))
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Make mtime cache for patched files"
|
||||
)
|
||||
subparsers = parser.add_subparsers(
|
||||
dest="operation", help="sub-command help"
|
||||
)
|
||||
|
||||
apply_subparser = subparsers.add_parser(
|
||||
"apply", help="apply the mtimes from the cache"
|
||||
)
|
||||
apply_subparser.add_argument(
|
||||
"--cache-file", required=True, help="mtime cache file"
|
||||
)
|
||||
apply_subparser.add_argument(
|
||||
"--preserve-cache",
|
||||
action="store_true",
|
||||
help="don't delete cache after applying",
|
||||
)
|
||||
|
||||
generate_subparser = subparsers.add_parser(
|
||||
"generate", help="generate the mtime cache"
|
||||
)
|
||||
generate_subparser.add_argument(
|
||||
"--cache-file",
|
||||
type=argparse.FileType("w"),
|
||||
required=True,
|
||||
help="mtime cache file",
|
||||
)
|
||||
|
||||
set_subparser = subparsers.add_parser(
|
||||
"set", help="set all mtimes to a specific date"
|
||||
)
|
||||
set_subparser.add_argument(
|
||||
"--mtime",
|
||||
type=int,
|
||||
required=True,
|
||||
help="mtime to use for all patched files",
|
||||
)
|
||||
|
||||
for subparser in [generate_subparser, set_subparser]:
|
||||
subparser.add_argument(
|
||||
"--patches-config",
|
||||
type=argparse.FileType("r"),
|
||||
required=True,
|
||||
help="patches' config in the JSON format",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.operation == "generate":
|
||||
try:
|
||||
mtime_cache = generate_cache(json.load(args.patches_config))
|
||||
json.dump(mtime_cache, args.cache_file, indent=2)
|
||||
except Exception:
|
||||
print(
|
||||
"ERROR: failed to generate mtime cache for patches",
|
||||
file=sys.stderr,
|
||||
)
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
return 0
|
||||
elif args.operation == "apply":
|
||||
if not os.path.exists(args.cache_file):
|
||||
print("ERROR: --cache-file does not exist", file=sys.stderr)
|
||||
return 0 # Cache file may not exist, fail more gracefully
|
||||
|
||||
try:
|
||||
with open(args.cache_file, mode="r") as f:
|
||||
apply_mtimes(json.load(f))
|
||||
|
||||
if not args.preserve_cache:
|
||||
os.remove(args.cache_file)
|
||||
except Exception:
|
||||
print(
|
||||
"ERROR: failed to apply mtime cache for patches",
|
||||
file=sys.stderr,
|
||||
)
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
return 0
|
||||
elif args.operation == "set":
|
||||
# Python 2/3 compatibility
|
||||
try:
|
||||
user_input = raw_input
|
||||
except NameError:
|
||||
user_input = input
|
||||
|
||||
answer = user_input(
|
||||
"WARNING: Manually setting mtimes could mess up your build. "
|
||||
"If you're sure, type yes: "
|
||||
)
|
||||
|
||||
if answer.lower() != "yes":
|
||||
print("Aborting")
|
||||
return 0
|
||||
|
||||
set_mtimes(json.load(args.patches_config), args.mtime)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -381,6 +381,7 @@ async function getBranchNameOfRef (ref, dir) {
|
||||
return (await runGit(dir, ['branch', '--all', '--contains', ref, '--sort', 'version:refname']))
|
||||
.split(/\r?\n/) // split into lines
|
||||
.shift() // we sorted by refname and want the first result
|
||||
.match(/(?:\s?\*\s){0,1}(.*)/)[1] // if present, remove leading '* ' in case we're currently in that branch
|
||||
.match(/(?:.*\/)?(.*)/)[1] // 'remote/origins/10-x-y' -> '10-x-y'
|
||||
.trim();
|
||||
}
|
||||
@@ -398,7 +399,7 @@ const getNotes = async (fromRef, toRef, newVersion) => {
|
||||
const pool = new Pool();
|
||||
const toBranch = await getBranchNameOfRef(toRef, ELECTRON_DIR);
|
||||
|
||||
console.log(`Generating release notes between ${fromRef} and ${toRef} for version ${newVersion} in branch ${toBranch}`);
|
||||
console.log(`Generating release notes between '${fromRef}' and '${toRef}' for version '${newVersion}' in branch '${toBranch}'`);
|
||||
|
||||
// get the electron/electron commits
|
||||
const electron = { owner: 'electron', repo: 'electron', dir: ELECTRON_DIR };
|
||||
|
||||
@@ -46,7 +46,9 @@ def main():
|
||||
|
||||
for symbol_file in files:
|
||||
print("Generating Sentry src bundle for: " + symbol_file)
|
||||
subprocess.check_output([NPX_CMD, '@sentry/cli@1.51.1', 'difutil', 'bundle-sources', symbol_file])
|
||||
subprocess.check_output([
|
||||
NPX_CMD, '@sentry/cli@1.51.1', 'difutil', 'bundle-sources',
|
||||
symbol_file])
|
||||
|
||||
files += glob.glob(SYMBOLS_DIR + '/*/*/*.src.zip')
|
||||
|
||||
|
||||
@@ -36,7 +36,8 @@ SYMBOLS_NAME = get_zip_name(PROJECT_NAME, ELECTRON_VERSION, 'symbols')
|
||||
DSYM_NAME = get_zip_name(PROJECT_NAME, ELECTRON_VERSION, 'dsym')
|
||||
PDB_NAME = get_zip_name(PROJECT_NAME, ELECTRON_VERSION, 'pdb')
|
||||
DEBUG_NAME = get_zip_name(PROJECT_NAME, ELECTRON_VERSION, 'debug')
|
||||
TOOLCHAIN_PROFILE_NAME = get_zip_name(PROJECT_NAME, ELECTRON_VERSION, 'toolchain-profile')
|
||||
TOOLCHAIN_PROFILE_NAME = get_zip_name(PROJECT_NAME, ELECTRON_VERSION,
|
||||
'toolchain-profile')
|
||||
|
||||
|
||||
def main():
|
||||
@@ -59,7 +60,8 @@ def main():
|
||||
tag_exists = True
|
||||
|
||||
if not args.upload_to_s3:
|
||||
assert release['exists'], 'Release does not exist; cannot upload to GitHub!'
|
||||
assert release['exists'], \
|
||||
'Release does not exist; cannot upload to GitHub!'
|
||||
assert tag_exists == args.overwrite, \
|
||||
'You have to pass --overwrite to overwrite a published release'
|
||||
|
||||
@@ -114,7 +116,8 @@ def main():
|
||||
|
||||
if PLATFORM == 'linux' and get_target_arch() == 'x64':
|
||||
# Upload the hunspell dictionaries only from the linux x64 build
|
||||
hunspell_dictionaries_zip = os.path.join(OUT_DIR, 'hunspell_dictionaries.zip')
|
||||
hunspell_dictionaries_zip = os.path.join(
|
||||
OUT_DIR, 'hunspell_dictionaries.zip')
|
||||
upload_electron(release, hunspell_dictionaries_zip, args)
|
||||
|
||||
if not tag_exists and not args.upload_to_s3:
|
||||
@@ -126,7 +129,9 @@ def main():
|
||||
if PLATFORM == 'win32':
|
||||
toolchain_profile_zip = os.path.join(OUT_DIR, TOOLCHAIN_PROFILE_NAME)
|
||||
with ZipFile(toolchain_profile_zip, 'w') as myzip:
|
||||
myzip.write(os.path.join(OUT_DIR, 'windows_toolchain_profile.json'), 'toolchain_profile.json')
|
||||
myzip.write(
|
||||
os.path.join(OUT_DIR, 'windows_toolchain_profile.json'),
|
||||
'toolchain_profile.json')
|
||||
upload_electron(release, toolchain_profile_zip, args)
|
||||
|
||||
|
||||
@@ -170,12 +175,10 @@ class NonZipFileError(ValueError):
|
||||
def zero_zip_date_time(fname):
|
||||
""" Wrap strip-zip zero_zip_date_time within a file opening operation """
|
||||
try:
|
||||
zip = open(fname, 'r+b')
|
||||
_zero_zip_date_time(zip)
|
||||
with open(fname, 'r+b') as f:
|
||||
_zero_zip_date_time(f)
|
||||
except:
|
||||
raise NonZipFileError(fname)
|
||||
finally:
|
||||
zip.close()
|
||||
|
||||
|
||||
def _zero_zip_date_time(zip_):
|
||||
@@ -208,7 +211,7 @@ def _zero_zip_date_time(zip_):
|
||||
_, header_length = values
|
||||
extra_struct = Struct("<HH" + "B" * header_length)
|
||||
values = list(extra_struct.unpack_from(mm, offset))
|
||||
header_id, header_length, rest = values[0], values[1], values[2:]
|
||||
header_id, header_length = values[:2]
|
||||
|
||||
if header_id in (EXTENDED_TIME_DATA, UNIX_EXTRA_DATA):
|
||||
values[0] = STRIPZIP_OPTION_HEADER
|
||||
@@ -218,7 +221,7 @@ def _zero_zip_date_time(zip_):
|
||||
if header_id == ZIP64_EXTRA_HEADER:
|
||||
assert header_length == 16
|
||||
values = list(zip64_extra_struct.unpack_from(mm, offset))
|
||||
header_id, header_length, uncompressed_size, compressed_size = values
|
||||
header_id, header_length, _, compressed_size = values
|
||||
|
||||
offset += extra_header_struct.size + header_length
|
||||
|
||||
@@ -266,7 +269,7 @@ def _zero_zip_date_time(zip_):
|
||||
if signature_struct.unpack_from(mm, offset) != (FILE_HEADER_SIGNATURE,):
|
||||
break
|
||||
values = list(local_file_header_struct.unpack_from(mm, offset))
|
||||
_, _, _, _, _, _, _, compressed_size, _, name_length, extra_field_length = values
|
||||
compressed_size, _, name_length, extra_field_length = values[7:11]
|
||||
# reset last_mod_time
|
||||
values[4] = 0
|
||||
# reset last_mod_date
|
||||
@@ -274,20 +277,22 @@ def _zero_zip_date_time(zip_):
|
||||
local_file_header_struct.pack_into(mm, offset, *values)
|
||||
offset += local_file_header_struct.size + name_length
|
||||
if extra_field_length != 0:
|
||||
compressed_size = purify_extra_data(mm, offset, extra_field_length, compressed_size)
|
||||
compressed_size = purify_extra_data(mm, offset, extra_field_length,
|
||||
compressed_size)
|
||||
offset += compressed_size + extra_field_length
|
||||
|
||||
while offset < archive_size:
|
||||
if signature_struct.unpack_from(mm, offset) != (CENDIR_HEADER_SIGNATURE,):
|
||||
break
|
||||
values = list(central_directory_header_struct.unpack_from(mm, offset))
|
||||
_, _, _, _, _, _, _, _, _, _, file_name_length, extra_field_length, file_comment_length, _, _, _, _ = values
|
||||
file_name_length, extra_field_length, file_comment_length = values[10:13]
|
||||
# reset last_mod_time
|
||||
values[5] = 0
|
||||
# reset last_mod_date
|
||||
values[6] = 0x21
|
||||
central_directory_header_struct.pack_into(mm, offset, *values)
|
||||
offset += central_directory_header_struct.size + file_name_length + extra_field_length + file_comment_length
|
||||
offset += central_directory_header_struct.size
|
||||
offset += file_name_length + extra_field_length + file_comment_length
|
||||
if extra_field_length != 0:
|
||||
purify_extra_data(mm, offset - extra_field_length, extra_field_length)
|
||||
|
||||
|
||||
@@ -22,7 +22,9 @@ def strip_binary(binary_path, target_cpu):
|
||||
strip = 'mips64el-redhat-linux-strip'
|
||||
else:
|
||||
strip = 'strip'
|
||||
execute([strip, '--discard-all', '--strip-debug', '--preserve-dates', binary_path])
|
||||
execute([
|
||||
strip, '--discard-all', '--strip-debug', '--preserve-dates',
|
||||
binary_path])
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
|
||||
@@ -20,7 +20,10 @@ def parse_args():
|
||||
|
||||
parser.add_argument('--base-url', required=False,
|
||||
help="Base URL for all downloads")
|
||||
parser.add_argument('--force', action='store_true', default=False, required=False)
|
||||
parser.add_argument('--force',
|
||||
action='store_true',
|
||||
default=False,
|
||||
required=False)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
@@ -111,7 +114,9 @@ def download_binary(base_url, sha, binary_name, attempt=3):
|
||||
def validate_sha(file_path, sha):
|
||||
downloaded_sha = sha256(file_path)
|
||||
if downloaded_sha != sha:
|
||||
raise Exception("SHA for external binary file {} does not match expected '{}' != '{}'".format(file_path, downloaded_sha, sha))
|
||||
raise Exception("SHA for external binary file {} does not match "
|
||||
"expected '{}' != '{}'".format(
|
||||
file_path, downloaded_sha, sha))
|
||||
|
||||
|
||||
def download_to_temp_dir(url, filename, sha):
|
||||
|
||||
@@ -33,7 +33,9 @@ def main():
|
||||
|
||||
returncode = 0
|
||||
match = re.search(
|
||||
'^Starting ChromeDriver [0-9]+.[0-9]+.[0-9]+.[0-9]+ .* on port [0-9]+$', output)
|
||||
'^Starting ChromeDriver [0-9]+.[0-9]+.[0-9]+.[0-9]+ .* on port [0-9]+$',
|
||||
output
|
||||
)
|
||||
|
||||
if match is None:
|
||||
returncode = 1
|
||||
|
||||
@@ -837,7 +837,7 @@ void App::OnGpuProcessCrashed(base::TerminationStatus status) {
|
||||
void App::BrowserChildProcessLaunchedAndConnected(
|
||||
const content::ChildProcessData& data) {
|
||||
ChildProcessLaunched(data.process_type, data.GetProcess().Handle(),
|
||||
base::UTF16ToUTF8(data.name));
|
||||
data.metrics_name, base::UTF16ToUTF8(data.name));
|
||||
}
|
||||
|
||||
void App::BrowserChildProcessHostDisconnected(
|
||||
@@ -868,6 +868,7 @@ void App::BrowserChildProcessCrashedOrKilled(
|
||||
details.Set("type", content::GetProcessTypeNameInEnglish(data.process_type));
|
||||
details.Set("reason", info.status);
|
||||
details.Set("exitCode", info.exit_code);
|
||||
details.Set("serviceName", data.metrics_name);
|
||||
if (!data.name.empty()) {
|
||||
details.Set("name", data.name);
|
||||
}
|
||||
@@ -896,6 +897,7 @@ void App::RenderProcessDisconnected(base::ProcessId host_pid) {
|
||||
|
||||
void App::ChildProcessLaunched(int process_type,
|
||||
base::ProcessHandle handle,
|
||||
const std::string& service_name,
|
||||
const std::string& name) {
|
||||
auto pid = base::GetProcId(handle);
|
||||
|
||||
@@ -906,7 +908,7 @@ void App::ChildProcessLaunched(int process_type,
|
||||
auto metrics = base::ProcessMetrics::CreateProcessMetrics(handle);
|
||||
#endif
|
||||
app_metrics_[pid] = std::make_unique<electron::ProcessMetric>(
|
||||
process_type, handle, std::move(metrics), name);
|
||||
process_type, handle, std::move(metrics), service_name, name);
|
||||
}
|
||||
|
||||
void App::ChildProcessDisconnected(base::ProcessId pid) {
|
||||
@@ -1349,6 +1351,10 @@ std::vector<gin_helper::Dictionary> App::GetAppMetrics(v8::Isolate* isolate) {
|
||||
pid_dict.Set("creationTime",
|
||||
process_metric.second->process.CreationTime().ToJsTime());
|
||||
|
||||
if (!process_metric.second->service_name.empty()) {
|
||||
pid_dict.Set("serviceName", process_metric.second->service_name);
|
||||
}
|
||||
|
||||
if (!process_metric.second->name.empty()) {
|
||||
pid_dict.Set("name", process_metric.second->name);
|
||||
}
|
||||
|
||||
@@ -168,6 +168,7 @@ class App : public ElectronBrowserClient::Delegate,
|
||||
void SetAppPath(const base::FilePath& app_path);
|
||||
void ChildProcessLaunched(int process_type,
|
||||
base::ProcessHandle handle,
|
||||
const std::string& service_name = std::string(),
|
||||
const std::string& name = std::string());
|
||||
void ChildProcessDisconnected(base::ProcessId pid);
|
||||
|
||||
|
||||
@@ -951,7 +951,7 @@ std::vector<v8::Local<v8::Object>> BaseWindow::GetChildWindows() const {
|
||||
|
||||
v8::Local<v8::Value> BaseWindow::GetBrowserView(
|
||||
gin_helper::Arguments* args) const {
|
||||
if (browser_views_.size() == 0) {
|
||||
if (browser_views_.empty()) {
|
||||
return v8::Null(isolate());
|
||||
} else if (browser_views_.size() == 1) {
|
||||
auto first_view = browser_views_.begin();
|
||||
@@ -999,7 +999,7 @@ void BaseWindow::SetIcon(gin::Handle<NativeImage> icon) {
|
||||
static_cast<NativeWindowViews*>(window_.get())
|
||||
->SetIcon(icon->GetHICON(GetSystemMetrics(SM_CXSMICON)),
|
||||
icon->GetHICON(GetSystemMetrics(SM_CXICON)));
|
||||
#elif defined(USE_X11)
|
||||
#elif defined(OS_LINUX)
|
||||
static_cast<NativeWindowViews*>(window_.get())
|
||||
->SetIcon(icon->image().AsImageSkia());
|
||||
#endif
|
||||
|
||||
@@ -12,12 +12,39 @@
|
||||
#include "shell/browser/native_window.h"
|
||||
#include "shell/common/gin_converters/accelerator_converter.h"
|
||||
#include "shell/common/gin_converters/callback_converter.h"
|
||||
#include "shell/common/gin_converters/file_path_converter.h"
|
||||
#include "shell/common/gin_converters/gurl_converter.h"
|
||||
#include "shell/common/gin_converters/image_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/gin_helper/object_template_builder.h"
|
||||
#include "shell/common/node_includes.h"
|
||||
#include "ui/base/models/image_model.h"
|
||||
|
||||
#if defined(OS_MAC)
|
||||
|
||||
namespace gin {
|
||||
|
||||
using SharingItem = electron::ElectronMenuModel::SharingItem;
|
||||
|
||||
template <>
|
||||
struct Converter<SharingItem> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
SharingItem* out) {
|
||||
gin_helper::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
dict.GetOptional("texts", &(out->texts));
|
||||
dict.GetOptional("filePaths", &(out->file_paths));
|
||||
dict.GetOptional("urls", &(out->urls));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace gin
|
||||
|
||||
#endif
|
||||
|
||||
namespace electron {
|
||||
|
||||
namespace api {
|
||||
@@ -26,6 +53,15 @@ gin::WrapperInfo Menu::kWrapperInfo = {gin::kEmbedderNativeGin};
|
||||
|
||||
Menu::Menu(gin::Arguments* args) : model_(new ElectronMenuModel(this)) {
|
||||
model_->AddObserver(this);
|
||||
|
||||
#if defined(OS_MAC)
|
||||
gin_helper::Dictionary options;
|
||||
if (args->GetNext(&options)) {
|
||||
ElectronMenuModel::SharingItem item;
|
||||
if (options.Get("sharingItem", &item))
|
||||
model_->SetSharingItem(std::move(item));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Menu::~Menu() {
|
||||
@@ -81,6 +117,19 @@ bool Menu::ShouldRegisterAcceleratorForCommandId(int command_id) const {
|
||||
command_id);
|
||||
}
|
||||
|
||||
#if defined(OS_MAC)
|
||||
bool Menu::GetSharingItemForCommandId(
|
||||
int command_id,
|
||||
ElectronMenuModel::SharingItem* item) const {
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Local<v8::Value> val =
|
||||
gin_helper::CallMethod(isolate, const_cast<Menu*>(this),
|
||||
"_getSharingItemForCommandId", command_id);
|
||||
return gin::ConvertFromV8(isolate, val, item);
|
||||
}
|
||||
#endif
|
||||
|
||||
void Menu::ExecuteCommand(int command_id, int flags) {
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||