From 7f007109c3576af1005d358f612d931783fcaccf Mon Sep 17 00:00:00 2001 From: Felix Rieseberg Date: Tue, 26 Feb 2019 02:10:26 +0000 Subject: [PATCH] refactor: Port inspector to TypeScript (#16943) * refactor: Port inspector to TypeScript * refactor: Add another type to inspector * refactor: Use correct paths * Update lib/renderer/inspector.ts Co-Authored-By: felixrieseberg * refactor: Implement feedback <3 * refactor: Don't define blob at all * fix: Correct type --- filenames.gni | 2 +- lib/renderer/inspector.js | 65 ----------------------------------- lib/renderer/inspector.ts | 64 ++++++++++++++++++++++++++++++++++ typings/internal-ambient.d.ts | 15 ++++++++ 4 files changed, 80 insertions(+), 66 deletions(-) delete mode 100644 lib/renderer/inspector.js create mode 100644 lib/renderer/inspector.ts diff --git a/filenames.gni b/filenames.gni index 27bf760b8eca..b46c40c8e4f5 100644 --- a/filenames.gni +++ b/filenames.gni @@ -66,7 +66,7 @@ filenames = { "lib/renderer/chrome-api.ts", "lib/renderer/content-scripts-injector.ts", "lib/renderer/init.ts", - "lib/renderer/inspector.js", + "lib/renderer/inspector.ts", "lib/renderer/ipc-renderer-internal-utils.ts", "lib/renderer/ipc-renderer-internal.ts", "lib/renderer/remote.ts", diff --git a/lib/renderer/inspector.js b/lib/renderer/inspector.js deleted file mode 100644 index 05eeab8c62b4..000000000000 --- a/lib/renderer/inspector.js +++ /dev/null @@ -1,65 +0,0 @@ -'use strict' - -const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal') -const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils') - -window.onload = function () { - // Use menu API to show context menu. - window.InspectorFrontendHost.showContextMenuAtPoint = createMenu - - // correct for Chromium returning undefined for filesystem - window.Persistence.FileSystemWorkspaceBinding.completeURL = completeURL - - // Use dialog API to override file chooser dialog. - window.UI.createFileSelectorElement = createFileSelectorElement -} - -// Extra / is needed as a result of MacOS requiring absolute paths -function completeURL (project, path) { - project = 'file:///' - return `${project}${path}` -} - -window.confirm = function (message, title) { - return ipcRendererUtils.invokeSync('ELECTRON_INSPECTOR_CONFIRM', message, title) -} - -ipcRendererInternal.on('ELECTRON_INSPECTOR_CONTEXT_MENU_CLICK', function (event, id) { - window.DevToolsAPI.contextMenuItemSelected(id) -}) - -ipcRendererInternal.on('ELECTRON_INSPECTOR_CONTEXT_MENU_CLOSE', function () { - window.DevToolsAPI.contextMenuCleared() -}) - -const useEditMenuItems = function (x, y, items) { - return items.length === 0 && document.elementsFromPoint(x, y).some(function (element) { - return element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA' || element.isContentEditable - }) -} - -const createMenu = function (x, y, items) { - const isEditMenu = useEditMenuItems(x, y, items) - ipcRendererUtils.invoke('ELECTRON_INSPECTOR_CONTEXT_MENU', items, isEditMenu) -} - -const showFileChooserDialog = function (callback) { - ipcRendererUtils.invoke('ELECTRON_INSPECTOR_SELECT_FILE').then(([path, data]) => { - if (path && data) { - callback(dataToHtml5FileObject(path, data)) - } - }) -} - -const dataToHtml5FileObject = function (path, data) { - const blob = new Blob([data]) - blob.name = path - return blob -} - -const createFileSelectorElement = function (callback) { - const fileSelectorElement = document.createElement('span') - fileSelectorElement.style.display = 'none' - fileSelectorElement.click = showFileChooserDialog.bind(this, callback) - return fileSelectorElement -} diff --git a/lib/renderer/inspector.ts b/lib/renderer/inspector.ts new file mode 100644 index 000000000000..f5778e87f66e --- /dev/null +++ b/lib/renderer/inspector.ts @@ -0,0 +1,64 @@ +import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal' +import { invoke, invokeSync } from '@electron/internal/renderer/ipc-renderer-internal-utils' + +window.onload = function () { + // Use menu API to show context menu. + window.InspectorFrontendHost!.showContextMenuAtPoint = createMenu + + // correct for Chromium returning undefined for filesystem + window.Persistence!.FileSystemWorkspaceBinding.completeURL = completeURL + + // Use dialog API to override file chooser dialog. + window.UI!.createFileSelectorElement = createFileSelectorElement +} + +// Extra / is needed as a result of MacOS requiring absolute paths +function completeURL (project: string, path: string) { + project = 'file:///' + return `${project}${path}` +} + +// The DOM implementation expects (message?: string) => boolean +(window.confirm as any) = function (message: string, title: string) { + return invokeSync('ELECTRON_INSPECTOR_CONFIRM', message, title) as boolean +} + +ipcRendererInternal.on('ELECTRON_INSPECTOR_CONTEXT_MENU_CLICK', function (_event: Electron.Event, id: number) { + window.DevToolsAPI!.contextMenuItemSelected(id) +}) + +ipcRendererInternal.on('ELECTRON_INSPECTOR_CONTEXT_MENU_CLOSE', function () { + window.DevToolsAPI!.contextMenuCleared() +}) + +const useEditMenuItems = function (x: number, y: number, items: any[]) { + return items.length === 0 && document.elementsFromPoint(x, y).some(function (element) { + return element.nodeName === 'INPUT' || + element.nodeName === 'TEXTAREA' || + (element as HTMLElement).isContentEditable + }) +} + +const createMenu = function (x: number, y: number, items: any[]) { + const isEditMenu = useEditMenuItems(x, y, items) + invoke('ELECTRON_INSPECTOR_CONTEXT_MENU', items, isEditMenu) +} + +const showFileChooserDialog = function (callback: (blob: File) => void) { + invoke<[ string, any ]>('ELECTRON_INSPECTOR_SELECT_FILE').then(([path, data]) => { + if (path && data) { + callback(dataToHtml5FileObject(path, data)) + } + }) +} + +const dataToHtml5FileObject = function (path: string, data: any) { + return new File([data], path) +} + +const createFileSelectorElement = function (this: any, callback: () => void) { + const fileSelectorElement = document.createElement('span') + fileSelectorElement.style.display = 'none' + fileSelectorElement.click = showFileChooserDialog.bind(this, callback) + return fileSelectorElement +} diff --git a/typings/internal-ambient.d.ts b/typings/internal-ambient.d.ts index 3da02d021bc4..130c181958f6 100644 --- a/typings/internal-ambient.d.ts +++ b/typings/internal-ambient.d.ts @@ -48,4 +48,19 @@ declare module NodeJS { declare interface Window { ELECTRON_DISABLE_SECURITY_WARNINGS?: boolean; ELECTRON_ENABLE_SECURITY_WARNINGS?: boolean; + InspectorFrontendHost?: { + showContextMenuAtPoint: (x: number, y: number, items: any[]) => void + }; + DevToolsAPI?: { + contextMenuItemSelected: (id: number) => void; + contextMenuCleared: () => void + }; + UI?: { + createFileSelectorElement: (callback: () => void) => HTMLSpanElement + }; + Persistence?: { + FileSystemWorkspaceBinding: { + completeURL: (project: string, path: string) => string; + } + } }