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
46 changed files with 597 additions and 537 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
@@ -1541,25 +1541,6 @@ Unloads an extension.
**Note:** This API cannot be called before the `ready` event of the `app` module
is emitted.
#### `ses.enableExtension(extensionId)`
* `extensionId` string - ID of extension to enable
Enables the extension and activates it for use by starting any background
workers. If the extension is disabled, marks it as enabled.
**Note:** This API cannot be called before the `ready` event of the `app` module
is emitted.
#### `ses.disableExtension(extensionId)`
* `extensionId` string - ID of extension to disable
Disables the extension and deactives it.
**Note:** This API cannot be called before the `ready` event of the `app` module
is emitted.
#### `ses.getExtension(extensionId)`
* `extensionId` string - ID of extension to query

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

@@ -763,8 +763,6 @@ filenames = {
"shell/browser/extensions/electron_extension_host_delegate.h",
"shell/browser/extensions/electron_extension_loader.cc",
"shell/browser/extensions/electron_extension_loader.h",
"shell/browser/extensions/electron_extension_registrar_delegate.cc",
"shell/browser/extensions/electron_extension_registrar_delegate.h",
"shell/browser/extensions/electron_extension_system_factory.cc",
"shell/browser/extensions/electron_extension_system_factory.h",
"shell/browser/extensions/electron_extension_system.cc",

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

@@ -98,7 +98,6 @@
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
#include "extensions/browser/extension_registry.h"
#include "shell/browser/extensions/electron_extension_info.h"
#include "shell/browser/extensions/electron_extension_system.h"
#include "shell/common/gin_converters/extension_converter.h"
#endif
@@ -1310,8 +1309,7 @@ v8::Local<v8::Promise> Session::GetSharedDictionaryUsageInfo() {
v8::Local<v8::Promise> Session::LoadExtension(
const base::FilePath& extension_path,
gin::Arguments* args) {
gin_helper::Promise<const extensions::ElectronExtensionInfo&> promise(
isolate_);
gin_helper::Promise<const extensions::Extension*> promise(isolate_);
v8::Local<v8::Promise> handle = promise.GetHandle();
if (!extension_path.IsAbsolute()) {
@@ -1340,37 +1338,27 @@ v8::Local<v8::Promise> Session::LoadExtension(
extension_system->LoadExtension(
extension_path, load_flags,
base::BindOnce(
[](gin_helper::Promise<const extensions::ElectronExtensionInfo&>
promise,
base::WeakPtr<ElectronBrowserContext> browser_context,
[](gin_helper::Promise<const extensions::Extension*> promise,
const extensions::Extension* extension,
const std::string& error_msg) {
if (extension && browser_context) {
if (extension) {
if (!error_msg.empty())
util::EmitWarning(promise.isolate(), error_msg,
"ExtensionLoadWarning");
const auto& extension_info = extensions::ElectronExtensionInfo(
extension, browser_context.get());
promise.Resolve(extension_info);
promise.Resolve(extension);
} else {
promise.RejectWithErrorMessage(error_msg);
}
},
std::move(promise), browser_context()->GetWeakPtr()));
std::move(promise)));
return handle;
}
void Session::RemoveExtension(const std::string& extension_id) {
browser_context()->extension_system()->RemoveExtension(extension_id);
}
void Session::EnableExtension(const std::string& extension_id) {
browser_context()->extension_system()->EnableExtension(extension_id);
}
void Session::DisableExtension(const std::string& extension_id) {
browser_context()->extension_system()->DisableExtension(extension_id);
auto* extension_system = static_cast<extensions::ElectronExtensionSystem*>(
extensions::ExtensionSystem::Get(browser_context()));
extension_system->RemoveExtension(extension_id);
}
v8::Local<v8::Value> Session::GetExtension(const std::string& extension_id) {
@@ -1378,9 +1366,7 @@ v8::Local<v8::Value> Session::GetExtension(const std::string& extension_id) {
const extensions::Extension* extension =
registry->GetInstalledExtension(extension_id);
if (extension) {
const auto& extension_info =
extensions::ElectronExtensionInfo(extension, browser_context());
return gin::ConvertToV8(isolate_, extension_info);
return gin::ConvertToV8(isolate_, extension);
} else {
return v8::Null(isolate_);
}
@@ -1390,40 +1376,29 @@ v8::Local<v8::Value> Session::GetAllExtensions() {
auto* registry = extensions::ExtensionRegistry::Get(browser_context());
const extensions::ExtensionSet extensions =
registry->GenerateInstalledExtensionsSet();
std::vector<extensions::ElectronExtensionInfo> extensions_vector;
std::vector<const extensions::Extension*> extensions_vector;
for (const auto& extension : extensions) {
if (extension->location() !=
extensions::mojom::ManifestLocation::kComponent) {
const auto& extension_info =
extensions::ElectronExtensionInfo(extension.get(), browser_context());
extensions_vector.emplace_back(extension_info);
}
extensions::mojom::ManifestLocation::kComponent)
extensions_vector.emplace_back(extension.get());
}
return gin::ConvertToV8(isolate_, extensions_vector);
}
void Session::OnExtensionLoaded(
content::BrowserContext* content_browser_context,
const extensions::Extension* extension) {
const auto& extension_info =
extensions::ElectronExtensionInfo(extension, browser_context());
Emit("extension-loaded", extension_info);
void Session::OnExtensionLoaded(content::BrowserContext* browser_context,
const extensions::Extension* extension) {
Emit("extension-loaded", extension);
}
void Session::OnExtensionUnloaded(
content::BrowserContext* content_browser_context,
const extensions::Extension* extension,
extensions::UnloadedExtensionReason reason) {
const auto& extension_info =
extensions::ElectronExtensionInfo(extension, browser_context());
Emit("extension-unloaded", extension_info);
void Session::OnExtensionUnloaded(content::BrowserContext* browser_context,
const extensions::Extension* extension,
extensions::UnloadedExtensionReason reason) {
Emit("extension-unloaded", extension);
}
void Session::OnExtensionReady(content::BrowserContext* content_browser_context,
void Session::OnExtensionReady(content::BrowserContext* browser_context,
const extensions::Extension* extension) {
const auto& extension_info =
extensions::ElectronExtensionInfo(extension, browser_context());
Emit("extension-ready", extension_info);
Emit("extension-ready", extension);
}
#endif
@@ -1900,8 +1875,6 @@ void Session::FillObjectTemplate(v8::Isolate* isolate,
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
.SetMethod("loadExtension", &Session::LoadExtension)
.SetMethod("removeExtension", &Session::RemoveExtension)
.SetMethod("enableExtension", &Session::EnableExtension)
.SetMethod("disableExtension", &Session::DisableExtension)
.SetMethod("getExtension", &Session::GetExtension)
.SetMethod("getAllExtensions", &Session::GetAllExtensions)
#endif

View File

@@ -55,12 +55,6 @@ namespace net {
class ProxyConfig;
}
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
namespace extensions {
class ElectronExtensionSystem;
}
#endif
namespace electron {
class ElectronBrowserContext;
@@ -188,8 +182,6 @@ class Session final : public gin::Wrappable<Session>,
v8::Local<v8::Promise> LoadExtension(const base::FilePath& extension_path,
gin::Arguments* args);
void RemoveExtension(const std::string& extension_id);
void EnableExtension(const std::string& extension_id);
void DisableExtension(const std::string& extension_id);
v8::Local<v8::Value> GetExtension(const std::string& extension_id);
v8::Local<v8::Value> GetAllExtensions();

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

@@ -155,7 +155,10 @@ class ElectronBrowserContext : public content::BrowserContext {
}
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
extensions::ElectronExtensionSystem* extension_system() const {
extensions::ElectronExtensionSystem* extension_system() {
// Guard usages of extension_system() with !IsOffTheRecord()
// There is no extension system for in-memory sessions
DCHECK(!IsOffTheRecord());
return extension_system_;
}
#endif

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

@@ -1,33 +0,0 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ELECTRON_SHELL_BROWSER_EXTENSIONS_ELECTRON_EXTENSION_INFO_H_
#define ELECTRON_SHELL_BROWSER_EXTENSIONS_ELECTRON_EXTENSION_INFO_H_
#include "base/memory/raw_ptr.h"
namespace electron {
class ElectronBrowserContext;
}
namespace extensions {
class Extension;
struct ElectronExtensionInfo {
explicit ElectronExtensionInfo(const Extension* extension_in,
const electron::ElectronBrowserContext* browser_context_in)
: extension(extension_in),
browser_context(browser_context_in) {
DCHECK(extension_in);
DCHECK(browser_context_in);
}
raw_ptr<const Extension> extension;
raw_ptr<const electron::ElectronBrowserContext> browser_context;
};
} // namespace extensions
#endif // ELECTRON_SHELL_BROWSER_EXTENSIONS_ELECTRON_EXTENSION_INFO_H_

View File

@@ -6,6 +6,7 @@
#include <utility>
#include "base/auto_reset.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
@@ -16,14 +17,16 @@
#include "base/time/time.h"
#include "extensions/browser/extension_file_task_runner.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/pref_names.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/file_util.h"
#include "extensions/common/manifest_constants.h"
#include "shell/browser/extensions/electron_extension_system.h"
namespace extensions {
using LoadErrorBehavior = ExtensionRegistrar::LoadErrorBehavior;
namespace {
std::pair<scoped_refptr<const Extension>, std::string> LoadUnpacked(
@@ -89,9 +92,9 @@ std::pair<scoped_refptr<const Extension>, std::string> LoadUnpacked(
} // namespace
ElectronExtensionLoader::ElectronExtensionLoader(
content::BrowserContext* browser_context,
ElectronExtensionSystem* extension_system)
: browser_context_(browser_context), extension_system_(extension_system) {}
content::BrowserContext* browser_context)
: browser_context_(browser_context),
extension_registrar_(browser_context, this) {}
ElectronExtensionLoader::~ElectronExtensionLoader() = default;
@@ -105,12 +108,34 @@ void ElectronExtensionLoader::LoadExtension(
weak_factory_.GetWeakPtr(), std::move(cb)));
}
void ElectronExtensionLoader::ReloadExtension(const ExtensionId& extension_id) {
const Extension* extension = ExtensionRegistry::Get(browser_context_)
->GetInstalledExtension(extension_id);
// We shouldn't be trying to reload extensions that haven't been added.
DCHECK(extension);
// This should always start false since it's only set here, or in
// LoadExtensionForReload() as a result of the call below.
DCHECK_EQ(false, did_schedule_reload_);
base::AutoReset<bool> reset_did_schedule_reload(&did_schedule_reload_, false);
extension_registrar_.ReloadExtension(extension_id, LoadErrorBehavior::kQuiet);
if (did_schedule_reload_)
return;
}
void ElectronExtensionLoader::UnloadExtension(
const ExtensionId& extension_id,
extensions::UnloadedExtensionReason reason) {
extension_registrar_.RemoveExtension(extension_id, reason);
}
void ElectronExtensionLoader::FinishExtensionLoad(
base::OnceCallback<void(const Extension*, const std::string&)> cb,
std::pair<scoped_refptr<const Extension>, std::string> result) {
scoped_refptr<const Extension> extension = result.first;
if (extension) {
extension_system_->AddExtension(extension.get());
extension_registrar_.AddExtension(extension);
// Write extension install time to ExtensionPrefs. This is required by
// WebRequestAPI which calls extensions::ExtensionPrefs::GetInstallTime.
@@ -133,4 +158,89 @@ void ElectronExtensionLoader::FinishExtensionLoad(
std::move(cb).Run(extension.get(), result.second);
}
void ElectronExtensionLoader::FinishExtensionReload(
const ExtensionId& old_extension_id,
std::pair<scoped_refptr<const Extension>, std::string> result) {
scoped_refptr<const Extension> extension = result.first;
if (extension) {
extension_registrar_.AddExtension(extension);
}
}
void ElectronExtensionLoader::PreAddExtension(const Extension* extension,
const Extension* old_extension) {
if (old_extension)
return;
// The extension might be disabled if a previous reload attempt failed. In
// that case, we want to remove that disable reason.
ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(browser_context_);
if (extension_prefs->IsExtensionDisabled(extension->id()) &&
extension_prefs->HasDisableReason(extension->id(),
disable_reason::DISABLE_RELOAD)) {
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()).empty()) {
extension_prefs->SetExtensionEnabled(extension->id());
}
}
}
void ElectronExtensionLoader::PostActivateExtension(
scoped_refptr<const Extension> extension) {}
void ElectronExtensionLoader::PostDeactivateExtension(
scoped_refptr<const Extension> extension) {}
void ElectronExtensionLoader::PreUninstallExtension(
scoped_refptr<const Extension> extension) {}
void ElectronExtensionLoader::PostUninstallExtension(
scoped_refptr<const Extension> extension,
base::OnceClosure done_callback) {}
void ElectronExtensionLoader::PostNotifyUninstallExtension(
scoped_refptr<const Extension> extension) {}
void ElectronExtensionLoader::LoadExtensionForReload(
const ExtensionId& extension_id,
const base::FilePath& path,
LoadErrorBehavior load_error_behavior) {
CHECK(!path.empty());
// TODO(nornagon): we should save whether file access was granted
// when loading this extension and retain it here. As is, reloading an
// extension will cause the file access permission to be dropped.
int load_flags = Extension::FOLLOW_SYMLINKS_ANYWHERE;
GetExtensionFileTaskRunner()->PostTaskAndReplyWithResult(
FROM_HERE, base::BindOnce(&LoadUnpacked, path, load_flags),
base::BindOnce(&ElectronExtensionLoader::FinishExtensionReload,
weak_factory_.GetWeakPtr(), extension_id));
did_schedule_reload_ = true;
}
void ElectronExtensionLoader::ShowExtensionDisabledError(
const Extension* extension,
bool is_remote_install) {}
void ElectronExtensionLoader::FinishDelayedInstallationsIfAny() {}
bool ElectronExtensionLoader::CanAddExtension(const Extension* extension) {
return true;
}
bool ElectronExtensionLoader::CanEnableExtension(const Extension* extension) {
return true;
}
bool ElectronExtensionLoader::CanDisableExtension(const Extension* extension) {
// Extensions cannot be disabled by the user.
return false;
}
bool ElectronExtensionLoader::ShouldBlockExtension(const Extension* extension) {
return false;
}
} // namespace extensions

View File

@@ -11,6 +11,7 @@
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "extensions/browser/extension_registrar.h"
#include "extensions/common/extension_id.h"
namespace base {
@@ -24,14 +25,12 @@ class BrowserContext;
namespace extensions {
class Extension;
class ElectronExtensionSystem;
// Handles extension loading.
class ElectronExtensionLoader {
// Handles extension loading and reloading using ExtensionRegistrar.
class ElectronExtensionLoader : public ExtensionRegistrar::Delegate {
public:
explicit ElectronExtensionLoader(content::BrowserContext* browser_context,
ElectronExtensionSystem* extension_system);
~ElectronExtensionLoader();
explicit ElectronExtensionLoader(content::BrowserContext* browser_context);
~ElectronExtensionLoader() override;
// disable copy
ElectronExtensionLoader(const ElectronExtensionLoader&) = delete;
@@ -44,13 +43,64 @@ class ElectronExtensionLoader {
base::OnceCallback<void(const Extension* extension,
const std::string&)> cb);
// Starts reloading the extension. A keep-alive is maintained until the
// reload succeeds/fails. If the extension is an app, it will be launched upon
// reloading.
// This may invalidate references to the old Extension object, so it takes the
// ID by value.
void ReloadExtension(const ExtensionId& extension_id);
void UnloadExtension(const ExtensionId& extension_id,
extensions::UnloadedExtensionReason reason);
ExtensionRegistrar* registrar() { return &extension_registrar_; }
private:
// If the extension loaded successfully, enables it. If it's an app, launches
// it. If the load failed, updates ShellKeepAliveRequester.
void FinishExtensionReload(
const ExtensionId& old_extension_id,
std::pair<scoped_refptr<const Extension>, std::string> result);
void FinishExtensionLoad(
base::OnceCallback<void(const Extension*, const std::string&)> cb,
std::pair<scoped_refptr<const Extension>, std::string> result);
raw_ptr<content::BrowserContext> browser_context_; // Not owned.
raw_ptr<ElectronExtensionSystem> extension_system_; // Not owned.
// ExtensionRegistrar::Delegate:
void PreAddExtension(const Extension* extension,
const Extension* old_extension) override;
void PostActivateExtension(scoped_refptr<const Extension> extension) override;
void PostDeactivateExtension(
scoped_refptr<const Extension> extension) override;
void PreUninstallExtension(scoped_refptr<const Extension> extension) override;
void PostUninstallExtension(scoped_refptr<const Extension> extension,
base::OnceClosure done_callback) override;
void PostNotifyUninstallExtension(
scoped_refptr<const Extension> extension) override;
void LoadExtensionForReload(
const ExtensionId& extension_id,
const base::FilePath& path,
ExtensionRegistrar::LoadErrorBehavior load_error_behavior) override;
void ShowExtensionDisabledError(const Extension* extension,
bool is_remote_install) override;
void FinishDelayedInstallationsIfAny() override;
bool CanAddExtension(const Extension* extension) override;
bool CanEnableExtension(const Extension* extension) override;
bool CanDisableExtension(const Extension* extension) override;
bool ShouldBlockExtension(const Extension* extension) override;
raw_ptr<content::BrowserContext> browser_context_; // Not owned.
// Registers and unregisters extensions.
ExtensionRegistrar extension_registrar_;
// Holds keep-alives for relaunching apps.
// ShellKeepAliveRequester keep_alive_requester_;
// Indicates that we posted the (asynchronous) task to start reloading.
// Used by ReloadExtension() to check whether ExtensionRegistrar calls
// LoadExtensionForReload().
bool did_schedule_reload_ = false;
base::WeakPtrFactory<ElectronExtensionLoader> weak_factory_{this};
};

View File

@@ -1,127 +0,0 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "shell/browser/extensions/electron_extension_registrar_delegate.h"
#include <utility>
#include "base/auto_reset.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "extensions/browser/extension_file_task_runner.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/pref_names.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/file_util.h"
#include "extensions/common/manifest_constants.h"
#include "shell/browser/extensions/electron_extension_system.h"
namespace extensions {
using LoadErrorBehavior = ExtensionRegistrar::LoadErrorBehavior;
ElectronExtensionRegistrarDelegate::ElectronExtensionRegistrarDelegate(
content::BrowserContext* browser_context,
ElectronExtensionSystem* extension_system)
: browser_context_(browser_context), extension_system_(extension_system) {}
ElectronExtensionRegistrarDelegate::~ElectronExtensionRegistrarDelegate() =
default;
void ElectronExtensionRegistrarDelegate::PreAddExtension(
const Extension* extension,
const Extension* old_extension) {
if (old_extension)
return;
// The extension might be disabled if a previous reload attempt failed. In
// that case, we want to remove that disable reason.
ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(browser_context_);
if (extension_prefs->IsExtensionDisabled(extension->id()) &&
extension_prefs->HasDisableReason(extension->id(),
disable_reason::DISABLE_RELOAD)) {
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) {
extension_prefs->SetExtensionEnabled(extension->id());
}
}
}
void ElectronExtensionRegistrarDelegate::PostActivateExtension(
scoped_refptr<const Extension> extension) {}
void ElectronExtensionRegistrarDelegate::PostDeactivateExtension(
scoped_refptr<const Extension> extension) {}
void ElectronExtensionRegistrarDelegate::PreUninstallExtension(
scoped_refptr<const Extension> extension) {}
void ElectronExtensionRegistrarDelegate::PostUninstallExtension(
scoped_refptr<const Extension> extension,
base::OnceClosure done_callback) {}
void ElectronExtensionRegistrarDelegate::PostNotifyUninstallExtension(
scoped_refptr<const Extension> extension) {}
void ElectronExtensionRegistrarDelegate::LoadExtensionForReload(
const ExtensionId& extension_id,
const base::FilePath& path,
LoadErrorBehavior load_error_behavior) {
CHECK(!path.empty());
// TODO(nornagon): we should save whether file access was granted
// when loading this extension and retain it here. As is, reloading an
// extension will cause the file access permission to be dropped.
int load_flags = Extension::FOLLOW_SYMLINKS_ANYWHERE;
extension_system_->LoadExtension(
path, load_flags,
base::BindOnce(&ElectronExtensionRegistrarDelegate::FinishExtensionReload,
weak_factory_.GetWeakPtr()));
}
void ElectronExtensionRegistrarDelegate::FinishExtensionReload(
const Extension* extension,
const ExtensionId& extension_id) {
if (extension) {
extension_system_->AddExtension(extension);
}
}
void ElectronExtensionRegistrarDelegate::ShowExtensionDisabledError(
const Extension* extension,
bool is_remote_install) {}
void ElectronExtensionRegistrarDelegate::FinishDelayedInstallationsIfAny() {}
bool ElectronExtensionRegistrarDelegate::CanAddExtension(
const Extension* extension) {
return true;
}
bool ElectronExtensionRegistrarDelegate::CanEnableExtension(
const Extension* extension) {
return true;
}
bool ElectronExtensionRegistrarDelegate::CanDisableExtension(
const Extension* extension) {
return true;
}
bool ElectronExtensionRegistrarDelegate::ShouldBlockExtension(
const Extension* extension) {
return false;
}
} // namespace extensions

View File

@@ -1,86 +0,0 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ELECTRON_SHELL_BROWSER_EXTENSIONS_ELECTRON_EXTENSION_REGISTRAR_DELEGATE_H_
#define ELECTRON_SHELL_BROWSER_EXTENSIONS_ELECTRON_EXTENSION_REGISTRAR_DELEGATE_H_
#include <string>
#include <utility>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "extensions/browser/extension_registrar.h"
#include "extensions/common/extension_id.h"
namespace base {
class FilePath;
}
namespace content {
class BrowserContext;
}
namespace extensions {
class Extension;
class ElectronExtensionSystem;
// Handles extension loading and reloading using ExtensionRegistrar.
class ElectronExtensionRegistrarDelegate : public ExtensionRegistrar::Delegate {
public:
explicit ElectronExtensionRegistrarDelegate(
content::BrowserContext* browser_context,
ElectronExtensionSystem* extension_system);
~ElectronExtensionRegistrarDelegate() override;
// disable copy
ElectronExtensionRegistrarDelegate(
const ElectronExtensionRegistrarDelegate&) = delete;
ElectronExtensionRegistrarDelegate& operator=(
const ElectronExtensionRegistrarDelegate&) = delete;
void set_extension_registrar(ExtensionRegistrar* registrar) {
extension_registrar_ = registrar;
}
private:
// ExtensionRegistrar::Delegate:
void PreAddExtension(const Extension* extension,
const Extension* old_extension) override;
void PostActivateExtension(scoped_refptr<const Extension> extension) override;
void PostDeactivateExtension(
scoped_refptr<const Extension> extension) override;
void PreUninstallExtension(scoped_refptr<const Extension> extension) override;
void PostUninstallExtension(scoped_refptr<const Extension> extension,
base::OnceClosure done_callback) override;
void PostNotifyUninstallExtension(
scoped_refptr<const Extension> extension) override;
void LoadExtensionForReload(
const ExtensionId& extension_id,
const base::FilePath& path,
ExtensionRegistrar::LoadErrorBehavior load_error_behavior) override;
void ShowExtensionDisabledError(const Extension* extension,
bool is_remote_install) override;
void FinishDelayedInstallationsIfAny() override;
bool CanAddExtension(const Extension* extension) override;
bool CanEnableExtension(const Extension* extension) override;
bool CanDisableExtension(const Extension* extension) override;
bool ShouldBlockExtension(const Extension* extension) override;
// If the extension loaded successfully, enables it. If it's an app, launches
// it. If the load failed, updates ShellKeepAliveRequester.
void FinishExtensionReload(const Extension* extension,
const ExtensionId& extension_id);
raw_ptr<content::BrowserContext> browser_context_; // Not owned.
raw_ptr<ElectronExtensionSystem> extension_system_; // Not owned.
raw_ptr<ExtensionRegistrar> extension_registrar_ = nullptr;
base::WeakPtrFactory<ElectronExtensionRegistrarDelegate> weak_factory_{this};
};
} // namespace extensions
#endif // ELECTRON_SHELL_BROWSER_EXTENSIONS_ELECTRON_EXTENSION_REGISTRAR_DELEGATE_H_

View File

@@ -29,7 +29,6 @@
#include "extensions/browser/user_script_manager.h"
#include "extensions/common/constants.h"
#include "shell/browser/extensions/electron_extension_loader.h"
#include "shell/browser/extensions/electron_extension_registrar_delegate.h"
#if BUILDFLAG(ENABLE_PDF_VIEWER)
#include "chrome/browser/pdf/pdf_extension_util.h" // nogncheck
@@ -40,8 +39,6 @@ using content::BrowserThread;
namespace extensions {
using LoadErrorBehavior = ExtensionRegistrar::LoadErrorBehavior;
ElectronExtensionSystem::ElectronExtensionSystem(
BrowserContext* browser_context)
: browser_context_(browser_context),
@@ -50,10 +47,6 @@ ElectronExtensionSystem::ElectronExtensionSystem(
ElectronExtensionSystem::~ElectronExtensionSystem() = default;
void ElectronExtensionSystem::AddExtension(const Extension* extension) {
extension_registrar_->AddExtension(extension);
}
void ElectronExtensionSystem::LoadExtension(
const base::FilePath& extension_dir,
int load_flags,
@@ -67,56 +60,26 @@ void ElectronExtensionSystem::FinishInitialization() {
}
void ElectronExtensionSystem::ReloadExtension(const ExtensionId& extension_id) {
const Extension* extension = ExtensionRegistry::Get(browser_context_)
->GetInstalledExtension(extension_id);
// We shouldn't be trying to reload extensions that haven't been added.
DCHECK(extension);
extension_registrar_->ReloadExtension(extension_id,
LoadErrorBehavior::kQuiet);
extension_loader_->ReloadExtension(extension_id);
}
void ElectronExtensionSystem::RemoveExtension(const ExtensionId& extension_id) {
extension_registrar_->RemoveExtension(
extension_loader_->UnloadExtension(
extension_id, extensions::UnloadedExtensionReason::UNINSTALL);
}
void ElectronExtensionSystem::EnableExtension(const std::string& extension_id) {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
extension_registrar_->EnableExtension(extension_id);
}
void ElectronExtensionSystem::DisableExtension(
const ExtensionId& extension_id) {
extension_registrar_->DisableExtension(
extension_id, disable_reason::DisableReason::DISABLE_USER_ACTION);
}
bool ElectronExtensionSystem::IsExtensionEnabled(
const ExtensionId& extension_id) const {
return extension_registrar_->IsExtensionEnabled(extension_id);
}
void ElectronExtensionSystem::Shutdown() {
extension_loader_.reset();
}
void ElectronExtensionSystem::InitForRegularProfile(bool extensions_enabled) {
extension_registrar_delegate_ =
std::make_unique<ElectronExtensionRegistrarDelegate>(browser_context_,
this);
extension_registrar_ = std::make_unique<ExtensionRegistrar>(
browser_context_, extension_registrar_delegate_.get());
extension_registrar_delegate_->set_extension_registrar(
extension_registrar_.get());
service_worker_manager_ =
std::make_unique<ServiceWorkerManager>(browser_context_);
quota_service_ = std::make_unique<QuotaService>();
user_script_manager_ = std::make_unique<UserScriptManager>(browser_context_);
app_sorting_ = std::make_unique<NullAppSorting>();
extension_loader_ =
std::make_unique<ElectronExtensionLoader>(browser_context_, this);
std::make_unique<ElectronExtensionLoader>(browser_context_);
if (!browser_context_->IsOffTheRecord())
LoadComponentExtensions();
@@ -157,7 +120,7 @@ void ElectronExtensionSystem::LoadComponentExtensions() {
extensions::Extension::Create(
root_directory, extensions::mojom::ManifestLocation::kComponent,
*pdf_manifest, extensions::Extension::REQUIRE_KEY, &utf8_error);
AddExtension(pdf_extension.get());
extension_loader_->registrar()->AddExtension(pdf_extension);
}
#endif
}

View File

@@ -13,8 +13,6 @@
#include "base/one_shot_event.h"
#include "components/value_store/value_store_factory.h"
#include "components/value_store/value_store_factory_impl.h"
#include "extensions/browser/disable_reason.h"
#include "extensions/browser/extension_registrar.h"
#include "extensions/browser/extension_system.h"
namespace base {
@@ -28,7 +26,6 @@ class BrowserContext;
namespace extensions {
class ElectronExtensionLoader;
class ElectronExtensionRegistrarDelegate;
class ValueStoreFactory;
// A simplified version of ExtensionSystem for app_shell. Allows
@@ -43,10 +40,6 @@ class ElectronExtensionSystem : public ExtensionSystem {
ElectronExtensionSystem(const ElectronExtensionSystem&) = delete;
ElectronExtensionSystem& operator=(const ElectronExtensionSystem&) = delete;
// Adds |extension| to this ExtensionService and notifies observers that the
// extension has been loaded.
void AddExtension(const Extension* extension);
// Loads an unpacked extension from a directory. Returns the extension on
// success, or nullptr otherwise.
void LoadExtension(
@@ -62,17 +55,6 @@ class ElectronExtensionSystem : public ExtensionSystem {
void RemoveExtension(const ExtensionId& extension_id);
// Enables the extension. If the extension is already enabled, does
// nothing.
void EnableExtension(const ExtensionId& extension_id);
// Disables the extension. If the extension is already disabled, just adds
// the incoming disable reason(s). If the extension cannot be disabled (due to
// policy), does nothing.
void DisableExtension(const ExtensionId& extension_id);
bool IsExtensionEnabled(const ExtensionId& extension_id) const;
// KeyedService implementation:
void Shutdown() override;
@@ -104,10 +86,6 @@ class ElectronExtensionSystem : public ExtensionSystem {
const std::string& extension_id,
const base::Value::Dict& attributes) override;
base::WeakPtr<ElectronExtensionSystem> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
private:
void OnExtensionRegisteredWithRequestContexts(
scoped_refptr<Extension> extension);
@@ -121,12 +99,6 @@ class ElectronExtensionSystem : public ExtensionSystem {
std::unique_ptr<AppSorting> app_sorting_;
std::unique_ptr<ManagementPolicy> management_policy_;
std::unique_ptr<ElectronExtensionRegistrarDelegate>
extension_registrar_delegate_;
// Helper to register and unregister extensions.
std::unique_ptr<ExtensionRegistrar> extension_registrar_;
std::unique_ptr<ElectronExtensionLoader> extension_loader_;
scoped_refptr<value_store::ValueStoreFactory> store_factory_;

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,9 +6,6 @@
#include "extensions/common/extension.h"
#include "gin/dictionary.h"
#include "shell/browser/electron_browser_context.h"
#include "shell/browser/extensions/electron_extension_info.h"
#include "shell/browser/extensions/electron_extension_system.h"
#include "shell/common/gin_converters/file_path_converter.h"
#include "shell/common/gin_converters/gurl_converter.h"
#include "shell/common/gin_converters/value_converter.h"
@@ -16,20 +13,16 @@
namespace gin {
// static
v8::Local<v8::Value> Converter<extensions::ElectronExtensionInfo>::ToV8(
v8::Local<v8::Value> Converter<const extensions::Extension*>::ToV8(
v8::Isolate* isolate,
const extensions::ElectronExtensionInfo& info) {
auto extension_id = info.extension->id();
const extensions::Extension* extension) {
auto dict = gin::Dictionary::CreateEmpty(isolate);
dict.Set("id", extension_id);
dict.Set("name", info.extension->name());
dict.Set("path", info.extension->path());
dict.Set("url", info.extension->url());
dict.Set("version", info.extension->VersionString());
dict.Set("manifest", *info.extension->manifest()->value());
auto* ext_system = info.browser_context->extension_system();
dict.Set("enabled", ext_system->IsExtensionEnabled(extension_id));
dict.Set("id", extension->id());
dict.Set("name", extension->name());
dict.Set("path", extension->path());
dict.Set("url", extension->url());
dict.Set("version", extension->VersionString());
dict.Set("manifest", *extension->manifest()->value());
return gin::ConvertToV8(isolate, dict);
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2025 Salesforce, Inc.
// Copyright (c) 2019 Slack Technologies, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
@@ -8,16 +8,15 @@
#include "gin/converter.h"
namespace extensions {
struct ElectronExtensionInfo;
class Extension;
}
namespace gin {
template <>
struct Converter<extensions::ElectronExtensionInfo> {
static v8::Local<v8::Value> ToV8(
v8::Isolate* isolate,
const extensions::ElectronExtensionInfo& val);
struct Converter<const extensions::Extension*> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const extensions::Extension* val);
};
} // namespace gin

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;