Compare commits

...

13 Commits

Author SHA1 Message Date
LeUser111
7376539603 docs: tutorial/security.md - fixed linting issue 2025-02-25 06:34:42 +01:00
LeUser111
1709b786cd docs: security.md/session.md incorporated more review feedback 2025-02-14 09:28:11 +01:00
LeUser111
4f919c727d docs: security.md/session.md incorporated more review feedback 2025-02-14 06:17:56 +01:00
LeUser111
1029bd1057 docs: security.md/session.md incorporated review feedback 2025-02-13 09:35:03 +01:00
LeUser111
685412e1be docs: security.md, session.md - added clarification on defaultSession, added csp example 2025-02-13 06:41:04 +01:00
Teaveloper
edd7b537c1 Merge branch 'electron:main' into docs-security-examples 2025-02-13 06:29:34 +01:00
Keeley Hammond
237429bb85 build: set chromium cookie on depot tools requests (#45581)
* build: set chromium cookie on depot tools requests

* build: correct secrets syntax

* build: handle windows cmd
2025-02-12 17:44:43 +01:00
Will Anderson
50d1c803dd chore: remove var declarations from DEPS that no longer have any effect (#45535)
* chore: Remove checkout_google_benchmark var that no longer has any effect

This variable stopped having any effect in https://chromium-review.googlesource.com/c/chromium/src/+/4322306

It was removed from Chromium entirely in https://chromium-review.googlesource.com/c/chromium/src/+/4339138

* chore: remove checkout_oculus_sdk and checkout_libaom from DEPS
2025-02-12 10:51:11 +01:00
John Kleinschmidt
0d3e34d0be test: disable unexpectedly quit dialog on macOS (#45553)
* test: disable unexpectedly quit dialog on macOS

* test: take screenshot before keyboard lock test

* Revert "test: take screenshot before keyboard lock test"

This reverts commit 3ba5c6984f.
2025-02-11 21:08:38 -05:00
Charles Kerr
aa06b065c0 chore: bump chromium to 134.0.6998.10 (main) (#45564)
* chore: bump chromium to 134.0.6992.0

* chore: add BrowserProcessImpl::CreateGlobalFeaturesForTesting() stub

Xref: https://chromium-review.googlesource.com/c/chromium/src/+/6216193

Remove GlobalFeatures from TestingBrowserProcess::Init

* chore: bump chromium to 134.0.6994.0

* 6208630: Mac sandbox: don't use protobuf for policy serialization | https://chromium-review.googlesource.com/c/chromium/src/+/6208630

* [PDF] Remove HasUnsupportedFeature Mojo interface

Xref: https://chromium-review.googlesource.com/c/chromium/src/+/6220800

* 6217444: Remove scoped_gdi_object.h type aliases. | https://chromium-review.googlesource.com/c/chromium/src/+/6217444

* chore: bump chromium to 134.0.6998.10

* 6221378: Revert [OBC] Exclude Aliasing Cookies in FilterCookiesWithOptions() | https://chromium-review.googlesource.com/c/chromium/src/+/6221378

* Update ExtensionPrefs::GetDisableReasons to return DisableReasonSet

Xref: https://chromium-review.googlesource.com/c/chromium/src/+/6218840

change copied from 6218840 extensions/shell/browser/shell_extension_loader.cc

* 6218402: Typemap ui.gfx.DXGIHandle <=> gfx::DXGIHandle | https://chromium-review.googlesource.com/c/chromium/src/+/6218402

* chore: disable flaky contentTracing test

not new to this roll; it is happening in main as well

* fixup! chore: disable flaky contentTracing test

---------

Co-authored-by: alice <alice@makenotion.com>
2025-02-11 17:26:39 -06:00
Felix Rieseberg
9f47c9a051 feat: Restore webContents navigation history and page state (#45433)
* feat: Working navigationHistory.restore with just title/url

* feat: Restore page state, too

* chore: Docs, lint, tests

* Implement feedback

* More magic

* Make _awaitNextLoad truly private

* Implement API group feedback

* One more round of feedback
2025-02-11 15:09:38 -08:00
LeUser111
dabb95c3f0 Removed semi-colon for uniform js code style in examples
Signed-off-by: LeUser111 <florian.wiedenmann@grob.de>
2025-02-11 12:48:46 +01:00
LeUser111
d05cf9c6bb docs: security.md use runnable examples for permissions and csp
Signed-off-by: LeUser111 <florian.wiedenmann@grob.de>
2025-02-11 12:48:37 +01:00
34 changed files with 383 additions and 112 deletions

View File

@@ -20,6 +20,8 @@ runs:
uses: ./src/electron/.github/actions/install-dependencies
- name: Install Build Tools
uses: ./src/electron/.github/actions/install-build-tools
- name: Set Chromium Git Cookie
uses: ./src/electron/.github/actions/set-chromium-cookie
- name: Get Depot Tools
shell: bash
run: |

View File

@@ -0,0 +1,26 @@
name: 'Set Chromium Git Cookie'
description: 'Sets an authenticated cookie from Chromium to allow for a higher request limit'
runs:
using: "composite"
steps:
- name: Set the git cookie from chromium.googlesource.com (Unix)
if: ${{ runner.os != 'Windows' }}
shell: bash
run: |
eval 'set +o history' 2>/dev/null || setopt HIST_IGNORE_SPACE 2>/dev/null
touch ~/.gitcookies
chmod 0600 ~/.gitcookies
git config --global http.cookiefile ~/.gitcookies
tr , \\t <<\__END__ >>~/.gitcookies
${{ env.CHROMIUM_GIT_COOKIE }}
__END__
eval 'set -o history' 2>/dev/null || unsetopt HIST_IGNORE_SPACE 2>/dev/null
- name: Set the git cookie from chromium.googlesource.com (Windows)
if: ${{ runner.os == 'Windows' }}
shell: cmd
run: |
git config --global http.cookiefile "%USERPROFILE%\.gitcookies"
powershell -noprofile -nologo -command Write-Output "${{ env.CHROMIUM_GIT_COOKIE_WINDOWS_STRING }}" >>"%USERPROFILE%\.gitcookies"

View File

@@ -100,6 +100,7 @@ jobs:
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
- /var/run/sas:/var/run/sas
env:
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac'
outputs:
build-image-sha: ${{ needs.setup.outputs.build-image-sha }}
@@ -126,6 +127,7 @@ jobs:
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
- /var/run/sas:/var/run/sas
env:
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
PATCH_UP_APP_CREDS: ${{ secrets.PATCH_UP_APP_CREDS }}
outputs:
@@ -150,6 +152,8 @@ jobs:
volumes:
- /mnt/cross-instance-cache:/mnt/cross-instance-cache
env:
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
CHROMIUM_GIT_COOKIE_WINDOWS_STRING: ${{ secrets.CHROMIUM_GIT_COOKIE_WINDOWS_STRING }}
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_win=True'
TARGET_OS: 'win'
ELECTRON_DEPOT_TOOLS_WIN_TOOLCHAIN: '1'

View File

@@ -27,6 +27,8 @@ jobs:
ref: ${{ github.event.pull_request.head.sha }}
- name: Install Dependencies
uses: ./src/electron/.github/actions/install-dependencies
- name: Set Chromium Git Cookie
uses: ./src/electron/.github/actions/set-chromium-cookie
- name: Setup third_party Depot Tools
shell: bash
run: |

View File

@@ -65,6 +65,8 @@ concurrency:
cancel-in-progress: ${{ github.ref_protected != true }}
env:
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
CHROMIUM_GIT_COOKIE_WINDOWS_STRING: ${{ secrets.CHROMIUM_GIT_COOKIE_WINDOWS_STRING }}
ELECTRON_ARTIFACTS_BLOB_STORAGE: ${{ secrets.ELECTRON_ARTIFACTS_BLOB_STORAGE }}
ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }}
SUDOWOODO_EXCHANGE_URL: ${{ secrets.SUDOWOODO_EXCHANGE_URL }}
@@ -125,6 +127,8 @@ jobs:
GN_EXTRA_ARGS='is_asan=true'
fi
echo "GN_EXTRA_ARGS=$GN_EXTRA_ARGS" >> $GITHUB_ENV
- name: Set Chromium Git Cookie
uses: ./src/electron/.github/actions/set-chromium-cookie
- name: Get Depot Tools
timeout-minutes: 5
run: |

View File

@@ -36,6 +36,8 @@ permissions:
pull-requests: read
env:
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
CHROMIUM_GIT_COOKIE_WINDOWS_STRING: ${{ secrets.CHROMIUM_GIT_COOKIE_WINDOWS_STRING }}
ELECTRON_OUT_DIR: Default
ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }}
@@ -113,6 +115,9 @@ jobs:
configure_sys_tccdb "$values"
fi
done
- name: Turn off the unexpectedly quit dialog on macOS
if: ${{ inputs.target-platform == 'macos' }}
run: defaults write com.apple.CrashReporter DialogType server
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
@@ -121,6 +126,8 @@ jobs:
ref: ${{ github.event.pull_request.head.sha }}
- name: Install Dependencies
uses: ./src/electron/.github/actions/install-dependencies
- name: Set Chromium Git Cookie
uses: ./src/electron/.github/actions/set-chromium-cookie
- name: Get Depot Tools
timeout-minutes: 5
run: |

View File

@@ -57,6 +57,8 @@ jobs:
e init -f --root=$(pwd) --out=Default ${{ inputs.gn-build-type }} --import ${{ inputs.gn-build-type }} --target-cpu ${{ inputs.target-arch }}
- name: Install Dependencies
uses: ./src/electron/.github/actions/install-dependencies
- name: Set Chromium Git Cookie
uses: ./src/electron/.github/actions/set-chromium-cookie
- name: Get Depot Tools
timeout-minutes: 5
run: |
@@ -118,6 +120,8 @@ jobs:
e init -f --root=$(pwd) --out=Default ${{ inputs.gn-build-type }}
- name: Install Dependencies
uses: ./src/electron/.github/actions/install-dependencies
- name: Set Chromium Git Cookie
uses: ./src/electron/.github/actions/set-chromium-cookie
- name: Get Depot Tools
timeout-minutes: 5
run: |

8
DEPS
View File

@@ -2,7 +2,7 @@ gclient_gn_args_from = 'src'
vars = {
'chromium_version':
'134.0.6990.0',
'134.0.6998.10',
'node_version':
'v22.13.1',
'nan_version':
@@ -62,10 +62,6 @@ vars = {
'checkout_nacl':
False,
'checkout_libaom':
True,
'checkout_oculus_sdk':
False,
'checkout_openxr':
False,
'build_with_chromium':
@@ -74,8 +70,6 @@ vars = {
False,
'checkout_android_native_support':
False,
'checkout_google_benchmark':
False,
'checkout_clang_tidy':
True,
}

View File

@@ -74,3 +74,22 @@ Returns `boolean` - Whether the navigation entry was removed from the webContent
#### `navigationHistory.getAllEntries()`
Returns [`NavigationEntry[]`](structures/navigation-entry.md) - WebContents complete history.
#### `navigationHistory.restore(options)`
Restores navigation history and loads the given entry in the in stack. Will make a best effort
to restore not just the navigation stack but also the state of the individual pages - for instance
including HTML form values or the scroll position. It's recommended to call this API before any
navigation entries are created, so ideally before you call `loadURL()` or `loadFile()` on the
`webContents` object.
This API allows you to create common flows that aim to restore, recreate, or clone other webContents.
* `options` Object
* `entries` [NavigationEntry[]](structures/navigation-entry.md) - Result of a prior `getAllEntries()` call
* `index` Integer (optional) - Index of the stack that should be loaded. If you set it to `0`, the webContents will load the first (oldest) entry. If you leave it undefined, Electron will automatically load the last (newest) entry.
Returns `Promise<void>` - the promise will resolve when the page has finished loading the selected navigation entry
(see [`did-finish-load`](web-contents.md#event-did-finish-load)), and rejects
if the page fails to load (see
[`did-fail-load`](web-contents.md#event-did-fail-load)). A noop rejection handler is already attached, which avoids unhandled rejection errors.

View File

@@ -66,7 +66,7 @@ The `session` module has the following properties:
### `session.defaultSession`
A `Session` object, the default session object of the app.
A `Session` object, the default session object of the app, available after `app.whenReady` is called.
## Class: Session

View File

@@ -2,3 +2,6 @@
* `url` string
* `title` string
* `pageState` string (optional) - A base64 encoded data string containing Chromium page state
including information like the current scroll position or form values. It is committed by
Chromium before a navigation event and on a regular interval.

View File

@@ -69,8 +69,25 @@ if (navigationHistory.canGoToOffset(2)) {
}
```
## Restoring history
A common flow is that you want to restore the history of a webContents - for instance to implement an "undo close tab" feature. To do so, you can call `navigationHistory.restore({ index, entries })`. This will restore the webContent's navigation history and the webContents location in said history, meaning that `goBack()` and `goForward()` navigate you through the stack as expected.
```js @ts-type={navigationHistory:Electron.NavigationHistory}
const firstWindow = new BrowserWindow()
// Later, you want a second window to have the same history and navigation position
async function restore () {
const entries = firstWindow.webContents.navigationHistory.getAllEntries()
const index = firstWindow.webContents.navigationHistory.getActiveIndex()
const secondWindow = new BrowserWindow()
await secondWindow.webContents.navigationHistory.restore({ index, entries })
}
```
Here's a full example that you can open with Electron Fiddle:
```fiddle docs/fiddles/features/navigation-history
```

View File

@@ -284,7 +284,7 @@ const { session } = require('electron')
const { URL } = require('url')
session
.fromPartition('some-partition')
.defaultSession
.setPermissionRequestHandler((webContents, permission, callback) => {
const parsedUrl = new URL(webContents.getURL())
@@ -301,6 +301,8 @@ session
})
```
Note: `session.defaultSession` is only available after `app.whenReady` is called.
### 6. Do not disable `webSecurity`
:::info
@@ -391,6 +393,8 @@ session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
})
```
Note: `session.defaultSession` is only available after `app.whenReady` is called.
#### CSP meta tag
CSP's preferred delivery mechanism is an HTTP header. However, it is not possible

View File

@@ -8,7 +8,7 @@ import * as deprecate from '@electron/internal/common/deprecate';
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
import { app, ipcMain, session, webFrameMain, dialog } from 'electron/main';
import type { BrowserWindowConstructorOptions, MessageBoxOptions } from 'electron/main';
import type { BrowserWindowConstructorOptions, MessageBoxOptions, NavigationEntry } from 'electron/main';
import * as path from 'path';
import * as url from 'url';
@@ -343,8 +343,8 @@ WebContents.prototype.loadFile = function (filePath, options = {}) {
type LoadError = { errorCode: number, errorDescription: string, url: string };
WebContents.prototype.loadURL = function (url, options) {
const p = new Promise<void>((resolve, reject) => {
function _awaitNextLoad (this: Electron.WebContents, navigationUrl: string) {
return new Promise<void>((resolve, reject) => {
const resolveAndCleanup = () => {
removeListeners();
resolve();
@@ -402,7 +402,7 @@ WebContents.prototype.loadURL = function (url, options) {
// the only one is with a bad scheme, perhaps ERR_INVALID_ARGUMENT
// would be more appropriate.
if (!error) {
error = { errorCode: -2, errorDescription: 'ERR_FAILED', url };
error = { errorCode: -2, errorDescription: 'ERR_FAILED', url: navigationUrl };
}
finishListener();
};
@@ -426,6 +426,10 @@ WebContents.prototype.loadURL = function (url, options) {
this.on('did-stop-loading', stopLoadingListener);
this.on('destroyed', stopLoadingListener);
});
};
WebContents.prototype.loadURL = function (url, options) {
const p = _awaitNextLoad.call(this, url);
// Add a no-op rejection handler to silence the unhandled rejection error.
p.catch(() => {});
this._loadURL(url, options ?? {});
@@ -611,7 +615,27 @@ WebContents.prototype._init = function () {
length: this._historyLength.bind(this),
getEntryAtIndex: this._getNavigationEntryAtIndex.bind(this),
removeEntryAtIndex: this._removeNavigationEntryAtIndex.bind(this),
getAllEntries: this._getHistory.bind(this)
getAllEntries: this._getHistory.bind(this),
restore: ({ index, entries }: { index?: number, entries: NavigationEntry[] }) => {
if (index === undefined) {
index = entries.length - 1;
}
if (index < 0 || !entries[index]) {
throw new Error('Invalid index. Index must be a positive integer and within the bounds of the entries length.');
}
const p = _awaitNextLoad.call(this, entries[index].url);
p.catch(() => {});
try {
this._restoreHistory(index, entries);
} catch (error) {
return Promise.reject(error);
}
return p;
}
},
writable: false,
enumerable: true

View File

@@ -35,10 +35,10 @@ system font by checking if it's kCTFontPriorityAttribute is set to
system priority.
diff --git a/base/BUILD.gn b/base/BUILD.gn
index a4ae9c4c242551f6850cdcbb42551b676db76c95..22281156bcfdd6999d15d511c508415f8f3f9ac7 100644
index 05ba2110698b69af677ad1fe898ae6e5953c7af4..7bcbb8f647faea889e295d8919f67745a7f72136 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1028,6 +1028,7 @@ component("base") {
@@ -1027,6 +1027,7 @@ component("base") {
"//build:ios_buildflags",
"//build/config/compiler:compiler_buildflags",
"//third_party/modp_b64",
@@ -192,10 +192,10 @@ index e12c1d078147d956a1d9b1bc498c1b1d6fe7b974..233362259dc4e728ed37435e65041764
} // namespace base
diff --git a/components/os_crypt/sync/BUILD.gn b/components/os_crypt/sync/BUILD.gn
index bfb0d2f208170f77df96fb9f14c8525e9dec6e11..e234d95a862198148bae97b4b276d93922f3ca92 100644
index ff1e356ff696d3830d02644969c36a71fdf32ff6..b39c716c52524b95f2d3417a98e60c0c41147c93 100644
--- a/components/os_crypt/sync/BUILD.gn
+++ b/components/os_crypt/sync/BUILD.gn
@@ -43,6 +43,8 @@ component("os_crypt") {
@@ -38,6 +38,8 @@ component("sync") {
"os_crypt_mac.mm",
]
deps += [ "//crypto:mock_apple_keychain" ]
@@ -269,7 +269,7 @@ index e9f4e5131238b9fb5f1b4b3e90a0cb84a7fc15b4..8b5f4cae3123ac5480ad73f0c873fca0
} // namespace
diff --git a/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm b/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm
index 19fff43c3daaef5451b6b60b84a610a21311448e..240b954661d34fcc4329d39490be33c485fa8b6e 100644
index 3a8b44a2a295119f37ca37d5866dfcfa21121db0..b408e9c73fe97dd8885b5479923481e20955cf8d 100644
--- a/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm
+++ b/components/remote_cocoa/app_shim/browser_native_widget_window_mac.mm
@@ -9,7 +9,9 @@
@@ -298,7 +298,7 @@ index 19fff43c3daaef5451b6b60b84a610a21311448e..240b954661d34fcc4329d39490be33c4
+ (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle {
// - NSThemeFrame and its subclasses will be nil if it's missing at runtime.
if ([BrowserWindowFrame class])
@@ -165,6 +170,8 @@ - (BOOL)_usesCustomDrawing {
@@ -163,6 +168,8 @@ - (BOOL)_usesCustomDrawing {
return NO;
}
@@ -307,7 +307,7 @@ index 19fff43c3daaef5451b6b60b84a610a21311448e..240b954661d34fcc4329d39490be33c4
// Handle "Move focus to the window toolbar" configured in System Preferences ->
// Keyboard -> Shortcuts -> Keyboard. Usually Ctrl+F5. The argument (|unknown|)
// tends to just be nil.
@@ -175,8 +182,8 @@ - (void)_handleFocusToolbarHotKey:(id)unknown {
@@ -173,8 +180,8 @@ - (void)_handleFocusToolbarHotKey:(id)unknown {
}
- (void)setAlwaysShowTrafficLights:(BOOL)alwaysShow {
@@ -354,7 +354,7 @@ index 3a815ebf505bd95fa7f6b61ba433d98fbfe20225..149de0175c2ec0e41e3ba40caad7019c
+
@end
diff --git a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h
index d55914779bc097cab8afb144f2c47c001bfa7350..e55db3f550b4c082aa087fbcab6760da237f8471 100644
index 127a2829fafa04bfbab0b883304dfb815d7e1c22..61d7946e52862f3586b1e098d7d44a125656de81 100644
--- a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h
+++ b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.h
@@ -9,6 +9,7 @@
@@ -382,7 +382,7 @@ index d55914779bc097cab8afb144f2c47c001bfa7350..e55db3f550b4c082aa087fbcab6760da
// The NSWindow used by BridgedNativeWidget. Provides hooks into AppKit that
// can only be accomplished by overriding methods.
diff --git a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
index 03ff0478f16f237e6b8082508d5399195bfdca44..9b74f6ca6de6ec057073e175170014b5512040b4 100644
index 2b50e3c3750c9ac6dd84a514663062a5d754b43e..49ced9aa87d3bcb00cd3d76ac32d4eec89873549 100644
--- a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
+++ b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
@@ -26,6 +26,7 @@
@@ -449,7 +449,7 @@ index 03ff0478f16f237e6b8082508d5399195bfdca44..9b74f6ca6de6ec057073e175170014b5
bool shouldShowWindowTitle = YES;
if (_bridge)
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
index 89aca4b47c202f137a5ffe8390986ef6dd62942a..59276806afa7659573eb276149ff8ed47ca72c1f 100644
index 36c522793dc37f7c72f7cccde50895927b5560cb..689351b5a6e6e6013b808c1b4924b8848dcc0fa2 100644
--- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
+++ b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
@@ -41,6 +41,7 @@
@@ -579,10 +579,10 @@ index a76028eed0249244d0559de102a756e3b2771b63..cb65efb56849d57e2e656f90d5b1d737
return kAttributes;
}
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 74ca66c0f38b4fc4448d50a9f3674cda6a078f0e..5c49a11dfbe1275f0f8cd21bf970d3b6b98cb71e 100644
index e5ca8881f7e05fc3c600cf6f785a2070efff2e5d..ce57b1e635f26ef248fbf8285cf69fe3c6c41105 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -329,6 +329,7 @@ source_set("browser") {
@@ -330,6 +330,7 @@ source_set("browser") {
"//ui/touch_selection",
"//ui/webui/resources",
"//v8:v8_version",
@@ -625,7 +625,7 @@ index bea4e26ef8577e8e8bc60287cf1b94c7dfcc9478..eed42b0cbc3422b7fd59ae1b2550c53d
// Used to force the NSApplication's focused accessibility element to be the
// content::BrowserAccessibilityCocoa accessibility tree when the NSView for
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 9185fd223c9611faee546570c0df36bc94cdb28c..86886e94e9e2c52e297a82175f6071852e792148 100644
index 430426a0123508a45bf48dcbfb46d1c4dc9d9347..efa697b7c4d428200d14e436ab062c13273916f4 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -48,6 +48,7 @@
@@ -647,7 +647,7 @@ index 9185fd223c9611faee546570c0df36bc94cdb28c..86886e94e9e2c52e297a82175f607185
// Reset `ns_view_` before resetting `remote_ns_view_` to avoid dangling
// pointers. `ns_view_` gets reinitialized later in this method.
@@ -1616,8 +1619,10 @@ void CombineTextNodesAndMakeCallback(SpeechCallback callback,
@@ -1622,8 +1625,10 @@ void CombineTextNodesAndMakeCallback(SpeechCallback callback,
gfx::NativeViewAccessible
RenderWidgetHostViewMac::AccessibilityGetNativeViewAccessibleForWindow() {
@@ -658,7 +658,7 @@ index 9185fd223c9611faee546570c0df36bc94cdb28c..86886e94e9e2c52e297a82175f607185
return [GetInProcessNSView() window];
}
@@ -1666,9 +1671,11 @@ void CombineTextNodesAndMakeCallback(SpeechCallback callback,
@@ -1672,9 +1677,11 @@ void CombineTextNodesAndMakeCallback(SpeechCallback callback,
}
void RenderWidgetHostViewMac::SetAccessibilityWindow(NSWindow* window) {
@@ -670,7 +670,7 @@ index 9185fd223c9611faee546570c0df36bc94cdb28c..86886e94e9e2c52e297a82175f607185
}
bool RenderWidgetHostViewMac::SyncIsWidgetForMainFrame(
@@ -2195,20 +2202,26 @@ void CombineTextNodesAndMakeCallback(SpeechCallback callback,
@@ -2201,20 +2208,26 @@ void CombineTextNodesAndMakeCallback(SpeechCallback callback,
void RenderWidgetHostViewMac::GetRenderWidgetAccessibilityToken(
GetRenderWidgetAccessibilityTokenCallback callback) {
base::ProcessId pid = getpid();
@@ -792,7 +792,7 @@ index a1068589ad844518038ee7bc15a3de9bc5cba525..1ff781c49f086ec8015c7d3c44567dbe
} // namespace content
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 27adf4138c7ea1cb90460bdd21586163f7614a48..6b422c331bb14489b36a762ad2ced88544d21b60 100644
index 190b593519ab8ccfc6309b40947c6e42ff8c6131..ec3dd70e677d7215df1c2cb504faa62ac1e6dff4 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -652,6 +652,7 @@ static_library("test_support") {
@@ -811,7 +811,7 @@ index 27adf4138c7ea1cb90460bdd21586163f7614a48..6b422c331bb14489b36a762ad2ced885
}
mojom("content_test_mojo_bindings") {
@@ -1924,6 +1926,7 @@ test("content_browsertests") {
@@ -1935,6 +1937,7 @@ test("content_browsertests") {
"//ui/shell_dialogs",
"//ui/snapshot",
"//ui/webui:test_support",
@@ -819,7 +819,7 @@ index 27adf4138c7ea1cb90460bdd21586163f7614a48..6b422c331bb14489b36a762ad2ced885
]
if (!(is_chromeos && target_cpu == "arm64" && current_cpu == "arm")) {
@@ -3210,6 +3213,7 @@ test("content_unittests") {
@@ -3228,6 +3231,7 @@ test("content_unittests") {
"//ui/latency:test_support",
"//ui/shell_dialogs:shell_dialogs",
"//ui/webui:test_support",
@@ -932,10 +932,10 @@ index 36322ddd3047f96569f35807541a37d3c6672b09..0121a780cf3b79fc1120c1b85cd5cd30
namespace ui {
diff --git a/media/audio/BUILD.gn b/media/audio/BUILD.gn
index 977aa5b452c882ee69690ba034ec00c9e7ff7e24..3ae3e2ead48ea1af9307dcd12647ca2a24b3a6f4 100644
index 87126a36725849cbaf478e2dc24dc3a628a30846..a3a88b07af91b86191d9e5727a1d021ebbbb22ce 100644
--- a/media/audio/BUILD.gn
+++ b/media/audio/BUILD.gn
@@ -198,6 +198,7 @@ source_set("audio") {
@@ -196,6 +196,7 @@ source_set("audio") {
"CoreMedia.framework",
]
weak_frameworks = [ "ScreenCaptureKit.framework" ] # macOS 13.0
@@ -1023,18 +1023,18 @@ index 70d5665ad7b9ef62370497636af919ede2508ad4..f4dc3e2b8053cdb3e8c439ab1a1d6369
}
diff --git a/sandbox/mac/BUILD.gn b/sandbox/mac/BUILD.gn
index 4e53d573ff67615bc7dcee7db6f855c67094f414..8b061d66b1a854b51a5a38b6a71eadab6a7dbbec 100644
index 453e2185fc85fcb29fa7af3f94cce5bda8118b0c..1c383675bb9113b5b1df9280b8ee994123794dfc 100644
--- a/sandbox/mac/BUILD.gn
+++ b/sandbox/mac/BUILD.gn
@@ -39,6 +39,7 @@ component("seatbelt") {
]
public_deps = [ "//third_party/protobuf:protobuf_lite" ]
@@ -25,6 +25,7 @@ component("seatbelt") {
libs = [ "sandbox" ]
deps = [ ":seatbelt_export" ]
defines = [ "SEATBELT_IMPLEMENTATION" ]
+ deps += ["//electron/build/config:generate_mas_config"]
}
component("seatbelt_extension") {
@@ -52,6 +53,7 @@ component("seatbelt_extension") {
@@ -38,6 +39,7 @@ component("seatbelt_extension") {
libs = [ "sandbox" ]
public_deps = [ "//base" ]
defines = [ "SEATBELT_IMPLEMENTATION" ]
@@ -1042,7 +1042,7 @@ index 4e53d573ff67615bc7dcee7db6f855c67094f414..8b061d66b1a854b51a5a38b6a71eadab
}
component("system_services") {
@@ -66,6 +68,7 @@ component("system_services") {
@@ -52,6 +54,7 @@ component("system_services") {
deps = [ ":seatbelt_export" ]
public_deps = [ "//base" ]
defines = [ "SEATBELT_IMPLEMENTATION" ]
@@ -1050,36 +1050,6 @@ index 4e53d573ff67615bc7dcee7db6f855c67094f414..8b061d66b1a854b51a5a38b6a71eadab
}
source_set("sandbox_unittests") {
diff --git a/sandbox/mac/sandbox_compiler.cc b/sandbox/mac/sandbox_compiler.cc
index f35d9ef2a2df3db8ecbf1d7b909c7b1cf33f3cd9..5d52330d1bd70cd7b97ee3360721f10c8447c717 100644
--- a/sandbox/mac/sandbox_compiler.cc
+++ b/sandbox/mac/sandbox_compiler.cc
@@ -7,6 +7,7 @@
#include <string>
#include <vector>
+#include "electron/mas.h"
#include "sandbox/mac/seatbelt.h"
namespace sandbox {
@@ -47,6 +48,7 @@ bool SandboxCompiler::SetParameter(const std::string& key,
}
bool SandboxCompiler::CompileAndApplyProfile(std::string& error) {
+#if !IS_MAS_BUILD()
if (mode_ == Target::kSource) {
std::vector<const char*> params;
@@ -67,6 +69,9 @@ bool SandboxCompiler::CompileAndApplyProfile(std::string& error) {
}
}
return false;
+#else
+ return true;
+#endif
}
bool SandboxCompiler::CompilePolicyToProto(mac::SandboxPolicy& policy,
diff --git a/sandbox/mac/sandbox_logging.cc b/sandbox/mac/sandbox_logging.cc
index 095c639b9893e885d8937e29ed7d47a7c28bc6b6..7e0cf9b9f94b16741358bdb45122f8b2bd68c0f9 100644
--- a/sandbox/mac/sandbox_logging.cc
@@ -1117,7 +1087,7 @@ index 095c639b9893e885d8937e29ed7d47a7c28bc6b6..7e0cf9b9f94b16741358bdb45122f8b2
// |error| is strerror(errno) when a P* logging function is called. Pass
diff --git a/sandbox/mac/seatbelt.cc b/sandbox/mac/seatbelt.cc
index 15c835e118456394c0a00ac98c11241c14ca75bd..a16faabe2bd63a5e0fbe9082a3b4b7c8aa0ea064 100644
index 1960e1c8771fad615a098af09ff1f9a191f67764..29b97b352d08cd1fe73b17fd80cb41cc7e58dcaa 100644
--- a/sandbox/mac/seatbelt.cc
+++ b/sandbox/mac/seatbelt.cc
@@ -4,12 +4,14 @@
@@ -1220,14 +1190,21 @@ index 15c835e118456394c0a00ac98c11241c14ca75bd..a16faabe2bd63a5e0fbe9082a3b4b7c8
}
// static
@@ -129,10 +147,14 @@ bool Seatbelt::InitWithParams(const char* profile,
@@ -129,16 +147,21 @@ bool Seatbelt::InitWithParams(const std::string& profile,
uint64_t flags,
const char* const parameters[],
const std::vector<std::string>& parameters,
std::string* error) {
+#if !IS_MAS_BUILD()
std::vector<const char*> weak_params;
for (const std::string& param : parameters) {
weak_params.push_back(param.c_str());
}
// The parameters array must be null terminated.
weak_params.push_back(nullptr);
+
char* errorbuf = nullptr;
int rv =
::sandbox_init_with_parameters(profile, flags, parameters, &errorbuf);
int rv = ::sandbox_init_with_parameters(profile.c_str(), flags,
weak_params.data(), &errorbuf);
return HandleSandboxResult(rv, errorbuf, error);
+#else
+ return true;
@@ -1235,7 +1212,7 @@ index 15c835e118456394c0a00ac98c11241c14ca75bd..a16faabe2bd63a5e0fbe9082a3b4b7c8
}
// static
@@ -140,6 +162,7 @@ bool Seatbelt::Compile(const char* profile,
@@ -146,6 +169,7 @@ bool Seatbelt::Compile(const char* profile,
const Seatbelt::Parameters& params,
std::string& compiled_profile,
std::string* error) {
@@ -1243,7 +1220,7 @@ index 15c835e118456394c0a00ac98c11241c14ca75bd..a16faabe2bd63a5e0fbe9082a3b4b7c8
char* errorbuf = nullptr;
sandbox_profile_t* sandbox_profile =
::sandbox_compile_string(profile, params.params(), &errorbuf);
@@ -149,33 +172,44 @@ bool Seatbelt::Compile(const char* profile,
@@ -155,33 +179,44 @@ bool Seatbelt::Compile(const char* profile,
compiled_profile.assign(reinterpret_cast<const char*>(sandbox_profile->data),
sandbox_profile->size);
::sandbox_free_profile(sandbox_profile);
@@ -1392,7 +1369,7 @@ index eb81a70e4d5d5cd3e6ae9b45f8cd1c795ea76c51..9921ccb10d3455600eddd85f77f10228
} // namespace sandbox
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 076ae475b3c4f0d2568e5efc9fedf2de7ccc82ad..b961c9c000bbb82c5f6ae63466c6d5d679d92de6 100644
index 17b3ddd66513a01a631d77535cfeb1ae94881e0e..bde6c61489fe4f88abba79fd2fb809c292a3f99a 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -409,6 +409,7 @@ component("core") {
@@ -1634,7 +1611,7 @@ index c8171f0527fe5194f0ea73b57c4444d4c630fbc4..c2ac4da580e3e7f749a0a4de1e859af6
// Accessible object
if (AXElementWrapper::IsValidElement(value)) {
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index 5ca4c8fc961d24985aa4e0459dc2c42003a5346f..2f5880d1d3fbc3aa1461bbe611c33f789a6f4dde 100644
index f211074c41fd50597db8b72510149d27ffc8d90a..885511f666318ce1218a09c3ebf5ec1aa00e9ecf 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -363,6 +363,13 @@ component("base") {
@@ -1804,10 +1781,10 @@ index 29ae2da6a8a2c2a612dfb92f7f9c03ca5fa306b1..440c139a32a0c205e77b657d4aab6468
// Query the display's refresh rate.
if (@available(macos 12.0, *)) {
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn
index 6cf9f1a38ed76edc8f64500476b4b3014dc7677f..54dcf71bd0bf5a1455b31f3d042305f0fc3e345b 100644
index 230a9e8266fa494f870ed7fc7dc444d1db5bbb48..99facff7a8e98cbc175354ae4e1d1f592197320a 100644
--- a/ui/gfx/BUILD.gn
+++ b/ui/gfx/BUILD.gn
@@ -331,6 +331,12 @@ component("gfx") {
@@ -332,6 +332,12 @@ component("gfx") {
"//ui/base:ui_data_pack",
]
@@ -1859,7 +1836,7 @@ index fe3f85073e31de487a08e57d7f9b07aa4eccf8f3..cf5b07203c8bd559a404600cc98cc8ec
// enough.
return PlatformFontMac::SystemFontType::kGeneral;
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index 94afec13361d4ee8d0441da3cbe37d62e287c94b..fd13add3291b113dc57c69700f35ac9943124786 100644
index ee47ca61db4c321edce0d6ae49f9f6a21f01918a..c8fcad4a3af57cfb993018f0ad457c271bdefe0e 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -718,6 +718,8 @@ component("views") {
@@ -1871,7 +1848,7 @@ index 94afec13361d4ee8d0441da3cbe37d62e287c94b..fd13add3291b113dc57c69700f35ac99
}
if (is_win) {
@@ -1135,6 +1137,8 @@ source_set("test_support") {
@@ -1138,6 +1140,8 @@ source_set("test_support") {
"//ui/base/mojom:ui_base_types",
]

View File

@@ -250,11 +250,7 @@ const std::string InclusionStatusToString(net::CookieInclusionStatus status) {
{Reason::EXCLUDE_THIRD_PARTY_PHASEOUT,
"The cookie is blocked for third-party cookie phaseout."},
{Reason::EXCLUDE_NO_COOKIE_CONTENT,
"The cookie contains no content or only whitespace."},
{Reason::EXCLUDE_ALIASING,
"Cookie aliases that of another with a different source_port or "
"source scheme. I.e.: Two or more cookies share the same name "
"but have different ports/schemes."}});
"The cookie contains no content or only whitespace."}});
static_assert(
Reasons.size() ==
net::CookieInclusionStatus::ExclusionReasonBitset::kValueCount,

View File

@@ -54,6 +54,7 @@
#include "content/public/browser/keyboard_event_processing_result.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_entry_restore_context.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@@ -363,14 +364,60 @@ struct Converter<scoped_refptr<content::DevToolsAgentHost>> {
template <>
struct Converter<content::NavigationEntry*> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
content::NavigationEntry** out) {
gin_helper::Dictionary dict;
if (!gin::ConvertFromV8(isolate, val, &dict))
return false;
std::string url_str;
std::string title;
std::string encoded_page_state;
GURL url;
if (!dict.Get("url", &url) || !dict.Get("title", &title))
return false;
auto entry = content::NavigationEntry::Create();
entry->SetURL(url);
entry->SetTitle(base::UTF8ToUTF16(title));
// Handle optional page state
if (dict.Get("pageState", &encoded_page_state)) {
std::string decoded_page_state;
if (base::Base64Decode(encoded_page_state, &decoded_page_state)) {
auto restore_context = content::NavigationEntryRestoreContext::Create();
auto page_state =
blink::PageState::CreateFromEncodedData(decoded_page_state);
if (!page_state.IsValid())
return false;
entry->SetPageState(std::move(page_state), restore_context.get());
}
}
*out = entry.release();
return true;
}
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
content::NavigationEntry* entry) {
if (!entry) {
return v8::Null(isolate);
}
gin_helper::Dictionary dict(isolate, v8::Object::New(isolate));
gin_helper::Dictionary dict = gin_helper::Dictionary::CreateEmpty(isolate);
dict.Set("url", entry->GetURL().spec());
dict.Set("title", entry->GetTitleForDisplay());
// Page state saves scroll position and values of any form fields
const blink::PageState& page_state = entry->GetPageState();
if (page_state.IsValid()) {
std::string encoded_data = base::Base64Encode(page_state.ToEncodedData());
dict.Set("pageState", encoded_data);
}
return dict.GetHandle();
}
};
@@ -2572,6 +2619,47 @@ std::vector<content::NavigationEntry*> WebContents::GetHistory() const {
return history;
}
void WebContents::RestoreHistory(
v8::Isolate* isolate,
gin_helper::ErrorThrower thrower,
int index,
const std::vector<v8::Local<v8::Value>>& entries) {
if (!web_contents()
->GetController()
.GetLastCommittedEntry()
->IsInitialEntry()) {
thrower.ThrowError(
"Cannot restore history on webContents that have previously loaded "
"a page.");
return;
}
auto navigation_entries = std::make_unique<
std::vector<std::unique_ptr<content::NavigationEntry>>>();
for (const auto& entry : entries) {
content::NavigationEntry* nav_entry = nullptr;
if (!gin::Converter<content::NavigationEntry*>::FromV8(isolate, entry,
&nav_entry) ||
!nav_entry) {
// Invalid entry, bail out early
thrower.ThrowError(
"Failed to restore navigation history: Invalid navigation entry at "
"index " +
std::to_string(index) + ".");
return;
}
navigation_entries->push_back(
std::unique_ptr<content::NavigationEntry>(nav_entry));
}
if (!navigation_entries->empty()) {
web_contents()->GetController().Restore(
index, content::RestoreType::kRestored, navigation_entries.get());
web_contents()->GetController().LoadIfNecessary();
}
}
void WebContents::ClearHistory() {
// In some rare cases (normally while there is no real history) we are in a
// state where we can't prune navigation entries
@@ -4397,6 +4485,7 @@ void WebContents::FillObjectTemplate(v8::Isolate* isolate,
&WebContents::RemoveNavigationEntryAtIndex)
.SetMethod("_getHistory", &WebContents::GetHistory)
.SetMethod("_clearHistory", &WebContents::ClearHistory)
.SetMethod("_restoreHistory", &WebContents::RestoreHistory)
.SetMethod("isCrashed", &WebContents::IsCrashed)
.SetMethod("forcefullyCrashRenderer",
&WebContents::ForcefullyCrashRenderer)

View File

@@ -219,6 +219,10 @@ class WebContents final : public ExclusiveAccessContext,
bool RemoveNavigationEntryAtIndex(int index);
std::vector<content::NavigationEntry*> GetHistory() const;
void ClearHistory();
void RestoreHistory(v8::Isolate* isolate,
gin_helper::ErrorThrower thrower,
int index,
const std::vector<v8::Local<v8::Value>>& entries);
int GetHistoryLength() const;
const std::string GetWebRTCIPHandlingPolicy() const;
void SetWebRTCIPHandlingPolicy(const std::string& webrtc_ip_handling_policy);

View File

@@ -70,6 +70,7 @@ class BrowserProcessImpl : public BrowserProcess {
// BrowserProcess
BuildState* GetBuildState() override;
GlobalFeatures* GetFeatures() override;
void CreateGlobalFeaturesForTesting() override {}
void EndSession() override {}
void FlushLocalStateAndReply(base::OnceClosure reply) override {}
bool IsShuttingDown() override;

View File

@@ -20,7 +20,6 @@ class ElectronPDFDocumentHelperClient : public pdf::PDFDocumentHelperClient {
// pdf::PDFDocumentHelperClient
void UpdateContentRestrictions(content::RenderFrameHost* render_frame_host,
int content_restrictions) override;
void OnPDFHasUnsupportedFeature(content::WebContents* contents) override {}
void OnSaveURL(content::WebContents* contents) override {}
void SetPluginCanSave(content::RenderFrameHost* render_frame_host,
bool can_save) override;

View File

@@ -181,8 +181,7 @@ void ElectronExtensionLoader::PreAddExtension(const Extension* extension,
extension_prefs->RemoveDisableReason(extension->id(),
disable_reason::DISABLE_RELOAD);
// Only re-enable the extension if there are no other disable reasons.
if (extension_prefs->GetDisableReasons(extension->id()) ==
disable_reason::DISABLE_NONE) {
if (extension_prefs->GetDisableReasons(extension->id()).empty()) {
extension_prefs->SetExtensionEnabled(extension->id());
}
}

View File

@@ -1636,8 +1636,8 @@ gfx::Rect NativeWindowViews::WindowBoundsToContentBounds(
#if BUILDFLAG(IS_WIN)
void NativeWindowViews::SetIcon(HICON window_icon, HICON app_icon) {
// We are responsible for storing the images.
window_icon_ = base::win::ScopedHICON(CopyIcon(window_icon));
app_icon_ = base::win::ScopedHICON(CopyIcon(app_icon));
window_icon_ = base::win::ScopedGDIObject<HICON>(CopyIcon(window_icon));
app_icon_ = base::win::ScopedGDIObject<HICON>(CopyIcon(app_icon));
HWND hwnd = GetAcceleratedWidget();
SendMessage(hwnd, WM_SETICON, ICON_SMALL,

View File

@@ -277,8 +277,8 @@ class NativeWindowViews : public NativeWindow,
gfx::Rect restore_bounds_;
// The icons of window and taskbar.
base::win::ScopedHICON window_icon_;
base::win::ScopedHICON app_icon_;
base::win::ScopedGDIObject<HICON> window_icon_;
base::win::ScopedGDIObject<HICON> app_icon_;
// The set of windows currently forwarding mouse messages.
static std::set<NativeWindowViews*> forwarding_windows_;

View File

@@ -99,7 +99,7 @@ void OffScreenVideoConsumer::OnFrameCaptured(
#if BUILDFLAG(IS_WIN)
texture.shared_texture_handle =
reinterpret_cast<uintptr_t>(gmb_handle.dxgi_handle.Get());
reinterpret_cast<uintptr_t>(gmb_handle.dxgi_handle().buffer_handle());
#elif BUILDFLAG(IS_APPLE)
texture.shared_texture_handle =
reinterpret_cast<uintptr_t>(gmb_handle.io_surface.get());

View File

@@ -176,7 +176,7 @@ DialogResult ShowTaskDialogWstr(gfx::AcceleratedWidget parent,
config.pszWindowTitle = base::as_wcstr(title);
}
base::win::ScopedHICON hicon;
base::win::ScopedGDIObject<HICON> hicon;
if (!icon.isNull()) {
hicon = IconUtil::CreateHICONFromSkBitmap(*icon.bitmap());
config.dwFlags |= TDF_USE_HICON_MAIN;

View File

@@ -129,7 +129,7 @@ void NotifyIcon::ResetIcon() {
}
void NotifyIcon::SetImage(HICON image) {
icon_ = base::win::ScopedHICON(CopyIcon(image));
icon_ = base::win::ScopedGDIObject<HICON>(CopyIcon(image));
// Create the icon.
NOTIFYICONDATA icon_data;

View File

@@ -91,7 +91,7 @@ class NotifyIcon : public TrayIcon {
UINT message_id_;
// The currently-displayed icon for the window.
base::win::ScopedHICON icon_;
base::win::ScopedGDIObject<HICON> icon_;
// The context menu.
raw_ptr<ElectronMenuModel> menu_model_ = nullptr;

View File

@@ -73,7 +73,8 @@ bool TaskbarHost::SetThumbarButtons(HWND window,
// The number of buttons in thumbar can not be changed once it is created,
// so we have to claim kMaxButtonsCount buttons initially in case users add
// more buttons later.
auto icons = std::array<base::win::ScopedHICON, kMaxButtonsCount>{};
auto icons =
std::array<base::win::ScopedGDIObject<HICON>, kMaxButtonsCount>{};
auto thumb_buttons = std::array<THUMBBUTTON, kMaxButtonsCount>{};
for (size_t i = 0U; i < kMaxButtonsCount; ++i) {

View File

@@ -102,7 +102,8 @@ bool IsTemplateFilename(const base::FilePath& path) {
#endif
#if BUILDFLAG(IS_WIN)
base::win::ScopedHICON ReadICOFromPath(int size, const base::FilePath& path) {
base::win::ScopedGDIObject<HICON> ReadICOFromPath(int size,
const base::FilePath& path) {
// If file is in asar archive, we extract it to a temp file so LoadImage can
// load it.
base::FilePath asar_path, relative_path;
@@ -115,7 +116,7 @@ base::win::ScopedHICON ReadICOFromPath(int size, const base::FilePath& path) {
}
// Load the icon from file.
return base::win::ScopedHICON(
return base::win::ScopedGDIObject<HICON>(
static_cast<HICON>(LoadImage(nullptr, image_path.value().c_str(),
IMAGE_ICON, size, size, LR_LOADFROMFILE)));
}

View File

@@ -134,7 +134,7 @@ class NativeImage final : public gin::Wrappable<NativeImage> {
base::FilePath hicon_path_;
// size -> hicon
base::flat_map<int, base::win::ScopedHICON> hicons_;
base::flat_map<int, base::win::ScopedGDIObject<HICON>> hicons_;
#endif
gfx::Image image_;

View File

@@ -90,7 +90,7 @@ v8::Local<v8::Promise> NativeImage::CreateThumbnailFromPath(
icon_info.hbmMask = hBitmap;
icon_info.hbmColor = hBitmap;
base::win::ScopedHICON icon(CreateIconIndirect(&icon_info));
base::win::ScopedGDIObject<HICON> icon(CreateIconIndirect(&icon_info));
SkBitmap skbitmap = IconUtil::CreateSkBitmapFromHICON(icon.get());
gfx::ImageSkia image_skia =
gfx::ImageSkia::CreateFromBitmap(skbitmap, 1.0 /*scale factor*/);

View File

@@ -6,7 +6,7 @@ import * as fs from 'node:fs';
import * as path from 'node:path';
import { setTimeout } from 'node:timers/promises';
import { ifdescribe } from './lib/spec-helpers';
import { ifdescribe, ifit } from './lib/spec-helpers';
// FIXME: The tests are skipped on linux arm/arm64
ifdescribe(!(['arm', 'arm64'].includes(process.arch)) || (process.platform !== 'linux'))('contentTracing', () => {
@@ -112,7 +112,8 @@ ifdescribe(!(['arm', 'arm64'].includes(process.arch)) || (process.platform !== '
expect(fs.statSync(path).isFile()).to.be.true('output exists');
});
it('calls its callback with a result file path', async () => {
// FIXME(ckerr): this test regularly flakes
ifit(process.platform !== 'linux')('calls its callback with a result file path', async () => {
const resultFilePath = await record(/* options */ {}, outputFilePath);
expect(resultFilePath).to.be.a('string').and.be.equal(outputFilePath);
});

View File

@@ -699,12 +699,14 @@ describe('webContents module', () => {
describe('navigationHistory.getEntryAtIndex(index) API ', () => {
it('should fetch default navigation entry when no urls are loaded', async () => {
const result = w.webContents.navigationHistory.getEntryAtIndex(0);
expect(result).to.deep.equal({ url: '', title: '' });
expect(result.url).to.equal('');
expect(result.title).to.equal('');
});
it('should fetch navigation entry given a valid index', async () => {
await w.loadURL(urlPage1);
const result = w.webContents.navigationHistory.getEntryAtIndex(0);
expect(result).to.deep.equal({ url: urlPage1, title: 'Page 1' });
expect(result.url).to.equal(urlPage1);
expect(result.title).to.equal('Page 1');
});
it('should return null given an invalid index larger than history length', async () => {
await w.loadURL(urlPage1);
@@ -763,7 +765,10 @@ describe('webContents module', () => {
await w.loadURL(urlPage1);
await w.loadURL(urlPage2);
await w.loadURL(urlPage3);
const entries = w.webContents.navigationHistory.getAllEntries();
const entries = w.webContents.navigationHistory.getAllEntries().map(entry => ({
url: entry.url,
title: entry.title
}));
expect(entries.length).to.equal(3);
expect(entries[0]).to.deep.equal({ url: urlPage1, title: 'Page 1' });
expect(entries[1]).to.deep.equal({ url: urlPage2, title: 'Page 2' });
@@ -774,6 +779,92 @@ describe('webContents module', () => {
const entries = w.webContents.navigationHistory.getAllEntries();
expect(entries.length).to.equal(0);
});
it('should create a NavigationEntry with PageState that can be serialized/deserialized with JSON', async () => {
await w.loadURL(urlPage1);
await w.loadURL(urlPage2);
await w.loadURL(urlPage3);
const entries = w.webContents.navigationHistory.getAllEntries();
const serialized = JSON.stringify(entries);
const deserialized = JSON.parse(serialized);
expect(deserialized).to.deep.equal(entries);
});
});
describe('navigationHistory.restore({ index, entries }) API', () => {
let server: http.Server;
let serverUrl: string;
before(async () => {
server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
res.end('<html><head><title>Form</title></head><body><form><input type="text" value="value" /></form></body></html>');
});
serverUrl = (await listen(server)).url;
});
after(async () => {
if (server) await new Promise(resolve => server.close(resolve));
server = null as any;
});
it('should restore navigation history with PageState', async () => {
await w.loadURL(urlPage1);
await w.loadURL(urlPage2);
await w.loadURL(serverUrl);
// Fill out the form on the page
await w.webContents.executeJavaScript('document.querySelector("input").value = "Hi!";');
// PageState is committed:
// 1) When the page receives an unload event
// 2) During periodic serialization of page state
// To not wait randomly for the second option, we'll trigger another load
await w.loadURL(urlPage3);
// Save the navigation state
const entries = w.webContents.navigationHistory.getAllEntries();
// Close the window, make a new one
w.close();
w = new BrowserWindow();
const formValue = await new Promise<string>(resolve => {
w.webContents.once('dom-ready', () => resolve(w.webContents.executeJavaScript('document.querySelector("input").value')));
// Restore the navigation history
return w.webContents.navigationHistory.restore({ index: 2, entries });
});
expect(formValue).to.equal('Hi!');
});
it('should handle invalid base64 pageState', async () => {
await w.loadURL(urlPage1);
await w.loadURL(urlPage2);
await w.loadURL(urlPage3);
const brokenEntries = w.webContents.navigationHistory.getAllEntries().map(entry => ({
...entry,
pageState: 'invalid base64'
}));
// Close the window, make a new one
w.close();
w = new BrowserWindow();
await w.webContents.navigationHistory.restore({ index: 2, entries: brokenEntries });
const entries = w.webContents.navigationHistory.getAllEntries();
// Check that we used the original url and titles but threw away the broken
// pageState
entries.forEach((entry, index) => {
expect(entry.url).to.equal(brokenEntries[index].url);
expect(entry.title).to.equal(brokenEntries[index].title);
expect(entry.pageState?.length).to.be.greaterThanOrEqual(100);
});
});
});
});

View File

@@ -87,6 +87,7 @@ declare namespace Electron {
}
interface WebContents {
_awaitNextLoad(expectedUrl: string): Promise<void>;
_loadURL(url: string, options: ElectronInternal.LoadURLOptions): void;
getOwnerBrowserWindow(): Electron.BrowserWindow | null;
getLastWebPreferences(): Electron.WebPreferences | null;
@@ -115,6 +116,7 @@ declare namespace Electron {
_goToIndex(index: number): void;
_removeNavigationEntryAtIndex(index: number): boolean;
_getHistory(): Electron.NavigationEntry[];
_restoreHistory(index: number, entries: Electron.NavigationEntry[]): void
_clearHistory():void
canGoToIndex(index: number): boolean;
destroy(): void;