diff --git a/github-electron/github-electron-main-tests.ts b/github-electron/github-electron-main-tests.ts
index 0bec03bd1..545c60c68 100644
--- a/github-electron/github-electron-main-tests.ts
+++ b/github-electron/github-electron-main-tests.ts
@@ -69,7 +69,7 @@ app.on('ready', () => {
mainWindow.webContents.addWorkSpace('/path/to/workspace');
mainWindow.webContents.removeWorkSpace('/path/to/workspace');
var opened: boolean = mainWindow.webContents.isDevToolsOpened()
- var focused = mainWindow.webContents.isDevToolsFocused();
+ var focused = mainWindow.webContents.isDevToolsFocused();
// Emitted when the window is closed.
mainWindow.on('closed', () => {
// Dereference the window object, usually you would store windows
@@ -83,11 +83,6 @@ app.on('ready', () => {
mainWindow.print();
mainWindow.webContents.print();
- mainWindow.print({silent: true, printBackground: false});
- mainWindow.webContents.print({silent: true, printBackground: false});
- mainWindow.print();
- mainWindow.webContents.print();
-
mainWindow.printToPDF({
marginsType: 1,
pageSize: 'A3',
@@ -119,6 +114,35 @@ app.on('ready', () => {
mainWindow.webContents.stopFindInPage('clearSelection');
mainWindow.webContents.stopFindInPage('keepSelection');
mainWindow.webContents.stopFindInPage('activateSelection');
+
+ mainWindow.loadURL('https://github.com');
+
+ mainWindow.webContents.on('did-finish-load', function() {
+ mainWindow.webContents.savePage('/tmp/test.html', 'HTMLComplete', function(error) {
+ if (!error)
+ console.log("Save page successfully");
+ });
+ });
+
+ try {
+ mainWindow.webContents.debugger.attach("1.1");
+ } catch(err) {
+ console.log("Debugger attach failed : ", err);
+ };
+
+ mainWindow.webContents.debugger.on('detach', function(event, reason) {
+ console.log("Debugger detached due to : ", reason);
+ });
+
+ mainWindow.webContents.debugger.on('message', function(event, method, params) {
+ if (method == "Network.requestWillBeSent") {
+ if (params.request.url == "https://www.github.com") {
+ win.webContents.debugger.detach();
+ }
+ }
+ });
+
+ mainWindow.webContents.debugger.sendCommand("Network.enable");
});
// Locale
diff --git a/github-electron/github-electron.web-contents.d.ts b/github-electron/github-electron.web-contents.d.ts
index 4ef1c2ccb..260bc04b5 100644
--- a/github-electron/github-electron.web-contents.d.ts
+++ b/github-electron/github-electron.web-contents.d.ts
@@ -6,12 +6,207 @@
///
///
///
+///
declare namespace Electron {
/**
* A WebContents is responsible for rendering and controlling a web page.
*/
class WebContents extends EventEmitter {
+ /**
+ * Emitted when the navigation is done, i.e. the spinner of the tab has stopped spinning,
+ * and the onload event was dispatched.
+ */
+ on(event: 'did-finish-load', listener: Function): this;
+ /**
+ * This event is like did-finish-load but emitted when the load failed or was cancelled,
+ * e.g. window.stop() is invoked.
+ */
+ on(event: 'did-fail-load', listener: (event: Event, errorCode: number, errorDescription: string, validatedURL: string) => void): this;
+ /**
+ * Emitted when a frame has done navigation.
+ */
+ on(event: 'did-frame-finish-load', listener: (event: Event, isMainFrame: boolean) => void): this;
+ /**
+ * Corresponds to the points in time when the spinner of the tab started spinning.
+ */
+ on(event: 'did-start-loading', listener: Function): this;
+ /**
+ * Corresponds to the points in time when the spinner of the tab stopped spinning.
+ */
+ on(event: 'did-stop-loading', listener: Function): this;
+ /**
+ * Emitted when details regarding a requested resource are available.
+ * status indicates the socket connection to download the resource.
+ */
+ on(event: 'did-get-response-details', listener: (event: Event,
+ status: boolean,
+ newURL: string,
+ originalURL: string,
+ httpResponseCode: number,
+ requestMethod: string,
+ referrer: string,
+ headers: any
+ ) => void): this;
+ /**
+ *
+ */
+ on(event: 'did-get-redirect-request', listener: (event: Event,
+ oldURL: string,
+ newURL: string,
+ isMainFrame: boolean,
+ httpResponseCode: number,
+ requestMethod: string,
+ referrer: string,
+ headers: any
+ ) => void): this;
+ /**
+ * Emitted when the document in the given frame is loaded.
+ */
+ on(event: 'dom-ready', listener: (event: Event) => void): this;
+ /**
+ * Emitted when page receives favicon URLs.
+ */
+ on(event: 'page-favicon-updated', listener: (event: Event, favicons: string[]) => void): this;
+ /**
+ * Emitted when the page requests to open a new window for a url.
+ * It could be requested by window.open or an external link like .
+ *
+ * By default a new BrowserWindow will be created for the url.
+ *
+ * Calling event.preventDefault() will prevent creating new windows.
+ */
+ on(event: 'new-window', listener: (event: Event,
+ url: string,
+ frameName: string,
+ disposition: 'default' | 'foreground-tab' | 'background-tab' | 'new-window' | 'other',
+ /**
+ * The options which will be used for creating the new BrowserWindow.
+ */
+ options: any
+ ) => void): this;
+ /**
+ * Emitted when a user or the page wants to start navigation.
+ * It can happen when the window.location object is changed or a user clicks a link in the page.
+ *
+ * This event will not emit when the navigation is started programmatically with APIs like
+ * webContents.loadURL and webContents.back.
+ *
+ * It is also not emitted for in-page navigations, such as clicking anchor links
+ * or updating the window.location.hash. Use did-navigate-in-page event for this purpose.
+ *
+ * Calling event.preventDefault() will prevent the navigation.
+ */
+ on(event: 'will-navigate', listener: (event: Event, url: string) => void): this;
+ /**
+ * Emitted when a navigation is done.
+ *
+ * This event is not emitted for in-page navigations, such as clicking anchor links
+ * or updating the window.location.hash. Use did-navigate-in-page event for this purpose.
+ */
+ on(event: 'did-navigate', listener: (event: Event, url: string) => void): this;
+ /**
+ * Emitted when an in-page navigation happened.
+ *
+ * When in-page navigation happens, the page URL changes but does not cause
+ * navigation outside of the page. Examples of this occurring are when anchor links
+ * are clicked or when the DOM hashchange event is triggered.
+ */
+ on(event: 'did-navigate-in-page', listener: (event: Event, url: string) => void): this;
+ /**
+ * Emitted when the renderer process has crashed.
+ */
+ on(event: 'crashed', listener: Function): this;
+ /**
+ * Emitted when a plugin process has crashed.
+ */
+ on(event: 'plugin-crashed', listener: (event: Event, name: string, version: string) => void): this;
+ /**
+ * Emitted when webContents is destroyed.
+ */
+ on(event: 'destroyed', listener: Function): this;
+ /**
+ * Emitted when DevTools is opened.
+ */
+ on(event: 'devtools-opened', listener: Function): this;
+ /**
+ * Emitted when DevTools is closed.
+ */
+ on(event: 'devtools-closed', listener: Function): this;
+ /**
+ * Emitted when DevTools is focused / opened.
+ */
+ on(event: 'devtools-focused', listener: Function): this;
+ /**
+ * Emitted when failed to verify the certificate for url.
+ * The usage is the same with the "certificate-error" event of app.
+ */
+ on(event: 'certificate-error', listener: (event: Event,
+ url: string,
+ error: string,
+ certificate: Certificate,
+ callback: (trust: boolean) => void
+ ) => void): this;
+ /**
+ * Emitted when a client certificate is requested.
+ * The usage is the same with the "select-client-certificate" event of app.
+ */
+ on(event: 'select-client-certificate', listener: (event: Event,
+ url: string,
+ certificateList: Certificate[],
+ callback: (certificate: Certificate) => void
+ ) => void): this;
+ /**
+ * Emitted when webContents wants to do basic auth.
+ * The usage is the same with the "login" event of app.
+ */
+ on(event: 'login', listener: (event: Event,
+ request: LoginRequest,
+ authInfo: LoginAuthInfo,
+ callback: (username: string, password: string) => void
+ ) => void): this;
+ /**
+ * Emitted when a result is available for webContents.findInPage request.
+ */
+ on(event: 'found-in-page', listener: (event: Event, result: {
+ requestId: number;
+ /**
+ * ndicates if more responses are to follow.
+ */
+ finalUpdate: boolean;
+ /**
+ * Position of the active match.
+ */
+ activeMatchOrdinal?: number;
+ /**
+ * Number of Matches.
+ */
+ matches?: number;
+ /**
+ * Coordinates of first match region.
+ */
+ selectionArea?: any;
+ }) => void): this;
+ /**
+ * Emitted when media starts playing.
+ */
+ on(event: 'media-started-playing', listener: Function): this;
+ /**
+ * Emitted when media is paused or done playing.
+ */
+ on(event: 'media-paused', listener: Function): this;
+ /**
+ * Emitted when a page’s theme color changes. This is usually due to encountering a meta tag:
+ *
+ */
+ on(event: 'did-change-theme-color', listener: Function): this;
+ /**
+ * Emitted when the cursor’s type changes.
+ * If the type parameter is custom, the image parameter will hold the custom cursor image
+ * in a NativeImage, and the scale will hold scaling information for the image.
+ */
+ on(event: 'cursor-changed', listener: (event: Event, type: CursorType, image?: NativeImage, scale?: number) => void): this;
+ on(event: string, listener: Function): this;
/**
* Loads the url in the window.
* @param url Must contain the protocol prefix (e.g., the http:// or file://).
@@ -21,6 +216,11 @@ declare namespace Electron {
userAgent?: string;
extraHeaders?: string;
}): void;
+ /**
+ * Initiates a download of the resource at url without navigating.
+ * The will-download event of session will be triggered.
+ */
+ downloadURL(url: string): void;
/**
* @returns The URL of current web page.
*/
@@ -66,6 +266,10 @@ declare namespace Electron {
* @returns Whether the web page can go to offset.
*/
canGoToOffset(offset: number): boolean;
+ /**
+ * Clears the navigation history.
+ */
+ clearHistory(): void;
/**
* Makes the web page go back.
*/
@@ -90,6 +294,10 @@ declare namespace Electron {
* Overrides the user agent for this page.
*/
setUserAgent(userAgent: string): void;
+ /**
+ * @returns The user agent for this web page.
+ */
+ getUserAgent(): string;
/**
* Injects CSS into this page.
*/
@@ -99,6 +307,14 @@ declare namespace Electron {
* @param code Code to evaluate.
*/
executeJavaScript(code: string, userGesture?: boolean, callback?: (result: any) => void): void;
+ /**
+ * Mute the audio on the current web page.
+ */
+ setAudioMuted(muted: boolean): void;
+ /**
+ * @returns Whether this page has been muted.
+ */
+ isAudioMuted(): boolean;
/**
* Executes Edit -> Undo command in page.
*/
@@ -119,6 +335,10 @@ declare namespace Electron {
* Executes Edit -> Paste command in page.
*/
paste(): void;
+ /**
+ * Executes Edit -> Paste and Match Style in page.
+ */
+ pasteAndMatchStyle(): void;
/**
* Executes Edit -> Delete command in page.
*/
@@ -264,6 +484,10 @@ declare namespace Electron {
* Starts inspecting element at position (x, y).
*/
inspectElement(x: number, y: number): void;
+ /**
+ * Opens the developer tools for the service worker context.
+ */
+ inspectServiceWorker(): void;
/**
* Send args.. to the web page via channel in asynchronous message, the web page
* can handle it by listening to the channel event of ipc module.
@@ -274,13 +498,251 @@ declare namespace Electron {
* to a renderer process, because it would be very easy to cause dead locks.
*/
send(channel: string, ...args: any[]): void;
+ /**
+ * Enable device emulation with the given parameters.
+ */
+ enableDeviceEmulation(parameters: DeviceEmulationParameters): void;
+ /**
+ * Disable device emulation.
+ */
+ disableDeviceEmulation(): void;
+ /**
+ * Sends an input event to the page.
+ */
+ sendInputEvent(event: SendInputEvent): void;
+ /**
+ * Begin subscribing for presentation events and captured frames,
+ * The callback will be called when there is a presentation event.
+ */
+ beginFrameSubscription(callback: (
+ /**
+ * The frameBuffer is a Buffer that contains raw pixel data.
+ * On most machines, the pixel data is effectively stored in 32bit BGRA format,
+ * but the actual representation depends on the endianness of the processor
+ * (most modern processors are little-endian, on machines with big-endian
+ * processors the data is in 32bit ARGB format).
+ */
+ frameBuffer: Buffer
+ ) => void): void;
+ /**
+ * End subscribing for frame presentation events.
+ */
+ endFrameSubscription(): void;
+ /**
+ * @returns If the process of saving page has been initiated successfully.
+ */
+ savePage(fullPath: string, saveType: 'HTMLOnly' | 'HTMLComplete' | 'MHTML', callback?: (eror: Error) => void): boolean;
+ /**
+ * @returns The session object used by this webContents.
+ */
+ session: Session;
+ /**
+ * @returns The WebContents that might own this WebContents.
+ */
+ hostWebContents: WebContents;
+ /**
+ * @returns The WebContents of DevTools for this WebContents.
+ * Note: Users should never store this object because it may become null
+ * when the DevTools has been closed.
+ */
+ devToolsWebContents: WebContents;
+ /**
+ * @returns Debugger API
+ */
+ debugger: Debugger;
+ }
+
+ type CursorType = 'default' | 'crosshair' | 'pointer' | 'text' | 'wait' | 'help' | 'e-resize' | 'n-resize' | 'ne-resize' | 'nw-resize' | 's-resize' | 'se-resize' | 'sw-resize' | 'w-resize' | 'ns-resize' | 'ew-resize' | 'nesw-resize' | 'nwse-resize' | 'col-resize' | 'row-resize' | 'm-panning' | 'e-panning' | 'n-panning' | 'ne-panning' | 'nw-panning' | 's-panning' | 'se-panning' |'sw-panning' | 'w-panning' | 'move' | 'vertical-text' | 'cell' | 'context-menu' | 'alias' | 'progress' | 'nodrop' | 'copy' | 'none' | 'not-allowed' | 'zoom-in' | 'zoom-out' | 'grab' | 'grabbing' | 'custom';
+
+ interface Certificate {
+ /**
+ * PEM encoded data
+ */
+ data: Buffer;
+ issuerName: string;
+ }
+
+ interface LoginRequest {
+ method: string;
+ url: string;
+ referrer: string;
+ }
+
+ interface LoginAuthInfo {
+ isProxy: boolean;
+ scheme: string;
+ host: string;
+ port: number;
+ realm: string;
}
interface FindInPageOptions {
+ /**
+ * Whether to search forward or backward, defaults to true
+ */
forward?: boolean;
+ /**
+ * Whether the operation is first request or a follow up, defaults to false.
+ */
findNext?: boolean;
+ /**
+ * Whether search should be case-sensitive, defaults to false.
+ */
matchCase?: boolean;
+ /**
+ * Whether to look only at the start of words. defaults to false.
+ */
wordStart?: boolean;
+ /**
+ * When combined with wordStart, accepts a match in the middle of a word
+ * if the match begins with an uppercase letter followed by a lowercase
+ * or non-letter. Accepts several other intra-word matches, defaults to false.
+ */
medialCapitalAsWordStart?: boolean;
}
+
+ interface DeviceEmulationParameters {
+ /**
+ * Specify the screen type to emulated
+ * Default: desktop
+ */
+ screenPosition?: 'desktop' | 'mobile';
+ /**
+ * Set the emulated screen size (screenPosition == mobile)
+ */
+ screenSize?: {
+ /**
+ * Set the emulated screen width
+ */
+ width: number;
+ /**
+ * Set the emulated screen height
+ */
+ height: number;
+ };
+ /**
+ * Position the view on the screen (screenPosition == mobile)
+ * Default: {x: 0, y: 0}
+ */
+ viewPosition?: {
+ /**
+ * Set the x axis offset from top left corner
+ */
+ x: number;
+ /**
+ * Set the y axis offset from top left corner
+ */
+ y: number;
+ };
+ /**
+ * Set the device scale factor (if zero defaults to original device scale factor)
+ * Default: 0
+ */
+ deviceScaleFactor: number;
+ /**
+ * Set the emulated view size (empty means no override).
+ */
+ viewSize?: {
+ /**
+ * Set the emulated view width
+ */
+ width: number;
+ /**
+ * Set the emulated view height
+ */
+ height: number;
+ };
+ /**
+ * Whether emulated view should be scaled down if necessary to fit into available space
+ * Default: false
+ */
+ fitToView?: boolean;
+ /**
+ * Offset of the emulated view inside available space (not in fit to view mode)
+ * Default: {x: 0, y: 0}
+ */
+ offset?: {
+ /**
+ * Set the x axis offset from top left corner
+ */
+ x: number;
+ /**
+ * Set the y axis offset from top left corner
+ */
+ y: number;
+ };
+ /**
+ * Scale of emulated view inside available space (not in fit to view mode)
+ * Default: 1
+ */
+ scale: number;
+ }
+
+ interface SendInputEvent {
+ type: 'mouseDown' | 'mouseUp' | 'mouseEnter' | 'mouseLeave' | 'contextMenu' | 'mouseWheel' | 'mouseMove' | 'keyDown' | 'keyUp' | 'char';
+ modifiers: ('shift' | 'control' | 'alt' | 'meta' | 'isKeypad' | 'isAutoRepeat' | 'leftButtonDown' | 'middleButtonDown' | 'rightButtonDown' | 'capsLock' | 'numLock' | 'left' | 'right')[];
+ }
+
+ interface SendInputKeyboardEvent extends SendInputEvent {
+ keyCode: string;
+ }
+
+ interface SendInputMouseEvent extends SendInputEvent {
+ x: number;
+ y: number;
+ button?: 'left' | 'middle' | 'right';
+ globalX?: number;
+ globalY?: number;
+ movementX?: number;
+ movementY?: number;
+ clickCount?: number;
+ }
+
+ interface SendInputMouseWheelEvent extends SendInputEvent {
+ deltaX?: number;
+ deltaY?: number;
+ wheelTicksX?: number;
+ wheelTicksY?: number;
+ accelerationRatioX?: number;
+ accelerationRatioY?: number;
+ hasPreciseScrollingDeltas?: number;
+ canScroll?: boolean;
+ }
+
+ /**
+ * Debugger API serves as an alternate transport for remote debugging protocol.
+ */
+ interface Debugger extends NodeJS.EventEmitter {
+ /**
+ * Attaches the debugger to the webContents.
+ * @param protocolVersion Requested debugging protocol version.
+ */
+ attach(protocolVersion?: string): void;
+ /**
+ * @returns Whether a debugger is attached to the webContents.
+ */
+ isAttached(): boolean;
+ /**
+ * Detaches the debugger from the webContents.
+ */
+ detach(): void;
+ /**
+ * Send given command to the debugging target.
+ * @param method Method name, should be one of the methods defined by the remote debugging protocol.
+ * @param commandParams JSON object with request parameters.
+ * @param callback Response defined by the ‘returns’ attribute of the command description in the remote debugging protocol.
+ */
+ sendCommand(method: string, commandParams?: any, callback?: (error: Error, result: any) => void): void;
+ /**
+ * Emitted when debugging session is terminated. This happens either when
+ * webContents is closed or devtools is invoked for the attached webContents.
+ */
+ on(event: 'detach', listener: (event: Event, reason: string) => void): this;
+ /**
+ * Emitted whenever debugging target issues instrumentation event.
+ * Event parameters defined by the ‘parameters’ attribute in the remote debugging protocol.
+ */
+ on(event: 'message', listener: (event: Event, method: string, params: any) => void): this;
+ on(event: string, listener: Function): this;
+ }
}