mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
29 Commits
get-resour
...
v16.0.0-ni
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42936b07fe | ||
|
|
985f1b5c04 | ||
|
|
ac49e6af4a | ||
|
|
69f1c1b083 | ||
|
|
f17e6ae318 | ||
|
|
4f739d7837 | ||
|
|
590858a38d | ||
|
|
edb7413bae | ||
|
|
e223b4db94 | ||
|
|
08e9aea940 | ||
|
|
66c458a353 | ||
|
|
6a9cada98c | ||
|
|
d783e944d3 | ||
|
|
641260bc32 | ||
|
|
bc508c6113 | ||
|
|
ec6cd0053e | ||
|
|
8e1160fde4 | ||
|
|
320bea4c28 | ||
|
|
59ab79417d | ||
|
|
423172775e | ||
|
|
4703dc0a1d | ||
|
|
481b774fd7 | ||
|
|
acbd643e2a | ||
|
|
97929eab5f | ||
|
|
1c29734c91 | ||
|
|
8179349625 | ||
|
|
a17e48061a | ||
|
|
40e76dca07 | ||
|
|
6e43b0bcbf |
@@ -219,6 +219,8 @@ step-maybe-cleanup-arm64-mac: &step-maybe-cleanup-arm64-mac
|
||||
killall Safari || echo "No Safari processes left running"
|
||||
rm -rf ~/Library/Application\ Support/Electron*
|
||||
rm -rf ~/Library/Application\ Support/electron*
|
||||
security delete-generic-password -l "Chromium Safe Storage"
|
||||
security delete-generic-password -l "Electron Test Main Safe Storage"
|
||||
elif [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
XVFB=/usr/bin/Xvfb
|
||||
/sbin/start-stop-daemon --stop --exec $XVFB || echo "Xvfb not running"
|
||||
|
||||
@@ -1 +1 @@
|
||||
16.0.0-nightly.20210803
|
||||
16.0.0-nightly.20210811
|
||||
@@ -3,5 +3,7 @@
|
||||
"_schema": "0 == off, 1 == on, r == removed fuse",
|
||||
"_version": 1,
|
||||
"run_as_node": "1",
|
||||
"cookie_encryption": "0"
|
||||
"cookie_encryption": "0",
|
||||
"node_options": "1",
|
||||
"node_cli_inspect": "1"
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ template("npm_action") {
|
||||
|
||||
action("npm_pre_flight_" + target_name) {
|
||||
inputs = [
|
||||
"package.json",
|
||||
"yarn.lock",
|
||||
"//electron/package.json",
|
||||
"//electron/yarn.lock",
|
||||
]
|
||||
script = "//electron/build/npm-run.py"
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ template("webpack_build") {
|
||||
rebase_path("$target_gen_dir/buildflags/buildflags.h"),
|
||||
"--env.mode=" + mode,
|
||||
]
|
||||
deps += [ "buildflags" ]
|
||||
deps += [ "//electron/buildflags" ]
|
||||
|
||||
outputs = [ invoker.out_file ]
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@ following projects:
|
||||
* [socorro](https://github.com/mozilla/socorro)
|
||||
* [mini-breakpad-server](https://github.com/electron/mini-breakpad-server)
|
||||
|
||||
> **Note:** Electron uses Crashpad, not Breakpad, to collect and upload
|
||||
> crashes, but for the time being, the [upload protocol is the same](https://chromium.googlesource.com/crashpad/crashpad/+/HEAD/doc/overview_design.md#Upload-to-collection-server).
|
||||
|
||||
Or use a 3rd party hosted solution:
|
||||
|
||||
* [Backtrace](https://backtrace.io/electron/)
|
||||
@@ -26,49 +29,12 @@ Or use a 3rd party hosted solution:
|
||||
* [BugSplat](https://www.bugsplat.com/docs/platforms/electron)
|
||||
|
||||
Crash reports are stored temporarily before being uploaded in a directory
|
||||
underneath the app's user data directory (called 'Crashpad' on Windows and Mac,
|
||||
or 'Crash Reports' on Linux). You can override this directory by calling
|
||||
`app.setPath('crashDumps', '/path/to/crashes')` before starting the crash
|
||||
reporter.
|
||||
underneath the app's user data directory, called 'Crashpad'. You can override
|
||||
this directory by calling `app.setPath('crashDumps', '/path/to/crashes')`
|
||||
before starting the crash reporter.
|
||||
|
||||
On Windows and macOS, Electron uses
|
||||
[crashpad](https://chromium.googlesource.com/crashpad/crashpad/+/master/README.md)
|
||||
to monitor and report crashes. On Linux, Electron uses
|
||||
[breakpad](https://chromium.googlesource.com/breakpad/breakpad/+/master/). This
|
||||
is an implementation detail driven by Chromium, and it may change in future. In
|
||||
particular, crashpad is newer and will likely eventually replace breakpad on
|
||||
all platforms.
|
||||
|
||||
### Note about Node child processes on Linux
|
||||
|
||||
If you are using the Node.js `child_process` module and want to report crashes
|
||||
from those processes on Linux, there is an extra step you will need to take to
|
||||
properly initialize the crash reporter in the child process. This is not
|
||||
necessary on Mac or Windows, as those platforms use Crashpad, which
|
||||
automatically monitors child processes.
|
||||
|
||||
Since `require('electron')` is not available in Node child processes, the
|
||||
following APIs are available on the `process` object in Node child processes.
|
||||
Note that, on Linux, each Node child process has its own separate instance of
|
||||
the breakpad crash reporter. This is dissimilar to renderer child processes,
|
||||
which have a "stub" breakpad reporter which returns information to the main
|
||||
process for reporting.
|
||||
|
||||
#### `process.crashReporter.start(options)`
|
||||
|
||||
See [`crashReporter.start()`](#crashreporterstartoptions).
|
||||
|
||||
#### `process.crashReporter.getParameters()`
|
||||
|
||||
See [`crashReporter.getParameters()`](#crashreportergetparameters).
|
||||
|
||||
#### `process.crashReporter.addExtraParameter(key, value)`
|
||||
|
||||
See [`crashReporter.addExtraParameter(key, value)`](#crashreporteraddextraparameterkey-value).
|
||||
|
||||
#### `process.crashReporter.removeExtraParameter(key)`
|
||||
|
||||
See [`crashReporter.removeExtraParameter(key)`](#crashreporterremoveextraparameterkey).
|
||||
Electron uses [crashpad](https://chromium.googlesource.com/crashpad/crashpad/+/refs/heads/main/README.md)
|
||||
to monitor and report crashes.
|
||||
|
||||
## Methods
|
||||
|
||||
@@ -186,12 +152,6 @@ names must be no longer than 39 bytes, and values must be no longer than 20320
|
||||
bytes. Keys with names longer than the maximum will be silently ignored. Key
|
||||
values longer than the maximum length will be truncated.
|
||||
|
||||
**Note:** On linux values that are longer than 127 bytes will be chunked into
|
||||
multiple keys, each 127 bytes in length. E.g. `addExtraParameter('foo', 'a'.repeat(130))`
|
||||
will result in two chunked keys `foo__1` and `foo__2`, the first will contain
|
||||
the first 127 bytes and the second will contain the remaining 3 bytes. On
|
||||
your crash reporting backend you should stitch together keys in this format.
|
||||
|
||||
### `crashReporter.removeExtraParameter(key)`
|
||||
|
||||
* `key` String - Parameter key, must be no longer than 39 bytes.
|
||||
@@ -203,6 +163,32 @@ will not include this parameter.
|
||||
|
||||
Returns `Record<String, String>` - The current 'extra' parameters of the crash reporter.
|
||||
|
||||
## In Node child processes
|
||||
|
||||
Since `require('electron')` is not available in Node child processes, the
|
||||
following APIs are available on the `process` object in Node child processes.
|
||||
|
||||
#### `process.crashReporter.start(options)`
|
||||
|
||||
See [`crashReporter.start()`](#crashreporterstartoptions).
|
||||
|
||||
Note that if the crash reporter is started in the main process, it will
|
||||
automatically monitor child processes, so it should not be started in the child
|
||||
process. Only use this method if the main process does not initialize the crash
|
||||
reporter.
|
||||
|
||||
#### `process.crashReporter.getParameters()`
|
||||
|
||||
See [`crashReporter.getParameters()`](#crashreportergetparameters).
|
||||
|
||||
#### `process.crashReporter.addExtraParameter(key, value)`
|
||||
|
||||
See [`crashReporter.addExtraParameter(key, value)`](#crashreporteraddextraparameterkey-value).
|
||||
|
||||
#### `process.crashReporter.removeExtraParameter(key)`
|
||||
|
||||
See [`crashReporter.removeExtraParameter(key)`](#crashreporterremoveextraparameterkey).
|
||||
|
||||
## Crash Report Payload
|
||||
|
||||
The crash reporter will send the following data to the `submitURL` as
|
||||
|
||||
@@ -162,7 +162,7 @@ const template = [
|
||||
{ role: 'services' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'hide' },
|
||||
{ role: 'hideothers' },
|
||||
{ role: 'hideOthers' },
|
||||
{ role: 'unhide' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'quit' }
|
||||
|
||||
40
docs/api/safe-storage.md
Normal file
40
docs/api/safe-storage.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# safeStorage
|
||||
|
||||
> Allows access to simple encryption and decryption of strings for storage on the local machine.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
This module protects data stored on disk from being accessed by other applications or users with full disk access.
|
||||
|
||||
Note that on Mac, access to the system Keychain is required and
|
||||
these calls can block the current thread to collect user input.
|
||||
The same is true for Linux, if a password management tool is available.
|
||||
|
||||
## Methods
|
||||
|
||||
The `safeStorage` module has the following methods:
|
||||
|
||||
### `safeStorage.isEncryptionAvailable()`
|
||||
|
||||
Returns `Boolean` - Whether encryption is available.
|
||||
|
||||
On Linux, returns true if the secret key is
|
||||
available. On MacOS, returns true if Keychain is available.
|
||||
On Windows, returns true with no other preconditions.
|
||||
|
||||
### `safeStorage.encryptString(plainText)`
|
||||
|
||||
* `plainText` String
|
||||
|
||||
Returns `Buffer` - An array of bytes representing the encrypted string.
|
||||
|
||||
This function will throw an error if encryption fails.
|
||||
|
||||
### `safeStorage.decryptString(encrypted)`
|
||||
|
||||
* `encrypted` Buffer
|
||||
|
||||
Returns `String` - the decrypted string. Decrypts the encrypted buffer
|
||||
obtained with `safeStorage.encryptString` back into a string.
|
||||
|
||||
This function will throw an error if decryption fails.
|
||||
@@ -834,6 +834,19 @@ this purpose.
|
||||
|
||||
Calling `event.preventDefault()` does __NOT__ have any effect.
|
||||
|
||||
### Event: 'did-start-navigation'
|
||||
|
||||
Returns:
|
||||
|
||||
* `url` String
|
||||
* `isInPlace` Boolean
|
||||
* `isMainFrame` Boolean
|
||||
* `frameProcessId` Integer
|
||||
* `frameRoutingId` Integer
|
||||
|
||||
Emitted when any frame (including main) starts navigating. `isInPlace` will be
|
||||
`true` for in-page navigations.
|
||||
|
||||
### Event: 'did-navigate'
|
||||
|
||||
Returns:
|
||||
@@ -846,6 +859,23 @@ This event is not emitted for in-page navigations, such as clicking anchor links
|
||||
or updating the `window.location.hash`. Use `did-navigate-in-page` event for
|
||||
this purpose.
|
||||
|
||||
### Event: 'did-frame-navigate'
|
||||
|
||||
Returns:
|
||||
|
||||
* `url` String
|
||||
* `httpResponseCode` Integer - -1 for non HTTP navigations
|
||||
* `httpStatusText` String - empty for non HTTP navigations,
|
||||
* `isMainFrame` Boolean
|
||||
* `frameProcessId` Integer
|
||||
* `frameRoutingId` Integer
|
||||
|
||||
Emitted when any frame navigation is done.
|
||||
|
||||
This event is not emitted for in-page navigations, such as clicking anchor links
|
||||
or updating the `window.location.hash`. Use `did-navigate-in-page` event for
|
||||
this purpose.
|
||||
|
||||
### Event: 'did-navigate-in-page'
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -12,6 +12,21 @@ This document uses the following convention to categorize breaking changes:
|
||||
* **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
|
||||
* **Removed:** An API or feature was removed, and is no longer supported by Electron.
|
||||
|
||||
## Planned Breaking API Changes (16.0)
|
||||
|
||||
### Behavior Changed: `crashReporter` implementation switched to Crashpad on Linux
|
||||
|
||||
The underlying implementation of the `crashReporter` API on Linux has changed
|
||||
from Breakpad to Crashpad, bringing it in line with Windows and Mac. As a
|
||||
result of this, child processes are now automatically monitored, and calling
|
||||
`process.crashReporter.start` in Node child processes is no longer needed (and
|
||||
is not advisable, as it will start a second instance of the Crashpad reporter).
|
||||
|
||||
There are also some subtle changes to how annotations will be reported on
|
||||
Linux, including that long values will no longer be split between annotations
|
||||
appended with `__1`, `__2` and so on, and instead will be truncated at the
|
||||
(new, longer) annotation value limit.
|
||||
|
||||
## Planned Breaking API Changes (14.0)
|
||||
|
||||
### Removed: `app.allowRendererProcessReuse`
|
||||
|
||||
@@ -42,6 +42,7 @@ auto_filenames = {
|
||||
"docs/api/power-save-blocker.md",
|
||||
"docs/api/process.md",
|
||||
"docs/api/protocol.md",
|
||||
"docs/api/safe-storage.md",
|
||||
"docs/api/screen.md",
|
||||
"docs/api/service-workers.md",
|
||||
"docs/api/session.md",
|
||||
@@ -213,6 +214,7 @@ auto_filenames = {
|
||||
"lib/browser/api/power-monitor.ts",
|
||||
"lib/browser/api/power-save-blocker.ts",
|
||||
"lib/browser/api/protocol.ts",
|
||||
"lib/browser/api/safe-storage.ts",
|
||||
"lib/browser/api/screen.ts",
|
||||
"lib/browser/api/session.ts",
|
||||
"lib/browser/api/share-menu.ts",
|
||||
|
||||
@@ -180,8 +180,8 @@ filenames = {
|
||||
"shell/browser/ui/cocoa/root_view_mac.mm",
|
||||
"shell/browser/ui/cocoa/views_delegate_mac.h",
|
||||
"shell/browser/ui/cocoa/views_delegate_mac.mm",
|
||||
"shell/browser/ui/cocoa/window_buttons_view.h",
|
||||
"shell/browser/ui/cocoa/window_buttons_view.mm",
|
||||
"shell/browser/ui/cocoa/window_buttons_proxy.h",
|
||||
"shell/browser/ui/cocoa/window_buttons_proxy.mm",
|
||||
"shell/browser/ui/drag_util_mac.mm",
|
||||
"shell/browser/ui/file_dialog_mac.mm",
|
||||
"shell/browser/ui/inspectable_web_contents_view_mac.h",
|
||||
@@ -288,6 +288,8 @@ filenames = {
|
||||
"shell/browser/api/electron_api_printing.cc",
|
||||
"shell/browser/api/electron_api_protocol.cc",
|
||||
"shell/browser/api/electron_api_protocol.h",
|
||||
"shell/browser/api/electron_api_safe_storage.cc",
|
||||
"shell/browser/api/electron_api_safe_storage.h",
|
||||
"shell/browser/api/electron_api_screen.cc",
|
||||
"shell/browser/api/electron_api_screen.h",
|
||||
"shell/browser/api/electron_api_service_worker_context.cc",
|
||||
|
||||
@@ -24,6 +24,7 @@ export const browserModuleList: ElectronInternal.ModuleEntry[] = [
|
||||
{ name: 'powerMonitor', loader: () => require('./power-monitor') },
|
||||
{ name: 'powerSaveBlocker', loader: () => require('./power-save-blocker') },
|
||||
{ name: 'protocol', loader: () => require('./protocol') },
|
||||
{ name: 'safeStorage', loader: () => require('./safe-storage') },
|
||||
{ name: 'screen', loader: () => require('./screen') },
|
||||
{ name: 'session', loader: () => require('./session') },
|
||||
{ name: 'ShareMenu', loader: () => require('./share-menu') },
|
||||
|
||||
3
lib/browser/api/safe-storage.ts
Normal file
3
lib/browser/api/safe-storage.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
const safeStorage = process._linkedBinding('electron_browser_safe_storage');
|
||||
|
||||
module.exports = safeStorage;
|
||||
@@ -8,7 +8,7 @@ import { serialize } from '@electron/internal/common/type-utils';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
interface GuestInstance {
|
||||
elementInstanceId?: number;
|
||||
elementInstanceId: number;
|
||||
visibilityState?: VisibilityState;
|
||||
embedder: Electron.WebContents;
|
||||
guest: Electron.WebContents;
|
||||
@@ -46,6 +46,7 @@ function makeWebPreferences (embedder: Electron.WebContents, params: Record<stri
|
||||
webSecurity: !params.disablewebsecurity,
|
||||
enableBlinkFeatures: params.blinkfeatures,
|
||||
disableBlinkFeatures: params.disableblinkfeatures,
|
||||
partition: params.partition,
|
||||
...parsedWebPreferences
|
||||
};
|
||||
|
||||
@@ -77,14 +78,24 @@ function makeWebPreferences (embedder: Electron.WebContents, params: Record<stri
|
||||
|
||||
// Create a new guest instance.
|
||||
const createGuest = function (embedder: Electron.WebContents, embedderFrameId: number, elementInstanceId: number, params: Record<string, any>) {
|
||||
const webPreferences = makeWebPreferences(embedder, params);
|
||||
const event = eventBinding.createWithSender(embedder);
|
||||
|
||||
embedder.emit('will-attach-webview', event, webPreferences, params);
|
||||
if (event.defaultPrevented) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
const guest = (webContents as typeof ElectronInternal.WebContents).create({
|
||||
...webPreferences,
|
||||
type: 'webview',
|
||||
partition: params.partition,
|
||||
embedder
|
||||
});
|
||||
|
||||
const guestInstanceId = guest.id;
|
||||
guestInstances.set(guestInstanceId, {
|
||||
elementInstanceId,
|
||||
guest,
|
||||
embedder
|
||||
});
|
||||
@@ -98,9 +109,6 @@ const createGuest = function (embedder: Electron.WebContents, embedderFrameId: n
|
||||
|
||||
// Init guest web view after attached.
|
||||
guest.once('did-attach' as any, function (this: Electron.WebContents, event: Electron.Event) {
|
||||
params = this.attachParams!;
|
||||
delete this.attachParams;
|
||||
|
||||
const previouslyAttached = this.viewInstanceId != null;
|
||||
this.viewInstanceId = params.instanceId;
|
||||
|
||||
@@ -160,76 +168,25 @@ const createGuest = function (embedder: Electron.WebContents, embedderFrameId: n
|
||||
}
|
||||
});
|
||||
|
||||
if (attachGuest(embedder, embedderFrameId, elementInstanceId, guestInstanceId, params)) {
|
||||
return guestInstanceId;
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Attach the guest to an element of embedder.
|
||||
const attachGuest = function (embedder: Electron.WebContents, embedderFrameId: number, elementInstanceId: number, guestInstanceId: number, params: Record<string, any>) {
|
||||
// Destroy the old guest when attaching.
|
||||
const key = `${embedder.id}-${elementInstanceId}`;
|
||||
const oldGuestInstanceId = embedderElementsMap.get(key);
|
||||
if (oldGuestInstanceId != null) {
|
||||
// Reattachment to the same guest is just a no-op.
|
||||
if (oldGuestInstanceId === guestInstanceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const oldGuestInstance = guestInstances.get(oldGuestInstanceId);
|
||||
if (oldGuestInstance) {
|
||||
oldGuestInstance.guest.detachFromOuterFrame();
|
||||
}
|
||||
}
|
||||
|
||||
const guestInstance = guestInstances.get(guestInstanceId);
|
||||
// If this isn't a valid guest instance then do nothing.
|
||||
if (!guestInstance) {
|
||||
console.error(new Error(`Guest attach failed: Invalid guestInstanceId ${guestInstanceId}`));
|
||||
return false;
|
||||
}
|
||||
const { guest } = guestInstance;
|
||||
if (guest.hostWebContents !== embedder) {
|
||||
console.error(new Error(`Guest attach failed: Access denied to guestInstanceId ${guestInstanceId}`));
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this guest is already attached to an element then remove it
|
||||
if (guestInstance.elementInstanceId) {
|
||||
const oldKey = `${guestInstance.embedder.id}-${guestInstance.elementInstanceId}`;
|
||||
embedderElementsMap.delete(oldKey);
|
||||
|
||||
// Remove guest from embedder if moving across web views
|
||||
if (guest.viewInstanceId !== params.instanceId) {
|
||||
webViewManager.removeGuest(guestInstance.embedder, guestInstanceId);
|
||||
guestInstance.embedder._sendInternal(`${IPC_MESSAGES.GUEST_VIEW_INTERNAL_DESTROY_GUEST}-${guest.viewInstanceId}`);
|
||||
}
|
||||
}
|
||||
|
||||
const webPreferences = makeWebPreferences(embedder, params);
|
||||
|
||||
const event = eventBinding.createWithSender(embedder);
|
||||
embedder.emit('will-attach-webview', event, webPreferences, params);
|
||||
if (event.defaultPrevented) {
|
||||
if (guest.viewInstanceId == null) guest.viewInstanceId = params.instanceId;
|
||||
guest.destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
guest.attachParams = params;
|
||||
embedderElementsMap.set(key, guestInstanceId);
|
||||
|
||||
guest.setEmbedder(embedder);
|
||||
guestInstance.embedder = embedder;
|
||||
guestInstance.elementInstanceId = elementInstanceId;
|
||||
|
||||
watchEmbedder(embedder);
|
||||
|
||||
webViewManager.addGuest(guestInstanceId, embedder, guest, webPreferences);
|
||||
guest.attachToIframe(embedder, embedderFrameId);
|
||||
return true;
|
||||
|
||||
return guestInstanceId;
|
||||
};
|
||||
|
||||
// Remove an guest-embedder relationship.
|
||||
|
||||
@@ -7,7 +7,6 @@ export const enum IPC_MESSAGES {
|
||||
|
||||
GUEST_INSTANCE_VISIBILITY_CHANGE = 'GUEST_INSTANCE_VISIBILITY_CHANGE',
|
||||
|
||||
GUEST_VIEW_INTERNAL_DESTROY_GUEST = 'GUEST_VIEW_INTERNAL_DESTROY_GUEST',
|
||||
GUEST_VIEW_INTERNAL_DISPATCH_EVENT = 'GUEST_VIEW_INTERNAL_DISPATCH_EVENT',
|
||||
GUEST_VIEW_INTERNAL_IPC_MESSAGE = 'GUEST_VIEW_INTERNAL_IPC_MESSAGE',
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ const { mainFrame: webFrame } = process._linkedBinding('electron_renderer_web_fr
|
||||
|
||||
export interface GuestViewDelegate {
|
||||
dispatchEvent (eventName: string, props: Record<string, any>): void;
|
||||
reset(): void;
|
||||
}
|
||||
|
||||
const DEPRECATED_EVENTS: Record<string, string> = {
|
||||
@@ -28,11 +27,6 @@ const dispatchEvent = function (delegate: GuestViewDelegate, eventName: string,
|
||||
};
|
||||
|
||||
export function registerEvents (viewInstanceId: number, delegate: GuestViewDelegate) {
|
||||
ipcRendererInternal.on(`${IPC_MESSAGES.GUEST_VIEW_INTERNAL_DESTROY_GUEST}-${viewInstanceId}`, function () {
|
||||
delegate.reset();
|
||||
delegate.dispatchEvent('destroyed', {});
|
||||
});
|
||||
|
||||
ipcRendererInternal.on(`${IPC_MESSAGES.GUEST_VIEW_INTERNAL_DISPATCH_EVENT}-${viewInstanceId}`, function (event, eventName, ...args) {
|
||||
dispatchEvent(delegate, eventName, eventName, ...args);
|
||||
});
|
||||
@@ -43,7 +37,6 @@ export function registerEvents (viewInstanceId: number, delegate: GuestViewDeleg
|
||||
}
|
||||
|
||||
export function deregisterEvents (viewInstanceId: number) {
|
||||
ipcRendererInternal.removeAllListeners(`${IPC_MESSAGES.GUEST_VIEW_INTERNAL_DESTROY_GUEST}-${viewInstanceId}`);
|
||||
ipcRendererInternal.removeAllListeners(`${IPC_MESSAGES.GUEST_VIEW_INTERNAL_DISPATCH_EVENT}-${viewInstanceId}`);
|
||||
ipcRendererInternal.removeAllListeners(`${IPC_MESSAGES.GUEST_VIEW_INTERNAL_IPC_MESSAGE}-${viewInstanceId}`);
|
||||
}
|
||||
|
||||
@@ -55,8 +55,7 @@ const defineWebViewElement = (hooks: WebViewImplHooks) => {
|
||||
}
|
||||
if (!internal.elementAttached) {
|
||||
hooks.guestViewInternal.registerEvents(internal.viewInstanceId, {
|
||||
dispatchEvent: internal.dispatchEvent.bind(internal),
|
||||
reset: internal.reset.bind(internal)
|
||||
dispatchEvent: internal.dispatchEvent.bind(internal)
|
||||
});
|
||||
internal.elementAttached = true;
|
||||
(internal.attributes.get(WEB_VIEW_CONSTANTS.ATTRIBUTE_SRC) as SrcAttribute).parse();
|
||||
|
||||
@@ -195,7 +195,7 @@ export class WebViewImpl {
|
||||
|
||||
attachGuestInstance (guestInstanceId: number) {
|
||||
if (guestInstanceId === -1) {
|
||||
// Do nothing
|
||||
this.dispatchEvent('destroyed');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "16.0.0-nightly.20210803",
|
||||
"version": "16.0.0-nightly.20210811",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
|
||||
@@ -102,3 +102,4 @@ refactor_restore_base_adaptcallbackforrepeating.patch
|
||||
hack_to_allow_gclient_sync_with_host_os_mac_on_linux_in_ci.patch
|
||||
don_t_run_pcscan_notifythreadcreated_if_pcscan_is_disabled.patch
|
||||
add_gin_wrappable_crash_key.patch
|
||||
logging_win32_only_create_a_console_if_logging_to_stderr.patch
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Rose <jeremya@chromium.org>
|
||||
Date: Mon, 2 Aug 2021 15:56:56 -0700
|
||||
Subject: only create a console if logging to stderr
|
||||
|
||||
This fixes an issue on Windows where, when `--enable-logging=file` is
|
||||
passed and the app was not run from the console, a console window would
|
||||
be created for each child process, despite logs being redirected to a
|
||||
file.
|
||||
|
||||
diff --git a/content/app/content_main.cc b/content/app/content_main.cc
|
||||
index a26c5c2e053eddb4c70afb166a4643f38eb3c7f6..265b9af981454ab09ed34542ca845fb566b4a75d 100644
|
||||
--- a/content/app/content_main.cc
|
||||
+++ b/content/app/content_main.cc
|
||||
@@ -370,8 +370,12 @@ RunContentProcess(const ContentMainParams& params,
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Route stdio to parent console (if any) or create one.
|
||||
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
- switches::kEnableLogging)) {
|
||||
+ auto* cmd_line = base::CommandLine::ForCurrentProcess();
|
||||
+ bool log_to_stderr =
|
||||
+ cmd_line->HasSwitch(switches::kEnableLogging) &&
|
||||
+ cmd_line->GetSwitchValueASCII(switches::kEnableLogging) != "file" &&
|
||||
+ !cmd_line->HasSwitch(switches::kLogFile);
|
||||
+ if (log_to_stderr) {
|
||||
base::RouteStdioToConsole(true);
|
||||
}
|
||||
#endif
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
"src/electron/patches/boringssl": "src/third_party/boringssl/src",
|
||||
|
||||
"src/electron/patches/webrtc": "src/third_party/webrtc",
|
||||
|
||||
"src/electron/patches/v8": "src/v8",
|
||||
|
||||
"src/electron/patches/node": "src/third_party/electron_node",
|
||||
|
||||
@@ -25,3 +25,5 @@ src_allow_embedders_to_provide_a_custom_pageallocator_to.patch
|
||||
fix_crypto_tests_to_run_with_bssl.patch
|
||||
fix_account_for_debugger_agent_race_condition.patch
|
||||
fix_use_new_v8_error_message_property_access_format.patch
|
||||
add_should_read_node_options_from_env_option_to_disable_node_options.patch
|
||||
repl_fix_crash_when_sharedarraybuffer_disabled.patch
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <samuel.r.attard@gmail.com>
|
||||
Date: Wed, 21 Jul 2021 13:40:59 -0700
|
||||
Subject: add should_read_node_options_from_env option to disable NODE_OPTIONS
|
||||
parsing at runtime
|
||||
|
||||
We can remove the NODE_OPTIONS environment variable but it in theory could be injected / re-inserted at runtime and be used for workers. In order to ensure the fuse is respected we need a hard runtime toggle for NODE_OPTION support.
|
||||
|
||||
diff --git a/src/env.cc b/src/env.cc
|
||||
index 1cc7da1ce15f43905ce607adcc1a23ed9d92948a..16af6aec3791df1363682f1ed024c52208b9a8f6 100644
|
||||
--- a/src/env.cc
|
||||
+++ b/src/env.cc
|
||||
@@ -329,6 +329,9 @@ std::string GetExecPath(const std::vector<std::string>& argv) {
|
||||
return exec_path;
|
||||
}
|
||||
|
||||
+/* static */
|
||||
+bool Environment::should_read_node_options_from_env_ = true;
|
||||
+
|
||||
Environment::Environment(IsolateData* isolate_data,
|
||||
Isolate* isolate,
|
||||
const std::vector<std::string>& args,
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index 45210f074a0ca4d57f9fdc5019e8e82540b28b72..c0da6c53028bc9459065caf25c1221f556b22d68 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -1143,6 +1143,8 @@ class Environment : public MemoryRetainer {
|
||||
inline double trigger_async_id();
|
||||
inline double get_default_trigger_async_id();
|
||||
|
||||
+ static bool should_read_node_options_from_env_;
|
||||
+
|
||||
// List of id's that have been destroyed and need the destroy() cb called.
|
||||
inline std::vector<double>* destroy_async_id_list();
|
||||
|
||||
diff --git a/src/node.cc b/src/node.cc
|
||||
index 6302bb925339d709a54151a8fc8b58f1a2253881..48a9eedfaf6350fc05fb104a1f44e85b75878f9a 100644
|
||||
--- a/src/node.cc
|
||||
+++ b/src/node.cc
|
||||
@@ -882,7 +882,7 @@ int InitializeNodeWithArgs(std::vector<std::string>* argv,
|
||||
#if !defined(NODE_WITHOUT_NODE_OPTIONS)
|
||||
std::string node_options;
|
||||
|
||||
- if (credentials::SafeGetenv("NODE_OPTIONS", &node_options)) {
|
||||
+ if (Environment::should_read_node_options_from_env_ && credentials::SafeGetenv("NODE_OPTIONS", &node_options)) {
|
||||
std::vector<std::string> env_argv =
|
||||
ParseNodeOptionsEnvVar(node_options, errors);
|
||||
|
||||
diff --git a/src/node_worker.cc b/src/node_worker.cc
|
||||
index 43a3862cc69dc39b95b329f713691b19de3b8d7e..7782e8488f797a8cf83b1e02f012797ef256afe7 100644
|
||||
--- a/src/node_worker.cc
|
||||
+++ b/src/node_worker.cc
|
||||
@@ -457,6 +457,7 @@ void Worker::New(const FunctionCallbackInfo<Value>& args) {
|
||||
});
|
||||
|
||||
#ifndef NODE_WITHOUT_NODE_OPTIONS
|
||||
+ if (Environment::should_read_node_options_from_env_) {
|
||||
MaybeLocal<String> maybe_node_opts =
|
||||
env_vars->Get(isolate, OneByteString(isolate, "NODE_OPTIONS"));
|
||||
Local<String> node_opts;
|
||||
@@ -487,6 +488,7 @@ void Worker::New(const FunctionCallbackInfo<Value>& args) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
+ }
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Mon, 9 Aug 2021 18:42:15 +0200
|
||||
Subject: repl: fix crash when SharedArrayBuffer disabled
|
||||
|
||||
It's possible for SharedArrayBuffers to be disabled with
|
||||
--no-harmony-sharedarraybuffer so we first need to check that this
|
||||
isn't the case before attempting to use them in the repl or a crash occurs.
|
||||
|
||||
Upstreamed at https://github.com/nodejs/node/pull/39718.
|
||||
|
||||
diff --git a/benchmark/worker/atomics-wait.js b/benchmark/worker/atomics-wait.js
|
||||
index a771b1813731edf4f0dd60f3505799e389f1d876..b9461677e2d7d1df192e752496e62cca837717b5 100644
|
||||
--- a/benchmark/worker/atomics-wait.js
|
||||
+++ b/benchmark/worker/atomics-wait.js
|
||||
@@ -7,6 +7,10 @@ const bench = common.createBenchmark(main, {
|
||||
});
|
||||
|
||||
function main({ n }) {
|
||||
+ if (typeof SharedArrayBuffer === 'undefined') {
|
||||
+ throw new Error('SharedArrayBuffers must be enabled to run this benchmark');
|
||||
+ }
|
||||
+
|
||||
const i32arr = new Int32Array(new SharedArrayBuffer(4));
|
||||
bench.start();
|
||||
for (let i = 0; i < n; i++)
|
||||
diff --git a/lib/internal/main/worker_thread.js b/lib/internal/main/worker_thread.js
|
||||
index d6434ff96e118535bc6ded88ee4d2f0ff253a8f7..1b8894f44e71c6f25f1f50e84293006afe158513 100644
|
||||
--- a/lib/internal/main/worker_thread.js
|
||||
+++ b/lib/internal/main/worker_thread.js
|
||||
@@ -9,7 +9,7 @@ const {
|
||||
ArrayPrototypeSplice,
|
||||
ObjectDefineProperty,
|
||||
PromisePrototypeCatch,
|
||||
- globalThis: { Atomics },
|
||||
+ globalThis: { Atomics, SharedArrayBuffer },
|
||||
} = primordials;
|
||||
|
||||
const {
|
||||
@@ -140,6 +140,9 @@ port.on('message', (message) => {
|
||||
const originalCwd = process.cwd;
|
||||
|
||||
process.cwd = function() {
|
||||
+ // SharedArrayBuffers can be disabled with --no-harmony-sharedarraybuffer.
|
||||
+ if (typeof SharedArrayBuffer === 'undefined') return originalCwd();
|
||||
+
|
||||
const currentCounter = Atomics.load(cwdCounter, 0);
|
||||
if (currentCounter === lastCounter)
|
||||
return cachedCwd;
|
||||
diff --git a/lib/internal/worker.js b/lib/internal/worker.js
|
||||
index 931bce0c518fc3355a9f94a7760556b6f0b75b96..99baa3e7f747bb3b351cb13c6ed512f2bb88812a 100644
|
||||
--- a/lib/internal/worker.js
|
||||
+++ b/lib/internal/worker.js
|
||||
@@ -92,7 +92,8 @@ let cwdCounter;
|
||||
|
||||
const environmentData = new SafeMap();
|
||||
|
||||
-if (isMainThread) {
|
||||
+// SharedArrayBuffers can be disabled with --no-harmony-sharedarraybuffer.
|
||||
+if (isMainThread && typeof SharedArrayBuffer !== 'undefined') {
|
||||
cwdCounter = new Uint32Array(new SharedArrayBuffer(4));
|
||||
const originalChdir = process.chdir;
|
||||
process.chdir = function(path) {
|
||||
1
patches/webrtc/.patches
Normal file
1
patches/webrtc/.patches
Normal file
@@ -0,0 +1 @@
|
||||
add_thread_local_to_x_error_trap_cc.patch
|
||||
24
patches/webrtc/add_thread_local_to_x_error_trap_cc.patch
Normal file
24
patches/webrtc/add_thread_local_to_x_error_trap_cc.patch
Normal file
@@ -0,0 +1,24 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Rose <nornagon@nornagon.net>
|
||||
Date: Tue, 27 Jul 2021 10:32:54 -0700
|
||||
Subject: add thread_local to x_error_trap.cc
|
||||
|
||||
Per https://bugs.chromium.org/p/chromium/issues/detail?id=781618#c6.
|
||||
|
||||
To fix this DCHECK firing: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/modules/desktop_capture/linux/x_error_trap.cc;l=35;drc=25ab3228f3e473f2226f219531ec617d2daa175e
|
||||
|
||||
diff --git a/modules/desktop_capture/linux/x_error_trap.cc b/modules/desktop_capture/linux/x_error_trap.cc
|
||||
index 13233d827470d9d42be0333c3080e3d107f86fd5..62efb5b5b5194fc8961a27fe2a1efcd77e385d08 100644
|
||||
--- a/modules/desktop_capture/linux/x_error_trap.cc
|
||||
+++ b/modules/desktop_capture/linux/x_error_trap.cc
|
||||
@@ -19,8 +19,8 @@ namespace webrtc {
|
||||
namespace {
|
||||
|
||||
// TODO(sergeyu): This code is not thread safe. Fix it. Bug 2202.
|
||||
-static bool g_xserver_error_trap_enabled = false;
|
||||
-static int g_last_xserver_error_code = 0;
|
||||
+static thread_local bool g_xserver_error_trap_enabled = false;
|
||||
+static thread_local int g_last_xserver_error_code = 0;
|
||||
|
||||
int XServerErrorHandler(Display* display, XErrorEvent* error_event) {
|
||||
RTC_DCHECK(g_xserver_error_trap_enabled);
|
||||
@@ -3,7 +3,14 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Fallback to blow away old cache keys
|
||||
const HASH_VERSION = 3;
|
||||
const FALLBACK_HASH_VERSION = 3;
|
||||
|
||||
// Per platform hash versions to bust the cache on different platforms
|
||||
const HASH_VERSIONS = {
|
||||
darwin: 3,
|
||||
win32: 4,
|
||||
linux: 3
|
||||
};
|
||||
|
||||
// Base files to hash
|
||||
const filesToHash = [
|
||||
@@ -28,7 +35,7 @@ addAllFiles(path.resolve(__dirname, '../patches'));
|
||||
|
||||
// Create Hash
|
||||
const hasher = crypto.createHash('SHA256');
|
||||
hasher.update(`HASH_VERSION:${HASH_VERSION}`);
|
||||
hasher.update(`HASH_VERSION:${HASH_VERSIONS[process.platform] || FALLBACK_HASH_VERSION}`);
|
||||
for (const file of filesToHash) {
|
||||
hasher.update(fs.readFileSync(file));
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ function getLastBumpCommit (tag) {
|
||||
async function revertBumpCommit (tag) {
|
||||
const branch = await getCurrentBranch();
|
||||
const commitToRevert = getLastBumpCommit(tag).hash;
|
||||
await GitProcess.exec(['pull', '--rebase']);
|
||||
await GitProcess.exec(['revert', commitToRevert], ELECTRON_DIR);
|
||||
const pushDetails = await GitProcess.exec(['push', 'origin', `HEAD:${branch}`, '--follow-tags'], ELECTRON_DIR);
|
||||
if (pushDetails.exitCode === 0) {
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
#elif defined(OS_LINUX) // defined(OS_WIN)
|
||||
#include <unistd.h>
|
||||
#include <cstdio>
|
||||
#include "base/base_switches.h"
|
||||
#include "base/command_line.h"
|
||||
#include "content/public/app/content_main.h"
|
||||
#include "shell/app/electron_main_delegate.h" // NOLINT
|
||||
#else // defined(OS_LINUX)
|
||||
@@ -304,9 +306,14 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
electron::ElectronMainDelegate delegate;
|
||||
content::ContentMainParams params(&delegate);
|
||||
electron::ElectronCommandLine::Init(argc, argv);
|
||||
params.argc = argc;
|
||||
params.argv = const_cast<const char**>(argv);
|
||||
electron::ElectronCommandLine::Init(argc, argv);
|
||||
base::CommandLine::Init(params.argc, params.argv);
|
||||
// TODO(https://crbug.com/1176772): Remove when Chrome Linux is fully migrated
|
||||
// to Crashpad.
|
||||
base::CommandLine::ForCurrentProcess()->AppendSwitch(
|
||||
::switches::kEnableCrashpad);
|
||||
return content::ContentMain(params);
|
||||
}
|
||||
|
||||
|
||||
121
shell/browser/api/electron_api_safe_storage.cc
Normal file
121
shell/browser/api/electron_api_safe_storage.cc
Normal file
@@ -0,0 +1,121 @@
|
||||
// Copyright (c) 2021 Slack Technologies, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/api/electron_api_safe_storage.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "components/os_crypt/os_crypt.h"
|
||||
#include "shell/browser/browser.h"
|
||||
#include "shell/common/gin_converters/base_converter.h"
|
||||
#include "shell/common/gin_converters/callback_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/node_includes.h"
|
||||
#include "shell/common/platform_util.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
namespace safestorage {
|
||||
|
||||
static const char* kEncryptionVersionPrefixV10 = "v10";
|
||||
static const char* kEncryptionVersionPrefixV11 = "v11";
|
||||
|
||||
#if DCHECK_IS_ON()
|
||||
static bool electron_crypto_ready = false;
|
||||
|
||||
void SetElectronCryptoReady(bool ready) {
|
||||
electron_crypto_ready = ready;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool IsEncryptionAvailable() {
|
||||
return OSCrypt::IsEncryptionAvailable();
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> EncryptString(v8::Isolate* isolate,
|
||||
const std::string& plaintext) {
|
||||
if (!OSCrypt::IsEncryptionAvailable()) {
|
||||
gin_helper::ErrorThrower(isolate).ThrowError(
|
||||
"Error while decrypting the ciphertext provided to "
|
||||
"safeStorage.decryptString. "
|
||||
"Encryption is not available.");
|
||||
return v8::Local<v8::Value>();
|
||||
}
|
||||
|
||||
std::string ciphertext;
|
||||
bool encrypted = OSCrypt::EncryptString(plaintext, &ciphertext);
|
||||
|
||||
if (!encrypted) {
|
||||
gin_helper::ErrorThrower(isolate).ThrowError(
|
||||
"Error while encrypting the text provided to "
|
||||
"safeStorage.encryptString.");
|
||||
return v8::Local<v8::Value>();
|
||||
}
|
||||
|
||||
return node::Buffer::Copy(isolate, ciphertext.c_str(), ciphertext.size())
|
||||
.ToLocalChecked();
|
||||
}
|
||||
|
||||
std::string DecryptString(v8::Isolate* isolate, v8::Local<v8::Value> buffer) {
|
||||
if (!OSCrypt::IsEncryptionAvailable()) {
|
||||
gin_helper::ErrorThrower(isolate).ThrowError(
|
||||
"Error while decrypting the ciphertext provided to "
|
||||
"safeStorage.decryptString. "
|
||||
"Decryption is not available.");
|
||||
return "";
|
||||
}
|
||||
|
||||
if (!node::Buffer::HasInstance(buffer)) {
|
||||
gin_helper::ErrorThrower(isolate).ThrowError(
|
||||
"Expected the first argument of decryptString() to be a buffer");
|
||||
return "";
|
||||
}
|
||||
|
||||
// ensures an error is thrown in Mac or Linux on
|
||||
// decryption failure, rather than failing silently
|
||||
const char* data = node::Buffer::Data(buffer);
|
||||
auto size = node::Buffer::Length(buffer);
|
||||
std::string ciphertext(data, size);
|
||||
if (ciphertext.empty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (ciphertext.find(kEncryptionVersionPrefixV10) != 0 &&
|
||||
ciphertext.find(kEncryptionVersionPrefixV11) != 0) {
|
||||
gin_helper::ErrorThrower(isolate).ThrowError(
|
||||
"Error while decrypting the ciphertext provided to "
|
||||
"safeStorage.decryptString. "
|
||||
"Ciphertext does not appear to be encrypted.");
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string plaintext;
|
||||
bool decrypted = OSCrypt::DecryptString(ciphertext, &plaintext);
|
||||
if (!decrypted) {
|
||||
gin_helper::ErrorThrower(isolate).ThrowError(
|
||||
"Error while decrypting the ciphertext provided to "
|
||||
"safeStorage.decryptString.");
|
||||
return "";
|
||||
}
|
||||
return plaintext;
|
||||
}
|
||||
|
||||
} // namespace safestorage
|
||||
|
||||
} // namespace electron
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
gin_helper::Dictionary dict(isolate, exports);
|
||||
dict.SetMethod("isEncryptionAvailable",
|
||||
&electron::safestorage::IsEncryptionAvailable);
|
||||
dict.SetMethod("encryptString", &electron::safestorage::EncryptString);
|
||||
dict.SetMethod("decryptString", &electron::safestorage::DecryptString);
|
||||
}
|
||||
|
||||
NODE_LINKED_MODULE_CONTEXT_AWARE(electron_browser_safe_storage, Initialize)
|
||||
25
shell/browser/api/electron_api_safe_storage.h
Normal file
25
shell/browser/api/electron_api_safe_storage.h
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2021 Slack Technologies, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef SHELL_BROWSER_API_ELECTRON_API_SAFE_STORAGE_H_
|
||||
#define SHELL_BROWSER_API_ELECTRON_API_SAFE_STORAGE_H_
|
||||
|
||||
#include "base/dcheck_is_on.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
namespace safestorage {
|
||||
|
||||
// Used in a DCHECK to validate that our assumption that the network context
|
||||
// manager has initialized before app ready holds true. Only used in the
|
||||
// testing build
|
||||
#if DCHECK_IS_ON()
|
||||
void SetElectronCryptoReady(bool ready);
|
||||
#endif
|
||||
|
||||
} // namespace safestorage
|
||||
|
||||
} // namespace electron
|
||||
|
||||
#endif // SHELL_BROWSER_API_ELECTRON_API_SAFE_STORAGE_H_
|
||||
@@ -28,10 +28,6 @@ void AddGuest(int guest_instance_id,
|
||||
electron::WebContentsZoomController::FromWebContents(guest_web_contents)
|
||||
->SetDefaultZoomFactor(zoom_factor);
|
||||
}
|
||||
|
||||
WebContentsPreferences::From(guest_web_contents)->Merge(options);
|
||||
// Trigger re-calculation of webkit prefs.
|
||||
guest_web_contents->NotifyPreferencesChanged();
|
||||
}
|
||||
|
||||
void RemoveGuest(content::WebContents* embedder, int guest_instance_id) {
|
||||
|
||||
@@ -103,20 +103,14 @@ void BrowserProcessImpl::PostEarlyInitialization() {
|
||||
|
||||
// Only use a persistent prefs store when cookie encryption is enabled as that
|
||||
// is the only key that needs it
|
||||
if (electron::fuses::IsCookieEncryptionEnabled()) {
|
||||
base::FilePath prefs_path;
|
||||
CHECK(base::PathService::Get(chrome::DIR_USER_DATA, &prefs_path));
|
||||
prefs_path = prefs_path.Append(FILE_PATH_LITERAL("Local State"));
|
||||
base::ThreadRestrictions::ScopedAllowIO allow_io;
|
||||
scoped_refptr<JsonPrefStore> user_pref_store =
|
||||
base::MakeRefCounted<JsonPrefStore>(prefs_path);
|
||||
user_pref_store->ReadPrefs();
|
||||
prefs_factory.set_user_prefs(user_pref_store);
|
||||
} else {
|
||||
auto user_pref_store =
|
||||
base::MakeRefCounted<OverlayUserPrefStore>(new InMemoryPrefStore);
|
||||
prefs_factory.set_user_prefs(user_pref_store);
|
||||
}
|
||||
base::FilePath prefs_path;
|
||||
CHECK(base::PathService::Get(chrome::DIR_USER_DATA, &prefs_path));
|
||||
prefs_path = prefs_path.Append(FILE_PATH_LITERAL("Local State"));
|
||||
base::ThreadRestrictions::ScopedAllowIO allow_io;
|
||||
scoped_refptr<JsonPrefStore> user_pref_store =
|
||||
base::MakeRefCounted<JsonPrefStore>(prefs_path);
|
||||
user_pref_store->ReadPrefs();
|
||||
prefs_factory.set_user_prefs(user_pref_store);
|
||||
local_state_ = prefs_factory.Create(std::move(pref_registry));
|
||||
}
|
||||
|
||||
|
||||
@@ -536,13 +536,11 @@ void ElectronBrowserMainParts::PreCreateMainMessageLoopCommon() {
|
||||
media::SetLocalizedStringProvider(MediaStringProvider);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
if (electron::fuses::IsCookieEncryptionEnabled()) {
|
||||
auto* local_state = g_browser_process->local_state();
|
||||
DCHECK(local_state);
|
||||
auto* local_state = g_browser_process->local_state();
|
||||
DCHECK(local_state);
|
||||
|
||||
bool os_crypt_init = OSCrypt::Init(local_state);
|
||||
DCHECK(os_crypt_init);
|
||||
}
|
||||
bool os_crypt_init = OSCrypt::Init(local_state);
|
||||
DCHECK(os_crypt_init);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
@class ElectronNSWindowDelegate;
|
||||
@class ElectronPreviewItem;
|
||||
@class ElectronTouchBar;
|
||||
@class WindowButtonsView;
|
||||
@class WindowButtonsProxy;
|
||||
|
||||
namespace electron {
|
||||
|
||||
@@ -156,9 +156,6 @@ class NativeWindowMac : public NativeWindow,
|
||||
void NotifyWindowWillEnterFullScreen();
|
||||
void NotifyWindowWillLeaveFullScreen();
|
||||
|
||||
// Ensure the buttons view are always floated on the top.
|
||||
void ReorderButtonsView();
|
||||
|
||||
// Cleanup observers when window is getting closed. Note that the destructor
|
||||
// can be called much later after window gets closed, so we should not do
|
||||
// cleanup in destructor.
|
||||
@@ -215,7 +212,6 @@ class NativeWindowMac : public NativeWindow,
|
||||
void AddContentViewLayers();
|
||||
|
||||
void InternalSetWindowButtonVisibility(bool visible);
|
||||
void InternalSetStandardButtonsVisibility(bool visible);
|
||||
void InternalSetParentWindow(NativeWindow* parent, bool attach);
|
||||
void SetForwardMouseMessages(bool forward);
|
||||
|
||||
@@ -224,7 +220,6 @@ class NativeWindowMac : public NativeWindow,
|
||||
base::scoped_nsobject<ElectronNSWindowDelegate> window_delegate_;
|
||||
base::scoped_nsobject<ElectronPreviewItem> preview_item_;
|
||||
base::scoped_nsobject<ElectronTouchBar> touch_bar_;
|
||||
base::scoped_nsobject<WindowButtonsView> buttons_view_;
|
||||
|
||||
// Event monitor for scroll wheel event.
|
||||
id wheel_event_monitor_;
|
||||
@@ -263,6 +258,9 @@ class NativeWindowMac : public NativeWindow,
|
||||
// setWindowButtonVisibility().
|
||||
absl::optional<bool> window_button_visibility_;
|
||||
|
||||
// Controls the position and visibility of window buttons.
|
||||
base::scoped_nsobject<WindowButtonsProxy> buttons_proxy_;
|
||||
|
||||
// Maximizable window state; necessary for persistence through redraws.
|
||||
bool maximizable_ = true;
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "shell/browser/ui/cocoa/electron_preview_item.h"
|
||||
#include "shell/browser/ui/cocoa/electron_touch_bar.h"
|
||||
#include "shell/browser/ui/cocoa/root_view_mac.h"
|
||||
#include "shell/browser/ui/cocoa/window_buttons_view.h"
|
||||
#include "shell/browser/ui/cocoa/window_buttons_proxy.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_view.h"
|
||||
#include "shell/browser/window_list.h"
|
||||
@@ -381,8 +381,26 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
|
||||
[window_ setTitleVisibility:NSWindowTitleHidden];
|
||||
// Remove non-transparent corners, see http://git.io/vfonD.
|
||||
[window_ setOpaque:NO];
|
||||
// Hide the window buttons.
|
||||
InternalSetStandardButtonsVisibility(false);
|
||||
// Show window buttons if titleBarStyle is not "normal".
|
||||
if (title_bar_style_ == TitleBarStyle::kNormal) {
|
||||
InternalSetWindowButtonVisibility(false);
|
||||
} else {
|
||||
buttons_proxy_.reset([[WindowButtonsProxy alloc] initWithWindow:window_]);
|
||||
if (traffic_light_position_) {
|
||||
[buttons_proxy_ setMargin:*traffic_light_position_];
|
||||
} else if (title_bar_style_ == TitleBarStyle::kHiddenInset) {
|
||||
// For macOS >= 11, while this value does not match offical macOS apps
|
||||
// like Safari or Notes, it matches titleBarStyle's old implementation
|
||||
// before Electron <= 12.
|
||||
[buttons_proxy_ setMargin:gfx::Point(12, 11)];
|
||||
}
|
||||
if (title_bar_style_ == TitleBarStyle::kCustomButtonsOnHover) {
|
||||
[buttons_proxy_ setShowOnHover:YES];
|
||||
} else {
|
||||
// customButtonsOnHover does not show buttons initialiy.
|
||||
InternalSetWindowButtonVisibility(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a tab only if tabbing identifier is specified and window has
|
||||
@@ -461,9 +479,6 @@ void NativeWindowMac::SetContentView(views::View* view) {
|
||||
set_content_view(view);
|
||||
root_view->AddChildView(content_view());
|
||||
|
||||
if (buttons_view_)
|
||||
ReorderButtonsView();
|
||||
|
||||
root_view->Layout();
|
||||
}
|
||||
|
||||
@@ -806,8 +821,6 @@ bool NativeWindowMac::IsMovable() {
|
||||
|
||||
void NativeWindowMac::SetMinimizable(bool minimizable) {
|
||||
SetStyleMask(minimizable, NSMiniaturizableWindowMask);
|
||||
if (buttons_view_)
|
||||
[[buttons_view_ viewWithTag:1] setEnabled:minimizable];
|
||||
}
|
||||
|
||||
bool NativeWindowMac::IsMinimizable() {
|
||||
@@ -829,8 +842,6 @@ void NativeWindowMac::SetFullScreenable(bool fullscreenable) {
|
||||
// On EL Capitan this flag is required to hide fullscreen button.
|
||||
SetCollectionBehavior(!fullscreenable,
|
||||
NSWindowCollectionBehaviorFullScreenAuxiliary);
|
||||
if (buttons_view_)
|
||||
[[buttons_view_ viewWithTag:2] setEnabled:fullscreenable];
|
||||
}
|
||||
|
||||
bool NativeWindowMac::IsFullScreenable() {
|
||||
@@ -840,8 +851,6 @@ bool NativeWindowMac::IsFullScreenable() {
|
||||
|
||||
void NativeWindowMac::SetClosable(bool closable) {
|
||||
SetStyleMask(closable, NSWindowStyleMaskClosable);
|
||||
if (buttons_view_)
|
||||
[[buttons_view_ viewWithTag:0] setEnabled:closable];
|
||||
}
|
||||
|
||||
bool NativeWindowMac::IsClosable() {
|
||||
@@ -947,6 +956,8 @@ void NativeWindowMac::Invalidate() {
|
||||
|
||||
void NativeWindowMac::SetTitle(const std::string& title) {
|
||||
[window_ setTitle:base::SysUTF8ToNSString(title)];
|
||||
if (buttons_proxy_)
|
||||
[buttons_proxy_ redraw];
|
||||
}
|
||||
|
||||
std::string NativeWindowMac::GetTitle() {
|
||||
@@ -1182,8 +1193,6 @@ void NativeWindowMac::AddBrowserView(NativeBrowserView* view) {
|
||||
}
|
||||
|
||||
[CATransaction commit];
|
||||
|
||||
ReorderButtonsView();
|
||||
}
|
||||
|
||||
void NativeWindowMac::RemoveBrowserView(NativeBrowserView* view) {
|
||||
@@ -1225,8 +1234,6 @@ void NativeWindowMac::SetTopBrowserView(NativeBrowserView* view) {
|
||||
}
|
||||
|
||||
[CATransaction commit];
|
||||
|
||||
ReorderButtonsView();
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetParentWindow(NativeWindow* parent) {
|
||||
@@ -1488,25 +1495,26 @@ void NativeWindowMac::SetVibrancy(const std::string& type) {
|
||||
|
||||
void NativeWindowMac::SetWindowButtonVisibility(bool visible) {
|
||||
window_button_visibility_ = visible;
|
||||
InternalSetWindowButtonVisibility(visible);
|
||||
// The visibility of window buttons are managed by |buttons_proxy_| if the
|
||||
// style is customButtonsOnHover.
|
||||
if (title_bar_style_ == TitleBarStyle::kCustomButtonsOnHover)
|
||||
[buttons_proxy_ setVisible:visible];
|
||||
else
|
||||
InternalSetWindowButtonVisibility(visible);
|
||||
NotifyLayoutWindowControlsOverlay();
|
||||
}
|
||||
|
||||
bool NativeWindowMac::GetWindowButtonVisibility() const {
|
||||
if (buttons_view_)
|
||||
return ![buttons_view_ isHidden];
|
||||
else
|
||||
return ![window_ standardWindowButton:NSWindowZoomButton].hidden ||
|
||||
![window_ standardWindowButton:NSWindowMiniaturizeButton].hidden ||
|
||||
![window_ standardWindowButton:NSWindowCloseButton].hidden;
|
||||
return ![window_ standardWindowButton:NSWindowZoomButton].hidden ||
|
||||
![window_ standardWindowButton:NSWindowMiniaturizeButton].hidden ||
|
||||
![window_ standardWindowButton:NSWindowCloseButton].hidden;
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetTrafficLightPosition(
|
||||
absl::optional<gfx::Point> position) {
|
||||
traffic_light_position_ = std::move(position);
|
||||
if (buttons_view_) {
|
||||
[buttons_view_ setMargin:traffic_light_position_];
|
||||
[buttons_view_ viewDidMoveToWindow];
|
||||
if (buttons_proxy_) {
|
||||
[buttons_proxy_ setMargin:traffic_light_position_];
|
||||
NotifyLayoutWindowControlsOverlay();
|
||||
}
|
||||
}
|
||||
@@ -1516,8 +1524,8 @@ absl::optional<gfx::Point> NativeWindowMac::GetTrafficLightPosition() const {
|
||||
}
|
||||
|
||||
void NativeWindowMac::RedrawTrafficLights() {
|
||||
if (buttons_view_)
|
||||
[buttons_view_ setNeedsDisplayForButtons];
|
||||
if (buttons_proxy_ && !IsFullscreen())
|
||||
[buttons_proxy_ redraw];
|
||||
}
|
||||
|
||||
// In simpleFullScreen mode, update the frame for new bounds.
|
||||
@@ -1649,35 +1657,30 @@ gfx::Rect NativeWindowMac::WindowBoundsToContentBounds(
|
||||
void NativeWindowMac::NotifyWindowEnterFullScreen() {
|
||||
NativeWindow::NotifyWindowEnterFullScreen();
|
||||
// Restore the window title under fullscreen mode.
|
||||
if (buttons_view_)
|
||||
if (buttons_proxy_)
|
||||
[window_ setTitleVisibility:NSWindowTitleVisible];
|
||||
RedrawTrafficLights();
|
||||
}
|
||||
|
||||
void NativeWindowMac::NotifyWindowLeaveFullScreen() {
|
||||
NativeWindow::NotifyWindowLeaveFullScreen();
|
||||
// Restore window buttons.
|
||||
if (buttons_proxy_ && window_button_visibility_.value_or(true)) {
|
||||
[buttons_proxy_ redraw];
|
||||
[buttons_proxy_ setVisible:YES];
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindowMac::NotifyWindowWillEnterFullScreen() {
|
||||
// Remove the buttonsView otherwise window buttons won't show under
|
||||
// fullscreen mode.
|
||||
if (buttons_view_) {
|
||||
[buttons_view_ removeFromSuperview];
|
||||
InternalSetStandardButtonsVisibility(true);
|
||||
}
|
||||
|
||||
UpdateVibrancyRadii(true);
|
||||
}
|
||||
|
||||
void NativeWindowMac::NotifyWindowWillLeaveFullScreen() {
|
||||
// Hide window title and restore buttonsView when leaving fullscreen.
|
||||
if (buttons_view_) {
|
||||
if (buttons_proxy_) {
|
||||
// Hide window title when leaving fullscreen.
|
||||
[window_ setTitleVisibility:NSWindowTitleHidden];
|
||||
InternalSetStandardButtonsVisibility(false);
|
||||
[[window_ contentView] addSubview:buttons_view_];
|
||||
// Hide the container otherwise traffic light buttons jump.
|
||||
[buttons_proxy_ setVisible:NO];
|
||||
}
|
||||
|
||||
RedrawTrafficLights();
|
||||
UpdateVibrancyRadii(false);
|
||||
}
|
||||
|
||||
@@ -1689,13 +1692,6 @@ bool NativeWindowMac::IsActive() const {
|
||||
return is_active_;
|
||||
}
|
||||
|
||||
void NativeWindowMac::ReorderButtonsView() {
|
||||
if (buttons_view_ && !IsFullscreen()) {
|
||||
[buttons_view_ removeFromSuperview];
|
||||
[[window_ contentView] addSubview:buttons_view_];
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindowMac::Cleanup() {
|
||||
DCHECK(!IsClosed());
|
||||
ui::NativeTheme::GetInstanceForNativeUi()->RemoveObserver(this);
|
||||
@@ -1791,37 +1787,10 @@ void NativeWindowMac::AddContentViewLayers() {
|
||||
(IMP)ViewDidMoveToSuperview, "v@:");
|
||||
[[window_ contentView] viewDidMoveToWindow];
|
||||
}
|
||||
|
||||
// Create a custom window buttons view.
|
||||
if (title_bar_style_ != TitleBarStyle::kNormal) {
|
||||
buttons_view_.reset(
|
||||
[[WindowButtonsView alloc] initWithMargin:traffic_light_position_]);
|
||||
if (title_bar_style_ == TitleBarStyle::kCustomButtonsOnHover)
|
||||
[buttons_view_ setShowOnHover:YES];
|
||||
if (title_bar_style_ == TitleBarStyle::kHiddenInset &&
|
||||
!traffic_light_position_)
|
||||
[buttons_view_ setMargin:[WindowButtonsView hiddenInsetMargin]];
|
||||
|
||||
if (!IsClosable())
|
||||
[[buttons_view_ viewWithTag:0] setEnabled:NO];
|
||||
if (!IsMinimizable())
|
||||
[[buttons_view_ viewWithTag:1] setEnabled:NO];
|
||||
if (!IsFullScreenable())
|
||||
[[buttons_view_ viewWithTag:2] setEnabled:NO];
|
||||
|
||||
[[window_ contentView] addSubview:buttons_view_];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindowMac::InternalSetWindowButtonVisibility(bool visible) {
|
||||
if (buttons_view_)
|
||||
[buttons_view_ setHidden:!visible];
|
||||
else
|
||||
InternalSetStandardButtonsVisibility(visible);
|
||||
}
|
||||
|
||||
void NativeWindowMac::InternalSetStandardButtonsVisibility(bool visible) {
|
||||
[[window_ standardWindowButton:NSWindowCloseButton] setHidden:!visible];
|
||||
[[window_ standardWindowButton:NSWindowMiniaturizeButton] setHidden:!visible];
|
||||
[[window_ standardWindowButton:NSWindowZoomButton] setHidden:!visible];
|
||||
@@ -1861,24 +1830,17 @@ void NativeWindowMac::SetForwardMouseMessages(bool forward) {
|
||||
}
|
||||
|
||||
gfx::Rect NativeWindowMac::GetWindowControlsOverlayRect() {
|
||||
gfx::Rect bounding_rect;
|
||||
if (titlebar_overlay_ && !has_frame() && buttons_view_ &&
|
||||
![buttons_view_ isHidden]) {
|
||||
NSRect button_frame = [buttons_view_ frame];
|
||||
gfx::Point buttons_view_margin = [buttons_view_ getMargin];
|
||||
const int overlay_width = GetContentSize().width() - NSWidth(button_frame) -
|
||||
buttons_view_margin.x();
|
||||
CGFloat overlay_height =
|
||||
NSHeight(button_frame) + buttons_view_margin.y() * 2;
|
||||
if (base::i18n::IsRTL()) {
|
||||
bounding_rect = gfx::Rect(0, 0, overlay_width, overlay_height);
|
||||
} else {
|
||||
bounding_rect =
|
||||
gfx::Rect(button_frame.size.width + buttons_view_margin.x(), 0,
|
||||
overlay_width, overlay_height);
|
||||
}
|
||||
if (titlebar_overlay_ && buttons_proxy_ &&
|
||||
window_button_visibility_.value_or(true)) {
|
||||
NSRect buttons = [buttons_proxy_ getButtonsContainerBounds];
|
||||
gfx::Rect overlay;
|
||||
overlay.set_width(GetContentSize().width() - NSWidth(buttons));
|
||||
overlay.set_height(NSHeight(buttons));
|
||||
if (!base::i18n::IsRTL())
|
||||
overlay.set_x(NSMaxX(buttons));
|
||||
return overlay;
|
||||
}
|
||||
return bounding_rect;
|
||||
return gfx::Rect();
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -217,9 +217,7 @@ NativeWindowViews::NativeWindowViews(const gin_helper::Dictionary& options,
|
||||
#endif
|
||||
|
||||
widget()->Init(std::move(params));
|
||||
#if defined(OS_WIN)
|
||||
SetCanResize(resizable_);
|
||||
#endif
|
||||
|
||||
bool fullscreen = false;
|
||||
options.Get(options::kFullscreen, &fullscreen);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "services/network/public/cpp/features.h"
|
||||
#include "services/network/public/cpp/shared_url_loader_factory.h"
|
||||
#include "services/network/public/mojom/network_context.mojom.h"
|
||||
#include "shell/browser/api/electron_api_safe_storage.h"
|
||||
#include "shell/browser/browser.h"
|
||||
#include "shell/browser/electron_browser_client.h"
|
||||
#include "shell/common/application_info.h"
|
||||
@@ -39,6 +40,10 @@
|
||||
#include "components/os_crypt/keychain_password_mac.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
#include "components/os_crypt/key_storage_config_linux.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
// The global instance of the SystemNetworkContextmanager.
|
||||
@@ -233,38 +238,56 @@ void SystemNetworkContextManager::OnNetworkServiceCreated(
|
||||
network_context_.BindNewPipeAndPassReceiver(),
|
||||
CreateNetworkContextParams());
|
||||
|
||||
if (electron::fuses::IsCookieEncryptionEnabled()) {
|
||||
std::string app_name = electron::Browser::Get()->GetName();
|
||||
std::string app_name = electron::Browser::Get()->GetName();
|
||||
#if defined(OS_MAC)
|
||||
*KeychainPassword::service_name = app_name + " Safe Storage";
|
||||
*KeychainPassword::account_name = app_name;
|
||||
*KeychainPassword::service_name = app_name + " Safe Storage";
|
||||
*KeychainPassword::account_name = app_name;
|
||||
#endif
|
||||
// The OSCrypt keys are process bound, so if network service is out of
|
||||
// process, send it the required key.
|
||||
if (content::IsOutOfProcessNetworkService()) {
|
||||
#if defined(OS_LINUX)
|
||||
// c.f.
|
||||
// https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/net/system_network_context_manager.cc;l=515;drc=9d82515060b9b75fa941986f5db7390299669ef1;bpv=1;bpt=1
|
||||
const base::CommandLine& command_line =
|
||||
*base::CommandLine::ForCurrentProcess();
|
||||
// c.f.
|
||||
// https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/net/system_network_context_manager.cc;l=515;drc=9d82515060b9b75fa941986f5db7390299669ef1;bpv=1;bpt=1
|
||||
const base::CommandLine& command_line =
|
||||
*base::CommandLine::ForCurrentProcess();
|
||||
|
||||
network::mojom::CryptConfigPtr config =
|
||||
network::mojom::CryptConfig::New();
|
||||
config->application_name = app_name;
|
||||
config->product_name = app_name;
|
||||
// c.f.
|
||||
// https://source.chromium.org/chromium/chromium/src/+/master:chrome/common/chrome_switches.cc;l=689;drc=9d82515060b9b75fa941986f5db7390299669ef1
|
||||
config->store =
|
||||
command_line.GetSwitchValueASCII(::switches::kPasswordStore);
|
||||
config->should_use_preference =
|
||||
command_line.HasSwitch(::switches::kEnableEncryptionSelection);
|
||||
base::PathService::Get(chrome::DIR_USER_DATA, &config->user_data_path);
|
||||
network_service->SetCryptConfig(std::move(config));
|
||||
#else
|
||||
network_service->SetEncryptionKey(OSCrypt::GetRawEncryptionKey());
|
||||
auto config = std::make_unique<os_crypt::Config>();
|
||||
config->store = command_line.GetSwitchValueASCII(::switches::kPasswordStore);
|
||||
config->product_name = app_name;
|
||||
config->application_name = app_name;
|
||||
config->main_thread_runner = base::ThreadTaskRunnerHandle::Get();
|
||||
// c.f.
|
||||
// https://source.chromium.org/chromium/chromium/src/+/master:chrome/common/chrome_switches.cc;l=689;drc=9d82515060b9b75fa941986f5db7390299669ef1
|
||||
config->should_use_preference =
|
||||
command_line.HasSwitch(::switches::kEnableEncryptionSelection);
|
||||
base::PathService::Get(chrome::DIR_USER_DATA, &config->user_data_path);
|
||||
#endif
|
||||
|
||||
// The OSCrypt keys are process bound, so if network service is out of
|
||||
// process, send it the required key.
|
||||
if (content::IsOutOfProcessNetworkService() &&
|
||||
electron::fuses::IsCookieEncryptionEnabled()) {
|
||||
#if defined(OS_LINUX)
|
||||
network::mojom::CryptConfigPtr network_crypt_config =
|
||||
network::mojom::CryptConfig::New();
|
||||
network_crypt_config->application_name = config->application_name;
|
||||
network_crypt_config->product_name = config->product_name;
|
||||
network_crypt_config->store = config->store;
|
||||
network_crypt_config->should_use_preference = config->should_use_preference;
|
||||
network_crypt_config->user_data_path = config->user_data_path;
|
||||
|
||||
network_service->SetCryptConfig(std::move(network_crypt_config));
|
||||
|
||||
#else
|
||||
network_service->SetEncryptionKey(OSCrypt::GetRawEncryptionKey());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
OSCrypt::SetConfig(std::move(config));
|
||||
#endif
|
||||
|
||||
#if DCHECK_IS_ON()
|
||||
electron::safestorage::SetElectronCryptoReady(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
network::mojom::NetworkContextParamsPtr
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 16,0,0,20210803
|
||||
PRODUCTVERSION 16,0,0,20210803
|
||||
FILEVERSION 16,0,0,20210811
|
||||
PRODUCTVERSION 16,0,0,20210811
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
||||
@@ -168,6 +168,7 @@ using FullScreenTransitionState =
|
||||
- (void)windowDidResize:(NSNotification*)notification {
|
||||
[super windowDidResize:notification];
|
||||
shell_->NotifyWindowResize();
|
||||
shell_->RedrawTrafficLights();
|
||||
}
|
||||
|
||||
- (void)windowWillMove:(NSNotification*)notification {
|
||||
|
||||
66
shell/browser/ui/cocoa/window_buttons_proxy.h
Normal file
66
shell/browser/ui/cocoa/window_buttons_proxy.h
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) 2021 Microsoft, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef SHELL_BROWSER_UI_COCOA_WINDOW_BUTTONS_PROXY_H_
|
||||
#define SHELL_BROWSER_UI_COCOA_WINDOW_BUTTONS_PROXY_H_
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "base/mac/scoped_nsobject.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
#include "ui/gfx/geometry/point.h"
|
||||
|
||||
@class WindowButtonsProxy;
|
||||
|
||||
// A helper view that floats above the window buttons.
|
||||
@interface ButtonsAreaHoverView : NSView {
|
||||
@private
|
||||
WindowButtonsProxy* proxy_;
|
||||
}
|
||||
- (id)initWithProxy:(WindowButtonsProxy*)proxy;
|
||||
@end
|
||||
|
||||
// Manipulating the window buttons.
|
||||
@interface WindowButtonsProxy : NSObject {
|
||||
@private
|
||||
NSWindow* window_;
|
||||
// The view that contains the window buttons and title.
|
||||
NSView* titlebar_container_;
|
||||
|
||||
// The window buttons.
|
||||
NSButton* left_;
|
||||
NSButton* right_;
|
||||
NSButton* middle_;
|
||||
|
||||
// Current left-top margin of buttons.
|
||||
gfx::Point margin_;
|
||||
// The default left-top margin.
|
||||
gfx::Point default_margin_;
|
||||
|
||||
// Track mouse moves above window buttons.
|
||||
BOOL show_on_hover_;
|
||||
BOOL mouse_inside_;
|
||||
base::scoped_nsobject<NSTrackingArea> tracking_area_;
|
||||
base::scoped_nsobject<ButtonsAreaHoverView> hover_view_;
|
||||
}
|
||||
|
||||
- (id)initWithWindow:(NSWindow*)window;
|
||||
|
||||
- (void)setVisible:(BOOL)visible;
|
||||
- (BOOL)isVisible;
|
||||
|
||||
// Only show window buttons when mouse moves above them.
|
||||
- (void)setShowOnHover:(BOOL)yes;
|
||||
|
||||
// Set left-top margin of the window buttons..
|
||||
- (void)setMargin:(const absl::optional<gfx::Point>&)margin;
|
||||
|
||||
// Return the bounds of all 3 buttons, with margin on all sides.
|
||||
- (NSRect)getButtonsContainerBounds;
|
||||
|
||||
- (void)redraw;
|
||||
- (void)updateTrackingAreas;
|
||||
@end
|
||||
|
||||
#endif // SHELL_BROWSER_UI_COCOA_WINDOW_BUTTONS_PROXY_H_
|
||||
200
shell/browser/ui/cocoa/window_buttons_proxy.mm
Normal file
200
shell/browser/ui/cocoa/window_buttons_proxy.mm
Normal file
@@ -0,0 +1,200 @@
|
||||
// Copyright (c) 2021 Microsoft, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/ui/cocoa/window_buttons_proxy.h"
|
||||
|
||||
#include "base/i18n/rtl.h"
|
||||
#include "base/notreached.h"
|
||||
|
||||
@implementation ButtonsAreaHoverView : NSView
|
||||
|
||||
- (id)initWithProxy:(WindowButtonsProxy*)proxy {
|
||||
if ((self = [super init])) {
|
||||
proxy_ = proxy;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
// Ignore all mouse events.
|
||||
- (NSView*)hitTest:(NSPoint)aPoint {
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)updateTrackingAreas {
|
||||
[proxy_ updateTrackingAreas];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation WindowButtonsProxy
|
||||
|
||||
- (id)initWithWindow:(NSWindow*)window {
|
||||
window_ = window;
|
||||
show_on_hover_ = NO;
|
||||
mouse_inside_ = NO;
|
||||
|
||||
// Save the sequence of the buttons for later computation.
|
||||
if (base::i18n::IsRTL()) {
|
||||
left_ = [window_ standardWindowButton:NSWindowZoomButton];
|
||||
right_ = [window_ standardWindowButton:NSWindowCloseButton];
|
||||
} else {
|
||||
left_ = [window_ standardWindowButton:NSWindowCloseButton];
|
||||
right_ = [window_ standardWindowButton:NSWindowZoomButton];
|
||||
}
|
||||
middle_ = [window_ standardWindowButton:NSWindowMiniaturizeButton];
|
||||
|
||||
// Safety check just in case Apple changes the view structure in a macOS
|
||||
// upgrade.
|
||||
if (!left_.superview || !left_.superview.superview) {
|
||||
NOTREACHED() << "macOS has changed its window buttons view structure.";
|
||||
titlebar_container_ = nullptr;
|
||||
return self;
|
||||
}
|
||||
titlebar_container_ = left_.superview.superview;
|
||||
|
||||
// Remember the default margin.
|
||||
margin_ = default_margin_ = [self getCurrentMargin];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
if (hover_view_)
|
||||
[hover_view_ removeFromSuperview];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)setVisible:(BOOL)visible {
|
||||
if (!titlebar_container_)
|
||||
return;
|
||||
[titlebar_container_ setHidden:!visible];
|
||||
}
|
||||
|
||||
- (BOOL)isVisible {
|
||||
if (!titlebar_container_)
|
||||
return YES;
|
||||
return ![titlebar_container_ isHidden];
|
||||
}
|
||||
|
||||
- (void)setShowOnHover:(BOOL)yes {
|
||||
if (!titlebar_container_)
|
||||
return;
|
||||
show_on_hover_ = yes;
|
||||
// Put a transparent view above the window buttons so we can track mouse
|
||||
// events when mouse enter/leave the window buttons.
|
||||
if (show_on_hover_) {
|
||||
hover_view_.reset([[ButtonsAreaHoverView alloc] initWithProxy:self]);
|
||||
[hover_view_ setFrame:[self getButtonsBounds]];
|
||||
[titlebar_container_ addSubview:hover_view_.get()];
|
||||
} else {
|
||||
[hover_view_ removeFromSuperview];
|
||||
hover_view_.reset();
|
||||
}
|
||||
[self updateButtonsVisibility];
|
||||
}
|
||||
|
||||
- (void)setMargin:(const absl::optional<gfx::Point>&)margin {
|
||||
if (margin)
|
||||
margin_ = *margin;
|
||||
else
|
||||
margin_ = default_margin_;
|
||||
[self redraw];
|
||||
}
|
||||
|
||||
- (NSRect)getButtonsContainerBounds {
|
||||
return NSInsetRect([self getButtonsBounds], -margin_.x(), -margin_.y());
|
||||
}
|
||||
|
||||
- (void)redraw {
|
||||
if (!titlebar_container_)
|
||||
return;
|
||||
|
||||
float button_width = NSWidth(left_.frame);
|
||||
float button_height = NSHeight(left_.frame);
|
||||
float padding = NSMinX(middle_.frame) - NSMaxX(left_.frame);
|
||||
float start;
|
||||
if (base::i18n::IsRTL())
|
||||
start =
|
||||
NSWidth(window_.frame) - 3 * button_width - 2 * padding - margin_.x();
|
||||
else
|
||||
start = margin_.x();
|
||||
|
||||
NSRect cbounds = titlebar_container_.frame;
|
||||
cbounds.size.height = button_height + 2 * margin_.y();
|
||||
cbounds.origin.y = NSHeight(window_.frame) - NSHeight(cbounds);
|
||||
[titlebar_container_ setFrame:cbounds];
|
||||
|
||||
[left_ setFrameOrigin:NSMakePoint(start, margin_.y())];
|
||||
start += button_width + padding;
|
||||
[middle_ setFrameOrigin:NSMakePoint(start, margin_.y())];
|
||||
start += button_width + padding;
|
||||
[right_ setFrameOrigin:NSMakePoint(start, margin_.y())];
|
||||
|
||||
if (hover_view_)
|
||||
[hover_view_ setFrame:[self getButtonsBounds]];
|
||||
}
|
||||
|
||||
- (void)updateTrackingAreas {
|
||||
if (tracking_area_)
|
||||
[hover_view_ removeTrackingArea:tracking_area_.get()];
|
||||
tracking_area_.reset([[NSTrackingArea alloc]
|
||||
initWithRect:NSZeroRect
|
||||
options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways |
|
||||
NSTrackingInVisibleRect
|
||||
owner:self
|
||||
userInfo:nil]);
|
||||
[hover_view_ addTrackingArea:tracking_area_.get()];
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(NSEvent*)event {
|
||||
mouse_inside_ = YES;
|
||||
[self updateButtonsVisibility];
|
||||
}
|
||||
|
||||
- (void)mouseExited:(NSEvent*)event {
|
||||
mouse_inside_ = NO;
|
||||
[self updateButtonsVisibility];
|
||||
}
|
||||
|
||||
- (void)updateButtonsVisibility {
|
||||
NSArray* buttons = @[
|
||||
[window_ standardWindowButton:NSWindowCloseButton],
|
||||
[window_ standardWindowButton:NSWindowMiniaturizeButton],
|
||||
[window_ standardWindowButton:NSWindowZoomButton],
|
||||
];
|
||||
// Show buttons when mouse hovers above them.
|
||||
BOOL hidden = show_on_hover_ && !mouse_inside_;
|
||||
// Always show buttons under fullscreen.
|
||||
if ([window_ styleMask] & NSWindowStyleMaskFullScreen)
|
||||
hidden = NO;
|
||||
for (NSView* button in buttons) {
|
||||
[button setHidden:hidden];
|
||||
[button setNeedsDisplay:YES];
|
||||
}
|
||||
}
|
||||
|
||||
// Return the bounds of all 3 buttons.
|
||||
- (NSRect)getButtonsBounds {
|
||||
return NSMakeRect(NSMinX(left_.frame), NSMinY(left_.frame),
|
||||
NSMaxX(right_.frame) - NSMinX(left_.frame),
|
||||
NSHeight(left_.frame));
|
||||
}
|
||||
|
||||
// Compute margin from position of current buttons.
|
||||
- (gfx::Point)getCurrentMargin {
|
||||
gfx::Point result;
|
||||
if (!titlebar_container_)
|
||||
return result;
|
||||
|
||||
result.set_y((NSHeight(titlebar_container_.frame) - NSHeight(left_.frame)) /
|
||||
2);
|
||||
|
||||
if (base::i18n::IsRTL())
|
||||
result.set_x(NSWidth(window_.frame) - NSMaxX(right_.frame));
|
||||
else
|
||||
result.set_x(NSMinX(left_.frame));
|
||||
return result;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright (c) 2021 Microsoft, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef SHELL_BROWSER_UI_COCOA_WINDOW_BUTTONS_VIEW_H_
|
||||
#define SHELL_BROWSER_UI_COCOA_WINDOW_BUTTONS_VIEW_H_
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "base/mac/scoped_nsobject.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
#include "ui/gfx/geometry/point.h"
|
||||
|
||||
// Custom Quit, Minimize and Full Screen button container for frameless
|
||||
// windows.
|
||||
@interface WindowButtonsView : NSView {
|
||||
@private
|
||||
BOOL mouse_inside_;
|
||||
BOOL show_on_hover_;
|
||||
BOOL is_rtl_;
|
||||
gfx::Point margin_;
|
||||
base::scoped_nsobject<NSTrackingArea> tracking_area_;
|
||||
}
|
||||
|
||||
+ (gfx::Point)defaultMargin;
|
||||
+ (gfx::Point)hiddenInsetMargin;
|
||||
- (id)initWithMargin:(const absl::optional<gfx::Point>&)margin;
|
||||
- (void)setMargin:(const absl::optional<gfx::Point>&)margin;
|
||||
- (void)setShowOnHover:(BOOL)yes;
|
||||
- (void)setNeedsDisplayForButtons;
|
||||
- (gfx::Point)getMargin;
|
||||
@end
|
||||
|
||||
#endif // SHELL_BROWSER_UI_COCOA_WINDOW_BUTTONS_VIEW_H_
|
||||
@@ -1,138 +0,0 @@
|
||||
// Copyright (c) 2021 Microsoft, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/ui/cocoa/window_buttons_view.h"
|
||||
|
||||
#include "base/cxx17_backports.h"
|
||||
#include "base/i18n/rtl.h"
|
||||
#include "base/logging.h"
|
||||
#include "ui/gfx/mac/coordinate_conversion.h"
|
||||
|
||||
namespace {
|
||||
|
||||
const CGFloat kButtonPadding = 20.;
|
||||
|
||||
const NSWindowButton kButtonTypes[] = {
|
||||
NSWindowCloseButton,
|
||||
NSWindowMiniaturizeButton,
|
||||
NSWindowZoomButton,
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@implementation WindowButtonsView
|
||||
|
||||
+ (gfx::Point)defaultMargin {
|
||||
if (@available(macOS 11.0, *)) {
|
||||
return gfx::Point(7, 6);
|
||||
} else {
|
||||
return gfx::Point(7, 3);
|
||||
}
|
||||
}
|
||||
|
||||
+ (gfx::Point)hiddenInsetMargin {
|
||||
// For macOS >= 11, while this value does not match offical macOS apps like
|
||||
// Safari or Notes, it matches titleBarStyle's old implementation before
|
||||
// Electron <= 12.
|
||||
return gfx::Point(12, 11);
|
||||
}
|
||||
|
||||
- (id)initWithMargin:(const absl::optional<gfx::Point>&)margin {
|
||||
self = [super initWithFrame:NSZeroRect];
|
||||
[self setMargin:margin];
|
||||
|
||||
mouse_inside_ = false;
|
||||
show_on_hover_ = false;
|
||||
is_rtl_ = base::i18n::IsRTL();
|
||||
|
||||
for (size_t i = 0; i < base::size(kButtonTypes); ++i) {
|
||||
NSButton* button = [NSWindow standardWindowButton:kButtonTypes[i]
|
||||
forStyleMask:NSWindowStyleMaskTitled];
|
||||
[button setTag:i];
|
||||
int left_index = is_rtl_ ? base::size(kButtonTypes) - i - 1 : i;
|
||||
[button setFrameOrigin:NSMakePoint(left_index * kButtonPadding, 0)];
|
||||
[self addSubview:button];
|
||||
}
|
||||
|
||||
NSView* last_button =
|
||||
is_rtl_ ? [[self subviews] firstObject] : [[self subviews] lastObject];
|
||||
[self setFrameSize:NSMakeSize(last_button.frame.origin.x +
|
||||
last_button.frame.size.width,
|
||||
last_button.frame.size.height)];
|
||||
[self setNeedsDisplayForButtons];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setMargin:(const absl::optional<gfx::Point>&)margin {
|
||||
margin_ = margin.value_or([WindowButtonsView defaultMargin]);
|
||||
}
|
||||
|
||||
- (void)setShowOnHover:(BOOL)yes {
|
||||
show_on_hover_ = yes;
|
||||
[self setNeedsDisplayForButtons];
|
||||
}
|
||||
|
||||
- (void)setNeedsDisplayForButtons {
|
||||
for (NSView* subview in self.subviews) {
|
||||
[subview setHidden:(show_on_hover_ && !mouse_inside_)];
|
||||
[subview setNeedsDisplay:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeFromSuperview {
|
||||
[super removeFromSuperview];
|
||||
mouse_inside_ = NO;
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToWindow {
|
||||
// Stay in upper left corner.
|
||||
CGFloat y =
|
||||
self.superview.frame.size.height - self.frame.size.height - margin_.y();
|
||||
if (is_rtl_) {
|
||||
CGFloat x =
|
||||
self.superview.frame.size.width - self.frame.size.width - margin_.x();
|
||||
[self setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin];
|
||||
[self setFrameOrigin:NSMakePoint(x, y)];
|
||||
} else {
|
||||
[self setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
|
||||
[self setFrameOrigin:NSMakePoint(margin_.x(), y)];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)_mouseInGroup:(NSButton*)button {
|
||||
return mouse_inside_;
|
||||
}
|
||||
|
||||
- (void)updateTrackingAreas {
|
||||
[super updateTrackingAreas];
|
||||
if (tracking_area_)
|
||||
[self removeTrackingArea:tracking_area_.get()];
|
||||
|
||||
tracking_area_.reset([[NSTrackingArea alloc]
|
||||
initWithRect:NSZeroRect
|
||||
options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways |
|
||||
NSTrackingInVisibleRect
|
||||
owner:self
|
||||
userInfo:nil]);
|
||||
[self addTrackingArea:tracking_area_.get()];
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(NSEvent*)event {
|
||||
[super mouseEntered:event];
|
||||
mouse_inside_ = YES;
|
||||
[self setNeedsDisplayForButtons];
|
||||
}
|
||||
|
||||
- (void)mouseExited:(NSEvent*)event {
|
||||
[super mouseExited:event];
|
||||
mouse_inside_ = NO;
|
||||
[self setNeedsDisplayForButtons];
|
||||
}
|
||||
|
||||
- (gfx::Point)getMargin {
|
||||
return margin_;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "sandbox/policy/switches.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/native_window.h"
|
||||
#include "shell/browser/session_preferences.h"
|
||||
#include "shell/common/gin_converters/value_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/options_switches.h"
|
||||
@@ -127,7 +128,7 @@ void WebContentsPreferences::Clear() {
|
||||
node_integration_in_worker_ = false;
|
||||
disable_html_fullscreen_window_resize_ = false;
|
||||
webview_tag_ = false;
|
||||
sandbox_ = false;
|
||||
sandbox_ = absl::nullopt;
|
||||
native_window_open_ = true;
|
||||
context_isolation_ = true;
|
||||
javascript_ = true;
|
||||
@@ -174,11 +175,7 @@ void WebContentsPreferences::Clear() {
|
||||
void WebContentsPreferences::SetFromDictionary(
|
||||
const gin_helper::Dictionary& web_preferences) {
|
||||
Clear();
|
||||
Merge(web_preferences);
|
||||
}
|
||||
|
||||
void WebContentsPreferences::Merge(
|
||||
const gin_helper::Dictionary& web_preferences) {
|
||||
web_preferences.Get(options::kPlugins, &plugins_);
|
||||
web_preferences.Get(options::kExperimentalFeatures, &experimental_features_);
|
||||
web_preferences.Get(options::kNodeIntegration, &node_integration_);
|
||||
@@ -189,7 +186,9 @@ void WebContentsPreferences::Merge(
|
||||
web_preferences.Get(options::kDisableHtmlFullscreenWindowResize,
|
||||
&disable_html_fullscreen_window_resize_);
|
||||
web_preferences.Get(options::kWebviewTag, &webview_tag_);
|
||||
web_preferences.Get(options::kSandbox, &sandbox_);
|
||||
bool sandbox;
|
||||
if (web_preferences.Get(options::kSandbox, &sandbox))
|
||||
sandbox_ = sandbox;
|
||||
web_preferences.Get(options::kNativeWindowOpen, &native_window_open_);
|
||||
web_preferences.Get(options::kContextIsolation, &context_isolation_);
|
||||
web_preferences.Get(options::kJavaScript, &javascript_);
|
||||
@@ -311,6 +310,16 @@ bool WebContentsPreferences::GetPreloadPath(base::FilePath* path) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WebContentsPreferences::IsSandboxed() const {
|
||||
if (sandbox_)
|
||||
return *sandbox_;
|
||||
bool sandbox_disabled_by_default =
|
||||
node_integration_ || node_integration_in_worker_ || preload_path_ ||
|
||||
!SessionPreferences::GetValidPreloads(web_contents_->GetBrowserContext())
|
||||
.empty();
|
||||
return !sandbox_disabled_by_default;
|
||||
}
|
||||
|
||||
// static
|
||||
content::WebContents* WebContentsPreferences::GetWebContentsFromProcessID(
|
||||
int process_id) {
|
||||
@@ -342,7 +351,7 @@ void WebContentsPreferences::AppendCommandLineSwitches(
|
||||
// unless nodeIntegrationInSubFrames is enabled
|
||||
bool can_sandbox_frame = is_subframe && !node_integration_in_sub_frames_;
|
||||
|
||||
if (sandbox_ || can_sandbox_frame) {
|
||||
if (IsSandboxed() || can_sandbox_frame) {
|
||||
command_line->AppendSwitch(switches::kEnableSandbox);
|
||||
} else if (!command_line->HasSwitch(switches::kEnableSandbox)) {
|
||||
command_line->AppendSwitch(sandbox::policy::switches::kNoSandbox);
|
||||
@@ -391,7 +400,7 @@ void WebContentsPreferences::SaveLastPreferences() {
|
||||
base::Value(node_integration_in_sub_frames_));
|
||||
last_web_preferences_.SetKey(options::kNativeWindowOpen,
|
||||
base::Value(native_window_open_));
|
||||
last_web_preferences_.SetKey(options::kSandbox, base::Value(sandbox_));
|
||||
last_web_preferences_.SetKey(options::kSandbox, base::Value(IsSandboxed()));
|
||||
last_web_preferences_.SetKey(options::kContextIsolation,
|
||||
base::Value(context_isolation_));
|
||||
last_web_preferences_.SetKey(options::kJavaScript, base::Value(javascript_));
|
||||
@@ -414,7 +423,7 @@ void WebContentsPreferences::OverrideWebkitPrefs(
|
||||
blink::web_pref::WebPreferences* prefs) {
|
||||
prefs->javascript_enabled = javascript_;
|
||||
prefs->images_enabled = images_;
|
||||
// GetImageAnimationPolicy(&preference_, &prefs->animation_policy);
|
||||
prefs->animation_policy = image_animation_policy_;
|
||||
prefs->text_areas_are_resizable = text_areas_are_resizable_;
|
||||
prefs->navigate_on_drag_drop = navigate_on_drag_drop_;
|
||||
prefs->autoplay_policy = autoplay_policy_;
|
||||
|
||||
@@ -36,8 +36,6 @@ class WebContentsPreferences
|
||||
const gin_helper::Dictionary& web_preferences);
|
||||
~WebContentsPreferences() override;
|
||||
|
||||
void Merge(const gin_helper::Dictionary& new_web_preferences);
|
||||
|
||||
void SetFromDictionary(const gin_helper::Dictionary& new_web_preferences);
|
||||
|
||||
// Append command paramters according to preferences.
|
||||
@@ -70,6 +68,7 @@ class WebContentsPreferences
|
||||
bool ShouldUseNativeWindowOpen() const { return native_window_open_; }
|
||||
bool IsWebSecurityEnabled() const { return web_security_; }
|
||||
bool GetPreloadPath(base::FilePath* path) const;
|
||||
bool IsSandboxed() const;
|
||||
|
||||
private:
|
||||
friend class content::WebContentsUserData<WebContentsPreferences>;
|
||||
@@ -90,7 +89,7 @@ class WebContentsPreferences
|
||||
bool node_integration_in_worker_;
|
||||
bool disable_html_fullscreen_window_resize_;
|
||||
bool webview_tag_;
|
||||
bool sandbox_;
|
||||
absl::optional<bool> sandbox_;
|
||||
bool native_window_open_;
|
||||
bool context_isolation_;
|
||||
bool javascript_;
|
||||
|
||||
@@ -14,25 +14,42 @@
|
||||
#include "base/strings/string_split.h"
|
||||
#include "components/crash/core/common/crash_key.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "electron/fuses.h"
|
||||
#include "shell/common/electron_constants.h"
|
||||
#include "shell/common/options_switches.h"
|
||||
#include "third_party/crashpad/crashpad/client/annotation.h"
|
||||
|
||||
#include "gin/wrappable.h"
|
||||
#include "shell/browser/api/electron_api_app.h"
|
||||
#include "shell/browser/api/electron_api_auto_updater.h"
|
||||
#include "shell/browser/api/electron_api_browser_view.h"
|
||||
#include "shell/browser/api/electron_api_cookies.h"
|
||||
#include "shell/browser/api/electron_api_data_pipe_holder.h"
|
||||
#include "shell/browser/api/electron_api_debugger.h"
|
||||
#include "shell/browser/api/electron_api_desktop_capturer.h"
|
||||
#include "shell/browser/api/electron_api_download_item.h"
|
||||
#include "shell/browser/api/electron_api_global_shortcut.h"
|
||||
#include "shell/browser/api/electron_api_in_app_purchase.h"
|
||||
#include "shell/browser/api/electron_api_menu.h"
|
||||
#include "shell/browser/api/electron_api_native_theme.h"
|
||||
#include "shell/browser/api/electron_api_net_log.h"
|
||||
#include "shell/browser/api/electron_api_notification.h"
|
||||
#include "shell/browser/api/electron_api_power_monitor.h"
|
||||
#include "shell/browser/api/electron_api_power_save_blocker.h"
|
||||
#include "shell/browser/api/electron_api_protocol.h"
|
||||
#include "shell/browser/api/electron_api_service_worker_context.h"
|
||||
#include "shell/browser/api/electron_api_session.h"
|
||||
#include "shell/browser/api/electron_api_system_preferences.h"
|
||||
#include "shell/browser/api/electron_api_url_loader.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/api/electron_api_web_frame_main.h"
|
||||
#include "shell/browser/api/electron_api_web_request.h"
|
||||
#include "shell/browser/api/event.h"
|
||||
#include "shell/common/api/electron_api_native_image.h"
|
||||
#if !defined(OS_WIN)
|
||||
#include "shell/browser/api/electron_api_tray.h"
|
||||
#endif
|
||||
|
||||
namespace electron {
|
||||
|
||||
@@ -186,8 +203,14 @@ void SetCrashKeyForGinWrappable(gin::WrapperInfo* info) {
|
||||
crash_location = "Notification";
|
||||
else if (info == &electron::api::Cookies::kWrapperInfo)
|
||||
crash_location = "Cookies";
|
||||
#if BUILDFLAG(ENABLE_DESKTOP_CAPTURER)
|
||||
else if (info == &electron::api::DesktopCapturer::kWrapperInfo)
|
||||
crash_location = "DesktopCapturer";
|
||||
#endif
|
||||
#if !defined(OS_WIN)
|
||||
else if (info == &electron::api::Tray::kWrapperInfo)
|
||||
crash_location = "Tray";
|
||||
#endif // OS_WIN
|
||||
else if (info == &electron::api::NetLog::kWrapperInfo)
|
||||
crash_location = "NetLog";
|
||||
else if (info == &electron::api::NativeImage::kWrapperInfo)
|
||||
@@ -204,6 +227,32 @@ void SetCrashKeyForGinWrappable(gin::WrapperInfo* info) {
|
||||
crash_location = "WebFrameMain";
|
||||
else if (info == &electron::api::WebRequest::kWrapperInfo)
|
||||
crash_location = "WebRequest";
|
||||
else if (info == &electron::api::SystemPreferences::kWrapperInfo)
|
||||
crash_location = "SystemPreferences";
|
||||
else if (info == &electron::api::Session::kWrapperInfo)
|
||||
crash_location = "Session";
|
||||
else if (info == &electron::api::DownloadItem::kWrapperInfo)
|
||||
crash_location = "DownloadItem";
|
||||
else if (info == &electron::api::NativeTheme::kWrapperInfo)
|
||||
crash_location = "NativeTheme";
|
||||
else if (info == &electron::api::Debugger::kWrapperInfo)
|
||||
crash_location = "Debugger";
|
||||
else if (info == &electron::api::GlobalShortcut::kWrapperInfo)
|
||||
crash_location = "GlobalShortcut";
|
||||
else if (info == &electron::api::InAppPurchase::kWrapperInfo)
|
||||
crash_location = "InAppPurchase";
|
||||
else if (info == &electron::api::DataPipeHolder::kWrapperInfo)
|
||||
crash_location = "DataPipeHolder";
|
||||
else if (info == &electron::api::AutoUpdater::kWrapperInfo)
|
||||
crash_location = "AutoUpdater";
|
||||
else if (info == &electron::api::SimpleURLLoaderWrapper::kWrapperInfo)
|
||||
crash_location = "SimpleURLLoaderWrapper";
|
||||
else if (info == &gin_helper::Event::kWrapperInfo)
|
||||
crash_location = "Event";
|
||||
else if (info == &electron::api::PowerSaveBlocker::kWrapperInfo)
|
||||
crash_location = "PowerSaveBlocker";
|
||||
else if (info == &electron::api::App::kWrapperInfo)
|
||||
crash_location = "App";
|
||||
else
|
||||
crash_location =
|
||||
"Deleted kWrapperInfo does not match listed component. Please review "
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/common/content_paths.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "electron/fuses.h"
|
||||
#include "shell/browser/api/electron_api_app.h"
|
||||
#include "shell/common/api/electron_bindings.h"
|
||||
#include "shell/common/electron_command_line.h"
|
||||
@@ -59,6 +60,7 @@
|
||||
V(electron_browser_power_save_blocker) \
|
||||
V(electron_browser_protocol) \
|
||||
V(electron_browser_printing) \
|
||||
V(electron_browser_safe_storage) \
|
||||
V(electron_browser_session) \
|
||||
V(electron_browser_system_preferences) \
|
||||
V(electron_browser_base_window) \
|
||||
@@ -188,16 +190,26 @@ void ErrorMessageListener(v8::Local<v8::Message> message,
|
||||
}
|
||||
}
|
||||
|
||||
const std::unordered_set<base::StringPiece, base::StringPieceHash>
|
||||
GetAllowedDebugOptions() {
|
||||
if (electron::fuses::IsNodeCliInspectEnabled()) {
|
||||
// Only allow DebugOptions in non-ELECTRON_RUN_AS_NODE mode
|
||||
return {
|
||||
"--inspect", "--inspect-brk",
|
||||
"--inspect-port", "--debug",
|
||||
"--debug-brk", "--debug-port",
|
||||
"--inspect-brk-node", "--inspect-publish-uid",
|
||||
};
|
||||
}
|
||||
// If node CLI inspect support is disabled, allow no debug options.
|
||||
return {};
|
||||
}
|
||||
|
||||
// Initialize Node.js cli options to pass to Node.js
|
||||
// See https://nodejs.org/api/cli.html#cli_options
|
||||
void SetNodeCliFlags() {
|
||||
// Only allow DebugOptions in non-ELECTRON_RUN_AS_NODE mode
|
||||
const std::unordered_set<base::StringPiece, base::StringPieceHash> allowed = {
|
||||
"--inspect", "--inspect-brk",
|
||||
"--inspect-port", "--debug",
|
||||
"--debug-brk", "--debug-port",
|
||||
"--inspect-brk-node", "--inspect-publish-uid",
|
||||
};
|
||||
const std::unordered_set<base::StringPiece, base::StringPieceHash> allowed =
|
||||
GetAllowedDebugOptions();
|
||||
|
||||
const auto argv = base::CommandLine::ForCurrentProcess()->argv();
|
||||
std::vector<std::string> args;
|
||||
@@ -231,7 +243,7 @@ void SetNodeCliFlags() {
|
||||
} else if (!errors.empty()) {
|
||||
LOG(ERROR) << err_str << base::JoinString(errors, " ");
|
||||
}
|
||||
} // namespace
|
||||
}
|
||||
|
||||
// Initialize NODE_OPTIONS to pass to Node.js
|
||||
// See https://nodejs.org/api/cli.html#cli_node_options_options
|
||||
@@ -246,34 +258,39 @@ void SetNodeOptions(base::Environment* env) {
|
||||
"--http-parser"};
|
||||
|
||||
if (env->HasVar("NODE_OPTIONS")) {
|
||||
std::string options;
|
||||
env->GetVar("NODE_OPTIONS", &options);
|
||||
std::vector<std::string> parts = base::SplitString(
|
||||
options, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||
if (electron::fuses::IsNodeOptionsEnabled()) {
|
||||
std::string options;
|
||||
env->GetVar("NODE_OPTIONS", &options);
|
||||
std::vector<std::string> parts = base::SplitString(
|
||||
options, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||
|
||||
bool is_packaged_app = electron::api::App::IsPackaged();
|
||||
bool is_packaged_app = electron::api::App::IsPackaged();
|
||||
|
||||
for (const auto& part : parts) {
|
||||
// Strip off values passed to individual NODE_OPTIONs
|
||||
std::string option = part.substr(0, part.find('='));
|
||||
for (const auto& part : parts) {
|
||||
// Strip off values passed to individual NODE_OPTIONs
|
||||
std::string option = part.substr(0, part.find('='));
|
||||
|
||||
if (is_packaged_app &&
|
||||
allowed_in_packaged.find(option) == allowed_in_packaged.end()) {
|
||||
// Explicitly disallow majority of NODE_OPTIONS in packaged apps
|
||||
LOG(ERROR) << "Most NODE_OPTIONs are not supported in packaged apps."
|
||||
<< " See documentation for more details.";
|
||||
options.erase(options.find(option), part.length());
|
||||
} else if (disallowed.find(option) != disallowed.end()) {
|
||||
// Remove NODE_OPTIONS specifically disallowed for use in Node.js
|
||||
// through Electron owing to constraints like BoringSSL.
|
||||
LOG(ERROR) << "The NODE_OPTION " << option
|
||||
<< " is not supported in Electron";
|
||||
options.erase(options.find(option), part.length());
|
||||
if (is_packaged_app &&
|
||||
allowed_in_packaged.find(option) == allowed_in_packaged.end()) {
|
||||
// Explicitly disallow majority of NODE_OPTIONS in packaged apps
|
||||
LOG(ERROR) << "Most NODE_OPTIONs are not supported in packaged apps."
|
||||
<< " See documentation for more details.";
|
||||
options.erase(options.find(option), part.length());
|
||||
} else if (disallowed.find(option) != disallowed.end()) {
|
||||
// Remove NODE_OPTIONS specifically disallowed for use in Node.js
|
||||
// through Electron owing to constraints like BoringSSL.
|
||||
LOG(ERROR) << "The NODE_OPTION " << option
|
||||
<< " is not supported in Electron";
|
||||
options.erase(options.find(option), part.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// overwrite new NODE_OPTIONS without unsupported variables
|
||||
env->SetVar("NODE_OPTIONS", options);
|
||||
// overwrite new NODE_OPTIONS without unsupported variables
|
||||
env->SetVar("NODE_OPTIONS", options);
|
||||
} else {
|
||||
LOG(ERROR) << "NODE_OPTIONS have been disabled in this app";
|
||||
env->SetVar("NODE_OPTIONS", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,6 +381,8 @@ void NodeBindings::Initialize() {
|
||||
|
||||
auto env = base::Environment::Create();
|
||||
SetNodeOptions(env.get());
|
||||
node::Environment::should_read_node_options_from_env_ =
|
||||
fuses::IsNodeOptionsEnabled();
|
||||
|
||||
std::vector<std::string> argv = {"electron"};
|
||||
std::vector<std::string> exec_argv;
|
||||
|
||||
@@ -1593,13 +1593,14 @@ describe('BrowserWindow module', () => {
|
||||
expect(w._getWindowButtonVisibility()).to.equal(true);
|
||||
});
|
||||
|
||||
it('changes window button visibility for customButtonsOnHover window', () => {
|
||||
// Buttons of customButtonsOnHover are always hidden unless hovered.
|
||||
it('does not change window button visibility for customButtonsOnHover window', () => {
|
||||
const w = new BrowserWindow({ show: false, frame: false, titleBarStyle: 'customButtonsOnHover' });
|
||||
expect(w._getWindowButtonVisibility()).to.equal(true);
|
||||
w.setWindowButtonVisibility(false);
|
||||
expect(w._getWindowButtonVisibility()).to.equal(false);
|
||||
w.setWindowButtonVisibility(true);
|
||||
expect(w._getWindowButtonVisibility()).to.equal(true);
|
||||
expect(w._getWindowButtonVisibility()).to.equal(false);
|
||||
w.setWindowButtonVisibility(false);
|
||||
expect(w._getWindowButtonVisibility()).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -138,8 +138,11 @@ function waitForNewFileInDir (dir: string): Promise<string[]> {
|
||||
|
||||
// TODO(nornagon): Fix tests on linux/arm.
|
||||
ifdescribe(!isLinuxOnArm && !process.mas && !process.env.DISABLE_CRASH_REPORTER_TESTS)('crashReporter module', function () {
|
||||
for (const withLinuxCrashpad of (process.platform === 'linux' ? [false, true] : [false])) {
|
||||
const crashpadExtraArgs = withLinuxCrashpad ? ['--enable-crashpad'] : [];
|
||||
// TODO(nornagon): remove linux/breakpad tests once breakpad support is fully
|
||||
// removed.
|
||||
for (const enableLinuxCrashpad of (process.platform === 'linux' ? [false] : [false])) {
|
||||
const withLinuxCrashpad = enableLinuxCrashpad || (process.platform === 'linux');
|
||||
const crashpadExtraArgs = enableLinuxCrashpad ? ['--enable-crashpad'] : [];
|
||||
describe(withLinuxCrashpad ? '(with crashpad)' : '', () => {
|
||||
describe('should send minidump', () => {
|
||||
it('when renderer crashes', async () => {
|
||||
|
||||
103
spec-main/api-safe-storage-spec.ts
Normal file
103
spec-main/api-safe-storage-spec.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import * as cp from 'child_process';
|
||||
import * as path from 'path';
|
||||
import { safeStorage } from 'electron/main';
|
||||
import { expect } from 'chai';
|
||||
import { emittedOnce } from './events-helpers';
|
||||
import { ifdescribe } from './spec-helpers';
|
||||
import * as fs from 'fs';
|
||||
|
||||
/* isEncryptionAvailable returns false in Linux when running CI due to a mocked dbus. This stops
|
||||
* Chrome from reaching the system's keyring or libsecret. When running the tests with config.store
|
||||
* set to basic-text, a nullptr is returned from chromium, defaulting the available encryption to false.
|
||||
*
|
||||
* Because all encryption methods are gated by isEncryptionAvailable, the methods will never return the correct values
|
||||
* when run on CI and linux.
|
||||
*/
|
||||
|
||||
ifdescribe(process.platform !== 'linux')('safeStorage module', () => {
|
||||
after(async () => {
|
||||
const pathToEncryptedString = path.resolve(__dirname, 'fixtures', 'api', 'safe-storage', 'encrypted.txt');
|
||||
if (fs.existsSync(pathToEncryptedString)) {
|
||||
await fs.unlinkSync(pathToEncryptedString);
|
||||
}
|
||||
});
|
||||
|
||||
describe('SafeStorage.isEncryptionAvailable()', () => {
|
||||
it('should return true when encryption key is available (macOS, Windows)', () => {
|
||||
expect(safeStorage.isEncryptionAvailable()).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SafeStorage.encryptString()', () => {
|
||||
it('valid input should correctly encrypt string', () => {
|
||||
const plaintext = 'plaintext';
|
||||
const encrypted = safeStorage.encryptString(plaintext);
|
||||
expect(Buffer.isBuffer(encrypted)).to.equal(true);
|
||||
});
|
||||
|
||||
it('UTF-16 characters can be encrypted', () => {
|
||||
const plaintext = '€ - utf symbol';
|
||||
const encrypted = safeStorage.encryptString(plaintext);
|
||||
expect(Buffer.isBuffer(encrypted)).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SafeStorage.decryptString()', () => {
|
||||
it('valid input should correctly decrypt string', () => {
|
||||
const encrypted = safeStorage.encryptString('plaintext');
|
||||
expect(safeStorage.decryptString(encrypted)).to.equal('plaintext');
|
||||
});
|
||||
|
||||
it('UTF-16 characters can be decrypted', () => {
|
||||
const plaintext = '€ - utf symbol';
|
||||
const encrypted = safeStorage.encryptString(plaintext);
|
||||
expect(safeStorage.decryptString(encrypted)).to.equal(plaintext);
|
||||
});
|
||||
|
||||
it('unencrypted input should throw', () => {
|
||||
const plaintextBuffer = Buffer.from('I am unencoded!', 'utf-8');
|
||||
expect(() => {
|
||||
safeStorage.decryptString(plaintextBuffer);
|
||||
}).to.throw(Error);
|
||||
});
|
||||
|
||||
it('non-buffer input should throw', () => {
|
||||
const notABuffer = {} as any;
|
||||
expect(() => {
|
||||
safeStorage.decryptString(notABuffer);
|
||||
}).to.throw(Error);
|
||||
});
|
||||
});
|
||||
describe('safeStorage persists encryption key across app relaunch', () => {
|
||||
it('can decrypt after closing and reopening app', async () => {
|
||||
const fixturesPath = path.resolve(__dirname, 'fixtures');
|
||||
|
||||
const encryptAppPath = path.join(fixturesPath, 'api', 'safe-storage', 'encrypt-app');
|
||||
const encryptAppProcess = cp.spawn(process.execPath, [encryptAppPath]);
|
||||
let stdout: string = '';
|
||||
encryptAppProcess.stderr.on('data', data => { stdout += data; });
|
||||
encryptAppProcess.stderr.on('data', data => { stdout += data; });
|
||||
|
||||
try {
|
||||
await emittedOnce(encryptAppProcess, 'exit');
|
||||
|
||||
const appPath = path.join(fixturesPath, 'api', 'safe-storage', 'decrypt-app');
|
||||
const relaunchedAppProcess = cp.spawn(process.execPath, [appPath]);
|
||||
|
||||
let output = '';
|
||||
relaunchedAppProcess.stdout.on('data', data => { output += data; });
|
||||
relaunchedAppProcess.stderr.on('data', data => { output += data; });
|
||||
|
||||
const [code] = await emittedOnce(relaunchedAppProcess, 'exit');
|
||||
|
||||
if (!output.includes('plaintext')) {
|
||||
console.log(code, output);
|
||||
}
|
||||
expect(output).to.include('plaintext');
|
||||
} catch (e) {
|
||||
console.log(stdout);
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
13
spec-main/fixtures/api/safe-storage/decrypt-app/main.js
Normal file
13
spec-main/fixtures/api/safe-storage/decrypt-app/main.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const { app, safeStorage, ipcMain } = require('electron');
|
||||
const { promises: fs } = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const pathToEncryptedString = path.resolve(__dirname, '..', 'encrypted.txt');
|
||||
const readFile = fs.readFile;
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
const encryptedString = await readFile(pathToEncryptedString);
|
||||
const decrypted = safeStorage.decryptString(encryptedString);
|
||||
console.log(decrypted);
|
||||
app.quit();
|
||||
});
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "electron-safe-storage",
|
||||
"main": "main.js"
|
||||
}
|
||||
12
spec-main/fixtures/api/safe-storage/encrypt-app/main.js
Normal file
12
spec-main/fixtures/api/safe-storage/encrypt-app/main.js
Normal file
@@ -0,0 +1,12 @@
|
||||
const { app, safeStorage, ipcMain } = require('electron');
|
||||
const { promises: fs } = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const pathToEncryptedString = path.resolve(__dirname, '..', 'encrypted.txt');
|
||||
const writeFile = fs.writeFile;
|
||||
|
||||
app.whenReady().then(async () => {
|
||||
const encrypted = safeStorage.encryptString('plaintext');
|
||||
const encryptedString = await writeFile(pathToEncryptedString, encrypted);
|
||||
app.quit();
|
||||
});
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "electron-safe-storage",
|
||||
"main": "main.js"
|
||||
}
|
||||
@@ -2,7 +2,9 @@
|
||||
[
|
||||
"top=5,left=10,resizable=no",
|
||||
{
|
||||
"sender": "[WebContents]"
|
||||
"sender": "[WebContents]",
|
||||
"frameId": 1,
|
||||
"processId": "placeholder-process-id"
|
||||
},
|
||||
"about:blank",
|
||||
"frame-name",
|
||||
@@ -18,11 +20,10 @@
|
||||
"y": 5,
|
||||
"webPreferences": {
|
||||
"contextIsolation": true,
|
||||
"nativeWindowOpen": true,
|
||||
"nodeIntegration": false,
|
||||
"webviewTag": false,
|
||||
"nodeIntegrationInSubFrames": false,
|
||||
"openerId": null
|
||||
"openerId": "placeholder-opener-id"
|
||||
},
|
||||
"webContents": "[WebContents]"
|
||||
},
|
||||
@@ -36,7 +37,9 @@
|
||||
[
|
||||
"zoomFactor=2,resizable=0,x=0,y=10",
|
||||
{
|
||||
"sender": "[WebContents]"
|
||||
"sender": "[WebContents]",
|
||||
"frameId": 1,
|
||||
"processId": "placeholder-process-id"
|
||||
},
|
||||
"about:blank",
|
||||
"frame-name",
|
||||
@@ -51,11 +54,10 @@
|
||||
"webPreferences": {
|
||||
"zoomFactor": "2",
|
||||
"contextIsolation": true,
|
||||
"nativeWindowOpen": true,
|
||||
"nodeIntegration": false,
|
||||
"webviewTag": false,
|
||||
"nodeIntegrationInSubFrames": false,
|
||||
"openerId": null
|
||||
"openerId": "placeholder-opener-id"
|
||||
},
|
||||
"webContents": "[WebContents]"
|
||||
},
|
||||
@@ -69,7 +71,9 @@
|
||||
[
|
||||
"backgroundColor=gray,webPreferences=0,x=100,y=100",
|
||||
{
|
||||
"sender": "[WebContents]"
|
||||
"sender": "[WebContents]",
|
||||
"frameId": 1,
|
||||
"processId": "placeholder-process-id"
|
||||
},
|
||||
"about:blank",
|
||||
"frame-name",
|
||||
@@ -81,11 +85,10 @@
|
||||
"backgroundColor": "gray",
|
||||
"webPreferences": {
|
||||
"contextIsolation": true,
|
||||
"nativeWindowOpen": true,
|
||||
"nodeIntegration": false,
|
||||
"webviewTag": false,
|
||||
"nodeIntegrationInSubFrames": false,
|
||||
"openerId": null,
|
||||
"openerId": "placeholder-opener-id",
|
||||
"backgroundColor": "gray"
|
||||
},
|
||||
"x": 100,
|
||||
@@ -102,7 +105,9 @@
|
||||
[
|
||||
"x=50,y=20,title=sup",
|
||||
{
|
||||
"sender": "[WebContents]"
|
||||
"sender": "[WebContents]",
|
||||
"frameId": 1,
|
||||
"processId": "placeholder-process-id"
|
||||
},
|
||||
"about:blank",
|
||||
"frame-name",
|
||||
@@ -116,11 +121,10 @@
|
||||
"title": "sup",
|
||||
"webPreferences": {
|
||||
"contextIsolation": true,
|
||||
"nativeWindowOpen": true,
|
||||
"nodeIntegration": false,
|
||||
"webviewTag": false,
|
||||
"nodeIntegrationInSubFrames": false,
|
||||
"openerId": null
|
||||
"openerId": "placeholder-opener-id"
|
||||
},
|
||||
"webContents": "[WebContents]"
|
||||
},
|
||||
@@ -134,7 +138,9 @@
|
||||
[
|
||||
"show=false,top=1,left=1",
|
||||
{
|
||||
"sender": "[WebContents]"
|
||||
"sender": "[WebContents]",
|
||||
"frameId": 1,
|
||||
"processId": "placeholder-process-id"
|
||||
},
|
||||
"about:blank",
|
||||
"frame-name",
|
||||
@@ -149,11 +155,10 @@
|
||||
"y": 1,
|
||||
"webPreferences": {
|
||||
"contextIsolation": true,
|
||||
"nativeWindowOpen": true,
|
||||
"nodeIntegration": false,
|
||||
"webviewTag": false,
|
||||
"nodeIntegrationInSubFrames": false,
|
||||
"openerId": null
|
||||
"openerId": "placeholder-opener-id"
|
||||
},
|
||||
"webContents": "[WebContents]"
|
||||
},
|
||||
|
||||
@@ -33,7 +33,11 @@ describe('new-window event', () => {
|
||||
proxy: {
|
||||
snapshotFileName: 'proxy-window-open.snapshot.txt',
|
||||
browserWindowOptions: {
|
||||
show: false
|
||||
show: false,
|
||||
webPreferences: {
|
||||
nativeWindowOpen: false,
|
||||
sandbox: false
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
1
typings/internal-ambient.d.ts
vendored
1
typings/internal-ambient.d.ts
vendored
@@ -233,6 +233,7 @@ declare namespace NodeJS {
|
||||
};
|
||||
_linkedBinding(name: 'electron_browser_power_monitor'): PowerMonitorBinding;
|
||||
_linkedBinding(name: 'electron_browser_power_save_blocker'): { powerSaveBlocker: Electron.PowerSaveBlocker };
|
||||
_linkedBinding(name: 'electron_browser_safe_storage'): { safeStorage: Electron.SafeStorage };
|
||||
_linkedBinding(name: 'electron_browser_session'): typeof Electron.Session;
|
||||
_linkedBinding(name: 'electron_browser_system_preferences'): { systemPreferences: Electron.SystemPreferences };
|
||||
_linkedBinding(name: 'electron_browser_tray'): { Tray: Electron.Tray };
|
||||
|
||||
1
typings/internal-electron.d.ts
vendored
1
typings/internal-electron.d.ts
vendored
@@ -79,7 +79,6 @@ declare namespace Electron {
|
||||
attachToIframe(embedderWebContents: Electron.WebContents, embedderFrameId: number): void;
|
||||
detachFromOuterFrame(): void;
|
||||
setEmbedder(embedder: Electron.WebContents): void;
|
||||
attachParams?: Record<string, any>;
|
||||
viewInstanceId: number;
|
||||
}
|
||||
|
||||
|
||||
@@ -5576,9 +5576,9 @@ path-key@^3.0.0, path-key@^3.1.0:
|
||||
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
|
||||
|
||||
path-parse@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
|
||||
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||
|
||||
path-to-regexp@0.1.7:
|
||||
version "0.1.7"
|
||||
|
||||
Reference in New Issue
Block a user