mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
25 Commits
v12.0.0-ni
...
v12.0.0-ni
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
5
.gitignore
vendored
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
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.20201019
|
||||
12.0.0-nightly.20201021
|
||||
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
|
||||
45
docs/api/share-menu.md
Normal file
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
|
||||
|
||||
5
docs/api/structures/sharing-item.md
Normal file
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.
|
||||
BIN
docs/images/macos-dock-menu.png
Normal file
BIN
docs/images/macos-dock-menu.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 100 KiB |
BIN
docs/images/message-notification-renderer.png
Normal file
BIN
docs/images/message-notification-renderer.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
BIN
docs/images/notification-main.png
Normal file
BIN
docs/images/notification-main.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
BIN
docs/images/notification-renderer.png
Normal file
BIN
docs/images/notification-renderer.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
docs/images/online-event-detection.png
Normal file
BIN
docs/images/online-event-detection.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
BIN
docs/images/recent-documents.png
Normal file
BIN
docs/images/recent-documents.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 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
|
||||
```
|
||||
|
||||
@@ -32,4 +32,4 @@ 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
|
||||
[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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import("//build/config/ui.gni")
|
||||
|
||||
filenames = {
|
||||
default_app_ts_sources = [
|
||||
"default_app/default_app.ts",
|
||||
@@ -22,20 +24,10 @@ 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/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",
|
||||
@@ -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",
|
||||
|
||||
@@ -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
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;
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "12.0.0-nightly.20201019",
|
||||
"version": "12.0.0-nightly.20201021",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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, '..')
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,6 +186,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
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 };
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -64,6 +64,11 @@ class Menu : public gin::Wrappable<Menu>,
|
||||
bool use_default_accelerator,
|
||||
ui::Accelerator* accelerator) const override;
|
||||
bool ShouldRegisterAcceleratorForCommandId(int command_id) const override;
|
||||
#if defined(OS_MAC)
|
||||
bool GetSharingItemForCommandId(
|
||||
int command_id,
|
||||
ElectronMenuModel::SharingItem* item) const override;
|
||||
#endif
|
||||
void ExecuteCommand(int command_id, int event_flags) override;
|
||||
void OnMenuWillShow(ui::SimpleMenuModel* source) override;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "gin/handle.h"
|
||||
#include "net/base/network_change_notifier.h"
|
||||
#include "services/network/public/cpp/features.h"
|
||||
#include "shell/browser/api/electron_api_url_loader.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
@@ -14,6 +15,10 @@
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsOnline() {
|
||||
return !net::NetworkChangeNotifier::IsOffline();
|
||||
}
|
||||
|
||||
bool IsValidHeaderName(std::string header_name) {
|
||||
return net::HttpUtil::IsValidHeaderName(header_name);
|
||||
}
|
||||
@@ -31,6 +36,7 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
|
||||
gin_helper::Dictionary dict(isolate, exports);
|
||||
dict.SetMethod("isOnline", &IsOnline);
|
||||
dict.SetMethod("isValidHeaderName", &IsValidHeaderName);
|
||||
dict.SetMethod("isValidHeaderValue", &IsValidHeaderValue);
|
||||
dict.SetMethod("createURLLoader", &SimpleURLLoaderWrapper::Create);
|
||||
|
||||
@@ -236,11 +236,11 @@ const base::FilePath::StringPieceType kPathDelimiter = FILE_PATH_LITERAL(":");
|
||||
// below. Extension, and isolated apps require different privileges to be
|
||||
// granted to their RenderProcessHosts. This classification allows us to make
|
||||
// sure URLs are served by hosts with the right set of privileges.
|
||||
enum RenderProcessHostPrivilege {
|
||||
PRIV_NORMAL,
|
||||
PRIV_HOSTED,
|
||||
PRIV_ISOLATED,
|
||||
PRIV_EXTENSION,
|
||||
enum class RenderProcessHostPrivilege {
|
||||
Normal,
|
||||
Hosted,
|
||||
Isolated,
|
||||
Extension,
|
||||
};
|
||||
|
||||
RenderProcessHostPrivilege GetPrivilegeRequiredByUrl(
|
||||
@@ -253,12 +253,12 @@ RenderProcessHostPrivilege GetPrivilegeRequiredByUrl(
|
||||
// than normal webrenderer, the navigation logic will correct us out of band
|
||||
// anyways.
|
||||
if (!url.is_valid())
|
||||
return PRIV_NORMAL;
|
||||
return RenderProcessHostPrivilege::Normal;
|
||||
|
||||
if (!url.SchemeIs(extensions::kExtensionScheme))
|
||||
return PRIV_NORMAL;
|
||||
return RenderProcessHostPrivilege::Normal;
|
||||
|
||||
return PRIV_EXTENSION;
|
||||
return RenderProcessHostPrivilege::Extension;
|
||||
}
|
||||
|
||||
RenderProcessHostPrivilege GetProcessPrivilege(
|
||||
@@ -268,9 +268,9 @@ RenderProcessHostPrivilege GetProcessPrivilege(
|
||||
std::set<std::string> extension_ids =
|
||||
process_map->GetExtensionsInProcess(process_host->GetID());
|
||||
if (extension_ids.empty())
|
||||
return PRIV_NORMAL;
|
||||
return RenderProcessHostPrivilege::Normal;
|
||||
|
||||
return PRIV_EXTENSION;
|
||||
return RenderProcessHostPrivilege::Extension;
|
||||
}
|
||||
|
||||
const extensions::Extension* GetEnabledExtensionFromEffectiveURL(
|
||||
|
||||
@@ -59,20 +59,32 @@
|
||||
#include "ui/wm/core/wm_state.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_X11)
|
||||
#if defined(OS_LINUX)
|
||||
#include "base/environment.h"
|
||||
#include "base/nix/xdg_util.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "ui/gtk/gtk_ui.h"
|
||||
#include "ui/gtk/gtk_ui_delegate.h"
|
||||
#include "ui/gtk/gtk_util.h"
|
||||
#include "ui/views/linux_ui/linux_ui.h"
|
||||
|
||||
#if defined(USE_OZONE)
|
||||
#include "ui/ozone/public/ozone_platform.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_X11)
|
||||
#include "ui/base/x/x11_util.h"
|
||||
#include "ui/events/devices/x11/touch_factory_x11.h"
|
||||
#include "ui/gfx/color_utils.h"
|
||||
#include "ui/gfx/x/x11_types.h"
|
||||
#include "ui/gfx/x/xproto_util.h"
|
||||
#include "ui/gtk/gtk_ui.h"
|
||||
#include "ui/gtk/gtk_ui_delegate.h"
|
||||
#include "ui/gtk/gtk_util.h"
|
||||
#include "ui/gtk/x/gtk_ui_delegate_x11.h"
|
||||
#include "ui/views/linux_ui/linux_ui.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_OZONE) || defined(USE_X11)
|
||||
#include "ui/base/ui_base_features.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
@@ -336,11 +348,15 @@ void ElectronBrowserMainParts::PostDestroyThreads() {
|
||||
|
||||
void ElectronBrowserMainParts::ToolkitInitialized() {
|
||||
#if defined(USE_X11)
|
||||
// In Aura/X11, Gtk-based LinuxUI implementation is used.
|
||||
gtk_ui_delegate_ =
|
||||
std::make_unique<ui::GtkUiDelegateX11>(x11::Connection::Get());
|
||||
ui::GtkUiDelegate::SetInstance(gtk_ui_delegate_.get());
|
||||
views::LinuxUI* linux_ui = BuildGtkUi(gtk_ui_delegate_.get());
|
||||
if (!features::IsUsingOzonePlatform()) {
|
||||
// In Aura/X11, Gtk-based LinuxUI implementation is used.
|
||||
gtk_ui_delegate_ =
|
||||
std::make_unique<ui::GtkUiDelegateX11>(x11::Connection::Get());
|
||||
ui::GtkUiDelegate::SetInstance(gtk_ui_delegate_.get());
|
||||
}
|
||||
#endif
|
||||
#if defined(OS_LINUX)
|
||||
views::LinuxUI* linux_ui = BuildGtkUi(ui::GtkUiDelegate::instance());
|
||||
views::LinuxUI::SetInstance(linux_ui);
|
||||
linux_ui->Initialize();
|
||||
|
||||
@@ -402,14 +418,10 @@ void ElectronBrowserMainParts::PreMainMessageLoopRun() {
|
||||
#endif
|
||||
|
||||
#if defined(USE_X11)
|
||||
ui::TouchFactory::SetTouchDeviceListFromCommandLine();
|
||||
if (!features::IsUsingOzonePlatform())
|
||||
ui::TouchFactory::SetTouchDeviceListFromCommandLine();
|
||||
#endif
|
||||
|
||||
// Start idle gc.
|
||||
gc_timer_.Start(FROM_HERE, base::TimeDelta::FromMinutes(1),
|
||||
base::BindRepeating(&v8::Isolate::LowMemoryNotification,
|
||||
base::Unretained(js_env_->isolate())));
|
||||
|
||||
content::WebUIControllerFactory::RegisterFactory(
|
||||
ElectronWebUIControllerFactory::GetInstance());
|
||||
|
||||
@@ -444,6 +456,14 @@ void ElectronBrowserMainParts::PreDefaultMainMessageLoopRun(
|
||||
}
|
||||
|
||||
void ElectronBrowserMainParts::PostMainMessageLoopStart() {
|
||||
#if defined(USE_OZONE)
|
||||
if (features::IsUsingOzonePlatform()) {
|
||||
auto shutdown_cb =
|
||||
base::BindOnce(base::RunLoop::QuitCurrentWhenIdleClosureDeprecated());
|
||||
ui::OzonePlatform::GetInstance()->PostMainMessageLoopStart(
|
||||
std::move(shutdown_cb));
|
||||
}
|
||||
#endif
|
||||
#if defined(OS_LINUX)
|
||||
bluez::DBusBluezManagerWrapperLinux::Initialize();
|
||||
#endif
|
||||
|
||||
@@ -29,7 +29,7 @@ class WMState;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
#if defined(USE_X11)
|
||||
namespace ui {
|
||||
class GtkUiDelegate;
|
||||
}
|
||||
@@ -133,6 +133,9 @@ class ElectronBrowserMainParts : public content::BrowserMainParts {
|
||||
|
||||
#if defined(USE_X11)
|
||||
std::unique_ptr<ui::GtkUiDelegate> gtk_ui_delegate_;
|
||||
#endif
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
// Used to notify the native theme of changes to dark mode.
|
||||
std::unique_ptr<DarkThemeObserver> dark_theme_observer_;
|
||||
#endif
|
||||
@@ -158,8 +161,6 @@ class ElectronBrowserMainParts : public content::BrowserMainParts {
|
||||
std::unique_ptr<ElectronExtensionsBrowserClient> extensions_browser_client_;
|
||||
#endif
|
||||
|
||||
base::RepeatingTimer gc_timer_;
|
||||
|
||||
// List of callbacks should be executed before destroying JS env.
|
||||
std::list<base::OnceClosure> destructors_;
|
||||
|
||||
|
||||
@@ -63,6 +63,11 @@ void AddStringsForPdf(base::DictionaryValue* dict) {
|
||||
|
||||
void AddAdditionalDataForPdf(base::DictionaryValue* dict) {
|
||||
#if BUILDFLAG(ENABLE_PDF)
|
||||
dict->SetStringKey(
|
||||
"pdfViewerUpdateEnabledAttribute",
|
||||
base::FeatureList::IsEnabled(chrome_pdf::features::kPDFViewerUpdate)
|
||||
? "pdf-viewer-update-enabled"
|
||||
: "");
|
||||
dict->SetKey("pdfFormSaveEnabled",
|
||||
base::Value(base::FeatureList::IsEnabled(
|
||||
chrome_pdf::features::kSaveEditedPDFForm)));
|
||||
|
||||
@@ -27,7 +27,7 @@ void NativeBrowserViewViews::SetAutoResizeProportions(
|
||||
if ((auto_resize_flags_ & AutoResizeFlags::kAutoResizeHorizontal) &&
|
||||
!auto_horizontal_proportion_set_) {
|
||||
auto* iwc_view = GetInspectableWebContentsView();
|
||||
if (iwc_view)
|
||||
if (!iwc_view)
|
||||
return;
|
||||
auto* view = iwc_view->GetView();
|
||||
auto view_bounds = view->bounds();
|
||||
@@ -41,7 +41,7 @@ void NativeBrowserViewViews::SetAutoResizeProportions(
|
||||
if ((auto_resize_flags_ & AutoResizeFlags::kAutoResizeVertical) &&
|
||||
!auto_vertical_proportion_set_) {
|
||||
auto* iwc_view = GetInspectableWebContentsView();
|
||||
if (iwc_view)
|
||||
if (!iwc_view)
|
||||
return;
|
||||
auto* view = iwc_view->GetView();
|
||||
auto view_bounds = view->bounds();
|
||||
@@ -58,7 +58,7 @@ void NativeBrowserViewViews::AutoResize(const gfx::Rect& new_window,
|
||||
int width_delta,
|
||||
int height_delta) {
|
||||
auto* iwc_view = GetInspectableWebContentsView();
|
||||
if (iwc_view)
|
||||
if (!iwc_view)
|
||||
return;
|
||||
auto* view = iwc_view->GetView();
|
||||
const auto flags = GetAutoResizeFlags();
|
||||
|
||||
@@ -109,7 +109,7 @@ void NativeWindow::InitFromOptions(const gin_helper::Dictionary& options) {
|
||||
} else {
|
||||
SetSizeConstraints(size_constraints);
|
||||
}
|
||||
#if defined(OS_WIN) || defined(USE_X11)
|
||||
#if defined(OS_WIN) || defined(OS_LINUX)
|
||||
bool resizable;
|
||||
if (options.Get(options::kResizable, &resizable)) {
|
||||
SetResizable(resizable);
|
||||
|
||||
@@ -43,13 +43,17 @@
|
||||
#include "ui/wm/core/shadow_types.h"
|
||||
#include "ui/wm/core/window_util.h"
|
||||
|
||||
#if defined(USE_X11)
|
||||
#if defined(OS_LINUX)
|
||||
#include "base/strings/string_util.h"
|
||||
#include "shell/browser/browser.h"
|
||||
#include "shell/browser/linux/unity_service.h"
|
||||
#include "shell/browser/ui/views/frameless_view.h"
|
||||
#include "shell/browser/ui/views/global_menu_bar_x11.h"
|
||||
#include "shell/browser/ui/views/native_frame_view.h"
|
||||
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h"
|
||||
#include "ui/views/window/native_frame_view.h"
|
||||
|
||||
#if defined(USE_X11)
|
||||
#include "shell/browser/ui/views/global_menu_bar_x11.h"
|
||||
#include "shell/browser/ui/x/event_disabler.h"
|
||||
#include "shell/browser/ui/x/window_state_watcher.h"
|
||||
#include "shell/browser/ui/x/x_window_utils.h"
|
||||
@@ -57,8 +61,12 @@
|
||||
#include "ui/gfx/x/shape.h"
|
||||
#include "ui/gfx/x/x11_atom_cache.h"
|
||||
#include "ui/gfx/x/x11_types.h"
|
||||
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h"
|
||||
#include "ui/views/window/native_frame_view.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_OZONE) || defined(USE_X11)
|
||||
#include "ui/base/ui_base_features.h"
|
||||
#endif
|
||||
|
||||
#elif defined(OS_WIN)
|
||||
#include "base/win/win_util.h"
|
||||
#include "shell/browser/ui/views/win_frame_view.h"
|
||||
@@ -211,45 +219,56 @@ NativeWindowViews::NativeWindowViews(const gin_helper::Dictionary& options,
|
||||
options.Get(options::kType, &window_type);
|
||||
|
||||
#if defined(USE_X11)
|
||||
// Start monitoring window states.
|
||||
window_state_watcher_ = std::make_unique<WindowStateWatcher>(this);
|
||||
if (!features::IsUsingOzonePlatform()) {
|
||||
// Start monitoring window states.
|
||||
window_state_watcher_ = std::make_unique<WindowStateWatcher>(this);
|
||||
|
||||
// Set _GTK_THEME_VARIANT to dark if we have "dark-theme" option set.
|
||||
bool use_dark_theme = false;
|
||||
if (options.Get(options::kDarkTheme, &use_dark_theme) && use_dark_theme) {
|
||||
SetGTKDarkThemeEnabled(use_dark_theme);
|
||||
// Set _GTK_THEME_VARIANT to dark if we have "dark-theme" option set.
|
||||
bool use_dark_theme = false;
|
||||
if (options.Get(options::kDarkTheme, &use_dark_theme) && use_dark_theme) {
|
||||
SetGTKDarkThemeEnabled(use_dark_theme);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Before the window is mapped the SetWMSpecState can not work, so we have
|
||||
// to manually set the _NET_WM_STATE.
|
||||
std::vector<x11::Atom> state_atom_list;
|
||||
bool skip_taskbar = false;
|
||||
if (options.Get(options::kSkipTaskbar, &skip_taskbar) && skip_taskbar) {
|
||||
state_atom_list.push_back(gfx::GetAtom("_NET_WM_STATE_SKIP_TASKBAR"));
|
||||
}
|
||||
|
||||
// Before the window is mapped, there is no SHOW_FULLSCREEN_STATE.
|
||||
if (fullscreen) {
|
||||
state_atom_list.push_back(gfx::GetAtom("_NET_WM_STATE_FULLSCREEN"));
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
#if defined(OS_LINUX)
|
||||
if (parent)
|
||||
SetParentWindow(parent);
|
||||
// Force using dialog type for child window.
|
||||
window_type = "dialog";
|
||||
// Modal window needs the _NET_WM_STATE_MODAL hint.
|
||||
if (is_modal())
|
||||
state_atom_list.push_back(gfx::GetAtom("_NET_WM_STATE_MODAL"));
|
||||
#endif
|
||||
|
||||
#if defined(USE_X11)
|
||||
if (!features::IsUsingOzonePlatform()) {
|
||||
// Before the window is mapped the SetWMSpecState can not work, so we have
|
||||
// to manually set the _NET_WM_STATE.
|
||||
std::vector<x11::Atom> state_atom_list;
|
||||
bool skip_taskbar = false;
|
||||
if (options.Get(options::kSkipTaskbar, &skip_taskbar) && skip_taskbar) {
|
||||
state_atom_list.push_back(gfx::GetAtom("_NET_WM_STATE_SKIP_TASKBAR"));
|
||||
}
|
||||
|
||||
// Before the window is mapped, there is no SHOW_FULLSCREEN_STATE.
|
||||
if (fullscreen) {
|
||||
state_atom_list.push_back(gfx::GetAtom("_NET_WM_STATE_FULLSCREEN"));
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
// Force using dialog type for child window.
|
||||
window_type = "dialog";
|
||||
|
||||
// Modal window needs the _NET_WM_STATE_MODAL hint.
|
||||
if (is_modal())
|
||||
state_atom_list.push_back(gfx::GetAtom("_NET_WM_STATE_MODAL"));
|
||||
}
|
||||
|
||||
if (!state_atom_list.empty())
|
||||
ui::SetAtomArrayProperty(static_cast<x11::Window>(GetAcceleratedWidget()),
|
||||
"_NET_WM_STATE", "ATOM", state_atom_list);
|
||||
|
||||
// Set the _NET_WM_WINDOW_TYPE.
|
||||
if (!window_type.empty())
|
||||
SetWindowType(static_cast<x11::Window>(GetAcceleratedWidget()),
|
||||
window_type);
|
||||
}
|
||||
|
||||
if (!state_atom_list.empty())
|
||||
ui::SetAtomArrayProperty(static_cast<x11::Window>(GetAcceleratedWidget()),
|
||||
"_NET_WM_STATE", "ATOM", state_atom_list);
|
||||
|
||||
// Set the _NET_WM_WINDOW_TYPE.
|
||||
if (!window_type.empty())
|
||||
SetWindowType(static_cast<x11::Window>(GetAcceleratedWidget()),
|
||||
window_type);
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
@@ -331,14 +350,11 @@ NativeWindowViews::~NativeWindowViews() {
|
||||
|
||||
void NativeWindowViews::SetGTKDarkThemeEnabled(bool use_dark_theme) {
|
||||
#if defined(USE_X11)
|
||||
if (use_dark_theme) {
|
||||
if (!features::IsUsingOzonePlatform()) {
|
||||
const std::string color = use_dark_theme ? "dark" : "light";
|
||||
ui::SetStringProperty(static_cast<x11::Window>(GetAcceleratedWidget()),
|
||||
gfx::GetAtom("_GTK_THEME_VARIANT"),
|
||||
gfx::GetAtom("UTF8_STRING"), "dark");
|
||||
} else {
|
||||
ui::SetStringProperty(static_cast<x11::Window>(GetAcceleratedWidget()),
|
||||
gfx::GetAtom("_GTK_THEME_VARIANT"),
|
||||
gfx::GetAtom("UTF8_STRING"), "light");
|
||||
gfx::GetAtom("UTF8_STRING"), color);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -395,7 +411,7 @@ void NativeWindowViews::Show() {
|
||||
NotifyWindowShow();
|
||||
|
||||
#if defined(USE_X11)
|
||||
if (global_menu_bar_)
|
||||
if (!features::IsUsingOzonePlatform() && global_menu_bar_)
|
||||
global_menu_bar_->OnWindowMapped();
|
||||
#endif
|
||||
}
|
||||
@@ -406,7 +422,7 @@ void NativeWindowViews::ShowInactive() {
|
||||
NotifyWindowShow();
|
||||
|
||||
#if defined(USE_X11)
|
||||
if (global_menu_bar_)
|
||||
if (!features::IsUsingOzonePlatform() && global_menu_bar_)
|
||||
global_menu_bar_->OnWindowMapped();
|
||||
#endif
|
||||
}
|
||||
@@ -420,7 +436,7 @@ void NativeWindowViews::Hide() {
|
||||
NotifyWindowHide();
|
||||
|
||||
#if defined(USE_X11)
|
||||
if (global_menu_bar_)
|
||||
if (!features::IsUsingOzonePlatform() && global_menu_bar_)
|
||||
global_menu_bar_->OnWindowUnmapped();
|
||||
#endif
|
||||
}
|
||||
@@ -432,8 +448,14 @@ bool NativeWindowViews::IsVisible() {
|
||||
bool NativeWindowViews::IsEnabled() {
|
||||
#if defined(OS_WIN)
|
||||
return ::IsWindowEnabled(GetAcceleratedWidget());
|
||||
#elif defined(USE_X11)
|
||||
return !event_disabler_.get();
|
||||
#elif defined(OS_LINUX)
|
||||
#if defined(USE_X11)
|
||||
if (!features::IsUsingOzonePlatform()) {
|
||||
return !event_disabler_.get();
|
||||
}
|
||||
#endif
|
||||
NOTIMPLEMENTED();
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -470,15 +492,17 @@ void NativeWindowViews::SetEnabledInternal(bool enable) {
|
||||
#if defined(OS_WIN)
|
||||
::EnableWindow(GetAcceleratedWidget(), enable);
|
||||
#elif defined(USE_X11)
|
||||
views::DesktopWindowTreeHostPlatform* tree_host =
|
||||
views::DesktopWindowTreeHostLinux::GetHostForWidget(
|
||||
GetAcceleratedWidget());
|
||||
if (enable) {
|
||||
tree_host->RemoveEventRewriter(event_disabler_.get());
|
||||
event_disabler_.reset();
|
||||
} else {
|
||||
event_disabler_ = std::make_unique<EventDisabler>();
|
||||
tree_host->AddEventRewriter(event_disabler_.get());
|
||||
if (!features::IsUsingOzonePlatform()) {
|
||||
views::DesktopWindowTreeHostPlatform* tree_host =
|
||||
views::DesktopWindowTreeHostLinux::GetHostForWidget(
|
||||
GetAcceleratedWidget());
|
||||
if (enable) {
|
||||
tree_host->RemoveEventRewriter(event_disabler_.get());
|
||||
event_disabler_.reset();
|
||||
} else {
|
||||
event_disabler_ = std::make_unique<EventDisabler>();
|
||||
tree_host->AddEventRewriter(event_disabler_.get());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -584,7 +608,7 @@ bool NativeWindowViews::IsFullscreen() const {
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetBounds(const gfx::Rect& bounds, bool animate) {
|
||||
#if defined(OS_WIN) || defined(USE_X11)
|
||||
#if defined(OS_WIN) || defined(OS_LINUX)
|
||||
// On Linux and Windows the minimum and maximum size should be updated with
|
||||
// window size when window is not resizable.
|
||||
if (!resizable_) {
|
||||
@@ -675,11 +699,13 @@ bool NativeWindowViews::MoveAbove(const std::string& sourceId) {
|
||||
0, 0, 0,
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
|
||||
#elif defined(USE_X11)
|
||||
if (!IsWindowValid(static_cast<x11::Window>(id.id)))
|
||||
return false;
|
||||
if (!features::IsUsingOzonePlatform()) {
|
||||
if (!IsWindowValid(static_cast<x11::Window>(id.id)))
|
||||
return false;
|
||||
|
||||
electron::MoveWindowAbove(static_cast<x11::Window>(GetAcceleratedWidget()),
|
||||
static_cast<x11::Window>(id.id));
|
||||
electron::MoveWindowAbove(static_cast<x11::Window>(GetAcceleratedWidget()),
|
||||
static_cast<x11::Window>(id.id));
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@@ -695,8 +721,10 @@ void NativeWindowViews::MoveTop() {
|
||||
size.width(), size.height(),
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
|
||||
#elif defined(USE_X11)
|
||||
electron::MoveWindowToForeground(
|
||||
static_cast<x11::Window>(GetAcceleratedWidget()));
|
||||
if (!features::IsUsingOzonePlatform()) {
|
||||
electron::MoveWindowToForeground(
|
||||
static_cast<x11::Window>(GetAcceleratedWidget()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -881,8 +909,10 @@ void NativeWindowViews::SetSkipTaskbar(bool skip) {
|
||||
taskbar_host_.RestoreThumbarButtons(GetAcceleratedWidget());
|
||||
}
|
||||
#elif defined(USE_X11)
|
||||
SetWMSpecState(static_cast<x11::Window>(GetAcceleratedWidget()), skip,
|
||||
gfx::GetAtom("_NET_WM_STATE_SKIP_TASKBAR"));
|
||||
if (!features::IsUsingOzonePlatform()) {
|
||||
SetWMSpecState(static_cast<x11::Window>(GetAcceleratedWidget()), skip,
|
||||
gfx::GetAtom("_NET_WM_STATE_SKIP_TASKBAR"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -980,23 +1010,27 @@ void NativeWindowViews::SetIgnoreMouseEvents(bool ignore, bool forward) {
|
||||
SetForwardMouseMessages(forward);
|
||||
}
|
||||
#elif defined(USE_X11)
|
||||
auto* connection = x11::Connection::Get();
|
||||
if (ignore) {
|
||||
x11::Rectangle r{0, 0, 1, 1};
|
||||
connection->shape().Rectangles({
|
||||
.operation = x11::Shape::So::Set,
|
||||
.destination_kind = x11::Shape::Sk::Input,
|
||||
.ordering = x11::ClipOrdering::YXBanded,
|
||||
.destination_window = static_cast<x11::Window>(GetAcceleratedWidget()),
|
||||
.rectangles = {r},
|
||||
});
|
||||
} else {
|
||||
connection->shape().Mask({
|
||||
.operation = x11::Shape::So::Set,
|
||||
.destination_kind = x11::Shape::Sk::Input,
|
||||
.destination_window = static_cast<x11::Window>(GetAcceleratedWidget()),
|
||||
.source_bitmap = x11::Pixmap::None,
|
||||
});
|
||||
if (!features::IsUsingOzonePlatform()) {
|
||||
auto* connection = x11::Connection::Get();
|
||||
if (ignore) {
|
||||
x11::Rectangle r{0, 0, 1, 1};
|
||||
connection->shape().Rectangles({
|
||||
.operation = x11::Shape::So::Set,
|
||||
.destination_kind = x11::Shape::Sk::Input,
|
||||
.ordering = x11::ClipOrdering::YXBanded,
|
||||
.destination_window =
|
||||
static_cast<x11::Window>(GetAcceleratedWidget()),
|
||||
.rectangles = {r},
|
||||
});
|
||||
} else {
|
||||
connection->shape().Mask({
|
||||
.operation = x11::Shape::So::Set,
|
||||
.destination_kind = x11::Shape::Sk::Input,
|
||||
.destination_window =
|
||||
static_cast<x11::Window>(GetAcceleratedWidget()),
|
||||
.source_bitmap = x11::Pixmap::None,
|
||||
});
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1024,22 +1058,24 @@ void NativeWindowViews::SetFocusable(bool focusable) {
|
||||
|
||||
void NativeWindowViews::SetMenu(ElectronMenuModel* menu_model) {
|
||||
#if defined(USE_X11)
|
||||
// Remove global menu bar.
|
||||
if (global_menu_bar_ && menu_model == nullptr) {
|
||||
global_menu_bar_.reset();
|
||||
root_view_->UnregisterAcceleratorsWithFocusManager();
|
||||
return;
|
||||
}
|
||||
|
||||
// Use global application menu bar when possible.
|
||||
if (ShouldUseGlobalMenuBar()) {
|
||||
if (!global_menu_bar_)
|
||||
global_menu_bar_ = std::make_unique<GlobalMenuBarX11>(this);
|
||||
if (global_menu_bar_->IsServerStarted()) {
|
||||
root_view_->RegisterAcceleratorsWithFocusManager(menu_model);
|
||||
global_menu_bar_->SetMenu(menu_model);
|
||||
if (!features::IsUsingOzonePlatform()) {
|
||||
// Remove global menu bar.
|
||||
if (global_menu_bar_ && menu_model == nullptr) {
|
||||
global_menu_bar_.reset();
|
||||
root_view_->UnregisterAcceleratorsWithFocusManager();
|
||||
return;
|
||||
}
|
||||
|
||||
// Use global application menu bar when possible.
|
||||
if (ShouldUseGlobalMenuBar()) {
|
||||
if (!global_menu_bar_)
|
||||
global_menu_bar_ = std::make_unique<GlobalMenuBarX11>(this);
|
||||
if (global_menu_bar_->IsServerStarted()) {
|
||||
root_view_->RegisterAcceleratorsWithFocusManager(menu_model);
|
||||
global_menu_bar_->SetMenu(menu_model);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1104,11 +1140,13 @@ void NativeWindowViews::SetParentWindow(NativeWindow* parent) {
|
||||
NativeWindow::SetParentWindow(parent);
|
||||
|
||||
#if defined(USE_X11)
|
||||
ui::SetProperty(static_cast<x11::Window>(GetAcceleratedWidget()),
|
||||
x11::Atom::WM_TRANSIENT_FOR, x11::Atom::WINDOW,
|
||||
parent
|
||||
? static_cast<x11::Window>(parent->GetAcceleratedWidget())
|
||||
: ui::GetX11RootWindow());
|
||||
if (!features::IsUsingOzonePlatform()) {
|
||||
ui::SetProperty(
|
||||
static_cast<x11::Window>(GetAcceleratedWidget()),
|
||||
x11::Atom::WM_TRANSIENT_FOR, x11::Atom::WINDOW,
|
||||
parent ? static_cast<x11::Window>(parent->GetAcceleratedWidget())
|
||||
: ui::GetX11RootWindow());
|
||||
}
|
||||
#elif defined(OS_WIN)
|
||||
// To set parentship between windows into Windows is better to play with the
|
||||
// owner instead of the parent, as Windows natively seems to do if a parent
|
||||
@@ -1183,14 +1221,16 @@ void NativeWindowViews::SetVisibleOnAllWorkspaces(bool visible,
|
||||
|
||||
bool NativeWindowViews::IsVisibleOnAllWorkspaces() {
|
||||
#if defined(USE_X11)
|
||||
// Use the presence/absence of _NET_WM_STATE_STICKY in _NET_WM_STATE to
|
||||
// determine whether the current window is visible on all workspaces.
|
||||
x11::Atom sticky_atom = gfx::GetAtom("_NET_WM_STATE_STICKY");
|
||||
std::vector<x11::Atom> wm_states;
|
||||
ui::GetAtomArrayProperty(static_cast<x11::Window>(GetAcceleratedWidget()),
|
||||
"_NET_WM_STATE", &wm_states);
|
||||
return std::find(wm_states.begin(), wm_states.end(), sticky_atom) !=
|
||||
wm_states.end();
|
||||
if (!features::IsUsingOzonePlatform()) {
|
||||
// Use the presence/absence of _NET_WM_STATE_STICKY in _NET_WM_STATE to
|
||||
// determine whether the current window is visible on all workspaces.
|
||||
x11::Atom sticky_atom = gfx::GetAtom("_NET_WM_STATE_STICKY");
|
||||
std::vector<x11::Atom> wm_states;
|
||||
ui::GetAtomArrayProperty(static_cast<x11::Window>(GetAcceleratedWidget()),
|
||||
"_NET_WM_STATE", &wm_states);
|
||||
return std::find(wm_states.begin(), wm_states.end(), sticky_atom) !=
|
||||
wm_states.end();
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 12,0,0,20201019
|
||||
PRODUCTVERSION 12,0,0,20201019
|
||||
FILEVERSION 12,0,0,20201021
|
||||
PRODUCTVERSION 12,0,0,20201021
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
@@ -77,11 +77,13 @@ SerialChooserController::SerialChooserController(
|
||||
DCHECK(chooser_context_);
|
||||
chooser_context_->GetPortManager()->GetDevices(base::BindOnce(
|
||||
&SerialChooserController::OnGetDevices, weak_factory_.GetWeakPtr()));
|
||||
observer_.Add(chooser_context_.get());
|
||||
}
|
||||
|
||||
SerialChooserController::~SerialChooserController() {
|
||||
RunCallback(/*port=*/nullptr);
|
||||
if (chooser_context_) {
|
||||
chooser_context_->RemovePortObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
api::Session* SerialChooserController::GetSession() {
|
||||
@@ -114,10 +116,6 @@ void SerialChooserController::OnPortRemoved(
|
||||
}
|
||||
}
|
||||
|
||||
void SerialChooserController::OnPortManagerConnectionError() {
|
||||
observer_.RemoveAll();
|
||||
}
|
||||
|
||||
void SerialChooserController::OnDeviceChosen(const std::string& port_id) {
|
||||
if (port_id.empty()) {
|
||||
RunCallback(/*port=*/nullptr);
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/scoped_observer.h"
|
||||
#include "base/strings/string16.h"
|
||||
#include "content/public/browser/serial_chooser.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
@@ -44,7 +43,7 @@ class SerialChooserController final : public SerialChooserContext::PortObserver,
|
||||
// SerialChooserContext::PortObserver:
|
||||
void OnPortAdded(const device::mojom::SerialPortInfo& port) override;
|
||||
void OnPortRemoved(const device::mojom::SerialPortInfo& port) override;
|
||||
void OnPortManagerConnectionError() override;
|
||||
void OnPortManagerConnectionError() override {}
|
||||
|
||||
private:
|
||||
api::Session* GetSession();
|
||||
@@ -59,11 +58,6 @@ class SerialChooserController final : public SerialChooserContext::PortObserver,
|
||||
url::Origin embedding_origin_;
|
||||
|
||||
base::WeakPtr<SerialChooserContext> chooser_context_;
|
||||
ScopedObserver<SerialChooserContext,
|
||||
SerialChooserContext::PortObserver,
|
||||
&SerialChooserContext::AddPortObserver,
|
||||
&SerialChooserContext::RemovePortObserver>
|
||||
observer_{this};
|
||||
|
||||
std::vector<device::mojom::SerialPortInfoPtr> ports_;
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ class ElectronMenuModel;
|
||||
// allow for hierarchical menus). The tag is the index into that model for
|
||||
// that particular item. It is important that the model outlives this object
|
||||
// as it only maintains weak references.
|
||||
@interface ElectronMenuController : NSObject <NSMenuDelegate> {
|
||||
@interface ElectronMenuController
|
||||
: NSObject <NSMenuDelegate, NSSharingServiceDelegate> {
|
||||
@protected
|
||||
base::WeakPtr<electron::ElectronMenuModel> model_;
|
||||
base::scoped_nsobject<NSMenu> menu_;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#import "shell/browser/ui/cocoa/electron_menu_controller.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "base/logging.h"
|
||||
@@ -14,8 +15,11 @@
|
||||
#include "base/task/post_task.h"
|
||||
#include "content/public/browser/browser_task_traits.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "net/base/mac/url_conversions.h"
|
||||
#include "shell/browser/mac/electron_application.h"
|
||||
#include "shell/browser/native_window.h"
|
||||
#include "shell/browser/ui/electron_menu_model.h"
|
||||
#include "shell/browser/window_list.h"
|
||||
#include "ui/base/accelerators/accelerator.h"
|
||||
#include "ui/base/accelerators/platform_accelerator_cocoa.h"
|
||||
#include "ui/base/l10n/l10n_util_mac.h"
|
||||
@@ -24,6 +28,7 @@
|
||||
#include "ui/strings/grit/ui_strings.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
using SharingItem = electron::ElectronMenuModel::SharingItem;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -86,6 +91,24 @@ NSMenu* MakeEmptySubmenu() {
|
||||
return submenu.autorelease();
|
||||
}
|
||||
|
||||
// Convert an SharingItem to an array of NSObjects.
|
||||
NSArray* ConvertSharingItemToNS(const SharingItem& item) {
|
||||
NSMutableArray* result = [NSMutableArray array];
|
||||
if (item.texts) {
|
||||
for (const std::string& str : *item.texts)
|
||||
[result addObject:base::SysUTF8ToNSString(str)];
|
||||
}
|
||||
if (item.file_paths) {
|
||||
for (const base::FilePath& path : *item.file_paths)
|
||||
[result addObject:base::mac::FilePathToNSURL(path)];
|
||||
}
|
||||
if (item.urls) {
|
||||
for (const GURL& url : *item.urls)
|
||||
[result addObject:net::NSURLWithGURL(url)];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// This class stores a base::WeakPtr<electron::ElectronMenuModel> as an
|
||||
@@ -267,6 +290,31 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
||||
recentDocumentsMenuItem_.reset([item retain]);
|
||||
}
|
||||
|
||||
// Fill the menu with Share Menu items.
|
||||
- (NSMenu*)createShareMenuForItem:(const SharingItem&)item {
|
||||
NSArray* items = ConvertSharingItemToNS(item);
|
||||
if ([items count] == 0)
|
||||
return MakeEmptySubmenu();
|
||||
base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] init]);
|
||||
NSArray* services = [NSSharingService sharingServicesForItems:items];
|
||||
for (NSSharingService* service in services)
|
||||
[menu addItem:[self menuItemForService:service withItems:items]];
|
||||
return menu.autorelease();
|
||||
}
|
||||
|
||||
// Creates a menu item that calls |service| when invoked.
|
||||
- (NSMenuItem*)menuItemForService:(NSSharingService*)service
|
||||
withItems:(NSArray*)items {
|
||||
base::scoped_nsobject<NSMenuItem> item([[NSMenuItem alloc]
|
||||
initWithTitle:service.menuItemTitle
|
||||
action:@selector(performShare:)
|
||||
keyEquivalent:@""]);
|
||||
[item setTarget:self];
|
||||
[item setImage:service.image];
|
||||
[item setRepresentedObject:@{@"service" : service, @"items" : items}];
|
||||
return item.autorelease();
|
||||
}
|
||||
|
||||
// Adds an item or a hierarchical menu to the item at the |index|,
|
||||
// associated with the entry in the model identified by |modelIndex|.
|
||||
- (void)addItemToMenu:(NSMenu*)menu
|
||||
@@ -300,6 +348,12 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
||||
NSMenu* submenu = [[[NSMenu alloc] initWithTitle:label] autorelease];
|
||||
[item setSubmenu:submenu];
|
||||
[NSApp setServicesMenu:submenu];
|
||||
} else if (role == base::ASCIIToUTF16("sharemenu")) {
|
||||
SharingItem sharing_item;
|
||||
model->GetSharingItemAt(index, &sharing_item);
|
||||
[item setTarget:nil];
|
||||
[item setAction:nil];
|
||||
[item setSubmenu:[self createShareMenuForItem:sharing_item]];
|
||||
} else if (type == electron::ElectronMenuModel::TYPE_SUBMENU &&
|
||||
model->IsVisibleAt(index)) {
|
||||
// We need to specifically check that the submenu top-level item has been
|
||||
@@ -372,6 +426,8 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
||||
// radio, etc) of each item in the menu.
|
||||
- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item {
|
||||
SEL action = [item action];
|
||||
if (action == @selector(performShare:))
|
||||
return YES;
|
||||
if (action != @selector(itemSelected:))
|
||||
return NO;
|
||||
|
||||
@@ -405,14 +461,30 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
||||
}
|
||||
}
|
||||
|
||||
// Performs the share action using the sharing service represented by |sender|.
|
||||
- (void)performShare:(NSMenuItem*)sender {
|
||||
NSDictionary* object =
|
||||
base::mac::ObjCCastStrict<NSDictionary>([sender representedObject]);
|
||||
NSSharingService* service =
|
||||
base::mac::ObjCCastStrict<NSSharingService>(object[@"service"]);
|
||||
NSArray* items = base::mac::ObjCCastStrict<NSArray>(object[@"items"]);
|
||||
[service setDelegate:self];
|
||||
[service performWithItems:items];
|
||||
}
|
||||
|
||||
- (NSMenu*)menu {
|
||||
if (menu_)
|
||||
return menu_.get();
|
||||
|
||||
menu_.reset([[NSMenu alloc] initWithTitle:@""]);
|
||||
if (model_ && model_->GetSharingItem()) {
|
||||
NSMenu* menu = [self createShareMenuForItem:*model_->GetSharingItem()];
|
||||
menu_.reset([menu retain]);
|
||||
} else {
|
||||
menu_.reset([[NSMenu alloc] initWithTitle:@""]);
|
||||
if (model_)
|
||||
[self populateWithModel:model_.get()];
|
||||
}
|
||||
[menu_ setDelegate:self];
|
||||
if (model_)
|
||||
[self populateWithModel:model_.get()];
|
||||
return menu_.get();
|
||||
}
|
||||
|
||||
@@ -439,4 +511,18 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
||||
}
|
||||
}
|
||||
|
||||
// NSSharingServiceDelegate
|
||||
|
||||
- (NSWindow*)sharingService:(NSSharingService*)service
|
||||
sourceWindowForShareItems:(NSArray*)items
|
||||
sharingContentScope:(NSSharingContentScope*)scope {
|
||||
// Return the current active window.
|
||||
const auto& list = electron::WindowList::GetWindows();
|
||||
for (electron::NativeWindow* window : list) {
|
||||
if (window->IsFocused())
|
||||
return window->GetNativeWindow().GetNativeNSWindow();
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -4,10 +4,18 @@
|
||||
|
||||
#include "shell/browser/ui/electron_menu_model.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "base/stl_util.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
#if defined(OS_MAC)
|
||||
ElectronMenuModel::SharingItem::SharingItem() = default;
|
||||
ElectronMenuModel::SharingItem::SharingItem(SharingItem&&) = default;
|
||||
ElectronMenuModel::SharingItem::~SharingItem() = default;
|
||||
#endif
|
||||
|
||||
bool ElectronMenuModel::Delegate::GetAcceleratorForCommandId(
|
||||
int command_id,
|
||||
ui::Accelerator* accelerator) const {
|
||||
@@ -79,6 +87,23 @@ bool ElectronMenuModel::WorksWhenHiddenAt(int index) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(OS_MAC)
|
||||
bool ElectronMenuModel::GetSharingItemAt(int index, SharingItem* item) const {
|
||||
if (delegate_)
|
||||
return delegate_->GetSharingItemForCommandId(GetCommandIdAt(index), item);
|
||||
return false;
|
||||
}
|
||||
|
||||
void ElectronMenuModel::SetSharingItem(SharingItem item) {
|
||||
sharing_item_.emplace(std::move(item));
|
||||
}
|
||||
|
||||
const base::Optional<ElectronMenuModel::SharingItem>&
|
||||
ElectronMenuModel::GetSharingItem() const {
|
||||
return sharing_item_;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ElectronMenuModel::MenuWillClose() {
|
||||
ui::SimpleMenuModel::MenuWillClose();
|
||||
for (Observer& observer : observers_) {
|
||||
|
||||
@@ -6,16 +6,34 @@
|
||||
#define SHELL_BROWSER_UI_ELECTRON_MENU_MODEL_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/observer_list.h"
|
||||
#include "base/observer_list_types.h"
|
||||
#include "base/optional.h"
|
||||
#include "ui/base/models/simple_menu_model.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
class ElectronMenuModel : public ui::SimpleMenuModel {
|
||||
public:
|
||||
#if defined(OS_MAC)
|
||||
struct SharingItem {
|
||||
SharingItem();
|
||||
SharingItem(SharingItem&&);
|
||||
SharingItem(const SharingItem&) = delete;
|
||||
~SharingItem();
|
||||
|
||||
base::Optional<std::vector<std::string>> texts;
|
||||
base::Optional<std::vector<GURL>> urls;
|
||||
base::Optional<std::vector<base::FilePath>> file_paths;
|
||||
};
|
||||
#endif
|
||||
|
||||
class Delegate : public ui::SimpleMenuModel::Delegate {
|
||||
public:
|
||||
~Delegate() override {}
|
||||
@@ -30,6 +48,11 @@ class ElectronMenuModel : public ui::SimpleMenuModel {
|
||||
|
||||
virtual bool ShouldCommandIdWorkWhenHidden(int command_id) const = 0;
|
||||
|
||||
#if defined(OS_MAC)
|
||||
virtual bool GetSharingItemForCommandId(int command_id,
|
||||
SharingItem* item) const = 0;
|
||||
#endif
|
||||
|
||||
private:
|
||||
// ui::SimpleMenuModel::Delegate:
|
||||
bool GetAcceleratorForCommandId(
|
||||
@@ -65,6 +88,13 @@ class ElectronMenuModel : public ui::SimpleMenuModel {
|
||||
ui::Accelerator* accelerator) const;
|
||||
bool ShouldRegisterAcceleratorAt(int index) const;
|
||||
bool WorksWhenHiddenAt(int index) const;
|
||||
#if defined(OS_MAC)
|
||||
// Return the SharingItem of menu item.
|
||||
bool GetSharingItemAt(int index, SharingItem* item) const;
|
||||
// Set/Get the SharingItem of this menu.
|
||||
void SetSharingItem(SharingItem item);
|
||||
const base::Optional<SharingItem>& GetSharingItem() const;
|
||||
#endif
|
||||
|
||||
// ui::SimpleMenuModel:
|
||||
void MenuWillClose() override;
|
||||
@@ -80,6 +110,10 @@ class ElectronMenuModel : public ui::SimpleMenuModel {
|
||||
private:
|
||||
Delegate* delegate_; // weak ref.
|
||||
|
||||
#if defined(OS_MAC)
|
||||
base::Optional<SharingItem> sharing_item_;
|
||||
#endif
|
||||
|
||||
std::map<int, base::string16> toolTips_; // command id -> tooltip
|
||||
std::map<int, base::string16> roles_; // command id -> role
|
||||
std::map<int, base::string16> sublabels_; // command id -> sublabel
|
||||
|
||||
@@ -15,9 +15,16 @@
|
||||
#include "shell/browser/unresponsive_suppressor.h"
|
||||
#include "shell/common/gin_converters/file_path_converter.h"
|
||||
#include "ui/base/glib/glib_signal.h"
|
||||
#include "ui/events/platform/x11/x11_event_source.h"
|
||||
#include "ui/gtk/gtk_util.h"
|
||||
|
||||
#if defined(USE_X11)
|
||||
#include "ui/events/platform/x11/x11_event_source.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_OZONE) || defined(USE_X11)
|
||||
#include "ui/base/ui_base_features.h"
|
||||
#endif
|
||||
|
||||
namespace file_dialog {
|
||||
|
||||
DialogSettings::DialogSettings() = default;
|
||||
@@ -135,11 +142,15 @@ class FileChooserDialog {
|
||||
this);
|
||||
gtk_widget_show_all(dialog_);
|
||||
|
||||
// We need to call gtk_window_present after making the widgets visible to
|
||||
// make sure window gets correctly raised and gets focus.
|
||||
x11::Time time = ui::X11EventSource::GetInstance()->GetTimestamp();
|
||||
gtk_window_present_with_time(GTK_WINDOW(dialog_),
|
||||
static_cast<uint32_t>(time));
|
||||
#if defined(USE_X11)
|
||||
if (!features::IsUsingOzonePlatform()) {
|
||||
// We need to call gtk_window_present after making the widgets visible to
|
||||
// make sure window gets correctly raised and gets focus.
|
||||
x11::Time time = ui::X11EventSource::GetInstance()->GetTimestamp();
|
||||
gtk_window_present_with_time(GTK_WINDOW(dialog_),
|
||||
static_cast<uint32_t>(time));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void RunSaveAsynchronous(
|
||||
|
||||
@@ -22,6 +22,10 @@
|
||||
#include "ui/events/event_constants.h"
|
||||
#include "ui/events/keycodes/keyboard_code_conversion_x.h"
|
||||
|
||||
#if defined(USE_OZONE) || defined(USE_X11)
|
||||
#include "ui/base/ui_base_features.h"
|
||||
#endif
|
||||
|
||||
namespace electron {
|
||||
|
||||
namespace gtkui {
|
||||
@@ -222,12 +226,14 @@ void BuildSubmenuFromModel(ui::MenuModel* model,
|
||||
}
|
||||
|
||||
#if defined(USE_X11)
|
||||
ui::Accelerator accelerator;
|
||||
if (model->GetAcceleratorAt(i, &accelerator)) {
|
||||
gtk_widget_add_accelerator(menu_item, "activate", nullptr,
|
||||
GetGdkKeyCodeForAccelerator(accelerator),
|
||||
GetGdkModifierForAccelerator(accelerator),
|
||||
GTK_ACCEL_VISIBLE);
|
||||
if (!features::IsUsingOzonePlatform()) {
|
||||
ui::Accelerator accelerator;
|
||||
if (model->GetAcceleratorAt(i, &accelerator)) {
|
||||
gtk_widget_add_accelerator(menu_item, "activate", nullptr,
|
||||
GetGdkKeyCodeForAccelerator(accelerator),
|
||||
GetGdkModifierForAccelerator(accelerator),
|
||||
GTK_ACCEL_VISIBLE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -13,10 +13,17 @@
|
||||
#include "shell/browser/native_window_views.h"
|
||||
#include "shell/browser/unresponsive_suppressor.h"
|
||||
#include "ui/base/glib/glib_signal.h"
|
||||
#include "ui/events/platform/x11/x11_event_source.h"
|
||||
#include "ui/gfx/image/image_skia.h"
|
||||
#include "ui/gtk/gtk_util.h"
|
||||
|
||||
#if defined(USE_X11)
|
||||
#include "ui/events/platform/x11/x11_event_source.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_OZONE) || defined(USE_X11)
|
||||
#include "ui/base/ui_base_features.h"
|
||||
#endif
|
||||
|
||||
#define ANSI_FOREGROUND_RED "\x1b[31m"
|
||||
#define ANSI_FOREGROUND_BLACK "\x1b[30m"
|
||||
#define ANSI_TEXT_BOLD "\x1b[1m"
|
||||
@@ -133,11 +140,16 @@ class GtkMessageBox : public NativeWindowObserver {
|
||||
|
||||
void Show() {
|
||||
gtk_widget_show(dialog_);
|
||||
// We need to call gtk_window_present after making the widgets visible to
|
||||
// make sure window gets correctly raised and gets focus.
|
||||
x11::Time time = ui::X11EventSource::GetInstance()->GetTimestamp();
|
||||
gtk_window_present_with_time(GTK_WINDOW(dialog_),
|
||||
static_cast<uint32_t>(time));
|
||||
|
||||
#if defined(USE_X11)
|
||||
if (!features::IsUsingOzonePlatform()) {
|
||||
// We need to call gtk_window_present after making the widgets visible to
|
||||
// make sure window gets correctly raised and gets focus.
|
||||
x11::Time time = ui::X11EventSource::GetInstance()->GetTimestamp();
|
||||
gtk_window_present_with_time(GTK_WINDOW(dialog_),
|
||||
static_cast<uint32_t>(time));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int RunSynchronous() {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "ui/views/layout/box_layout.h"
|
||||
#include "ui/views/widget/widget.h"
|
||||
|
||||
#if defined(USE_X11)
|
||||
#if defined(OS_LINUX)
|
||||
#include "ui/gtk/gtk_util.h"
|
||||
#endif
|
||||
|
||||
@@ -282,7 +282,7 @@ void MenuBar::ButtonPressed(views::Button* source, const ui::Event& event) {
|
||||
void MenuBar::RefreshColorCache() {
|
||||
const ui::NativeTheme* theme = GetNativeTheme();
|
||||
if (theme) {
|
||||
#if defined(USE_X11)
|
||||
#if defined(OS_LINUX)
|
||||
background_color_ = gtk::GetBgColor("GtkMenuBar#menubar");
|
||||
enabled_color_ =
|
||||
gtk::GetFgColor("GtkMenuBar#menubar GtkMenuItem#menuitem GtkLabel");
|
||||
@@ -319,7 +319,7 @@ void MenuBar::UpdateViewColors() {
|
||||
// set child colors
|
||||
if (menu_model_ == nullptr)
|
||||
return;
|
||||
#if defined(USE_X11)
|
||||
#if defined(OS_LINUX)
|
||||
const auto& textColor = has_focus_ ? enabled_color_ : disabled_color_;
|
||||
for (auto* child : GetChildrenInZOrder()) {
|
||||
auto* button = static_cast<SubmenuButton*>(child);
|
||||
|
||||
@@ -90,7 +90,7 @@ class MenuBar : public views::AccessiblePaneView,
|
||||
|
||||
void RefreshColorCache();
|
||||
SkColor background_color_;
|
||||
#if defined(USE_X11)
|
||||
#if defined(OS_LINUX)
|
||||
SkColor enabled_color_;
|
||||
SkColor disabled_color_;
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
#define SHELL_COMMON_GIN_HELPER_DICTIONARY_H_
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "base/optional.h"
|
||||
#include "gin/dictionary.h"
|
||||
#include "shell/common/gin_converters/std_converter.h"
|
||||
#include "shell/common/gin_helper/function_template.h"
|
||||
@@ -59,6 +61,18 @@ class Dictionary : public gin::Dictionary {
|
||||
return !result.IsNothing() && result.FromJust();
|
||||
}
|
||||
|
||||
// Like normal Get but put result in an base::Optional.
|
||||
template <typename T>
|
||||
bool GetOptional(base::StringPiece key, base::Optional<T>* out) const {
|
||||
T ret;
|
||||
if (Get(key, &ret)) {
|
||||
out->emplace(std::move(ret));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool GetHidden(base::StringPiece key, T* out) const {
|
||||
v8::Local<v8::Context> context = isolate()->GetCurrentContext();
|
||||
|
||||
@@ -166,8 +166,8 @@ bool AllowWasmCodeGenerationCallback(v8::Local<v8::Context> context,
|
||||
context, v8::String::Empty(isolate));
|
||||
}
|
||||
|
||||
return node::Environment::AllowWasmCodeGenerationCallback(
|
||||
context, v8::String::Empty(isolate));
|
||||
return node::AllowWasmCodeGenerationCallback(context,
|
||||
v8::String::Empty(isolate));
|
||||
}
|
||||
|
||||
// Initialize Node.js cli options to pass to Node.js
|
||||
@@ -424,7 +424,7 @@ node::Environment* NodeBindings::CreateEnvironment(
|
||||
DCHECK(env);
|
||||
|
||||
// This will only be caught when something has gone terrible wrong as all
|
||||
// electron scripts are wrapped in a try {} catch {} in run-compiler.js
|
||||
// electron scripts are wrapped in a try {} catch {} by webpack
|
||||
if (try_catch.HasCaught()) {
|
||||
LOG(ERROR) << "Failed to initialize node environment in process: "
|
||||
<< process_type;
|
||||
|
||||
@@ -29,7 +29,7 @@ v8::MaybeLocal<v8::Value> CompileAndCall(
|
||||
v8::MaybeLocal<v8::Value> ret = fn->Call(
|
||||
context, v8::Null(isolate), arguments->size(), arguments->data());
|
||||
// This will only be caught when something has gone terrible wrong as all
|
||||
// electron scripts are wrapped in a try {} catch {} in run-compiler.js
|
||||
// electron scripts are wrapped in a try {} catch {} by webpack
|
||||
if (try_catch.HasCaught()) {
|
||||
LOG(ERROR) << "Failed to CompileAndCall electron script: " << id;
|
||||
}
|
||||
|
||||
@@ -1500,6 +1500,16 @@ describe('net module', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('net.isOnline', () => {
|
||||
it('getter returns boolean', () => {
|
||||
expect(net.isOnline()).to.be.a('boolean');
|
||||
});
|
||||
|
||||
it('property returns boolean', () => {
|
||||
expect(net.online).to.be.a('boolean');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Stability and performance', () => {
|
||||
it('should free unreferenced, never-started request objects without crash', (done) => {
|
||||
net.request('https://test');
|
||||
|
||||
@@ -7,6 +7,7 @@ import { v4 } from 'uuid';
|
||||
import { AddressInfo } from 'net';
|
||||
import { closeWindow } from './window-helpers';
|
||||
import { emittedOnce, emittedNTimes } from './events-helpers';
|
||||
import { ifdescribe } from './spec-helpers';
|
||||
|
||||
const partition = 'service-workers-spec';
|
||||
const uuid = v4();
|
||||
@@ -65,7 +66,8 @@ describe('session.serviceWorkers', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFromVersionID()', () => {
|
||||
// TODO (jkleinsc) - reenable this test once https://github.com/electron/electron/issues/26043 is resolved
|
||||
ifdescribe(!process.arch.includes('arm'))('getFromVersionID()', () => {
|
||||
it('should report the correct script url and scope', async () => {
|
||||
const eventInfo = await emittedOnce(ses.serviceWorkers, 'console-message', () => w.loadURL(`${baseUrl}/index.html`));
|
||||
const details: Electron.MessageDetails = eventInfo[1];
|
||||
|
||||
@@ -1375,7 +1375,8 @@ describe('webContents module', () => {
|
||||
}
|
||||
});
|
||||
|
||||
describe('did-change-theme-color event', () => {
|
||||
// TODO (jkleinsc) - reenable this test on WOA once https://github.com/electron/electron/issues/26045 is resolved
|
||||
ifdescribe(process.platform !== 'win32' || process.arch !== 'arm64')('did-change-theme-color event', () => {
|
||||
afterEach(closeAllWindows);
|
||||
it('is triggered with correct theme color', (done) => {
|
||||
const w = new BrowserWindow({ show: true });
|
||||
|
||||
@@ -986,7 +986,8 @@ describe('<webview> tag', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('did-change-theme-color event', () => {
|
||||
// TODO (jkleinsc) - reenable this test on WOA once https://github.com/electron/electron/issues/26045 is resolved
|
||||
ifdescribe(process.platform !== 'win32' || process.arch !== 'arm64')('did-change-theme-color event', () => {
|
||||
it('emits when theme color changes', async () => {
|
||||
loadWebView(webview, {
|
||||
src: `file://${fixtures}/pages/theme-color.html`
|
||||
|
||||
1
typings/internal-ambient.d.ts
vendored
1
typings/internal-ambient.d.ts
vendored
@@ -194,6 +194,7 @@ declare namespace NodeJS {
|
||||
createPair(): { port1: Electron.MessagePortMain, port2: Electron.MessagePortMain };
|
||||
};
|
||||
_linkedBinding(name: 'electron_browser_net'): {
|
||||
isOnline(): boolean;
|
||||
isValidHeaderName: (headerName: string) => boolean;
|
||||
isValidHeaderValue: (headerValue: string) => boolean;
|
||||
Net: any;
|
||||
|
||||
1
typings/internal-electron.d.ts
vendored
1
typings/internal-electron.d.ts
vendored
@@ -108,6 +108,7 @@ declare namespace Electron {
|
||||
_isCommandIdVisible(id: string): boolean;
|
||||
_getAcceleratorForCommandId(id: string, useDefaultAccelerator: boolean): Accelerator | undefined;
|
||||
_shouldRegisterAcceleratorForCommandId(id: string): boolean;
|
||||
_getSharingItemForCommandId(id: string): SharingItem | null;
|
||||
_callMenuWillShow(): void;
|
||||
_executeCommand(event: any, id: number): void;
|
||||
_menuWillShow(): void;
|
||||
|
||||
@@ -8151,7 +8151,7 @@ webpack-cli@^3.3.12:
|
||||
v8-compile-cache "^2.1.1"
|
||||
yargs "^13.3.2"
|
||||
|
||||
webpack-sources@^1.4.0, webpack-sources@^1.4.1:
|
||||
webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1:
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
|
||||
integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==
|
||||
@@ -8257,6 +8257,13 @@ wrapped@^1.0.1:
|
||||
co "3.1.0"
|
||||
sliced "^1.0.1"
|
||||
|
||||
wrapper-webpack-plugin@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/wrapper-webpack-plugin/-/wrapper-webpack-plugin-2.1.0.tgz#2b5d80f46af84c9eeb707d08796a115e233adeac"
|
||||
integrity sha512-e+2FhSYGCxhDq3PcUw5mRhH+8vcYa+9d9AuLChJUZ9ZbUPhQOHZ/O2dnN98iTqeUuvrzSSOv13+x/NhrAm5JEg==
|
||||
dependencies:
|
||||
webpack-sources "^1.1.0"
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
|
||||
Reference in New Issue
Block a user