зеркало из https://github.com/electron/electron.git
chore: tsify web-contents (#24325)
This commit is contained in:
Родитель
82af855579
Коммит
1f23807271
|
@ -222,7 +222,7 @@ auto_filenames = {
|
|||
"lib/browser/api/view.ts",
|
||||
"lib/browser/api/views/image-view.ts",
|
||||
"lib/browser/api/web-contents-view.ts",
|
||||
"lib/browser/api/web-contents.js",
|
||||
"lib/browser/api/web-contents.ts",
|
||||
"lib/browser/chrome-extension-shim.ts",
|
||||
"lib/browser/default-menu.ts",
|
||||
"lib/browser/desktop-capturer.ts",
|
||||
|
@ -234,7 +234,7 @@ auto_filenames = {
|
|||
"lib/browser/ipc-main-internal-utils.ts",
|
||||
"lib/browser/ipc-main-internal.ts",
|
||||
"lib/browser/message-port-main.ts",
|
||||
"lib/browser/navigation-controller.js",
|
||||
"lib/browser/navigation-controller.ts",
|
||||
"lib/browser/remote/objects-registry.ts",
|
||||
"lib/browser/remote/server.ts",
|
||||
"lib/browser/rpc-server.ts",
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
'use strict';
|
||||
import { app, ipcMain, session, deprecate } from 'electron';
|
||||
import type { MenuItem, MenuItemConstructorOptions, WebContentsInternal } from 'electron';
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const electron = require('electron');
|
||||
const path = require('path');
|
||||
const url = require('url');
|
||||
const { app, ipcMain, session } = electron;
|
||||
|
||||
const { internalWindowOpen } = require('@electron/internal/browser/guest-window-manager');
|
||||
const NavigationController = require('@electron/internal/browser/navigation-controller');
|
||||
const { ipcMainInternal } = require('@electron/internal/browser/ipc-main-internal');
|
||||
const ipcMainUtils = require('@electron/internal/browser/ipc-main-internal-utils');
|
||||
const { parseFeatures } = require('@electron/internal/common/parse-features-string');
|
||||
const { MessagePortMain } = require('@electron/internal/browser/message-port-main');
|
||||
import * as url from 'url';
|
||||
import * as path from 'path';
|
||||
import { internalWindowOpen } from '../guest-window-manager';
|
||||
import { NavigationController } from '../navigation-controller';
|
||||
import { ipcMainInternal } from '../ipc-main-internal';
|
||||
import * as ipcMainUtils from '../ipc-main-internal-utils';
|
||||
import { parseFeatures } from '../../common/parse-features-string';
|
||||
import { MessagePortMain } from '../message-port-main';
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
// session is not used here, the purpose is to make sure session is initalized
|
||||
// before the webContents module.
|
||||
|
@ -23,8 +21,18 @@ const getNextId = function () {
|
|||
return ++nextId;
|
||||
};
|
||||
|
||||
/* 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 = {
|
||||
const PDFPageSizes: Record<string, MediaSize> = {
|
||||
A5: {
|
||||
custom_display_name: 'A5',
|
||||
height_microns: 210000,
|
||||
|
@ -67,8 +75,8 @@ const PDFPageSizes = {
|
|||
// Default printing setting
|
||||
const defaultPrintingSetting = {
|
||||
// Customizable.
|
||||
pageRange: [],
|
||||
mediaSize: {},
|
||||
pageRange: [] as {from: number, to: number}[],
|
||||
mediaSize: {} as MediaSize,
|
||||
landscape: false,
|
||||
headerFooterEnabled: false,
|
||||
marginsType: 0,
|
||||
|
@ -93,18 +101,18 @@ const defaultPrintingSetting = {
|
|||
copies: 1,
|
||||
// 2 = color - see ColorModel in //printing/print_job_constants.h
|
||||
color: 2,
|
||||
collate: true
|
||||
collate: true,
|
||||
printerType: 2,
|
||||
title: undefined as string | undefined,
|
||||
url: undefined as string | undefined
|
||||
};
|
||||
|
||||
// JavaScript implementations of WebContents.
|
||||
const binding = process._linkedBinding('electron_browser_web_contents');
|
||||
const { WebContents } = binding;
|
||||
const { WebContents } = binding as { WebContents: { prototype: WebContentsInternal } };
|
||||
|
||||
Object.setPrototypeOf(NavigationController.prototype, EventEmitter.prototype);
|
||||
Object.setPrototypeOf(WebContents.prototype, NavigationController.prototype);
|
||||
Object.setPrototypeOf(WebContents.prototype, EventEmitter.prototype);
|
||||
|
||||
// WebContents::send(channel, args..)
|
||||
// WebContents::sendToAll(channel, args..)
|
||||
WebContents.prototype.send = function (channel, ...args) {
|
||||
if (typeof channel !== 'string') {
|
||||
throw new Error('Missing required channel argument');
|
||||
|
@ -123,17 +131,6 @@ WebContents.prototype.postMessage = function (...args) {
|
|||
this._postMessage(...args);
|
||||
};
|
||||
|
||||
WebContents.prototype.sendToAll = function (channel, ...args) {
|
||||
if (typeof channel !== 'string') {
|
||||
throw new Error('Missing required channel argument');
|
||||
}
|
||||
|
||||
const internal = false;
|
||||
const sendToAll = true;
|
||||
|
||||
return this._send(internal, sendToAll, channel, args);
|
||||
};
|
||||
|
||||
WebContents.prototype._sendInternal = function (channel, ...args) {
|
||||
if (typeof channel !== 'string') {
|
||||
throw new Error('Missing required channel argument');
|
||||
|
@ -185,15 +182,15 @@ const webFrameMethods = [
|
|||
'insertText',
|
||||
'removeInsertedCSS',
|
||||
'setVisualZoomLevelLimits'
|
||||
];
|
||||
] as ('insertCSS' | 'insertText' | 'removeInsertedCSS' | 'setVisualZoomLevelLimits')[];
|
||||
|
||||
for (const method of webFrameMethods) {
|
||||
WebContents.prototype[method] = function (...args) {
|
||||
WebContents.prototype[method] = function (...args: any[]): Promise<any> {
|
||||
return ipcMainUtils.invokeInWebContents(this, false, 'ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, ...args);
|
||||
};
|
||||
}
|
||||
|
||||
const waitTillCanExecuteJavaScript = async (webContents) => {
|
||||
const waitTillCanExecuteJavaScript = async (webContents: WebContentsInternal) => {
|
||||
if (webContents.getURL() && !webContents.isLoadingMainFrame()) return;
|
||||
|
||||
return new Promise((resolve) => {
|
||||
|
@ -326,7 +323,7 @@ WebContents.prototype.printToPDF = function (options) {
|
|||
height_microns: Math.ceil(pageSize.height),
|
||||
width_microns: Math.ceil(pageSize.width)
|
||||
};
|
||||
} else if (PDFPageSizes[pageSize]) {
|
||||
} else if (Object.prototype.hasOwnProperty.call(PDFPageSizes, pageSize)) {
|
||||
printSettings.mediaSize = PDFPageSizes[pageSize];
|
||||
} else {
|
||||
const error = new Error(`Unsupported pageSize: ${pageSize}`);
|
||||
|
@ -360,14 +357,14 @@ WebContents.prototype.print = function (options = {}, callback) {
|
|||
throw new Error('height and width properties are required for pageSize');
|
||||
}
|
||||
// Dimensions in Microns - 1 meter = 10^6 microns
|
||||
options.mediaSize = {
|
||||
(options as any).mediaSize = {
|
||||
name: 'CUSTOM',
|
||||
custom_display_name: 'Custom',
|
||||
height_microns: Math.ceil(pageSize.height),
|
||||
width_microns: Math.ceil(pageSize.width)
|
||||
};
|
||||
} else if (PDFPageSizes[pageSize]) {
|
||||
options.mediaSize = PDFPageSizes[pageSize];
|
||||
(options as any).mediaSize = PDFPageSizes[pageSize];
|
||||
} else {
|
||||
throw new Error(`Unsupported pageSize: ${pageSize}`);
|
||||
}
|
||||
|
@ -410,23 +407,23 @@ WebContents.prototype.loadFile = function (filePath, options = {}) {
|
|||
}));
|
||||
};
|
||||
|
||||
const addReplyToEvent = (event) => {
|
||||
event.reply = (...args) => {
|
||||
const addReplyToEvent = (event: any) => {
|
||||
event.reply = (...args: any[]) => {
|
||||
event.sender.sendToFrame(event.frameId, ...args);
|
||||
};
|
||||
};
|
||||
|
||||
const addReplyInternalToEvent = (event) => {
|
||||
const addReplyInternalToEvent = (event: any) => {
|
||||
Object.defineProperty(event, '_replyInternal', {
|
||||
configurable: false,
|
||||
enumerable: false,
|
||||
value: (...args) => {
|
||||
value: (...args: any[]) => {
|
||||
event.sender._sendToFrameInternal(event.frameId, ...args);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const addReturnValueToEvent = (event) => {
|
||||
const addReturnValueToEvent = (event: any) => {
|
||||
Object.defineProperty(event, 'returnValue', {
|
||||
set: (value) => event.sendReply([value]),
|
||||
get: () => {}
|
||||
|
@ -436,14 +433,30 @@ const addReturnValueToEvent = (event) => {
|
|||
// Add JavaScript wrappers for WebContents class.
|
||||
WebContents.prototype._init = function () {
|
||||
// The navigation controller.
|
||||
NavigationController.call(this, this);
|
||||
const navigationController = new NavigationController(this);
|
||||
this.loadURL = navigationController.loadURL.bind(navigationController);
|
||||
this.getURL = navigationController.getURL.bind(navigationController);
|
||||
this.stop = navigationController.stop.bind(navigationController);
|
||||
this.reload = navigationController.reload.bind(navigationController);
|
||||
this.reloadIgnoringCache = navigationController.reloadIgnoringCache.bind(navigationController);
|
||||
this.canGoBack = navigationController.canGoBack.bind(navigationController);
|
||||
this.canGoForward = navigationController.canGoForward.bind(navigationController);
|
||||
this.canGoToIndex = navigationController.canGoToIndex.bind(navigationController);
|
||||
this.canGoToOffset = navigationController.canGoToOffset.bind(navigationController);
|
||||
this.clearHistory = navigationController.clearHistory.bind(navigationController);
|
||||
this.goBack = navigationController.goBack.bind(navigationController);
|
||||
this.goForward = navigationController.goForward.bind(navigationController);
|
||||
this.goToIndex = navigationController.goToIndex.bind(navigationController);
|
||||
this.goToOffset = navigationController.goToOffset.bind(navigationController);
|
||||
this.getActiveIndex = navigationController.getActiveIndex.bind(navigationController);
|
||||
this.length = navigationController.length.bind(navigationController);
|
||||
|
||||
// Every remote callback from renderer process would add a listener to the
|
||||
// render-view-deleted event, so ignore the listeners warning.
|
||||
this.setMaxListeners(0);
|
||||
|
||||
// Dispatch IPC messages to the ipc module.
|
||||
this.on('-ipc-message', function (event, internal, channel, args) {
|
||||
this.on('-ipc-message' as any, function (this: WebContentsInternal, event: any, internal: boolean, channel: string, args: any[]) {
|
||||
if (internal) {
|
||||
addReplyInternalToEvent(event);
|
||||
ipcMainInternal.emit(channel, event, ...args);
|
||||
|
@ -454,21 +467,21 @@ WebContents.prototype._init = function () {
|
|||
}
|
||||
});
|
||||
|
||||
this.on('-ipc-invoke', function (event, internal, channel, args) {
|
||||
event._reply = (result) => event.sendReply({ result });
|
||||
event._throw = (error) => {
|
||||
this.on('-ipc-invoke' as any, function (event: any, internal: boolean, channel: string, args: any[]) {
|
||||
event._reply = (result: any) => event.sendReply({ result });
|
||||
event._throw = (error: Error) => {
|
||||
console.error(`Error occurred in handler for '${channel}':`, error);
|
||||
event.sendReply({ error: error.toString() });
|
||||
};
|
||||
const target = internal ? ipcMainInternal : ipcMain;
|
||||
if (target._invokeHandlers.has(channel)) {
|
||||
target._invokeHandlers.get(channel)(event, ...args);
|
||||
if ((target as any)._invokeHandlers.has(channel)) {
|
||||
(target as any)._invokeHandlers.get(channel)(event, ...args);
|
||||
} else {
|
||||
event._throw(`No handler registered for '${channel}'`);
|
||||
}
|
||||
});
|
||||
|
||||
this.on('-ipc-message-sync', function (event, internal, channel, args) {
|
||||
this.on('-ipc-message-sync' as any, function (this: WebContentsInternal, event: any, internal: boolean, channel: string, args: any[]) {
|
||||
addReturnValueToEvent(event);
|
||||
if (internal) {
|
||||
addReplyInternalToEvent(event);
|
||||
|
@ -480,15 +493,15 @@ WebContents.prototype._init = function () {
|
|||
}
|
||||
});
|
||||
|
||||
this.on('-ipc-ports', function (event, internal, channel, message, ports) {
|
||||
this.on('-ipc-ports' as any, function (event: any, 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', function (event, params, callback) {
|
||||
this.on('pepper-context-menu' as any, function (event: any, params: {x: number, y: number, menu: Array<(MenuItemConstructorOptions) | (MenuItem)>}, callback: () => void) {
|
||||
// Access Menu via electron.Menu to prevent circular require.
|
||||
const menu = electron.Menu.buildFromTemplate(params.menu);
|
||||
const menu = require('electron').Menu.buildFromTemplate(params.menu);
|
||||
menu.popup({
|
||||
window: event.sender.getOwnerBrowserWindow(),
|
||||
x: params.x,
|
||||
|
@ -506,14 +519,14 @@ WebContents.prototype._init = function () {
|
|||
});
|
||||
|
||||
// The devtools requests the webContents to reload.
|
||||
this.on('devtools-reload-page', function () {
|
||||
this.on('devtools-reload-page', function (this: WebContentsInternal) {
|
||||
this.reload();
|
||||
});
|
||||
|
||||
if (this.getType() !== 'remote') {
|
||||
// Make new windows requested by links behave like "window.open".
|
||||
this.on('-new-window', (event, url, frameName, disposition,
|
||||
rawFeatures, referrer, postData) => {
|
||||
this.on('-new-window' as any, (event: any, url: string, frameName: string, disposition: string,
|
||||
rawFeatures: string, referrer: string, postData: string) => {
|
||||
const { options, webPreferences, additionalFeatures } = parseFeatures(rawFeatures);
|
||||
const mergedOptions = {
|
||||
show: true,
|
||||
|
@ -529,9 +542,9 @@ 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', (event, webContents, disposition,
|
||||
userGesture, left, top, width, height, url, frameName,
|
||||
referrer, rawFeatures, postData) => {
|
||||
this.on('-add-new-contents' as any, (event: any, webContents: WebContentsInternal, disposition: string,
|
||||
userGesture: boolean, left: number, top: number, width: number, height: number, url: string, frameName: string,
|
||||
referrer: string, rawFeatures: string, postData: string) => {
|
||||
if ((disposition !== 'foreground-tab' && disposition !== 'new-window' &&
|
||||
disposition !== 'background-tab')) {
|
||||
event.preventDefault();
|
||||
|
@ -554,7 +567,7 @@ WebContents.prototype._init = function () {
|
|||
|
||||
const prefs = this.getWebPreferences() || {};
|
||||
if (prefs.webviewTag && prefs.contextIsolation) {
|
||||
electron.deprecate.log('Security Warning: A WebContents was just created with both webviewTag and contextIsolation enabled. This combination is fundamentally less secure and effectively bypasses the protections of contextIsolation. We strongly recommend you move away from webviews to OOPIF or BrowserView in order for your app to be more secure');
|
||||
deprecate.log('Security Warning: A WebContents was just created with both webviewTag and contextIsolation enabled. This combination is fundamentally less secure and effectively bypasses the protections of contextIsolation. We strongly recommend you move away from webviews to OOPIF or BrowserView in order for your app to be more secure');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -599,28 +612,25 @@ WebContents.prototype._init = function () {
|
|||
};
|
||||
|
||||
// Public APIs.
|
||||
module.exports = {
|
||||
create (options = {}) {
|
||||
return binding.create(options);
|
||||
},
|
||||
export function create (options = {}) {
|
||||
return binding.create(options);
|
||||
}
|
||||
|
||||
fromId (id) {
|
||||
return binding.fromId(id);
|
||||
},
|
||||
export function fromId (id: string) {
|
||||
return binding.fromId(id);
|
||||
}
|
||||
|
||||
getFocusedWebContents () {
|
||||
let focused = null;
|
||||
for (const contents of binding.getAllWebContents()) {
|
||||
if (!contents.isFocused()) continue;
|
||||
if (focused == null) focused = contents;
|
||||
// Return webview web contents which may be embedded inside another
|
||||
// web contents that is also reporting as focused
|
||||
if (contents.getType() === 'webview') return contents;
|
||||
}
|
||||
return focused;
|
||||
},
|
||||
|
||||
getAllWebContents () {
|
||||
return binding.getAllWebContents();
|
||||
export function getFocusedWebContents () {
|
||||
let focused = null;
|
||||
for (const contents of binding.getAllWebContents()) {
|
||||
if (!contents.isFocused()) continue;
|
||||
if (focused == null) focused = contents;
|
||||
// Return webview web contents which may be embedded inside another
|
||||
// web contents that is also reporting as focused
|
||||
if (contents.getType() === 'webview') return contents;
|
||||
}
|
||||
};
|
||||
return focused;
|
||||
}
|
||||
export function getAllWebContents () {
|
||||
return binding.getAllWebContents();
|
||||
}
|
|
@ -56,7 +56,7 @@ const mergeBrowserWindowOptions = function (embedder, options) {
|
|||
let parentOptions = embedder.browserWindowOptions;
|
||||
|
||||
// if parent's visibility is available, that overrides 'show' flag (#12125)
|
||||
const win = BrowserWindow.fromWebContents(embedder.webContents);
|
||||
const win = BrowserWindow.fromWebContents(embedder);
|
||||
if (win != null) {
|
||||
parentOptions = {
|
||||
...win.getBounds(),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const { ipcMainInternal } = require('@electron/internal/browser/ipc-main-internal');
|
||||
import { ipcMainInternal } from './ipc-main-internal';
|
||||
import type { WebContents, LoadURLOptions } from 'electron/main';
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
// The history operation in renderer is redirected to browser.
|
||||
ipcMainInternal.on('ELECTRON_NAVIGATION_CONTROLLER_GO_BACK', function (event) {
|
||||
|
@ -16,7 +16,7 @@ ipcMainInternal.on('ELECTRON_NAVIGATION_CONTROLLER_GO_TO_OFFSET', function (even
|
|||
});
|
||||
|
||||
ipcMainInternal.on('ELECTRON_NAVIGATION_CONTROLLER_LENGTH', function (event) {
|
||||
event.returnValue = event.sender.length();
|
||||
event.returnValue = (event.sender as any).length();
|
||||
});
|
||||
|
||||
// JavaScript implementation of Chromium's NavigationController.
|
||||
|
@ -24,9 +24,14 @@ ipcMainInternal.on('ELECTRON_NAVIGATION_CONTROLLER_LENGTH', function (event) {
|
|||
// control on user land, and only rely on WebContents.loadURL for navigation.
|
||||
// This helps us avoid Chromium's various optimizations so we can ensure renderer
|
||||
// process is restarted everytime.
|
||||
const NavigationController = (function () {
|
||||
function NavigationController (webContents) {
|
||||
this.webContents = webContents;
|
||||
export class NavigationController extends EventEmitter {
|
||||
currentIndex: number = -1;
|
||||
inPageIndex: number = -1;
|
||||
pendingIndex: number = -1;
|
||||
history: string[] = [];
|
||||
|
||||
constructor (private webContents: WebContents) {
|
||||
super();
|
||||
this.clearHistory();
|
||||
|
||||
// webContents may have already navigated to a page.
|
||||
|
@ -34,7 +39,7 @@ const NavigationController = (function () {
|
|||
this.currentIndex++;
|
||||
this.history.push(this.webContents._getURL());
|
||||
}
|
||||
this.webContents.on('navigation-entry-committed', (event, url, inPage, replaceEntry) => {
|
||||
this.webContents.on('navigation-entry-committed' as any, (event: any, url: string, inPage: boolean, replaceEntry: boolean) => {
|
||||
if (this.inPageIndex > -1 && !inPage) {
|
||||
// Navigated to a new page, clear in-page mark.
|
||||
this.inPageIndex = -1;
|
||||
|
@ -59,16 +64,16 @@ const NavigationController = (function () {
|
|||
});
|
||||
}
|
||||
|
||||
NavigationController.prototype.loadURL = function (url, options) {
|
||||
loadURL (url: string, options?: LoadURLOptions): Promise<void> {
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
const p = new Promise((resolve, reject) => {
|
||||
const p = new Promise<void>((resolve, reject) => {
|
||||
const resolveAndCleanup = () => {
|
||||
removeListeners();
|
||||
resolve();
|
||||
};
|
||||
const rejectAndCleanup = (errorCode, errorDescription, url) => {
|
||||
const rejectAndCleanup = (errorCode: number, errorDescription: string, url: string) => {
|
||||
const err = new Error(`${errorDescription} (${errorCode}) loading '${typeof url === 'string' ? url.substr(0, 2048) : url}'`);
|
||||
Object.assign(err, { errno: errorCode, code: errorDescription, url });
|
||||
removeListeners();
|
||||
|
@ -77,14 +82,14 @@ const NavigationController = (function () {
|
|||
const finishListener = () => {
|
||||
resolveAndCleanup();
|
||||
};
|
||||
const failListener = (event, errorCode, errorDescription, validatedURL, isMainFrame, frameProcessId, frameRoutingId) => {
|
||||
const failListener = (event: any, errorCode: number, errorDescription: string, validatedURL: string, isMainFrame: boolean) => {
|
||||
if (isMainFrame) {
|
||||
rejectAndCleanup(errorCode, errorDescription, validatedURL);
|
||||
}
|
||||
};
|
||||
|
||||
let navigationStarted = false;
|
||||
const navigationListener = (event, url, isSameDocument, isMainFrame, frameProcessId, frameRoutingId, navigationId) => {
|
||||
const navigationListener = (event: any, url: string, isSameDocument: boolean, isMainFrame: boolean) => {
|
||||
if (isMainFrame) {
|
||||
if (navigationStarted && !isSameDocument) {
|
||||
// the webcontents has started another unrelated navigation in the
|
||||
|
@ -129,58 +134,58 @@ const NavigationController = (function () {
|
|||
this.webContents._loadURL(url, options);
|
||||
this.webContents.emit('load-url', url, options);
|
||||
return p;
|
||||
};
|
||||
}
|
||||
|
||||
NavigationController.prototype.getURL = function () {
|
||||
getURL () {
|
||||
if (this.currentIndex === -1) {
|
||||
return '';
|
||||
} else {
|
||||
return this.history[this.currentIndex];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
NavigationController.prototype.stop = function () {
|
||||
stop () {
|
||||
this.pendingIndex = -1;
|
||||
return this.webContents._stop();
|
||||
};
|
||||
}
|
||||
|
||||
NavigationController.prototype.reload = function () {
|
||||
reload () {
|
||||
this.pendingIndex = this.currentIndex;
|
||||
return this.webContents._loadURL(this.getURL(), {});
|
||||
};
|
||||
}
|
||||
|
||||
NavigationController.prototype.reloadIgnoringCache = function () {
|
||||
reloadIgnoringCache () {
|
||||
this.pendingIndex = this.currentIndex;
|
||||
return this.webContents._loadURL(this.getURL(), {
|
||||
extraHeaders: 'pragma: no-cache\n',
|
||||
reloadIgnoringCache: true
|
||||
});
|
||||
};
|
||||
} as any);
|
||||
}
|
||||
|
||||
NavigationController.prototype.canGoBack = function () {
|
||||
canGoBack () {
|
||||
return this.getActiveIndex() > 0;
|
||||
};
|
||||
}
|
||||
|
||||
NavigationController.prototype.canGoForward = function () {
|
||||
canGoForward () {
|
||||
return this.getActiveIndex() < this.history.length - 1;
|
||||
};
|
||||
}
|
||||
|
||||
NavigationController.prototype.canGoToIndex = function (index) {
|
||||
canGoToIndex (index: number) {
|
||||
return index >= 0 && index < this.history.length;
|
||||
};
|
||||
}
|
||||
|
||||
NavigationController.prototype.canGoToOffset = function (offset) {
|
||||
canGoToOffset (offset: number) {
|
||||
return this.canGoToIndex(this.currentIndex + offset);
|
||||
};
|
||||
}
|
||||
|
||||
NavigationController.prototype.clearHistory = function () {
|
||||
clearHistory () {
|
||||
this.history = [];
|
||||
this.currentIndex = -1;
|
||||
this.pendingIndex = -1;
|
||||
this.inPageIndex = -1;
|
||||
};
|
||||
}
|
||||
|
||||
NavigationController.prototype.goBack = function () {
|
||||
goBack () {
|
||||
if (!this.canGoBack()) {
|
||||
return;
|
||||
}
|
||||
|
@ -190,9 +195,9 @@ const NavigationController = (function () {
|
|||
} else {
|
||||
return this.webContents._loadURL(this.history[this.pendingIndex], {});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
NavigationController.prototype.goForward = function () {
|
||||
goForward () {
|
||||
if (!this.canGoForward()) {
|
||||
return;
|
||||
}
|
||||
|
@ -202,17 +207,17 @@ const NavigationController = (function () {
|
|||
} else {
|
||||
return this.webContents._loadURL(this.history[this.pendingIndex], {});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
NavigationController.prototype.goToIndex = function (index) {
|
||||
goToIndex (index: number) {
|
||||
if (!this.canGoToIndex(index)) {
|
||||
return;
|
||||
}
|
||||
this.pendingIndex = index;
|
||||
return this.webContents._loadURL(this.history[this.pendingIndex], {});
|
||||
};
|
||||
}
|
||||
|
||||
NavigationController.prototype.goToOffset = function (offset) {
|
||||
goToOffset (offset: number) {
|
||||
if (!this.canGoToOffset(offset)) {
|
||||
return;
|
||||
}
|
||||
|
@ -223,21 +228,17 @@ const NavigationController = (function () {
|
|||
} else {
|
||||
return this.goToIndex(pendingIndex);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
NavigationController.prototype.getActiveIndex = function () {
|
||||
getActiveIndex () {
|
||||
if (this.pendingIndex === -1) {
|
||||
return this.currentIndex;
|
||||
} else {
|
||||
return this.pendingIndex;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
NavigationController.prototype.length = function () {
|
||||
length () {
|
||||
return this.history.length;
|
||||
};
|
||||
|
||||
return NavigationController;
|
||||
})();
|
||||
|
||||
module.exports = NavigationController;
|
||||
}
|
||||
}
|
|
@ -84,7 +84,7 @@ describe('renderer nodeIntegrationInSubFrames', () => {
|
|||
w.loadFile(path.resolve(__dirname, `fixtures/sub-frames/frame-container${fixtureSuffix}.html`));
|
||||
const details = await detailsPromise;
|
||||
const senders = details.map(event => event[0].sender);
|
||||
const isolatedGlobals = await Promise.all(senders.map(sender => sender.webContents.executeJavaScript('window.isolatedGlobal')));
|
||||
const isolatedGlobals = await Promise.all(senders.map(sender => sender.executeJavaScript('window.isolatedGlobal')));
|
||||
for (const result of isolatedGlobals) {
|
||||
if (webPreferences.contextIsolation) {
|
||||
expect(result).to.be.undefined();
|
||||
|
|
|
@ -12,7 +12,7 @@ app.whenReady().then(function () {
|
|||
callback('Hello World!');
|
||||
});
|
||||
|
||||
web.webContents.loadURL('test://abc/hello.txt');
|
||||
web.loadURL('test://abc/hello.txt');
|
||||
|
||||
web.webContents.on('did-finish-load', () => app.quit());
|
||||
web.on('did-finish-load', () => app.quit());
|
||||
});
|
||||
|
|
|
@ -31,7 +31,13 @@ declare namespace Electron {
|
|||
|
||||
interface WebContents {
|
||||
_getURL(): string;
|
||||
_loadURL(url: string, options: Electron.LoadURLOptions): void;
|
||||
_stop(): void;
|
||||
_goBack(): void;
|
||||
_goForward(): void;
|
||||
_goToOffset(offset: number): void;
|
||||
getOwnerBrowserWindow(): Electron.BrowserWindow;
|
||||
getWebPreferences(): Electron.WebPreferences;
|
||||
getLastWebPreferences(): Electron.WebPreferences;
|
||||
_getPreloadPaths(): string[];
|
||||
equal(other: WebContents): boolean;
|
||||
|
@ -86,8 +92,19 @@ declare namespace Electron {
|
|||
}
|
||||
|
||||
interface WebContentsInternal extends Electron.WebContents {
|
||||
_send(internal: boolean, sendToAll: boolean, channel: string, args: any): boolean;
|
||||
_sendToFrame(internal: boolean, sendToAll: boolean, frameId: number, channel: string, args: any): boolean;
|
||||
_sendToFrameInternal(frameId: number, channel: string, args: any): boolean;
|
||||
_postMessage(channel: string, message: any, transfer?: any[]): void;
|
||||
_sendInternal(channel: string, ...args: any[]): void;
|
||||
_sendInternalToAll(channel: string, ...args: any[]): void;
|
||||
_printToPDF(options: any): Promise<Buffer>;
|
||||
_print(options: any, callback?: (success: boolean, failureReason: string) => void): void;
|
||||
_getPrinters(): Electron.PrinterInfo[];
|
||||
_init(): void;
|
||||
canGoToIndex(index: number): boolean;
|
||||
getActiveIndex(): number;
|
||||
length(): number;
|
||||
}
|
||||
|
||||
const deprecate: ElectronInternal.DeprecationUtil;
|
||||
|
|
Загрузка…
Ссылка в новой задаче