mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
27 Commits
v15.0.0-be
...
v15.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3e6746fa9 | ||
|
|
436c3ba644 | ||
|
|
599babae00 | ||
|
|
5f7da14447 | ||
|
|
dc6f951f43 | ||
|
|
f4fa6c0cf4 | ||
|
|
98de50451a | ||
|
|
c78ab7a1f2 | ||
|
|
0928f322fa | ||
|
|
c6c59bf0b3 | ||
|
|
9d3bcfc559 | ||
|
|
fb2473bb5e | ||
|
|
4664b5da57 | ||
|
|
18c5401d08 | ||
|
|
3f81697e48 | ||
|
|
a00a43ba25 | ||
|
|
ce1435be30 | ||
|
|
c625b77bde | ||
|
|
4969c4ab19 | ||
|
|
9e1736f5bc | ||
|
|
200e26c602 | ||
|
|
bbc4545742 | ||
|
|
9874e940ab | ||
|
|
304453fa5c | ||
|
|
16a32a30d9 | ||
|
|
a227474809 | ||
|
|
3a2055ebba |
@@ -1209,6 +1209,9 @@ steps-tests: &steps-tests
|
||||
(cd electron && node script/yarn test --runners=main --trace-uncaught --enable-logging)
|
||||
(cd electron && node script/yarn test --runners=remote --trace-uncaught --enable-logging)
|
||||
else
|
||||
if [ "$TARGET_ARCH" == "ia32" ]; then
|
||||
npm_config_arch=x64 node electron/node_modules/dugite/script/download-git.js
|
||||
fi
|
||||
(cd electron && node script/yarn test --runners=main --trace-uncaught --enable-logging --files $(circleci tests glob spec-main/*-spec.ts | circleci tests split --split-by=timings))
|
||||
(cd electron && node script/yarn test --runners=remote --trace-uncaught --enable-logging --files $(circleci tests glob spec/*-spec.js | circleci tests split --split-by=timings))
|
||||
fi
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -26,6 +26,7 @@ compile_commands.json
|
||||
# npm package
|
||||
/npm/dist
|
||||
/npm/path.txt
|
||||
/npm/checksums.json
|
||||
|
||||
.npmrc
|
||||
|
||||
|
||||
2
DEPS
2
DEPS
@@ -15,7 +15,7 @@ gclient_gn_args = [
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'94.0.4606.31',
|
||||
'94.0.4606.51',
|
||||
'node_version':
|
||||
'v16.5.0',
|
||||
'nan_version':
|
||||
|
||||
@@ -1 +1 @@
|
||||
15.0.0-beta.6
|
||||
15.0.0
|
||||
@@ -2,7 +2,7 @@ is_electron_build = true
|
||||
root_extra_deps = [ "//electron" ]
|
||||
|
||||
# Registry of NMVs --> https://github.com/nodejs/node/blob/master/doc/abi_version_registry.json
|
||||
node_module_version = 89
|
||||
node_module_version = 98
|
||||
|
||||
v8_promise_internal_field_count = 1
|
||||
v8_typed_array_max_size_in_heap = 0
|
||||
|
||||
@@ -314,17 +314,13 @@ source_set("plugins") {
|
||||
sources += [
|
||||
"//chrome/renderer/pepper/chrome_renderer_pepper_host_factory.cc",
|
||||
"//chrome/renderer/pepper/chrome_renderer_pepper_host_factory.h",
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.cc",
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.h",
|
||||
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.cc",
|
||||
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.h",
|
||||
]
|
||||
if (enable_pdf_viewer) {
|
||||
sources += [
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.cc",
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.h",
|
||||
]
|
||||
if (enable_pdf_viewer) {
|
||||
deps += [ "//components/pdf/renderer" ]
|
||||
}
|
||||
deps += [ "//components/pdf/renderer" ]
|
||||
}
|
||||
deps += [
|
||||
"//components/strings",
|
||||
|
||||
@@ -22,12 +22,13 @@ win.loadFile('index.html')
|
||||
To create a window without chrome, or a transparent window in arbitrary shape,
|
||||
you can use the [Frameless Window](frameless-window.md) API.
|
||||
|
||||
## Showing window gracefully
|
||||
## Showing the window gracefully
|
||||
|
||||
When loading a page in the window directly, users may see the page load incrementally, which is not a good experience for a native app. To make the window display
|
||||
without visual flash, there are two solutions for different situations.
|
||||
When loading a page in the window directly, users may see the page load incrementally,
|
||||
which is not a good experience for a native app. To make the window display
|
||||
without a visual flash, there are two solutions for different situations.
|
||||
|
||||
## Using `ready-to-show` event
|
||||
### Using the `ready-to-show` event
|
||||
|
||||
While loading the page, the `ready-to-show` event will be emitted when the renderer
|
||||
process has rendered the page for the first time if the window has not been shown yet. Showing
|
||||
@@ -48,7 +49,7 @@ event.
|
||||
Please note that using this event implies that the renderer will be considered "visible" and
|
||||
paint even though `show` is false. This event will never fire if you use `paintWhenInitiallyHidden: false`
|
||||
|
||||
## Setting `backgroundColor`
|
||||
### Setting the `backgroundColor` property
|
||||
|
||||
For a complex app, the `ready-to-show` event could be emitted too late, making
|
||||
the app feel slow. In this case, it is recommended to show the window
|
||||
|
||||
@@ -86,8 +86,8 @@ available from next tick of the process.
|
||||
const { session } = require('electron')
|
||||
session.defaultSession.on('will-download', (event, item, webContents) => {
|
||||
event.preventDefault()
|
||||
require('request')(item.getURL(), (data) => {
|
||||
require('fs').writeFileSync('/somewhere', data)
|
||||
require('got')(item.getURL()).then((response) => {
|
||||
require('fs').writeFileSync('/somewhere', response.body)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
@@ -4,39 +4,38 @@
|
||||
|
||||
Context Isolation is a feature that ensures that both your `preload` scripts and Electron's internal logic run in a separate context to the website you load in a [`webContents`](../api/web-contents.md). This is important for security purposes as it helps prevent the website from accessing Electron internals or the powerful APIs your preload script has access to.
|
||||
|
||||
This means that the `window` object that your preload script has access to is actually a **different** object than the website would have access to. For example, if you set `window.hello = 'wave'` in your preload script and context isolation is enabled `window.hello` will be undefined if the website tries to access it.
|
||||
This means that the `window` object that your preload script has access to is actually a **different** object than the website would have access to. For example, if you set `window.hello = 'wave'` in your preload script and context isolation is enabled, `window.hello` will be undefined if the website tries to access it.
|
||||
|
||||
Every single application should have context isolation enabled and from Electron 12 it will be enabled by default.
|
||||
|
||||
## How do I enable it?
|
||||
|
||||
From Electron 12, it will be enabled by default. For lower versions it is an option in the `webPreferences` option when constructing `new BrowserWindow`'s.
|
||||
|
||||
```javascript
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
contextIsolation: true
|
||||
}
|
||||
})
|
||||
```
|
||||
Context isolation has been enabled by default since Electron 12, and it is a recommended security setting for _all applications_.
|
||||
|
||||
## Migration
|
||||
|
||||
> I used to provide APIs from my preload script using `window.X = apiObject` now what?
|
||||
> Without context isolation, I used to provide APIs from my preload script using `window.X = apiObject`. Now what?
|
||||
|
||||
Exposing APIs from your preload script to the loaded website is a common usecase and there is a dedicated module in Electron to help you do this in a painless way.
|
||||
### Before: context isolation disabled
|
||||
|
||||
**Before: With context isolation disabled**
|
||||
Exposing APIs from your preload script to a loaded website in the renderer process is a common use-case. With context isolation disabled, your preload script would share a common global `window` object with the renderer. You could then attach arbitrary properties to a preload script:
|
||||
|
||||
```javascript
|
||||
```javascript title='preload.js'
|
||||
// preload with contextIsolation disabled
|
||||
window.myAPI = {
|
||||
doAThing: () => {}
|
||||
}
|
||||
```
|
||||
|
||||
**After: With context isolation enabled**
|
||||
The `doAThing()` function could then be used directly in the renderer process:
|
||||
|
||||
```javascript
|
||||
```javascript title='renderer.js'
|
||||
// use the exposed API in the renderer
|
||||
window.myAPI.doAThing()
|
||||
```
|
||||
|
||||
### After: context isolation enabled
|
||||
|
||||
There is a dedicated module in Electron to help you do this in a painless way. The [`contextBridge`](../api/context-bridge.md) module can be used to **safely** expose APIs from your preload script's isolated context to the context the website is running in. The API will also be accessible from the website on `window.myAPI` just like it was before.
|
||||
|
||||
```javascript title='preload.js'
|
||||
// preload with contextIsolation enabled
|
||||
const { contextBridge } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('myAPI', {
|
||||
@@ -44,26 +43,63 @@ contextBridge.exposeInMainWorld('myAPI', {
|
||||
})
|
||||
```
|
||||
|
||||
The [`contextBridge`](../api/context-bridge.md) module can be used to **safely** expose APIs from the isolated context your preload script runs in to the context the website is running in. The API will also be accessible from the website on `window.myAPI` just like it was before.
|
||||
```javascript title='renderer.js'
|
||||
// use the exposed API in the renderer
|
||||
window.myAPI.doAThing()
|
||||
```
|
||||
|
||||
You should read the `contextBridge` documentation linked above to fully understand its limitations. For instance you can't send custom prototypes or symbols over the bridge.
|
||||
Please read the `contextBridge` documentation linked above to fully understand its limitations. For instance, you can't send custom prototypes or symbols over the bridge.
|
||||
|
||||
## Security Considerations
|
||||
## Security considerations
|
||||
|
||||
Just enabling `contextIsolation` and using `contextBridge` does not automatically mean that everything you do is safe. For instance this code is **unsafe**.
|
||||
Just enabling `contextIsolation` and using `contextBridge` does not automatically mean that everything you do is safe. For instance, this code is **unsafe**.
|
||||
|
||||
```javascript
|
||||
```javascript title='preload.js'
|
||||
// ❌ Bad code
|
||||
contextBridge.exposeInMainWorld('myAPI', {
|
||||
send: ipcRenderer.send
|
||||
})
|
||||
```
|
||||
|
||||
It directly exposes a powerful API without any kind of argument filtering. This would allow any website to send arbitrary IPC messages which you do not want to be possible. The correct way to expose IPC-based APIs would instead be to provide one method per IPC message.
|
||||
It directly exposes a powerful API without any kind of argument filtering. This would allow any website to send arbitrary IPC messages, which you do not want to be possible. The correct way to expose IPC-based APIs would instead be to provide one method per IPC message.
|
||||
|
||||
```javascript
|
||||
```javascript title='preload.js'
|
||||
// ✅ Good code
|
||||
contextBridge.exposeInMainWorld('myAPI', {
|
||||
loadPreferences: () => ipcRenderer.invoke('load-prefs')
|
||||
})
|
||||
```
|
||||
|
||||
## Usage with TypeScript
|
||||
|
||||
If you're building your Electron app with TypeScript, you'll want to add types to your APIs exposed over the context bridge. The renderer's `window` object won't have the correct typings unless you extend the types with a [declaration file].
|
||||
|
||||
For example, given this `preload.ts` script:
|
||||
|
||||
```typescript title='preload.ts'
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
loadPreferences: () => ipcRenderer.invoke('load-prefs')
|
||||
})
|
||||
```
|
||||
|
||||
You can create a `renderer.d.ts` declaration file and globally augment the `Window` interface:
|
||||
|
||||
```typescript title='renderer.d.ts'
|
||||
export interface IElectronAPI {
|
||||
loadPreferences: () => Promise<void>,
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
electronAPI: IElectronAPI
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Doing so will ensure that the TypeScript compiler will know about the `electronAPI` property on your global `window` object when writing scripts in your renderer process:
|
||||
|
||||
```typescript title='renderer.ts'
|
||||
window.electronAPI.loadPreferences()
|
||||
```
|
||||
|
||||
[declaration file]: https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html
|
||||
|
||||
@@ -90,6 +90,11 @@ ELECTRON_CUSTOM_DIR="{{ version }}"
|
||||
The above configuration will download from URLs such as
|
||||
`https://npm.taobao.org/mirrors/electron/8.0.0/electron-v8.0.0-linux-x64.zip`.
|
||||
|
||||
If your mirror serves artifacts with different checksums to the official
|
||||
Electron release you may have to set `ELECTRON_USE_REMOTE_CHECKSUMS=1` to
|
||||
force Electron to use the remote `SHASUMS256.txt` file to verify the checksum
|
||||
instead of the embedded checksums.
|
||||
|
||||
#### Cache
|
||||
|
||||
Alternatively, you can override the local cache. `@electron/get` will cache
|
||||
|
||||
@@ -120,9 +120,9 @@ file in the directory you executed it in. Both files can be analyzed using
|
||||
the Chrome Developer Tools, using the `Performance` and `Memory` tabs
|
||||
respectively.
|
||||
|
||||
![Performance CPU Profile][performance-cpu-prof]
|
||||

|
||||
|
||||
![Performance Heap Memory Profile][performance-heap-prof]
|
||||

|
||||
|
||||
In this example, on the author's machine, we saw that loading `request` took
|
||||
almost half a second, whereas `node-fetch` took dramatically less memory
|
||||
@@ -412,8 +412,6 @@ As of writing this article, the popular choices include [Webpack][webpack],
|
||||
[Parcel][parcel], and [rollup.js][rollup].
|
||||
|
||||
[security]: ./security.md
|
||||
[performance-cpu-prof]: ../images/performance-cpu-prof.png
|
||||
[performance-heap-prof]: ../images/performance-heap-prof.png
|
||||
[chrome-devtools-tutorial]: https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/
|
||||
[worker-threads]: https://nodejs.org/api/worker_threads.html
|
||||
[web-workers]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
|
||||
|
||||
@@ -7,16 +7,16 @@ without the need of switching to the window itself.
|
||||
|
||||
On Windows, you can use a taskbar button to display a progress bar.
|
||||
|
||||
![Windows Progress Bar][windows-progress-bar]
|
||||
![Windows Progress Bar][https://cloud.githubusercontent.com/assets/639601/5081682/16691fda-6f0e-11e4-9676-49b6418f1264.png]
|
||||
|
||||
On macOS, the progress bar will be displayed as a part of the dock icon.
|
||||
|
||||
![macOS Progress Bar][macos-progress-bar]
|
||||

|
||||
|
||||
On Linux, the Unity graphical interface also has a similar feature that allows
|
||||
you to specify the progress bar in the launcher.
|
||||
|
||||
![Linux Progress Bar][linux-progress-bar]
|
||||

|
||||
|
||||
> NOTE: on Windows, each window can have its own progress bar, whereas on macOS
|
||||
and Linux (Unity) there can be only one progress bar for the application.
|
||||
@@ -102,8 +102,4 @@ For macOS, the progress bar will also be indicated for your application
|
||||
when using [Mission Control](https://support.apple.com/en-us/HT204100):
|
||||
|
||||

|
||||
|
||||
[windows-progress-bar]: https://cloud.githubusercontent.com/assets/639601/5081682/16691fda-6f0e-11e4-9676-49b6418f1264.png
|
||||
[macos-progress-bar]: ../images/macos-progress-bar.png
|
||||
[linux-progress-bar]: ../images/linux-progress-bar.png
|
||||
[setprogressbar]: ../api/browser-window.md#winsetprogressbarprogress-options
|
||||
|
||||
@@ -70,10 +70,10 @@ until the maintainers feel the maintenance burden is too high to continue doing
|
||||
|
||||
### Currently supported versions
|
||||
|
||||
* 15.x.y
|
||||
* 14.x.y
|
||||
* 13.x.y
|
||||
* 12.x.y
|
||||
* 11.x.y
|
||||
* 12
|
||||
|
||||
### End-of-life
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { BrowserWindowConstructorOptions, LoadURLOptions } from 'electron/m
|
||||
import * as url from 'url';
|
||||
import * as path from 'path';
|
||||
import { openGuestWindow, makeWebPreferences, parseContentTypeFormat } from '@electron/internal/browser/guest-window-manager';
|
||||
import { parseFeatures } from '@electron/internal/common/parse-features-string';
|
||||
import { ipcMainInternal } from '@electron/internal/browser/ipc-main-internal';
|
||||
import * as ipcMainUtils from '@electron/internal/browser/ipc-main-internal-utils';
|
||||
import { MessagePortMain } from '@electron/internal/browser/message-port-main';
|
||||
@@ -665,6 +666,16 @@ WebContents.prototype._init = function () {
|
||||
postBody
|
||||
};
|
||||
windowOpenOverriddenOptions = this._callWindowOpenHandler(event, details);
|
||||
// if attempting to use this API with the deprecated window.open event,
|
||||
// windowOpenOverriddenOptions will always return null. This ensures
|
||||
// short-term backwards compatibility until window.open is removed.
|
||||
const parsedFeatures = parseFeatures(rawFeatures);
|
||||
const overriddenFeatures: BrowserWindowConstructorOptions = {
|
||||
...parsedFeatures.options,
|
||||
webPreferences: parsedFeatures.webPreferences
|
||||
};
|
||||
windowOpenOverriddenOptions = windowOpenOverriddenOptions || overriddenFeatures;
|
||||
|
||||
if (!event.defaultPrevented) {
|
||||
const secureOverrideWebPreferences = windowOpenOverriddenOptions ? {
|
||||
// Allow setting of backgroundColor as a webPreference even though
|
||||
|
||||
@@ -103,10 +103,14 @@ const warnAboutInsecureResources = function () {
|
||||
return;
|
||||
}
|
||||
|
||||
const isLocal = (url: URL): boolean =>
|
||||
['localhost', '127.0.0.1', '[::1]', ''].includes(url.hostname);
|
||||
const isInsecure = (url: URL): boolean =>
|
||||
['http:', 'ftp:'].includes(url.protocol) && !isLocal(url);
|
||||
|
||||
const resources = window.performance
|
||||
.getEntriesByType('resource')
|
||||
.filter(({ name }) => /^(http|ftp):/gi.test(name || ''))
|
||||
.filter(({ name }) => new URL(name).hostname !== 'localhost')
|
||||
.filter(({ name }) => isInsecure(new URL(name)))
|
||||
.map(({ name }) => `- ${name}`)
|
||||
.join('\n');
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ downloadArtifact({
|
||||
artifactName: 'electron',
|
||||
force: process.env.force_no_cache === 'true',
|
||||
cacheRoot: process.env.electron_config_cache,
|
||||
checksums: process.env.electron_use_remote_checksums ? undefined : require('./checksums.json'),
|
||||
platform,
|
||||
arch
|
||||
}).then(extractFile).catch(err => {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"postinstall": "node install.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@electron/get": "^1.0.1",
|
||||
"@electron/get": "^1.13.0",
|
||||
"@types/node": "^14.6.2",
|
||||
"extract-zip": "^1.0.3"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "15.0.0-beta.6",
|
||||
"version": "15.0.0",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
@@ -35,7 +35,7 @@
|
||||
"check-for-leaks": "^1.2.1",
|
||||
"colors": "^1.4.0",
|
||||
"dotenv-safe": "^4.0.4",
|
||||
"dugite": "^1.45.0",
|
||||
"dugite": "^1.103.0",
|
||||
"eslint": "^7.4.0",
|
||||
"eslint-config-standard": "^14.1.1",
|
||||
"eslint-plugin-import": "^2.22.0",
|
||||
@@ -54,12 +54,10 @@
|
||||
"markdownlint": "^0.21.1",
|
||||
"markdownlint-cli": "^0.25.0",
|
||||
"minimist": "^1.2.5",
|
||||
"nugget": "^2.0.1",
|
||||
"null-loader": "^4.0.0",
|
||||
"pre-flight": "^1.1.0",
|
||||
"remark-cli": "^4.0.0",
|
||||
"remark-preset-lint-markdown-style-guide": "^2.1.1",
|
||||
"request": "^2.88.2",
|
||||
"semver": "^5.6.0",
|
||||
"shx": "^0.3.2",
|
||||
"standard-markdown": "^6.0.0",
|
||||
|
||||
@@ -46,10 +46,10 @@ index 135ad9b24745f6d016806f3c95993efe65b370f3..c5e694cd56b9db940e8564c82e2773aa
|
||||
}
|
||||
|
||||
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
|
||||
index 3ddf1368f8ac78f32f523b2abde0addb79dcd9df..d878826b9782e65f92bf9316400f59cb55d2a4df 100644
|
||||
index 0fcf061bf93b4b11603ef944cf8dd4d456cf5f45..c2a035289bcd7424f1a2645da86133de5288ebaa 100644
|
||||
--- a/chrome/test/BUILD.gn
|
||||
+++ b/chrome/test/BUILD.gn
|
||||
@@ -5324,7 +5324,6 @@ test("unit_tests") {
|
||||
@@ -5325,7 +5325,6 @@ test("unit_tests") {
|
||||
assert(toolkit_views)
|
||||
sources += [ "../browser/ui/startup/credential_provider_signin_info_fetcher_win_unittest.cc" ]
|
||||
deps += [
|
||||
@@ -57,7 +57,7 @@ index 3ddf1368f8ac78f32f523b2abde0addb79dcd9df..d878826b9782e65f92bf9316400f59cb
|
||||
"//chrome/browser:chrome_process_finder",
|
||||
"//chrome/browser/safe_browsing/chrome_cleaner",
|
||||
"//chrome/browser/safe_browsing/chrome_cleaner:public",
|
||||
@@ -5337,6 +5336,12 @@ test("unit_tests") {
|
||||
@@ -5338,6 +5337,12 @@ test("unit_tests") {
|
||||
"//components/chrome_cleaner/public/proto",
|
||||
"//ui/events/devices:test_support",
|
||||
]
|
||||
@@ -70,7 +70,7 @@ index 3ddf1368f8ac78f32f523b2abde0addb79dcd9df..d878826b9782e65f92bf9316400f59cb
|
||||
}
|
||||
|
||||
# TODO(crbug.com/931218): Ninja cannot handle certain characters appearing
|
||||
@@ -5929,7 +5934,6 @@ test("unit_tests") {
|
||||
@@ -5930,7 +5935,6 @@ test("unit_tests") {
|
||||
}
|
||||
|
||||
deps += [
|
||||
@@ -78,7 +78,7 @@ index 3ddf1368f8ac78f32f523b2abde0addb79dcd9df..d878826b9782e65f92bf9316400f59cb
|
||||
"//chrome/browser:cart_db_content_proto",
|
||||
"//chrome/browser/media/router:test_support",
|
||||
"//chrome/browser/promo_browser_command:mojo_bindings",
|
||||
@@ -5965,6 +5969,9 @@ test("unit_tests") {
|
||||
@@ -5966,6 +5970,9 @@ test("unit_tests") {
|
||||
"//ui/color:test_support",
|
||||
"//ui/native_theme:test_support",
|
||||
]
|
||||
|
||||
@@ -9,10 +9,10 @@ potentially prevent a window from being created.
|
||||
TODO(loc): this patch is currently broken.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index 9bf31d2cb714f5def7db8ef4966d2ebff6223b92..621e5109e75db6e39ad488df0924b7bb98cc2aed 100644
|
||||
index a0cfdfbe055153861d35e5598c0ecea1aec3a0d1..2cba72ac8fc5b204e4c1e3a1d61fada89adced2a 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -6367,6 +6367,7 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
@@ -6413,6 +6413,7 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
last_committed_origin_, params->window_container_type,
|
||||
params->target_url, params->referrer.To<Referrer>(),
|
||||
params->frame_name, params->disposition, *params->features,
|
||||
|
||||
@@ -6,10 +6,10 @@ Subject: frame_host_manager.patch
|
||||
Allows embedder to intercept site instances created by chromium.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc
|
||||
index fd21a0ae3c653e262dd049674a4f943feb23ddf6..f5857235687e0b923e9d73e17c19c36495d10680 100644
|
||||
index d44fe1f7dbef9d5bc1ffbc508fad5d5642e850e7..f6dfd1d7cd9b4f9b8f59613ee2960dc4cc27e1a3 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_manager.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_manager.cc
|
||||
@@ -3077,6 +3077,9 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
|
||||
@@ -3095,6 +3095,9 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
|
||||
request->ResetStateForSiteInstanceChange();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,10 +14,10 @@ Note that we also need to manually update embedder's
|
||||
`api::WebContents::IsFullscreenForTabOrPending` value.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index 621e5109e75db6e39ad488df0924b7bb98cc2aed..7c7c1ad7d31a547e13411548468f777e76fff0fd 100644
|
||||
index 2cba72ac8fc5b204e4c1e3a1d61fada89adced2a..1cbf9e4d9919321895d8823f539f5f917a31e8a1 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -5790,6 +5790,15 @@ void RenderFrameHostImpl::EnterFullscreen(
|
||||
@@ -5836,6 +5836,15 @@ void RenderFrameHostImpl::EnterFullscreen(
|
||||
notified_instances.insert(parent_site_instance);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,5 +6,4 @@ workaround_an_undefined_symbol_error.patch
|
||||
do_not_export_private_v8_symbols_on_windows.patch
|
||||
fix_build_deprecated_attirbute_for_older_msvc_versions.patch
|
||||
fix_disable_implies_dcheck_for_node_stream_array_buffers.patch
|
||||
cppgc-js_fix_snapshot_node_merging.patch
|
||||
cppgc-js_support_eager_traced_value_in_ephemeron_pairs.patch
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Lippautz <mlippautz@chromium.org>
|
||||
Date: Tue, 24 Aug 2021 12:34:24 +0200
|
||||
Subject: cppgc-js: Fix snapshot node merging
|
||||
|
||||
In Blink, WindowProxy may be referred from two diffrent JS wrapper
|
||||
objects during page refresh (same site navigation reusing parts of the
|
||||
DOM). In this intermediate state, the old frame state is not yet
|
||||
reclaimed while the new state is already being added.
|
||||
|
||||
We would like to only merge nodes when there's a 1:1 relation between
|
||||
C++ and JS objects. Unfortunately, WindowProxy breaks that assumption
|
||||
in that the C++ object doesn't directly point to the wrapper. In
|
||||
addition, merging this case is important as otherwise detachedness
|
||||
would not be propagated to the Window object (JS wrapper) which is the
|
||||
main user of detachedness.
|
||||
|
||||
The CL allows overriding merged nodes, picking a random merged state
|
||||
during pageload while still resulting in the regular snapshot behavior
|
||||
outside of reloading the same page.
|
||||
|
||||
The proper fix is addressing chromium:1218404 and only create merged
|
||||
nodes when the back reference points to the same object.
|
||||
|
||||
Bug: chromium:1241610
|
||||
Change-Id: Ie77b51a56ce90ef377124304bb025342a724c600
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3114139
|
||||
Reviewed-by: Anton Bikineev <bikineev@chromium.org>
|
||||
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#76453}
|
||||
|
||||
diff --git a/src/heap/cppgc-js/cpp-snapshot.cc b/src/heap/cppgc-js/cpp-snapshot.cc
|
||||
index 28859d84f66aafa6b90325086d2289f2ef43a704..e72c6ad46998bb40ba91d37a740dc0ecfee2838b 100644
|
||||
--- a/src/heap/cppgc-js/cpp-snapshot.cc
|
||||
+++ b/src/heap/cppgc-js/cpp-snapshot.cc
|
||||
@@ -47,7 +47,13 @@ class EmbedderNode : public v8::EmbedderGraph::Node {
|
||||
void SetWrapperNode(v8::EmbedderGraph::Node* wrapper_node) {
|
||||
// An embedder node may only be merged with a single wrapper node, as
|
||||
// consumers of the graph may merge a node and its wrapper node.
|
||||
- DCHECK_NULL(wrapper_node_);
|
||||
+ //
|
||||
+ // TODO(chromium:1218404): Add a DCHECK() to avoid overriding an already
|
||||
+ // set `wrapper_node_`. This can currently happen with global proxies that
|
||||
+ // are rewired (and still kept alive) after reloading a page, see
|
||||
+ // `CreateMergedNode`. We accept overriding the wrapper node in such cases,
|
||||
+ // leading to a random merged node and separated nodes for all other
|
||||
+ // proxies.
|
||||
wrapper_node_ = wrapper_node;
|
||||
}
|
||||
Node* WrapperNode() final { return wrapper_node_; }
|
||||
@@ -28,7 +28,7 @@ Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#76658}
|
||||
|
||||
diff --git a/src/heap/cppgc-js/cpp-snapshot.cc b/src/heap/cppgc-js/cpp-snapshot.cc
|
||||
index e72c6ad46998bb40ba91d37a740dc0ecfee2838b..f64a7de116ac69221e3610370c7e2a5f0b7c60e5 100644
|
||||
index dc55753ff625a135b6e494344ee49105eb59121e..9b20b5c0a7831ea026819f90ea80c10eb2324282 100644
|
||||
--- a/src/heap/cppgc-js/cpp-snapshot.cc
|
||||
+++ b/src/heap/cppgc-js/cpp-snapshot.cc
|
||||
@@ -264,6 +264,10 @@ class State final : public StateBase {
|
||||
@@ -82,7 +82,7 @@ index e72c6ad46998bb40ba91d37a740dc0ecfee2838b..f64a7de116ac69221e3610370c7e2a5f
|
||||
DCHECK(parent.IsVisibleNotDependent());
|
||||
auto& current = states_.GetExistingState(header);
|
||||
if (!current.IsVisibleNotDependent()) return;
|
||||
@@ -449,7 +466,8 @@ class CppGraphBuilderImpl final {
|
||||
@@ -443,7 +460,8 @@ class CppGraphBuilderImpl final {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ index e72c6ad46998bb40ba91d37a740dc0ecfee2838b..f64a7de116ac69221e3610370c7e2a5f
|
||||
DCHECK(parent.IsVisibleNotDependent());
|
||||
v8::Local<v8::Value> v8_value = ref.Get(cpp_heap_.isolate());
|
||||
if (!v8_value.IsEmpty()) {
|
||||
@@ -457,12 +475,19 @@ class CppGraphBuilderImpl final {
|
||||
@@ -451,12 +469,19 @@ class CppGraphBuilderImpl final {
|
||||
parent.set_node(AddNode(*parent.header()));
|
||||
}
|
||||
auto* v8_node = graph_.V8Node(v8_value);
|
||||
@@ -114,7 +114,7 @@ index e72c6ad46998bb40ba91d37a740dc0ecfee2838b..f64a7de116ac69221e3610370c7e2a5f
|
||||
|
||||
void* back_reference_object = ExtractEmbedderDataBackref(
|
||||
reinterpret_cast<v8::internal::Isolate*>(cpp_heap_.isolate()),
|
||||
@@ -612,8 +637,18 @@ class WeakVisitor : public JSVisitor {
|
||||
@@ -598,8 +623,18 @@ class WeakVisitor : public JSVisitor {
|
||||
void VisitEphemeron(const void* key, const void* value,
|
||||
cppgc::TraceDescriptor value_desc) final {
|
||||
// For ephemerons, the key retains the value.
|
||||
@@ -134,7 +134,7 @@ index e72c6ad46998bb40ba91d37a740dc0ecfee2838b..f64a7de116ac69221e3610370c7e2a5f
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -659,7 +694,7 @@ class GraphBuildingVisitor final : public JSVisitor {
|
||||
@@ -645,7 +680,7 @@ class GraphBuildingVisitor final : public JSVisitor {
|
||||
void Visit(const void*, cppgc::TraceDescriptor desc) final {
|
||||
graph_builder_.AddEdge(
|
||||
parent_scope_.ParentAsRegularState(),
|
||||
@@ -143,7 +143,7 @@ index e72c6ad46998bb40ba91d37a740dc0ecfee2838b..f64a7de116ac69221e3610370c7e2a5f
|
||||
}
|
||||
void VisitWeakContainer(const void* object,
|
||||
cppgc::TraceDescriptor strong_desc,
|
||||
@@ -669,7 +704,8 @@ class GraphBuildingVisitor final : public JSVisitor {
|
||||
@@ -655,7 +690,8 @@ class GraphBuildingVisitor final : public JSVisitor {
|
||||
// container itself.
|
||||
graph_builder_.AddEdge(
|
||||
parent_scope_.ParentAsRegularState(),
|
||||
@@ -153,7 +153,7 @@ index e72c6ad46998bb40ba91d37a740dc0ecfee2838b..f64a7de116ac69221e3610370c7e2a5f
|
||||
}
|
||||
void VisitRoot(const void*, cppgc::TraceDescriptor desc,
|
||||
const cppgc::SourceLocation& loc) final {
|
||||
@@ -681,12 +717,18 @@ class GraphBuildingVisitor final : public JSVisitor {
|
||||
@@ -667,12 +703,18 @@ class GraphBuildingVisitor final : public JSVisitor {
|
||||
const void*, const cppgc::SourceLocation&) final {}
|
||||
// JS handling.
|
||||
void Visit(const TracedReferenceBase& ref) final {
|
||||
@@ -173,7 +173,7 @@ index e72c6ad46998bb40ba91d37a740dc0ecfee2838b..f64a7de116ac69221e3610370c7e2a5f
|
||||
};
|
||||
|
||||
// Base class for transforming recursion into iteration. Items are processed
|
||||
@@ -779,6 +821,19 @@ void CppGraphBuilderImpl::VisitForVisibility(State* parent,
|
||||
@@ -765,6 +807,19 @@ void CppGraphBuilderImpl::VisitForVisibility(State* parent,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ index e72c6ad46998bb40ba91d37a740dc0ecfee2838b..f64a7de116ac69221e3610370c7e2a5f
|
||||
void CppGraphBuilderImpl::VisitEphemeronForVisibility(
|
||||
const HeapObjectHeader& key, const HeapObjectHeader& value) {
|
||||
auto& key_state = states_.GetOrCreateState(key);
|
||||
@@ -834,6 +889,12 @@ void CppGraphBuilderImpl::Run() {
|
||||
@@ -820,6 +875,12 @@ void CppGraphBuilderImpl::Run() {
|
||||
state.ForAllEphemeronEdges([this, &state](const HeapObjectHeader& value) {
|
||||
AddEdge(state, value, "part of key -> value pair in ephemeron table");
|
||||
});
|
||||
|
||||
@@ -1,52 +1,23 @@
|
||||
const args = require('minimist')(process.argv.slice(2));
|
||||
const nugget = require('nugget');
|
||||
const request = require('request');
|
||||
const fs = require('fs');
|
||||
const got = require('got');
|
||||
const stream = require('stream');
|
||||
const { promisify } = require('util');
|
||||
|
||||
async function makeRequest (requestOptions, parseResponse) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request(requestOptions, (err, res, body) => {
|
||||
if (!err && res.statusCode >= 200 && res.statusCode < 300) {
|
||||
if (parseResponse) {
|
||||
const build = JSON.parse(body);
|
||||
resolve(build);
|
||||
} else {
|
||||
resolve(body);
|
||||
}
|
||||
} else {
|
||||
if (args.verbose) {
|
||||
console.error('Error occurred while requesting:', requestOptions.url);
|
||||
if (parseResponse) {
|
||||
try {
|
||||
console.log('Error: ', `(status ${res.statusCode})`, err || JSON.parse(res.body), requestOptions);
|
||||
} catch (err) {
|
||||
console.log('Error: ', `(status ${res.statusCode})`, err || res.body, requestOptions);
|
||||
}
|
||||
} else {
|
||||
console.log('Error: ', `(status ${res.statusCode})`, err || res.body, requestOptions);
|
||||
}
|
||||
}
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
const pipeline = promisify(stream.pipeline);
|
||||
|
||||
async function downloadArtifact (name, buildNum, dest) {
|
||||
const circleArtifactUrl = `https://circleci.com/api/v1.1/project/github/electron/electron/${args.buildNum}/artifacts?circle-token=${process.env.CIRCLE_TOKEN}`;
|
||||
const artifacts = await makeRequest({
|
||||
method: 'GET',
|
||||
url: circleArtifactUrl,
|
||||
const responsePromise = got(circleArtifactUrl, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json'
|
||||
}
|
||||
}, true).catch(err => {
|
||||
if (args.verbose) {
|
||||
console.log('Error calling CircleCI:', err);
|
||||
} else {
|
||||
console.error('Error calling CircleCI to get artifact details');
|
||||
}
|
||||
});
|
||||
const [response, artifacts] = await Promise.all([responsePromise, responsePromise.json()]);
|
||||
if (response.statusCode !== 200) {
|
||||
console.error('Could not fetch circleci artifact list, got status code:', response.statusCode);
|
||||
}
|
||||
const artifactToDownload = artifacts.find(artifact => {
|
||||
return (artifact.path === name);
|
||||
});
|
||||
@@ -86,19 +57,10 @@ async function downloadWithRetry (url, directory) {
|
||||
}
|
||||
|
||||
function downloadFile (url, directory) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const nuggetOpts = {
|
||||
dir: directory,
|
||||
quiet: args.verbose
|
||||
};
|
||||
nugget(url, nuggetOpts, (err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
return pipeline(
|
||||
got.stream(url),
|
||||
fs.createWriteStream(directory)
|
||||
);
|
||||
}
|
||||
|
||||
if (!args.name || !args.buildNum || !args.dest) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
if (!process.env.CI) require('dotenv-safe').load();
|
||||
|
||||
const assert = require('assert');
|
||||
const request = require('request');
|
||||
const got = require('got');
|
||||
|
||||
const BUILD_APPVEYOR_URL = 'https://ci.appveyor.com/api/builds';
|
||||
const CIRCLECI_PIPELINE_URL = 'https://circleci.com/api/v2/project/gh/electron/electron/pipeline';
|
||||
@@ -35,31 +35,24 @@ const vstsArmJobs = [
|
||||
|
||||
let jobRequestedCount = 0;
|
||||
|
||||
async function makeRequest (requestOptions, parseResponse) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request(requestOptions, (err, res, body) => {
|
||||
if (!err && res.statusCode >= 200 && res.statusCode < 300) {
|
||||
if (parseResponse) {
|
||||
const build = JSON.parse(body);
|
||||
resolve(build);
|
||||
} else {
|
||||
resolve(body);
|
||||
}
|
||||
} else {
|
||||
console.error('Error occurred while requesting:', requestOptions.url);
|
||||
if (parseResponse) {
|
||||
try {
|
||||
console.log('Error: ', `(status ${res.statusCode})`, err || JSON.parse(res.body));
|
||||
} catch (err) {
|
||||
console.log('Error: ', `(status ${res.statusCode})`, res.body);
|
||||
}
|
||||
} else {
|
||||
console.log('Error: ', `(status ${res.statusCode})`, err || res.body);
|
||||
}
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
async function makeRequest ({ auth, url, headers, body, method }) {
|
||||
const clonedHeaders = {
|
||||
...(headers || {})
|
||||
};
|
||||
if (auth && auth.bearer) {
|
||||
clonedHeaders.Authorization = `Bearer ${auth.bearer}`;
|
||||
}
|
||||
const response = await got(url, {
|
||||
headers: clonedHeaders,
|
||||
body,
|
||||
method,
|
||||
auth: auth && (auth.username || auth.password) ? `${auth.username}:${auth.password}` : undefined
|
||||
});
|
||||
if (response.statusCode < 200 || response.statusCode >= 300) {
|
||||
console.error('Error: ', `(status ${response.statusCode})`, response.body);
|
||||
throw new Error(`Unexpected status code ${response.statusCode} from ${url}`);
|
||||
}
|
||||
return JSON.parse(response.body);
|
||||
}
|
||||
|
||||
async function circleCIcall (targetBranch, workflowName, options) {
|
||||
|
||||
43
script/release/get-asset.js
Normal file
43
script/release/get-asset.js
Normal file
@@ -0,0 +1,43 @@
|
||||
const { Octokit } = require('@octokit/rest');
|
||||
const got = require('got');
|
||||
|
||||
const octokit = new Octokit({
|
||||
userAgent: 'electron-asset-fetcher',
|
||||
auth: process.env.ELECTRON_GITHUB_TOKEN
|
||||
});
|
||||
|
||||
async function getAssetContents (repo, assetId) {
|
||||
const requestOptions = octokit.repos.getReleaseAsset.endpoint({
|
||||
owner: 'electron',
|
||||
repo,
|
||||
asset_id: assetId,
|
||||
headers: {
|
||||
Accept: 'application/octet-stream'
|
||||
}
|
||||
});
|
||||
|
||||
const { url, headers } = requestOptions;
|
||||
headers.authorization = `token ${process.env.ELECTRON_GITHUB_TOKEN}`;
|
||||
|
||||
const response = await got(url, {
|
||||
followRedirect: false,
|
||||
method: 'HEAD',
|
||||
headers
|
||||
});
|
||||
if (!response.headers.location) {
|
||||
console.error(response.headers, `${response.body}`.slice(0, 300));
|
||||
throw new Error(`cannot find asset[${assetId}], asset download did not redirect`);
|
||||
}
|
||||
|
||||
const fileResponse = await got(response.headers.location);
|
||||
if (fileResponse.statusCode !== 200) {
|
||||
console.error(fileResponse.headers, `${fileResponse.body}`.slice(0, 300));
|
||||
throw new Error(`cannot download asset[${assetId}] from ${response.headers.location}, got status: ${fileResponse.status}`);
|
||||
}
|
||||
|
||||
return fileResponse.body;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getAssetContents
|
||||
};
|
||||
@@ -2,12 +2,14 @@ const temp = require('temp');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const childProcess = require('child_process');
|
||||
const { getCurrentBranch, ELECTRON_DIR } = require('../lib/utils');
|
||||
const request = require('request');
|
||||
const got = require('got');
|
||||
const semver = require('semver');
|
||||
|
||||
const { getCurrentBranch, ELECTRON_DIR } = require('../lib/utils');
|
||||
const rootPackageJson = require('../../package.json');
|
||||
|
||||
const { Octokit } = require('@octokit/rest');
|
||||
const { getAssetContents } = require('./get-asset');
|
||||
const octokit = new Octokit({
|
||||
userAgent: 'electron-npm-publisher',
|
||||
auth: process.env.ELECTRON_GITHUB_TOKEN
|
||||
@@ -86,27 +88,41 @@ new Promise((resolve, reject) => {
|
||||
}
|
||||
return release;
|
||||
})
|
||||
.then((release) => {
|
||||
.then(async (release) => {
|
||||
const tsdAsset = release.assets.find((asset) => asset.name === 'electron.d.ts');
|
||||
if (!tsdAsset) {
|
||||
throw new Error(`cannot find electron.d.ts from v${rootPackageJson.version} release assets`);
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
request.get({
|
||||
url: tsdAsset.url,
|
||||
headers: {
|
||||
accept: 'application/octet-stream',
|
||||
'user-agent': 'electron-npm-publisher'
|
||||
}
|
||||
}, (err, response, body) => {
|
||||
if (err || response.statusCode !== 200) {
|
||||
reject(err || new Error('Cannot download electron.d.ts'));
|
||||
} else {
|
||||
fs.writeFileSync(path.join(tempDir, 'electron.d.ts'), body);
|
||||
resolve(release);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const typingsContent = await getAssetContents(
|
||||
rootPackageJson.version.indexOf('nightly') > 0 ? 'nightlies' : 'electron',
|
||||
tsdAsset.id
|
||||
);
|
||||
|
||||
fs.writeFileSync(path.join(tempDir, 'electron.d.ts'), typingsContent);
|
||||
|
||||
return release;
|
||||
})
|
||||
.then(async (release) => {
|
||||
const checksumsAsset = release.assets.find((asset) => asset.name === 'SHASUMS256.txt');
|
||||
if (!checksumsAsset) {
|
||||
throw new Error(`cannot find SHASUMS256.txt from v${rootPackageJson.version} release assets`);
|
||||
}
|
||||
|
||||
const checksumsContent = await getAssetContents(
|
||||
rootPackageJson.version.indexOf('nightly') > 0 ? 'nightlies' : 'electron',
|
||||
checksumsAsset.id
|
||||
);
|
||||
|
||||
const checksumsObject = {};
|
||||
for (const line of checksumsContent.trim().split('\n')) {
|
||||
const [checksum, file] = line.split(' *');
|
||||
checksumsObject[file] = checksum;
|
||||
}
|
||||
|
||||
fs.writeFileSync(path.join(tempDir, 'checksums.json'), JSON.stringify(checksumsObject, null, 2));
|
||||
|
||||
return release;
|
||||
})
|
||||
.then(async (release) => {
|
||||
const currentBranch = await getCurrentBranch();
|
||||
@@ -150,10 +166,26 @@ new Promise((resolve, reject) => {
|
||||
// test that the package can install electron prebuilt from github release
|
||||
const tarballPath = path.join(tempDir, `${rootPackageJson.name}-${rootPackageJson.version}.tgz`);
|
||||
return new Promise((resolve, reject) => {
|
||||
childProcess.execSync(`npm install ${tarballPath} --force --silent`, {
|
||||
const result = childProcess.spawnSync('npm', ['install', tarballPath, '--force', '--silent'], {
|
||||
env: Object.assign({}, process.env, { electron_config_cache: tempDir }),
|
||||
cwd: tempDir
|
||||
cwd: tempDir,
|
||||
stdio: 'inherit'
|
||||
});
|
||||
if (result.status !== 0) {
|
||||
return reject(new Error(`npm install failed with status ${result.status}`));
|
||||
}
|
||||
try {
|
||||
const electronPath = require(path.resolve(tempDir, 'node_modules', rootPackageJson.name));
|
||||
if (typeof electronPath !== 'string') {
|
||||
return reject(new Error(`path to electron binary (${electronPath}) returned by the ${rootPackageJson.name} module is not a string`));
|
||||
}
|
||||
if (!fs.existsSync(electronPath)) {
|
||||
return reject(new Error(`path to electron binary (${electronPath}) returned by the ${rootPackageJson.name} module does not exist on disk`));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return reject(new Error(`loading the generated ${rootPackageJson.name} module failed with an error`));
|
||||
}
|
||||
resolve(tarballPath);
|
||||
});
|
||||
})
|
||||
@@ -186,6 +218,6 @@ new Promise((resolve, reject) => {
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(`Error: ${err}`);
|
||||
console.error('Error:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
@@ -384,7 +384,7 @@ async function verifyDraftGitHubReleaseAssets (release) {
|
||||
console.log('Fetching authenticated GitHub artifact URLs to verify shasums');
|
||||
|
||||
const remoteFilesToHash = await Promise.all(release.assets.map(async asset => {
|
||||
const requestOptions = await octokit.repos.getReleaseAsset.endpoint({
|
||||
const requestOptions = octokit.repos.getReleaseAsset.endpoint({
|
||||
owner: 'electron',
|
||||
repo: targetRepo,
|
||||
asset_id: asset.id,
|
||||
|
||||
@@ -17,7 +17,7 @@ void BrowserWindow::UpdateDraggableRegions(
|
||||
if (window_->has_frame())
|
||||
return;
|
||||
|
||||
if (&draggable_regions_ != ®ions) {
|
||||
if (&draggable_regions_ != ®ions && web_contents()) {
|
||||
auto* view =
|
||||
static_cast<content::WebContentsImpl*>(web_contents())->GetView();
|
||||
if (view) {
|
||||
|
||||
@@ -191,6 +191,7 @@ class NativeWindowMac : public NativeWindow,
|
||||
protected:
|
||||
// views::WidgetDelegate:
|
||||
views::View* GetContentsView() override;
|
||||
bool CanMaximize() const override;
|
||||
|
||||
// ui::NativeThemeObserver:
|
||||
void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override;
|
||||
|
||||
@@ -1715,31 +1715,35 @@ void NativeWindowMac::SetStyleMask(bool on, NSUInteger flag) {
|
||||
// we explicitly disable resizing while setting it.
|
||||
ScopedDisableResize disable_resize;
|
||||
|
||||
bool was_maximizable = IsMaximizable();
|
||||
if (on)
|
||||
[window_ setStyleMask:[window_ styleMask] | flag];
|
||||
else
|
||||
[window_ setStyleMask:[window_ styleMask] & (~flag)];
|
||||
|
||||
// Change style mask will make the zoom button revert to default, probably
|
||||
// a bug of Cocoa or macOS.
|
||||
SetMaximizable(was_maximizable);
|
||||
SetMaximizable(maximizable_);
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetCollectionBehavior(bool on, NSUInteger flag) {
|
||||
bool was_maximizable = IsMaximizable();
|
||||
if (on)
|
||||
[window_ setCollectionBehavior:[window_ collectionBehavior] | flag];
|
||||
else
|
||||
[window_ setCollectionBehavior:[window_ collectionBehavior] & (~flag)];
|
||||
|
||||
// Change collectionBehavior will make the zoom button revert to default,
|
||||
// probably a bug of Cocoa or macOS.
|
||||
SetMaximizable(was_maximizable);
|
||||
SetMaximizable(maximizable_);
|
||||
}
|
||||
|
||||
views::View* NativeWindowMac::GetContentsView() {
|
||||
return root_view_.get();
|
||||
}
|
||||
|
||||
bool NativeWindowMac::CanMaximize() const {
|
||||
return maximizable_;
|
||||
}
|
||||
|
||||
void NativeWindowMac::OnNativeThemeUpdated(ui::NativeTheme* observed_theme) {
|
||||
base::PostTask(
|
||||
FROM_HERE, {content::BrowserThread::UI},
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 15,0,0,6
|
||||
PRODUCTVERSION 15,0,0,6
|
||||
FILEVERSION 15,0,0,0
|
||||
PRODUCTVERSION 15,0,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
@@ -235,9 +235,10 @@ void WinFrameView::LayoutCaptionButtons() {
|
||||
// portion to return the correct hit test and be manually resized properly.
|
||||
// Alternatives can be explored, but the differences in view structures
|
||||
// between Electron and Chromium may result in this as the best option.
|
||||
int variable_width =
|
||||
IsMaximized() ? preferred_size.width() : preferred_size.width() - 1;
|
||||
caption_button_container_->SetBounds(width() - preferred_size.width(),
|
||||
WindowTopY(), preferred_size.width() - 1,
|
||||
height);
|
||||
WindowTopY(), variable_width, height);
|
||||
}
|
||||
|
||||
void WinFrameView::LayoutWindowControlsOverlay() {
|
||||
|
||||
@@ -3669,6 +3669,18 @@ describe('BrowserWindow module', () => {
|
||||
}
|
||||
});
|
||||
|
||||
// On Linux there is no "resizable" property of a window.
|
||||
ifit(process.platform !== 'linux')('does affect maximizability when disabled and enabled', () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
expect(w.resizable).to.be.true('resizable');
|
||||
|
||||
expect(w.maximizable).to.be.true('maximizable');
|
||||
w.resizable = false;
|
||||
expect(w.maximizable).to.be.false('not maximizable');
|
||||
w.resizable = true;
|
||||
expect(w.maximizable).to.be.true('maximizable');
|
||||
});
|
||||
|
||||
ifit(process.platform === 'win32')('works for a window smaller than 64x64', () => {
|
||||
const w = new BrowserWindow({
|
||||
show: false,
|
||||
|
||||
@@ -30,6 +30,7 @@ app.on('window-all-closed', () => null);
|
||||
|
||||
// Use fake device for Media Stream to replace actual camera and microphone.
|
||||
app.commandLine.appendSwitch('use-fake-device-for-media-stream');
|
||||
app.commandLine.appendSwitch('host-rules', 'MAP localhost2 127.0.0.1');
|
||||
|
||||
global.standardScheme = 'app';
|
||||
global.zoomScheme = 'zoom';
|
||||
|
||||
@@ -59,7 +59,7 @@ describe('security warnings', () => {
|
||||
});
|
||||
});
|
||||
}).listen(0, '127.0.0.1', () => {
|
||||
serverUrl = `http://127.0.0.1:${(server.address() as AddressInfo).port}`;
|
||||
serverUrl = `http://localhost2:${(server.address() as AddressInfo).port}`;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1103,7 +1103,7 @@ shell.writeShortcutLink('/home/user/Desktop/shortcut.lnk', 'update', shell.readS
|
||||
|
||||
session.defaultSession.on('will-download', (event, item, webContents) => {
|
||||
event.preventDefault()
|
||||
require('request')(item.getURL(), (data: any) => {
|
||||
require('got')(item.getURL()).then((data: any) => {
|
||||
require('fs').writeFileSync('/somewhere', data)
|
||||
})
|
||||
})
|
||||
|
||||
4
typings/internal-electron.d.ts
vendored
4
typings/internal-electron.d.ts
vendored
@@ -290,7 +290,7 @@ declare namespace ElectronInternal {
|
||||
|
||||
declare namespace Chrome {
|
||||
namespace Tabs {
|
||||
// https://developer.chrome.com/extensions/tabs#method-executeScript
|
||||
// https://developer.chrome.com/docs/extensions/tabs#method-executeScript
|
||||
interface ExecuteScriptDetails {
|
||||
code?: string;
|
||||
file?: string;
|
||||
@@ -303,7 +303,7 @@ declare namespace Chrome {
|
||||
|
||||
type ExecuteScriptCallback = (result: Array<any>) => void;
|
||||
|
||||
// https://developer.chrome.com/extensions/tabs#method-sendMessage
|
||||
// https://developer.chrome.com/docs/extensions/tabs#method-sendMessage
|
||||
interface SendMessageDetails {
|
||||
frameId?: number;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user