Compare commits

...

12 Commits

Author SHA1 Message Date
Jeremy Rose
325faae33c fix test 2021-02-03 13:28:25 -08:00
Jeremy Rose
94f8b4b39a fix: [net] no errors on response stream 2021-02-02 16:39:43 -08:00
Electron Bot
a75cd89d2a Bump v13.0.0-nightly.20210201 2021-02-01 06:31:11 -08:00
Cheng Zhao
8bf66f8974 fix: clean up implementations of titleBarStyle (#27489)
* Rewrite titleBarStyle impls with WindowButtonsView

* Remove fullscreenWindowTitle option

* Make buttons show correctly under RTL

* Fix docs about traffic lights position

* Fix test on fullscreen resizable

* Fix button states with closabe/minimizable/fullscreenable

* Fix typo

* Deprecate the fullscreenWindowTitle option
2021-01-30 17:15:10 -06:00
Cheng Zhao
6edf6c6a95 fix: pass button callback in constructor (#27545) 2021-01-29 12:43:51 -08:00
Milan Burda
79b3393768 chore: remove bunch of usages of any (#27512) 2021-01-29 12:41:59 -08:00
Electron Bot
c7aa35a519 Bump v13.0.0-nightly.20210129 2021-01-29 06:31:35 -08:00
Michaela Laurencin
357becd113 fix: replace default frameName title with null check (#27521)
* refactor: replace default frameName title with null check

* add isNativeWindowOpen check in makeBrowserWindowOptions

* modify snapshot test files

* replace title with frame-name again for proxy - not native open

* modify proxy snapshot title key-value to come after height key-value
2021-01-29 07:24:30 -06:00
Shelley Vohr
40aeb0d994 fix: dont try to serialize WasmModuleObjects (#27518) 2021-01-28 18:20:28 -08:00
Felix Rieseberg
4f2490f8b8 docs: Update Readme, don't mention Electron < 2 (#27535)
* chore: Update Readme, don't mention Electron < 2

* chore: Add back versioning info
2021-01-28 15:34:22 -06:00
Shelley Vohr
18f4c3129d test: fix failing http spec (#27525) 2021-01-28 11:51:08 -08:00
Milan Burda
0bb1ba822a docs: update Xcode / macOS SDK version in build-instructions-macos.md (#27513) 2021-01-28 11:19:20 -08:00
40 changed files with 452 additions and 438 deletions

View File

@@ -1 +1 @@
13.0.0-nightly.20210128
13.0.0-nightly.20210201

View File

@@ -28,15 +28,12 @@ The preferred method is to install Electron as a development dependency in your
app:
```sh
npm install electron --save-dev [--save-exact]
npm install electron --save-dev
```
The `--save-exact` flag is recommended for Electron prior to version 2, as it does not follow semantic
versioning. As of version 2.0.0, Electron follows semver, so you don't need `--save-exact` flag. For info on how to manage Electron versions in your apps, see
[Electron versioning](docs/tutorial/electron-versioning.md).
For more installation options and troubleshooting tips, see
[installation](docs/tutorial/installation.md).
[installation](docs/tutorial/installation.md). For info on how to manage Electron versions in your apps, see
[Electron versioning](docs/tutorial/electron-versioning.md).
## Quick start & Electron Fiddle

View File

@@ -222,16 +222,14 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
the top left.
* `hiddenInset` - Results in a hidden title bar with an alternative look
where the traffic light buttons are slightly more inset from the window edge.
* `customButtonsOnHover` Boolean (optional) - Draw custom close,
and minimize buttons on macOS frameless windows. These buttons will not display
unless hovered over in the top left of the window. These custom buttons prevent
issues with mouse events that occur with the standard window toolbar buttons.
**Note:** This option is currently experimental.
* `customButtonsOnHover` - Results in a hidden title bar and a full size
content window, the traffic light buttons will display when being hovered
over in the top left of the window. **Note:** This option is currently
experimental.
* `trafficLightPosition` [Point](structures/point.md) (optional) - Set a
custom position for the traffic light buttons. Can only be used with
`titleBarStyle` set to `hidden` or `customButtonsOnHover`.
* `fullscreenWindowTitle` Boolean (optional) - Shows the title in the
title bar in full screen mode on macOS for all `titleBarStyle` options.
custom position for the traffic light buttons in frameless windows.
* `fullscreenWindowTitle` Boolean (optional) _Deprecated_ - Shows the title in
the title bar in full screen mode on macOS for `hiddenInset` titleBarStyle.
Default is `false`.
* `thickFrame` Boolean (optional) - Use `WS_THICKFRAME` style for frameless windows on
Windows, which adds standard window frame. Setting it to `false` will remove
@@ -1740,13 +1738,12 @@ deprecated and will be removed in an upcoming version of macOS.
* `position` [Point](structures/point.md)
Set a custom position for the traffic light buttons. Can only be used with
`titleBarStyle` set to `hidden` or `customButtonsOnHover`.
Set a custom position for the traffic light buttons in frameless window.
#### `win.getTrafficLightPosition()` _macOS_
Returns `Point` - The current position for the traffic light buttons. Can only
be used with `titleBarStyle` set to `hidden` or `customButtonsOnHover`.
Returns `Point` - The custom position for the traffic light buttons in
frameless window.
#### `win.setTouchBar(touchBar)` _macOS_

View File

@@ -42,7 +42,7 @@ $ pip install pyobjc
If you're developing Electron and don't plan to redistribute your
custom Electron build, you may skip this section.
Official Electron builds are built with [Xcode 9.4.1](http://adcdownload.apple.com/Developer_Tools/Xcode_9.4.1/Xcode_9.4.1.xip), and the macOS 10.13 SDK. Building with a newer SDK works too, but the releases currently use the 10.13 SDK.
Official Electron builds are built with [Xcode 12.2](https://download.developer.apple.com/Developer_Tools/Xcode_12.2/Xcode_12.2.xip), and the macOS 11.0 SDK. Building with a newer SDK works too, but the releases currently use the 11.0 SDK.
## Building Electron

View File

@@ -180,6 +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/drag_util_mac.mm",
"shell/browser/ui/file_dialog_mac.mm",
"shell/browser/ui/inspectable_web_contents_view_mac.h",

View File

@@ -639,8 +639,10 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
fs.promises.readdir = util.promisify(fs.readdir);
type ReaddirSyncOptions = { encoding: BufferEncoding | null; withFileTypes?: false };
const { readdirSync } = fs;
fs.readdirSync = function (pathArgument: string, options: { encoding: BufferEncoding | null; withFileTypes?: false } | BufferEncoding | null) {
fs.readdirSync = function (pathArgument: string, options: ReaddirSyncOptions | BufferEncoding | null) {
const pathInfo = splitPath(pathArgument);
if (!pathInfo.isAsar) return readdirSync.apply(this, arguments);
const { asarPath, filePath } = pathInfo;
@@ -655,7 +657,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
throw createError(AsarError.NOT_FOUND, { asarPath, filePath });
}
if (options && (options as any).withFileTypes) {
if (options && (options as ReaddirSyncOptions).withFileTypes) {
const dirents = [];
for (const file of files) {
const childPath = path.join(filePath, file);

View File

@@ -231,12 +231,12 @@ function sortTemplate (template: (MenuItemConstructorOptions | MenuItem)[]) {
function generateGroupId (items: (MenuItemConstructorOptions | MenuItem)[], pos: number) {
if (pos > 0) {
for (let idx = pos - 1; idx >= 0; idx--) {
if (items[idx].type === 'radio') return (items[idx] as any).groupId;
if (items[idx].type === 'radio') return (items[idx] as MenuItem).groupId;
if (items[idx].type === 'separator') break;
}
} else if (pos < items.length) {
for (let idx = pos; idx <= items.length - 1; idx++) {
if (items[idx].type === 'radio') return (items[idx] as any).groupId;
if (items[idx].type === 'radio') return (items[idx] as MenuItem).groupId;
if (items[idx].type === 'separator') break;
}
}

View File

@@ -432,9 +432,7 @@ export class ClientRequest extends Writable implements Electron.ClientRequest {
if (this._response) { this._response._storeInternalData(null, null); }
});
this._urlLoader.on('error', (event, netErrorString) => {
const error = new Error(netErrorString);
if (this._response) this._response.destroy(error);
this._die(error);
this._die(new Error(netErrorString));
});
this._urlLoader.on('login', (event, authInfo, callback) => {
@@ -515,7 +513,7 @@ export class ClientRequest extends Writable implements Electron.ClientRequest {
this.destroy(err);
if (this._urlLoader) {
this._urlLoader.cancel();
if (this._response) this._response.destroy(err);
if (this._response) this._response.destroy();
}
}

View File

@@ -13,14 +13,14 @@ const extendConstructHook = (target: any, hook: Function) => {
};
const ImmutableProperty = <T extends TouchBarItem<any>>(def: (config: T extends TouchBarItem<infer C> ? C : never, setInternalProp: <K extends keyof T>(k: K, v: T[K]) => void) => any) => (target: T, propertyKey: keyof T) => {
extendConstructHook(target as any, function (this: T) {
extendConstructHook(target, function (this: T) {
(this as any)[hiddenProperties][propertyKey] = def((this as any)._config, (k, v) => {
(this as any)[hiddenProperties][k] = v;
});
});
Object.defineProperty(target, propertyKey, {
get: function () {
return (this as any)[hiddenProperties][propertyKey];
return this[hiddenProperties][propertyKey];
},
set: function () {
throw new Error(`Cannot override property ${name}`);
@@ -31,7 +31,7 @@ const ImmutableProperty = <T extends TouchBarItem<any>>(def: (config: T extends
};
const LiveProperty = <T extends TouchBarItem<any>>(def: (config: T extends TouchBarItem<infer C> ? C : never) => any, onMutate?: (self: T, newValue: any) => void) => (target: T, propertyKey: keyof T) => {
extendConstructHook(target as any, function (this: T) {
extendConstructHook(target, function (this: T) {
(this as any)[hiddenProperties][propertyKey] = def((this as any)._config);
if (onMutate) onMutate((this as any), (this as any)[hiddenProperties][propertyKey]);
});
@@ -59,7 +59,7 @@ abstract class TouchBarItem<ConfigType> extends EventEmitter {
constructor (config: ConfigType) {
super();
this._config = this._config || config || {} as any;
this._config = this._config || config || {} as ConfigType;
(this as any)[hiddenProperties] = {};
const hook = (this as any)._hook;
if (hook) hook.call(this);

View File

@@ -22,18 +22,8 @@ const getNextId = function () {
type PostData = LoadURLOptions['postData']
/* eslint-disable camelcase */
type MediaSize = {
name: string,
custom_display_name: string,
height_microns: number,
width_microns: number,
is_default?: 'true',
}
/* eslint-enable camelcase */
// Stock page sizes
const PDFPageSizes: Record<string, MediaSize> = {
const PDFPageSizes: Record<string, ElectronInternal.MediaSize> = {
A5: {
custom_display_name: 'A5',
height_microns: 210000,
@@ -90,7 +80,7 @@ const isValidCustomPageSize = (width: number, height: number) => {
const defaultPrintingSetting = {
// Customizable.
pageRange: [] as {from: number, to: number}[],
mediaSize: {} as MediaSize,
mediaSize: {} as ElectronInternal.MediaSize,
landscape: false,
headerFooterEnabled: false,
marginsType: 0,
@@ -353,7 +343,7 @@ WebContents.prototype.printToPDF = async function (options) {
}
};
WebContents.prototype.print = function (options = {}, callback) {
WebContents.prototype.print = function (options: ElectronInternal.WebContentsPrintOptions = {}, callback) {
// TODO(codebytere): deduplicate argument sanitization by moving rest of
// print param logic into new file shared between printToPDF and print
if (typeof options === 'object') {
@@ -372,14 +362,14 @@ WebContents.prototype.print = function (options = {}, callback) {
throw new Error('height and width properties must be minimum 352 microns.');
}
(options as any).mediaSize = {
options.mediaSize = {
name: 'CUSTOM',
custom_display_name: 'Custom',
height_microns: height,
width_microns: width
};
} else if (PDFPageSizes[pageSize]) {
(options as any).mediaSize = PDFPageSizes[pageSize];
options.mediaSize = PDFPageSizes[pageSize];
} else {
throw new Error(`Unsupported pageSize: ${pageSize}`);
}
@@ -428,7 +418,7 @@ WebContents.prototype.setWindowOpenHandler = function (handler: (details: Electr
this._windowOpenHandler = handler;
};
WebContents.prototype._callWindowOpenHandler = function (event: any, url: string, frameName: string, rawFeatures: string): BrowserWindowConstructorOptions | null {
WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, url: string, frameName: string, rawFeatures: string): BrowserWindowConstructorOptions | null {
if (!this._windowOpenHandler) {
return null;
}
@@ -458,21 +448,21 @@ WebContents.prototype._callWindowOpenHandler = function (event: any, url: string
}
};
const addReplyToEvent = (event: any) => {
const addReplyToEvent = (event: Electron.IpcMainEvent) => {
const { processId, frameId } = event;
event.reply = (...args: any[]) => {
event.sender.sendToFrame([processId, frameId], ...args);
event.reply = (channel: string, ...args: any[]) => {
event.sender.sendToFrame([processId, frameId], channel, ...args);
};
};
const addSenderFrameToEvent = (event: any) => {
const addSenderFrameToEvent = (event: Electron.IpcMainEvent | Electron.IpcMainInvokeEvent) => {
const { processId, frameId } = event;
Object.defineProperty(event, 'senderFrame', {
get: () => webFrameMain.fromId(processId, frameId)
});
};
const addReturnValueToEvent = (event: any) => {
const addReturnValueToEvent = (event: Electron.IpcMainEvent) => {
Object.defineProperty(event, 'returnValue', {
set: (value) => event.sendReply(value),
get: () => {}
@@ -521,7 +511,7 @@ WebContents.prototype._init = function () {
this.setMaxListeners(0);
// Dispatch IPC messages to the ipc module.
this.on('-ipc-message' as any, function (this: Electron.WebContents, event: any, internal: boolean, channel: string, args: any[]) {
this.on('-ipc-message' as any, function (this: Electron.WebContents, event: Electron.IpcMainEvent, internal: boolean, channel: string, args: any[]) {
addSenderFrameToEvent(event);
if (internal) {
ipcMainInternal.emit(channel, event, ...args);
@@ -532,7 +522,7 @@ WebContents.prototype._init = function () {
}
});
this.on('-ipc-invoke' as any, function (event: any, internal: boolean, channel: string, args: any[]) {
this.on('-ipc-invoke' as any, function (event: Electron.IpcMainInvokeEvent, internal: boolean, channel: string, args: any[]) {
addSenderFrameToEvent(event);
event._reply = (result: any) => event.sendReply({ result });
event._throw = (error: Error) => {
@@ -547,7 +537,7 @@ WebContents.prototype._init = function () {
}
});
this.on('-ipc-message-sync' as any, function (this: Electron.WebContents, event: any, internal: boolean, channel: string, args: any[]) {
this.on('-ipc-message-sync' as any, function (this: Electron.WebContents, event: Electron.IpcMainEvent, internal: boolean, channel: string, args: any[]) {
addSenderFrameToEvent(event);
addReturnValueToEvent(event);
if (internal) {
@@ -559,13 +549,13 @@ WebContents.prototype._init = function () {
}
});
this.on('-ipc-ports' as any, function (event: any, internal: boolean, channel: string, message: any, ports: any[]) {
this.on('-ipc-ports' as any, function (event: Electron.IpcMainEvent, internal: boolean, channel: string, message: any, ports: any[]) {
event.ports = ports.map(p => new MessagePortMain(p));
ipcMain.emit(channel, event, message);
});
// Handle context menu action request from pepper plugin.
this.on('pepper-context-menu' as any, function (event: any, params: {x: number, y: number, menu: Array<(MenuItemConstructorOptions) | (MenuItem)>}, callback: () => void) {
this.on('pepper-context-menu' as any, function (event: ElectronInternal.Event, params: {x: number, y: number, menu: Array<(MenuItemConstructorOptions) | (MenuItem)>}, callback: () => void) {
// Access Menu via electron.Menu to prevent circular require.
const menu = require('electron').Menu.buildFromTemplate(params.menu);
menu.popup({
@@ -596,8 +586,8 @@ WebContents.prototype._init = function () {
if (this.getType() !== 'remote') {
// Make new windows requested by links behave like "window.open".
this.on('-new-window' as any, (event: any, url: string, frameName: string, disposition: string,
rawFeatures: string, referrer: any, postData: PostData) => {
this.on('-new-window' as any, (event: ElectronInternal.Event, url: string, frameName: string, disposition: string,
rawFeatures: string, referrer: Electron.Referrer, postData: PostData) => {
openGuestWindow({
event,
embedder: event.sender,
@@ -614,7 +604,7 @@ WebContents.prototype._init = function () {
});
let windowOpenOverriddenOptions: BrowserWindowConstructorOptions | null = null;
this.on('-will-add-new-contents' as any, (event: any, url: string, frameName: string, rawFeatures: string) => {
this.on('-will-add-new-contents' as any, (event: ElectronInternal.Event, url: string, frameName: string, rawFeatures: string) => {
windowOpenOverriddenOptions = this._callWindowOpenHandler(event, url, frameName, rawFeatures);
if (!event.defaultPrevented) {
const secureOverrideWebPreferences = windowOpenOverriddenOptions ? {
@@ -632,7 +622,7 @@ WebContents.prototype._init = function () {
// Create a new browser window for the native implementation of
// "window.open", used in sandbox and nativeWindowOpen mode.
this.on('-add-new-contents' as any, (event: any, webContents: Electron.WebContents, disposition: string,
this.on('-add-new-contents' as any, (event: ElectronInternal.Event, webContents: Electron.WebContents, disposition: string,
_userGesture: boolean, _left: number, _top: number, _width: number, _height: number, url: string, frameName: string,
referrer: Electron.Referrer, rawFeatures: string, postData: PostData) => {
const overriddenOptions = windowOpenOverriddenOptions || undefined;

View File

@@ -197,7 +197,7 @@ const attachGuest = function (event: Electron.IpcMainInvokeEvent,
// Inherit certain option values from embedder
const lastWebPreferences = embedder.getLastWebPreferences();
for (const [name, value] of inheritedWebPreferences) {
if ((lastWebPreferences as any)[name] === value) {
if (lastWebPreferences[name as keyof Electron.WebPreferences] === value) {
(webPreferences as any)[name] = value;
}
}

View File

@@ -47,6 +47,7 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition
embedder,
features,
frameName,
isNativeWindowOpen,
overrideOptions: overrideBrowserWindowOptions
});
@@ -84,7 +85,7 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition
httpReferrer: referrer,
...(postData && {
postData,
extraHeaders: formatPostDataHeaders(postData)
extraHeaders: formatPostDataHeaders(postData as Electron.UploadRawData[])
})
});
}
@@ -133,7 +134,7 @@ const handleWindowLifecycleEvents = function ({ embedder, guest, frameName }: {
* `did-create-window` in 11.0.0. Will be removed in 12.0.0.
*/
function emitDeprecatedNewWindowEvent ({ event, embedder, guest, windowOpenArgs, browserWindowOptions, additionalFeatures, disposition, referrer, postData }: {
event: { sender: WebContents, defaultPrevented: boolean },
event: { sender: WebContents, defaultPrevented: boolean, newGuest?: BrowserWindow },
embedder: WebContents,
guest?: WebContents,
windowOpenArgs: WindowOpenArgs,
@@ -144,10 +145,10 @@ function emitDeprecatedNewWindowEvent ({ event, embedder, guest, windowOpenArgs,
postData?: PostData,
}): boolean {
const { url, frameName } = windowOpenArgs;
const isWebViewWithPopupsDisabled = embedder.getType() === 'webview' && (embedder as any).getLastWebPreferences().disablePopups;
const isWebViewWithPopupsDisabled = embedder.getType() === 'webview' && embedder.getLastWebPreferences().disablePopups;
const postBody = postData ? {
data: postData,
headers: formatPostDataHeaders(postData)
headers: formatPostDataHeaders(postData as Electron.UploadRawData[])
} : null;
embedder.emit(
@@ -165,14 +166,14 @@ function emitDeprecatedNewWindowEvent ({ event, embedder, guest, windowOpenArgs,
postBody
);
const { newGuest } = event as any;
const { newGuest } = event;
if (isWebViewWithPopupsDisabled) return true;
if (event.defaultPrevented) {
if (newGuest) {
if (guest === newGuest.webContents) {
// The webContents is not changed, so set defaultPrevented to false to
// stop the callers of this event from destroying the webContents.
(event as any).defaultPrevented = false;
event.defaultPrevented = false;
}
handleWindowLifecycleEvents({
@@ -199,10 +200,11 @@ const securityWebPreferences: { [key: string]: boolean } = {
enableWebSQL: false
};
function makeBrowserWindowOptions ({ embedder, features, frameName, overrideOptions, useDeprecatedBehaviorForBareValues = true, useDeprecatedBehaviorForOptionInheritance = true }: {
function makeBrowserWindowOptions ({ embedder, features, frameName, isNativeWindowOpen, overrideOptions, useDeprecatedBehaviorForBareValues = true, useDeprecatedBehaviorForOptionInheritance = true }: {
embedder: WebContents,
features: string,
frameName: string,
isNativeWindowOpen: boolean,
overrideOptions?: BrowserWindowConstructorOptions,
useDeprecatedBehaviorForBareValues?: boolean
useDeprecatedBehaviorForOptionInheritance?: boolean
@@ -216,13 +218,13 @@ function makeBrowserWindowOptions ({ embedder, features, frameName, overrideOpti
options: {
...(useDeprecatedBehaviorForOptionInheritance && deprecatedInheritedOptions),
show: true,
title: frameName,
width: 800,
height: 600,
...(!isNativeWindowOpen && { title: frameName }),
...parsedOptions,
...overrideOptions,
webPreferences: makeWebPreferences({ embedder, insecureParsedWebPreferences: parsedWebPreferences, secureOverrideWebPreferences: overrideOptions && overrideOptions.webPreferences, useDeprecatedBehaviorForOptionInheritance: true })
}
} as Electron.BrowserViewConstructorOptions
};
}
@@ -237,13 +239,13 @@ export function makeWebPreferences ({ embedder, secureOverrideWebPreferences = {
useDeprecatedBehaviorForOptionInheritance?: boolean
}) {
const deprecatedInheritedOptions = getDeprecatedInheritedOptions(embedder);
const parentWebPreferences = (embedder as any).getLastWebPreferences();
const securityWebPreferencesFromParent = Object.keys(securityWebPreferences).reduce((map, key) => {
if (securityWebPreferences[key] === parentWebPreferences[key]) {
map[key] = parentWebPreferences[key];
const parentWebPreferences = embedder.getLastWebPreferences();
const securityWebPreferencesFromParent = (Object.keys(securityWebPreferences).reduce((map, key) => {
if (securityWebPreferences[key] === parentWebPreferences[key as keyof Electron.WebPreferences]) {
(map as any)[key] = parentWebPreferences[key as keyof Electron.WebPreferences];
}
return map;
}, {} as any);
}, {} as Electron.WebPreferences));
const openerId = parentWebPreferences.nativeWindowOpen ? null : embedder.id;
return {
@@ -268,18 +270,18 @@ export function makeWebPreferences ({ embedder, secureOverrideWebPreferences = {
* only critical security preferences will be inherited by default.
*/
function getDeprecatedInheritedOptions (embedder: WebContents) {
if (!(embedder as any).browserWindowOptions) {
if (!embedder.browserWindowOptions) {
// If it's a webview, return just the webPreferences.
return {
webPreferences: (embedder as any).getLastWebPreferences()
webPreferences: embedder.getLastWebPreferences()
};
}
const { type, show, ...inheritableOptions } = (embedder as any).browserWindowOptions;
const { type, show, ...inheritableOptions } = embedder.browserWindowOptions;
return inheritableOptions;
}
function formatPostDataHeaders (postData: any) {
function formatPostDataHeaders (postData: Electron.UploadRawData[]) {
if (!postData) return;
let extraHeaders = 'content-type: application/x-www-form-urlencoded';

View File

@@ -28,7 +28,7 @@ const getGuestWindow = function (guestContents: WebContents) {
};
const isChildWindow = function (sender: WebContents, target: WebContents) {
return (target as any).getLastWebPreferences().openerId === sender.id;
return target.getLastWebPreferences().openerId === sender.id;
};
const isRelatedWindow = function (sender: WebContents, target: WebContents) {
@@ -43,7 +43,7 @@ const isScriptableWindow = function (sender: WebContents, target: WebContents) {
};
const isNodeIntegrationEnabled = function (sender: WebContents) {
return (sender as any).getLastWebPreferences().nodeIntegration === true;
return sender.getLastWebPreferences().nodeIntegration === true;
};
// Checks whether |sender| can access the |target|:
@@ -65,15 +65,15 @@ ipcMainInternal.on(
features: string
) => {
// This should only be allowed for senders that have nativeWindowOpen: false
const lastWebPreferences = (event.sender as any).getLastWebPreferences();
const lastWebPreferences = event.sender.getLastWebPreferences();
if (lastWebPreferences.nativeWindowOpen || lastWebPreferences.sandbox) {
(event as any).returnValue = null;
event.returnValue = null;
throw new Error(
'GUEST_WINDOW_MANAGER_WINDOW_OPEN denied: expected native window.open'
);
}
const browserWindowOptions = (event.sender as any)._callWindowOpenHandler(event, url, frameName, features);
const browserWindowOptions = event.sender._callWindowOpenHandler(event, url, frameName, features);
if (event.defaultPrevented) {
return;
}
@@ -82,7 +82,7 @@ ipcMainInternal.on(
embedder: event.sender,
referrer: { url: '', policy: 'default' },
disposition: 'new-window',
overrideBrowserWindowOptions: browserWindowOptions,
overrideBrowserWindowOptions: browserWindowOptions!,
windowOpenArgs: {
url: url || 'about:blank',
frameName: frameName || '',
@@ -90,7 +90,7 @@ ipcMainInternal.on(
}
});
(event as any).returnValue = guest ? guest.webContents.id : null;
event.returnValue = guest ? guest.webContents.id : null;
}
);

View File

@@ -206,7 +206,7 @@ const removeRemoteListenersAndLogWarning = (sender: any, callIntoRenderer: (...a
if (remoteEvents.length > 0) {
message += `\nRemote event names: ${remoteEvents.join(', ')}`;
remoteEvents.forEach((eventName) => {
sender.removeListener(eventName as any, callIntoRenderer);
sender.removeListener(eventName, callIntoRenderer);
});
}
}
@@ -365,7 +365,7 @@ handleRemoteCommand(IPC_MESSAGES.BROWSER_REQUIRE, function (event, contextId, mo
if (customEvent.defaultPrevented) {
throw new Error(`Blocked remote.require('${moduleName}')`);
} else {
customEvent.returnValue = (process as any).mainModule.require(moduleName);
customEvent.returnValue = process.mainModule.require(moduleName);
}
}

View File

@@ -12,7 +12,7 @@ const contextBridge: Electron.ContextBridge = {
checkContextIsolationEnabled();
return binding.exposeAPIInMainWorld(key, api);
}
} as any;
};
export default contextBridge;

View File

@@ -144,7 +144,7 @@ if (nodeIntegration) {
// We do not want to add `uncaughtException` to our definitions
// because we don't want anyone else (anywhere) to throw that kind
// of error.
global.process.emit('uncaughtException' as any, error as any);
global.process.emit('uncaughtException', error as any);
return true;
} else {
return false;

View File

@@ -79,7 +79,7 @@ const isLocalhost = function () {
*/
const isUnsafeEvalEnabled: () => Promise<boolean> = function () {
// Call _executeJavaScript to bypass the world-safe deprecation warning
return (webFrame as any)._executeJavaScript(`(${(() => {
return webFrame._executeJavaScript(`(${(() => {
try {
eval(window.trustedTypes.emptyScript); // eslint-disable-line no-eval
} catch {

View File

@@ -60,7 +60,7 @@ export class WebViewAttribute implements MutationHandler {
}
// Called when the attribute's value changes.
public handleMutation: MutationHandler['handleMutation'] = () => undefined as any
public handleMutation: MutationHandler['handleMutation'] = () => undefined
}
// An attribute that is treated as a Boolean.

View File

@@ -94,7 +94,7 @@ const registerWebViewElement = (v8Util: NodeJS.V8UtilBinding, webViewImpl: typeo
// The customElements.define has to be called in a special scope.
webViewImpl.webFrame.allowGuestViewElementDefinition(window, () => {
window.customElements.define('webview', WebViewElement);
(window as any).WebView = WebViewElement;
window.WebView = WebViewElement;
// Delete the callbacks so developers cannot call them and produce unexpected
// behavior.

View File

@@ -1,6 +1,6 @@
{
"name": "electron",
"version": "13.0.0-nightly.20210128",
"version": "13.0.0-nightly.20210201",
"repository": "https://github.com/electron/electron",
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": {

View File

@@ -280,8 +280,8 @@ class NativeWindow : public base::SupportsUserData,
void NotifyWindowRotateGesture(float rotation);
void NotifyWindowSheetBegin();
void NotifyWindowSheetEnd();
void NotifyWindowEnterFullScreen();
void NotifyWindowLeaveFullScreen();
virtual void NotifyWindowEnterFullScreen();
virtual void NotifyWindowLeaveFullScreen();
void NotifyWindowEnterHtmlFullScreen();
void NotifyWindowLeaveHtmlFullScreen();
void NotifyWindowAlwaysOnTopChanged();

View File

@@ -21,7 +21,7 @@
@class ElectronNSWindowDelegate;
@class ElectronPreviewItem;
@class ElectronTouchBar;
@class CustomWindowButtonView;
@class WindowButtonsView;
namespace electron {
@@ -139,6 +139,11 @@ class NativeWindowMac : public NativeWindow, public ui::NativeThemeObserver {
void CloseFilePreview() override;
gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& bounds) const override;
gfx::Rect WindowBoundsToContentBounds(const gfx::Rect& bounds) const override;
void NotifyWindowEnterFullScreen() override;
void NotifyWindowLeaveFullScreen() override;
void NotifyWindowWillEnterFullScreen();
void NotifyWindowWillLeaveFullScreen();
// 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
@@ -153,8 +158,6 @@ class NativeWindowMac : public NativeWindow, public ui::NativeThemeObserver {
void SetCollectionBehavior(bool on, NSUInteger flag);
void SetWindowLevel(int level);
void SetExitingFullScreen(bool flag);
enum class VisualEffectState {
kFollowWindow,
kActive,
@@ -172,7 +175,6 @@ class NativeWindowMac : public NativeWindow, public ui::NativeThemeObserver {
ElectronPreviewItem* preview_item() const { return preview_item_.get(); }
ElectronTouchBar* touch_bar() const { return touch_bar_.get(); }
bool zoom_to_page_width() const { return zoom_to_page_width_; }
bool fullscreen_window_title() const { return fullscreen_window_title_; }
bool always_simple_fullscreen() const { return always_simple_fullscreen_; }
bool exiting_fullscreen() const { return exiting_fullscreen_; }
@@ -186,9 +188,10 @@ class NativeWindowMac : public NativeWindow, public ui::NativeThemeObserver {
private:
// Add custom layers to the content view.
void AddContentViewLayers(bool minimizable, bool closable);
void AddContentViewLayers();
void InternalSetWindowButtonVisibility(bool visible);
void InternalSetStandardButtonsVisibility(bool visible);
void InternalSetParentWindow(NativeWindow* parent, bool attach);
void SetForwardMouseMessages(bool forward);
@@ -197,7 +200,7 @@ class NativeWindowMac : public NativeWindow, public ui::NativeThemeObserver {
base::scoped_nsobject<ElectronNSWindowDelegate> window_delegate_;
base::scoped_nsobject<ElectronPreviewItem> preview_item_;
base::scoped_nsobject<ElectronTouchBar> touch_bar_;
base::scoped_nsobject<CustomWindowButtonView> buttons_view_;
base::scoped_nsobject<WindowButtonsView> buttons_view_;
// Event monitor for scroll wheel event.
id wheel_event_monitor_;
@@ -213,7 +216,6 @@ class NativeWindowMac : public NativeWindow, public ui::NativeThemeObserver {
bool is_kiosk_ = false;
bool was_fullscreen_ = false;
bool zoom_to_page_width_ = false;
bool fullscreen_window_title_ = false;
bool resizable_ = true;
bool exiting_fullscreen_ = false;
base::Optional<gfx::Point> traffic_light_position_;

View File

@@ -29,6 +29,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/inspectable_web_contents.h"
#include "shell/browser/ui/inspectable_web_contents_view.h"
#include "shell/browser/window_list.h"
@@ -119,106 +120,6 @@
@end
// Custom Quit, Minimize and Full Screen button container for frameless
// windows.
@interface CustomWindowButtonView : NSView {
@private
BOOL mouse_inside_;
gfx::Point margin_;
}
- (id)initWithMargin:(const base::Optional<gfx::Point>&)margin;
- (void)setMargin:(const base::Optional<gfx::Point>&)margin;
@end
@implementation CustomWindowButtonView
- (id)initWithMargin:(const base::Optional<gfx::Point>&)margin {
self = [super initWithFrame:NSZeroRect];
[self setMargin:margin];
NSButton* close_button =
[NSWindow standardWindowButton:NSWindowCloseButton
forStyleMask:NSWindowStyleMaskTitled];
[close_button setTag:1];
NSButton* miniaturize_button =
[NSWindow standardWindowButton:NSWindowMiniaturizeButton
forStyleMask:NSWindowStyleMaskTitled];
[miniaturize_button setTag:2];
CGFloat x = 0;
const CGFloat space_between = 20;
[close_button setFrameOrigin:NSMakePoint(x, 0)];
x += space_between;
[self addSubview:close_button];
[miniaturize_button setFrameOrigin:NSMakePoint(x, 0)];
x += space_between;
[self addSubview:miniaturize_button];
const auto last_button_frame = miniaturize_button.frame;
[self setFrameSize:NSMakeSize(last_button_frame.origin.x +
last_button_frame.size.width,
last_button_frame.size.height)];
mouse_inside_ = NO;
[self setNeedsDisplayForButtons];
return self;
}
- (void)setMargin:(const base::Optional<gfx::Point>&)margin {
margin_ = margin.value_or(gfx::Point(7, 3));
}
- (void)viewDidMoveToWindow {
if (!self.window) {
return;
}
// Stay in upper left corner.
[self setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin];
[self setFrameOrigin:NSMakePoint(margin_.x(), self.window.frame.size.height -
self.frame.size.height -
margin_.y())];
}
- (BOOL)_mouseInGroup:(NSButton*)button {
return mouse_inside_;
}
- (void)updateTrackingAreas {
auto tracking_area = [[[NSTrackingArea alloc]
initWithRect:NSZeroRect
options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways |
NSTrackingInVisibleRect
owner:self
userInfo:nil] autorelease];
[self addTrackingArea:tracking_area];
}
- (void)mouseEntered:(NSEvent*)event {
[super mouseEntered:event];
mouse_inside_ = YES;
[self setNeedsDisplayForButtons];
}
- (void)mouseExited:(NSEvent*)event {
[super mouseExited:event];
mouse_inside_ = NO;
[self setNeedsDisplayForButtons];
}
- (void)setNeedsDisplayForButtons {
for (NSView* subview in self.subviews) {
[subview setHidden:!mouse_inside_];
[subview setNeedsDisplay:YES];
}
}
@end
@interface ElectronProgressBar : NSProgressIndicator
@end
@@ -370,11 +271,17 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
options.Get(options::kResizable, &resizable_);
options.Get(options::kTitleBarStyle, &title_bar_style_);
options.Get(options::kZoomToPageWidth, &zoom_to_page_width_);
options.Get(options::kFullscreenWindowTitle, &fullscreen_window_title_);
options.Get(options::kSimpleFullScreen, &always_simple_fullscreen_);
options.GetOptional(options::kTrafficLightPosition, &traffic_light_position_);
options.Get(options::kVisualEffectState, &visual_effect_state_);
if (options.Has(options::kFullscreenWindowTitle)) {
EmitWarning(node::Environment::GetCurrent(v8::Isolate::GetCurrent()),
"\"fullscreenWindowTitle\" option has been deprecated and is "
"no-op now.",
"electron");
}
bool minimizable = true;
options.Get(options::kMinimizable, &minimizable);
@@ -457,6 +364,8 @@ 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);
}
// Create a tab only if tabbing identifier is specified and window has
@@ -471,14 +380,6 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
}
}
// Hide the title bar.
if (title_bar_style_ == TitleBarStyle::kHiddenInset) {
base::scoped_nsobject<NSToolbar> toolbar(
[[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]);
[toolbar setShowsBaselineSeparator:NO];
[window_ setToolbar:toolbar];
}
// Resize to content bounds.
bool use_content_size = false;
options.Get(options::kUseContentSize, &use_content_size);
@@ -527,7 +428,7 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
// Default content view.
SetContentView(new views::View());
AddContentViewLayers(minimizable, closable);
AddContentViewLayers();
original_frame_ = [window_ frame];
original_level_ = [window_ level];
@@ -830,6 +731,8 @@ bool NativeWindowMac::IsMovable() {
void NativeWindowMac::SetMinimizable(bool minimizable) {
SetStyleMask(minimizable, NSMiniaturizableWindowMask);
if (buttons_view_)
[[buttons_view_ viewWithTag:1] setEnabled:minimizable];
}
bool NativeWindowMac::IsMinimizable() {
@@ -851,6 +754,8 @@ 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() {
@@ -860,6 +765,8 @@ bool NativeWindowMac::IsFullScreenable() {
void NativeWindowMac::SetClosable(bool closable) {
SetStyleMask(closable, NSWindowStyleMaskClosable);
if (buttons_view_)
[[buttons_view_ viewWithTag:0] setEnabled:closable];
}
bool NativeWindowMac::IsClosable() {
@@ -940,9 +847,6 @@ void NativeWindowMac::Invalidate() {
void NativeWindowMac::SetTitle(const std::string& title) {
[window_ setTitle:base::SysUTF8ToNSString(title)];
if (title_bar_style_ == TitleBarStyle::kHidden) {
RedrawTrafficLights();
}
}
std::string NativeWindowMac::GetTitle() {
@@ -1004,14 +908,7 @@ void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) {
window.level = NSPopUpMenuWindowLevel;
}
if (!fullscreen_window_title()) {
// Hide the titlebar
SetStyleMask(false, NSWindowStyleMaskTitled);
// Resize the window to accommodate the _entire_ screen size
fullscreenFrame.size.height -=
[[[NSApplication sharedApplication] mainMenu] menuBarHeight];
} else if (!window_button_visibility_.has_value()) {
if (!window_button_visibility_.has_value()) {
// Lets keep previous behaviour - hide window controls in titled
// fullscreen mode when not specified otherwise.
InternalSetWindowButtonVisibility(false);
@@ -1027,11 +924,6 @@ void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) {
} else if (!simple_fullscreen && is_simple_fullscreen_) {
is_simple_fullscreen_ = false;
if (!fullscreen_window_title()) {
// Restore the titlebar
SetStyleMask(true, NSWindowStyleMaskTitled);
}
// Restore default window controls visibility state.
if (!window_button_visibility_.has_value()) {
bool visibility;
@@ -1450,9 +1342,7 @@ bool NativeWindowMac::GetWindowButtonVisibility() const {
void NativeWindowMac::SetTrafficLightPosition(
base::Optional<gfx::Point> position) {
traffic_light_position_ = std::move(position);
if (title_bar_style_ == TitleBarStyle::kHidden) {
RedrawTrafficLights();
} else if (title_bar_style_ == TitleBarStyle::kCustomButtonsOnHover) {
if (buttons_view_) {
[buttons_view_ setMargin:position];
[buttons_view_ viewDidMoveToWindow];
}
@@ -1463,64 +1353,8 @@ base::Optional<gfx::Point> NativeWindowMac::GetTrafficLightPosition() const {
}
void NativeWindowMac::RedrawTrafficLights() {
// Ensure maximizable options retain pre-existing state.
SetMaximizable(maximizable_);
// Changing system titlebar is only allowed for "hidden" titleBarStyle.
if (!traffic_light_position_ || title_bar_style_ != TitleBarStyle::kHidden)
return;
if (IsFullscreen())
return;
NSWindow* window = window_;
NSButton* close = [window standardWindowButton:NSWindowCloseButton];
NSButton* miniaturize =
[window standardWindowButton:NSWindowMiniaturizeButton];
NSButton* zoom = [window standardWindowButton:NSWindowZoomButton];
// Safety check just in case apple changes the view structure in a macOS
// update
DCHECK(close.superview);
DCHECK(close.superview.superview);
if (!close.superview || !close.superview.superview)
return;
NSView* titleBarContainerView = close.superview.superview;
// Hide the container when exiting fullscreen, otherwise traffic light buttons
// jump
if (exiting_fullscreen_) {
[titleBarContainerView setHidden:YES];
return;
}
[titleBarContainerView setHidden:NO];
CGFloat buttonHeight = [close frame].size.height;
CGFloat titleBarFrameHeight = buttonHeight + traffic_light_position_->y();
CGRect titleBarRect = titleBarContainerView.frame;
CGFloat titleBarWidth = NSWidth(titleBarRect);
titleBarRect.size.height = titleBarFrameHeight;
titleBarRect.origin.y = window.frame.size.height - titleBarFrameHeight;
[titleBarContainerView setFrame:titleBarRect];
BOOL isRTL = [titleBarContainerView userInterfaceLayoutDirection] ==
NSUserInterfaceLayoutDirectionRightToLeft;
NSArray* windowButtons = @[ close, miniaturize, zoom ];
const CGFloat space_between =
[miniaturize frame].origin.x - [close frame].origin.x;
for (NSUInteger i = 0; i < windowButtons.count; i++) {
NSView* view = [windowButtons objectAtIndex:i];
CGRect rect = [view frame];
if (isRTL) {
CGFloat buttonWidth = NSWidth(rect);
// origin is always top-left, even in RTL
rect.origin.x = titleBarWidth - traffic_light_position_->x() +
(i * space_between) - buttonWidth;
} else {
rect.origin.x = traffic_light_position_->x() + (i * space_between);
}
rect.origin.y = (titleBarFrameHeight - rect.size.height) / 2;
[view setFrameOrigin:rect.origin];
}
if (buttons_view_)
[buttons_view_ setNeedsDisplayForButtons];
}
void NativeWindowMac::SetTouchBar(
@@ -1642,6 +1476,41 @@ gfx::Rect NativeWindowMac::WindowBoundsToContentBounds(
}
}
void NativeWindowMac::NotifyWindowEnterFullScreen() {
NativeWindow::NotifyWindowEnterFullScreen();
// Restore the window title under fullscreen mode.
if (buttons_view_)
[window_ setTitleVisibility:NSWindowTitleVisible];
RedrawTrafficLights();
}
void NativeWindowMac::NotifyWindowLeaveFullScreen() {
NativeWindow::NotifyWindowLeaveFullScreen();
exiting_fullscreen_ = false;
// Add back buttonsView after leaving fullscreen mode.
if (buttons_view_) {
InternalSetStandardButtonsVisibility(false);
[[window_ contentView] addSubview:buttons_view_];
}
}
void NativeWindowMac::NotifyWindowWillEnterFullScreen() {
// Remove the buttonsView otherwise window buttons won't show under
// fullscreen mode.
if (buttons_view_) {
[buttons_view_ removeFromSuperview];
InternalSetStandardButtonsVisibility(true);
}
}
void NativeWindowMac::NotifyWindowWillLeaveFullScreen() {
// Hide window title after leaving fullscreen.
if (buttons_view_)
[window_ setTitleVisibility:NSWindowTitleHidden];
exiting_fullscreen_ = true;
RedrawTrafficLights();
}
void NativeWindowMac::Cleanup() {
DCHECK(!IsClosed());
ui::NativeTheme::GetInstanceForNativeUi()->RemoveObserver(this);
@@ -1663,7 +1532,7 @@ void NativeWindowMac::OverrideNSWindowContentView() {
[container_view_
setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[window_ setContentView:container_view_];
AddContentViewLayers(IsMinimizable(), IsClosable());
AddContentViewLayers();
}
void NativeWindowMac::SetStyleMask(bool on, NSUInteger flag) {
@@ -1692,10 +1561,6 @@ void NativeWindowMac::SetCollectionBehavior(bool on, NSUInteger flag) {
SetMaximizable(was_maximizable);
}
void NativeWindowMac::SetExitingFullScreen(bool flag) {
exiting_fullscreen_ = flag;
}
bool NativeWindowMac::CanResize() const {
return resizable_;
}
@@ -1710,7 +1575,7 @@ void NativeWindowMac::OnNativeThemeUpdated(ui::NativeTheme* observed_theme) {
base::BindOnce(&NativeWindow::RedrawTrafficLights, GetWeakPtr()));
}
void NativeWindowMac::AddContentViewLayers(bool minimizable, bool closable) {
void NativeWindowMac::AddContentViewLayers() {
// Make sure the bottom corner is rounded for non-modal windows:
// http://crbug.com/396264.
if (!is_modal()) {
@@ -1742,46 +1607,39 @@ void NativeWindowMac::AddContentViewLayers(bool minimizable, bool closable) {
[[window_ contentView] viewDidMoveToWindow];
}
// The fullscreen button should always be hidden for frameless window.
[[window_ standardWindowButton:NSWindowFullScreenButton] setHidden:YES];
// 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:gfx::Point(12, 11)];
// Create a custom window buttons view for kCustomButtonsOnHover.
if (title_bar_style_ == TitleBarStyle::kCustomButtonsOnHover) {
buttons_view_.reset([[CustomWindowButtonView alloc]
initWithMargin:traffic_light_position_]);
if (!minimizable)
[[buttons_view_ viewWithTag:2] removeFromSuperview];
if (!closable)
[[buttons_view_ viewWithTag:1] removeFromSuperview];
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_];
}
// Hide the window buttons except for kHidden and kHiddenInset.
if (title_bar_style_ == TitleBarStyle::kNormal ||
title_bar_style_ == TitleBarStyle::kCustomButtonsOnHover) {
[[window_ standardWindowButton:NSWindowZoomButton] setHidden:YES];
[[window_ standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
[[window_ standardWindowButton:NSWindowCloseButton] setHidden:YES];
// Some third-party macOS utilities check the zoom button's enabled state
// to determine whether to show custom UI on hover, so we disable it here
// to prevent them from doing so in a frameless app window.
SetMaximizable(false);
}
}
}
void NativeWindowMac::InternalSetWindowButtonVisibility(bool visible) {
if (buttons_view_) {
if (buttons_view_)
[buttons_view_ setHidden:!visible];
} else {
[[window_ standardWindowButton:NSWindowCloseButton] setHidden:!visible];
[[window_ standardWindowButton:NSWindowMiniaturizeButton]
setHidden:!visible];
[[window_ standardWindowButton:NSWindowZoomButton] 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];
}
void NativeWindowMac::InternalSetParentWindow(NativeWindow* parent,

View File

@@ -50,8 +50,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 13,0,0,20210128
PRODUCTVERSION 13,0,0,20210128
FILEVERSION 13,0,0,20210201
PRODUCTVERSION 13,0,0,20210201
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L

View File

@@ -91,14 +91,17 @@ using TitleBarStyle = electron::NativeWindowMac::TitleBarStyle;
- (void)windowDidBecomeMain:(NSNotification*)notification {
shell_->NotifyWindowFocus();
shell_->RedrawTrafficLights();
}
- (void)windowDidResignMain:(NSNotification*)notification {
shell_->NotifyWindowBlur();
shell_->RedrawTrafficLights();
}
- (void)windowDidBecomeKey:(NSNotification*)notification {
shell_->NotifyWindowIsKeyChanged(true);
shell_->RedrawTrafficLights();
}
- (void)windowDidResignKey:(NSNotification*)notification {
@@ -110,6 +113,7 @@ using TitleBarStyle = electron::NativeWindowMac::TitleBarStyle;
return;
shell_->NotifyWindowIsKeyChanged(false);
shell_->RedrawTrafficLights();
}
- (NSSize)windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize {
@@ -151,9 +155,6 @@ using TitleBarStyle = electron::NativeWindowMac::TitleBarStyle;
- (void)windowDidResize:(NSNotification*)notification {
[super windowDidResize:notification];
shell_->NotifyWindowResize();
if (shell_->title_bar_style() == TitleBarStyle::kHidden) {
shell_->RedrawTrafficLights();
}
}
- (void)windowWillMove:(NSNotification*)notification {
@@ -212,75 +213,23 @@ using TitleBarStyle = electron::NativeWindowMac::TitleBarStyle;
}
- (void)windowWillEnterFullScreen:(NSNotification*)notification {
// Setting resizable to true before entering fullscreen
shell_->NotifyWindowWillEnterFullScreen();
// Setting resizable to true before entering fullscreen.
is_resizable_ = shell_->IsResizable();
shell_->SetResizable(true);
// Hide the native toolbar before entering fullscreen, so there is no visual
// artifacts.
if (shell_->title_bar_style() == TitleBarStyle::kHiddenInset) {
NSWindow* window = shell_->GetNativeWindow().GetNativeNSWindow();
[window setToolbar:nil];
}
}
- (void)windowDidEnterFullScreen:(NSNotification*)notification {
shell_->NotifyWindowEnterFullScreen();
// For frameless window we don't show set title for normal mode since the
// titlebar is expected to be empty, but after entering fullscreen mode we
// have to set one, because title bar is visible here.
NSWindow* window = shell_->GetNativeWindow().GetNativeNSWindow();
if ((shell_->transparent() || !shell_->has_frame()) &&
// FIXME(zcbenz): Showing titlebar for hiddenInset window is weird under
// fullscreen mode.
// Show title if fullscreen_window_title flag is set
(shell_->title_bar_style() != TitleBarStyle::kHiddenInset ||
shell_->fullscreen_window_title())) {
[window setTitleVisibility:NSWindowTitleVisible];
}
// Restore the native toolbar immediately after entering fullscreen, if we
// do this before leaving fullscreen, traffic light buttons will be jumping.
if (shell_->title_bar_style() == TitleBarStyle::kHiddenInset) {
base::scoped_nsobject<NSToolbar> toolbar(
[[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]);
[toolbar setShowsBaselineSeparator:NO];
[window setToolbar:toolbar];
// Set window style to hide the toolbar, otherwise the toolbar will show
// in fullscreen mode.
[window setTitlebarAppearsTransparent:NO];
shell_->SetStyleMask(true, NSWindowStyleMaskFullSizeContentView);
}
}
- (void)windowWillExitFullScreen:(NSNotification*)notification {
// Restore the titlebar visibility.
NSWindow* window = shell_->GetNativeWindow().GetNativeNSWindow();
if ((shell_->transparent() || !shell_->has_frame()) &&
(shell_->title_bar_style() != TitleBarStyle::kHiddenInset ||
shell_->fullscreen_window_title())) {
[window setTitleVisibility:NSWindowTitleHidden];
}
// Turn off the style for toolbar.
if (shell_->title_bar_style() == TitleBarStyle::kHiddenInset) {
shell_->SetStyleMask(false, NSWindowStyleMaskFullSizeContentView);
[window setTitlebarAppearsTransparent:YES];
}
shell_->SetExitingFullScreen(true);
if (shell_->title_bar_style() == TitleBarStyle::kHidden) {
shell_->RedrawTrafficLights();
}
shell_->NotifyWindowWillLeaveFullScreen();
}
- (void)windowDidExitFullScreen:(NSNotification*)notification {
shell_->SetResizable(is_resizable_);
shell_->NotifyWindowLeaveFullScreen();
shell_->SetExitingFullScreen(false);
if (shell_->title_bar_style() == TitleBarStyle::kHidden) {
shell_->RedrawTrafficLights();
}
}
- (void)windowWillClose:(NSNotification*)notification {

View File

@@ -0,0 +1,31 @@
// 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 "base/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_;
}
- (id)initWithMargin:(const base::Optional<gfx::Point>&)margin;
- (void)setMargin:(const base::Optional<gfx::Point>&)margin;
- (void)setShowOnHover:(BOOL)yes;
- (void)setNeedsDisplayForButtons;
@end
#endif // SHELL_BROWSER_UI_COCOA_WINDOW_BUTTONS_VIEW_H_

View File

@@ -0,0 +1,119 @@
// 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/i18n/rtl.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "ui/gfx/mac/coordinate_conversion.h"
namespace {
const CGFloat kButtonPadding = 20.;
const NSWindowButton kButtonTypes[] = {
NSWindowCloseButton,
NSWindowMiniaturizeButton,
NSWindowZoomButton,
};
} // namespace
@implementation WindowButtonsView
- (id)initWithMargin:(const base::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 base::Optional<gfx::Point>&)margin {
margin_ = margin.value_or(gfx::Point(7, 3));
}
- (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];
}
@end

View File

@@ -167,7 +167,7 @@ bool MenuBar::AcceleratorPressed(const ui::Accelerator& accelerator) {
if (keycode == accelerator.key_code()) {
auto event = accelerator.ToKeyEvent();
ButtonPressed(button, event);
ButtonPressed(button->tag(), event);
return true;
}
}
@@ -254,7 +254,7 @@ const char* MenuBar::GetClassName() const {
return kViewClassName;
}
void MenuBar::ButtonPressed(views::Button* source, const ui::Event& event) {
void MenuBar::ButtonPressed(int id, const ui::Event& event) {
// Hide the accelerator when a submenu is activated.
SetAcceleratorVisibility(false);
@@ -264,13 +264,22 @@ void MenuBar::ButtonPressed(views::Button* source, const ui::Event& event) {
if (!window_->HasFocus())
window_->RequestFocus();
int id = source->tag();
ElectronMenuModel::ItemType type = menu_model_->GetTypeAt(id);
if (type != ElectronMenuModel::TYPE_SUBMENU) {
menu_model_->ActivatedAt(id, 0);
return;
}
SubmenuButton* source = nullptr;
for (auto* child : children()) {
auto* button = static_cast<SubmenuButton*>(child);
if (button->tag() == id) {
source = button;
break;
}
}
DCHECK(source);
// Deleted in MenuDelegate::OnMenuClosed
auto* menu_delegate = new MenuDelegate(this);
menu_delegate->RunMenu(
@@ -304,12 +313,10 @@ void MenuBar::OnThemeChanged() {
void MenuBar::RebuildChildren() {
RemoveAllChildViews(true);
for (int i = 0, n = GetItemCount(); i < n; ++i) {
auto* button =
new SubmenuButton(menu_model_->GetLabelAt(i), background_color_);
auto* button = new SubmenuButton(
base::BindRepeating(&MenuBar::ButtonPressed, base::Unretained(this), i),
menu_model_->GetLabelAt(i), background_color_);
button->set_tag(i);
button->SetCallback(base::BindRepeating(&MenuBar::ButtonPressed,
base::Unretained(this),
base::Unretained(button)));
AddChildView(button);
}
UpdateViewColors();

View File

@@ -80,7 +80,7 @@ class MenuBar : public views::AccessiblePaneView,
// views::View:
const char* GetClassName() const override;
void ButtonPressed(views::Button* source, const ui::Event& event);
void ButtonPressed(int id, const ui::Event& event);
void RebuildChildren();
void UpdateViewColors();

View File

@@ -20,9 +20,10 @@
namespace electron {
SubmenuButton::SubmenuButton(const base::string16& title,
SubmenuButton::SubmenuButton(PressedCallback callback,
const base::string16& title,
const SkColor& background_color)
: views::MenuButton(PressedCallback(), gfx::RemoveAccelerator(title)),
: views::MenuButton(callback, gfx::RemoveAccelerator(title)),
background_color_(background_color) {
#if defined(OS_LINUX)
// Dont' use native style border.

View File

@@ -16,7 +16,9 @@ namespace electron {
// Special button that used by menu bar to show submenus.
class SubmenuButton : public views::MenuButton {
public:
SubmenuButton(const base::string16& title, const SkColor& background_color);
SubmenuButton(PressedCallback callback,
const base::string16& title,
const SkColor& background_color);
~SubmenuButton() override;
void SetAcceleratorVisibility(bool visible);

View File

@@ -96,7 +96,8 @@ bool IsPlainObject(const v8::Local<v8::Value>& object) {
object->IsArrayBuffer() || object->IsArrayBufferView() ||
object->IsArray() || object->IsDataView() ||
object->IsSharedArrayBuffer() || object->IsProxy() ||
object->IsWasmModuleObject() || object->IsModuleNamespaceObject());
object->IsWasmModuleObject() || object->IsWasmMemoryObject() ||
object->IsModuleNamespaceObject());
}
bool IsPlainArray(const v8::Local<v8::Value>& arr) {

View File

@@ -981,7 +981,7 @@ describe('contextBridge', () => {
describe('overrideGlobalValueFromIsolatedWorld', () => {
it('should override top level properties', async () => {
await makeBindingWindow(() => {
contextBridge.internalContextBridge.overrideGlobalValueFromIsolatedWorld(['open'], () => ({ you: 'are a wizard' }));
contextBridge.internalContextBridge!.overrideGlobalValueFromIsolatedWorld(['open'], () => ({ you: 'are a wizard' }));
});
const result = await callWithBindings(async (root: any) => {
return root.open();
@@ -991,7 +991,7 @@ describe('contextBridge', () => {
it('should override deep properties', async () => {
await makeBindingWindow(() => {
contextBridge.internalContextBridge.overrideGlobalValueFromIsolatedWorld(['document', 'foo'], () => 'I am foo');
contextBridge.internalContextBridge!.overrideGlobalValueFromIsolatedWorld(['document', 'foo'], () => 'I am foo');
});
const result = await callWithBindings(async (root: any) => {
return root.document.foo();
@@ -1008,7 +1008,7 @@ describe('contextBridge', () => {
callCount++;
return true;
};
contextBridge.internalContextBridge.overrideGlobalPropertyFromIsolatedWorld(['isFun'], getter);
contextBridge.internalContextBridge!.overrideGlobalPropertyFromIsolatedWorld(['isFun'], getter);
contextBridge.exposeInMainWorld('foo', {
callCount: () => callCount
});
@@ -1022,7 +1022,7 @@ describe('contextBridge', () => {
it('should not make a setter if none is provided', async () => {
await makeBindingWindow(() => {
contextBridge.internalContextBridge.overrideGlobalPropertyFromIsolatedWorld(['isFun'], () => true);
contextBridge.internalContextBridge!.overrideGlobalPropertyFromIsolatedWorld(['isFun'], () => true);
});
const result = await callWithBindings(async (root: any) => {
root.isFun = 123;
@@ -1038,7 +1038,7 @@ describe('contextBridge', () => {
callArgs.push(args);
return true;
};
contextBridge.internalContextBridge.overrideGlobalPropertyFromIsolatedWorld(['isFun'], () => true, setter);
contextBridge.internalContextBridge!.overrideGlobalPropertyFromIsolatedWorld(['isFun'], () => true, setter);
contextBridge.exposeInMainWorld('foo', {
callArgs: () => callArgs
});
@@ -1056,7 +1056,7 @@ describe('contextBridge', () => {
describe('overrideGlobalValueWithDynamicPropsFromIsolatedWorld', () => {
it('should not affect normal values', async () => {
await makeBindingWindow(() => {
contextBridge.internalContextBridge.overrideGlobalValueWithDynamicPropsFromIsolatedWorld(['thing'], {
contextBridge.internalContextBridge!.overrideGlobalValueWithDynamicPropsFromIsolatedWorld(['thing'], {
a: 123,
b: () => 2,
c: () => ({ d: 3 })
@@ -1070,7 +1070,7 @@ describe('contextBridge', () => {
it('should work with getters', async () => {
await makeBindingWindow(() => {
contextBridge.internalContextBridge.overrideGlobalValueWithDynamicPropsFromIsolatedWorld(['thing'], {
contextBridge.internalContextBridge!.overrideGlobalValueWithDynamicPropsFromIsolatedWorld(['thing'], {
get foo () {
return 'hi there';
}
@@ -1085,7 +1085,7 @@ describe('contextBridge', () => {
it('should work with setters', async () => {
await makeBindingWindow(() => {
let a: any = null;
contextBridge.internalContextBridge.overrideGlobalValueWithDynamicPropsFromIsolatedWorld(['thing'], {
contextBridge.internalContextBridge!.overrideGlobalValueWithDynamicPropsFromIsolatedWorld(['thing'], {
get foo () {
return a;
},
@@ -1103,7 +1103,7 @@ describe('contextBridge', () => {
it('should work with deep properties', async () => {
await makeBindingWindow(() => {
contextBridge.internalContextBridge.overrideGlobalValueWithDynamicPropsFromIsolatedWorld(['thing'], {
contextBridge.internalContextBridge!.overrideGlobalValueWithDynamicPropsFromIsolatedWorld(['thing'], {
a: () => ({
get foo () {
return 'still here';

View File

@@ -2,7 +2,7 @@ import { expect } from 'chai';
import { net, session, ClientRequest, BrowserWindow, ClientRequestConstructorOptions } from 'electron/main';
import * as http from 'http';
import * as url from 'url';
import { AddressInfo, Socket } from 'net';
import { AddressInfo, Socket, createServer } from 'net';
import { emittedOnce } from './events-helpers';
import { defer, delay } from './spec-helpers';
@@ -1536,6 +1536,34 @@ describe('net module', () => {
expect(response.statusCode).to.equal(200);
await collectStreamBody(response);
});
it('should not trigger errors on the response stream', async () => {
const ses = session.fromPartition(`${Math.random()}`);
const serverPort = await new Promise(resolve => {
const server = createServer((c) => {
c.end('HTTP/1.1 407 Authentication Required\nProxy-Authenticate: Basic realm="Foo"\n\n');
}).listen(0, '127.0.0.1', async () => {
resolve((server.address() as AddressInfo).port);
});
});
await ses.setProxy({ proxyRules: `127.0.0.1:${serverPort}` });
const error = await new Promise<Error>((resolve, reject) => {
net
.request({ method: 'GET', url: 'https://example.com', session: ses })
.once('response', (res) => {
res.on('error', () => {
reject(new Error('response stream should not emit error'));
});
})
.once('abort', () => reject(new Error('should not abort')))
.once('error', (err) => {
resolve(err);
})
.once('login', (_, callback) => { callback('username', 'password'); })
.end();
});
expect(error.message).to.equal('net::ERR_TUNNEL_CONNECTION_FAILED');
});
});
describe('IncomingMessage API', () => {

View File

@@ -277,12 +277,12 @@ describe('chrome extensions', () => {
it('can cancel http requests', async () => {
await w.loadURL(url);
await customSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-webRequest'));
await expect(fetch(w.webContents, url)).to.eventually.be.rejectedWith(TypeError);
await expect(fetch(w.webContents, url)).to.eventually.be.rejectedWith('Failed to fetch');
});
it('does not cancel http requests when no extension loaded', async () => {
await w.loadURL(url);
await expect(fetch(w.webContents, url)).to.not.be.rejectedWith(TypeError);
await expect(fetch(w.webContents, url)).to.not.be.rejectedWith('Failed to fetch');
});
});

View File

@@ -5,11 +5,11 @@
"sender": "[WebContents]"
},
"about:blank",
"frame name",
"frame-name",
"new-window",
{
"width": 800,
"title": "frame name",
"title": "cool",
"backgroundColor": "blue",
"focusable": false,
"webPreferences": {
@@ -43,11 +43,11 @@
"sender": "[WebContents]"
},
"about:blank",
"frame name",
"frame-name",
"new-window",
{
"width": 800,
"title": "frame name",
"title": "cool",
"backgroundColor": "blue",
"focusable": false,
"webPreferences": {
@@ -80,11 +80,11 @@
"sender": "[WebContents]"
},
"about:blank",
"frame name",
"frame-name",
"new-window",
{
"width": 800,
"title": "frame name",
"title": "cool",
"backgroundColor": "gray",
"focusable": false,
"webPreferences": {
@@ -115,7 +115,7 @@
"sender": "[WebContents]"
},
"about:blank",
"frame name",
"frame-name",
"new-window",
{
"width": 800,
@@ -150,11 +150,11 @@
"sender": "[WebContents]"
},
"about:blank",
"frame name",
"frame-name",
"new-window",
{
"width": 800,
"title": "frame name",
"title": "cool",
"backgroundColor": "blue",
"focusable": false,
"webPreferences": {

View File

@@ -7,13 +7,13 @@
"processId": "placeholder-process-id"
},
"about:blank",
"frame name",
"frame-name",
"new-window",
{
"show": true,
"title": "frame name",
"width": 800,
"height": 600,
"title": "frame-name",
"top": 5,
"left": 10,
"resizable": false,
@@ -42,13 +42,13 @@
"processId": "placeholder-process-id"
},
"about:blank",
"frame name",
"frame-name",
"new-window",
{
"show": true,
"title": "frame name",
"width": 800,
"height": 600,
"title": "frame-name",
"resizable": false,
"x": 0,
"y": 10,
@@ -76,13 +76,13 @@
"processId": "placeholder-process-id"
},
"about:blank",
"frame name",
"frame-name",
"new-window",
{
"show": true,
"title": "frame name",
"width": 800,
"height": 600,
"title": "frame-name",
"backgroundColor": "gray",
"webPreferences": {
"nodeIntegration": false,
@@ -110,13 +110,13 @@
"processId": "placeholder-process-id"
},
"about:blank",
"frame name",
"frame-name",
"new-window",
{
"show": true,
"title": "sup",
"width": 800,
"height": 600,
"title": "sup",
"x": 50,
"y": 20,
"webPreferences": {
@@ -142,13 +142,13 @@
"processId": "placeholder-process-id"
},
"about:blank",
"frame name",
"frame-name",
"new-window",
{
"show": false,
"title": "frame name",
"width": 800,
"height": 600,
"title": "frame-name",
"top": 1,
"left": 1,
"x": 1,

View File

@@ -10,7 +10,7 @@ function genSnapshot (browserWindow: BrowserWindow, features: string) {
browserWindow.webContents.on('new-window', (...args: any[]) => {
resolve([features, ...args]);
});
browserWindow.webContents.executeJavaScript(`window.open('about:blank', 'frame name', '${features}') && true`);
browserWindow.webContents.executeJavaScript(`window.open('about:blank', 'frame-name', '${features}') && true`);
});
}

View File

@@ -232,6 +232,7 @@ declare namespace NodeJS {
_firstFileName?: string;
helperExecPath: string;
mainModule: NodeJS.Module;
}
}
@@ -271,6 +272,7 @@ declare interface Window {
completeURL: (project: string, path: string) => string;
}
};
WebView: typeof ElectronInternal.WebViewElement;
ResizeObserver: ResizeObserver;
trustedTypes: TrustedTypePolicyFactory;
}

View File

@@ -37,8 +37,12 @@ declare namespace Electron {
removeListener(event: '-touch-bar-interaction', listener: (event: Event, itemID: string, details: any) => void): this;
}
interface BrowserWindowConstructorOptions {
webContents?: WebContents;
}
interface ContextBridge {
internalContextBridge: {
internalContextBridge?: {
contextIsolationEnabled: boolean;
overrideGlobalValueFromIsolatedWorld(keys: string[], value: any): void;
overrideGlobalValueWithDynamicPropsFromIsolatedWorld(keys: string[], value: any): void;
@@ -88,6 +92,7 @@ declare namespace Electron {
}
interface WebFrame {
_executeJavaScript(code: string, userGesture?: boolean): Promise<any>;
getWebFrameId(window: Window): number;
allowGuestViewElementDefinition(window: Window, context: any): void;
}
@@ -100,7 +105,7 @@ declare namespace Electron {
interface WebPreferences {
guestInstanceId?: number;
openerId?: number;
openerId?: number | null;
disablePopups?: boolean;
preloadURL?: string;
embedder?: Electron.WebContents;
@@ -147,9 +152,14 @@ declare namespace Electron {
acceleratorWorksWhenHidden?: boolean;
}
interface IpcMainEvent {
sendReply(value: any): void;
}
interface IpcMainInvokeEvent {
sendReply(value: any): void;
_reply(value: any): void;
_throw(error: Error): void;
_throw(error: Error | string): void;
}
const deprecate: ElectronInternal.DeprecationUtil;
@@ -250,10 +260,26 @@ declare namespace ElectronInternal {
once(channel: string, listener: (event: IpcMainInternalEvent, ...args: any[]) => void): this;
}
interface Event extends Electron.Event {
sender: WebContents;
}
interface LoadURLOptions extends Electron.LoadURLOptions {
reloadIgnoringCache?: boolean;
}
interface WebContentsPrintOptions extends Electron.WebContentsPrintOptions {
mediaSize?: MediaSize;
}
type MediaSize = {
name: string,
custom_display_name: string,
height_microns: number,
width_microns: number,
is_default?: 'true',
}
type ModuleLoader = () => any;
interface ModuleEntry {