From 860e14c0da9d40689fba83de931ebe8f340443a3 Mon Sep 17 00:00:00 2001 From: Samuel Maddock Date: Tue, 8 Sep 2020 07:11:38 -0400 Subject: [PATCH] chore(extensions): remove old renderer code (#25347) --- lib/renderer/content-scripts-injector.ts | 119 ---------------------- lib/renderer/extensions/event.ts | 20 ---- lib/renderer/extensions/i18n.ts | 60 ----------- lib/renderer/extensions/storage.ts | 86 ---------------- lib/renderer/extensions/web-navigation.ts | 19 ---- shell/common/world_ids.h | 3 +- 6 files changed, 1 insertion(+), 306 deletions(-) delete mode 100644 lib/renderer/content-scripts-injector.ts delete mode 100644 lib/renderer/extensions/event.ts delete mode 100644 lib/renderer/extensions/i18n.ts delete mode 100644 lib/renderer/extensions/storage.ts delete mode 100644 lib/renderer/extensions/web-navigation.ts diff --git a/lib/renderer/content-scripts-injector.ts b/lib/renderer/content-scripts-injector.ts deleted file mode 100644 index 0d990260dd99..000000000000 --- a/lib/renderer/content-scripts-injector.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { webFrame } from 'electron'; - -import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils'; - -const v8Util = process._linkedBinding('electron_common_v8_util'); - -const IsolatedWorldIDs = { - /** - * Start of extension isolated world IDs, as defined in - * electron_render_frame_observer.h - */ - ISOLATED_WORLD_EXTENSIONS: 1 << 20 -}; - -let isolatedWorldIds = IsolatedWorldIDs.ISOLATED_WORLD_EXTENSIONS; -const extensionWorldId: {[key: string]: number | undefined} = {}; - -// https://cs.chromium.org/chromium/src/extensions/renderer/script_injection.cc?type=cs&sq=package:chromium&g=0&l=52 -const getIsolatedWorldIdForInstance = () => { - // TODO(samuelmaddock): allocate and cleanup IDs - return isolatedWorldIds++; -}; - -const escapePattern = function (pattern: string) { - return pattern.replace(/[\\^$+?.()|[\]{}]/g, '\\$&'); -}; - -// Check whether pattern matches. -// https://developer.chrome.com/extensions/match_patterns -const matchesPattern = function (pattern: string) { - if (pattern === '') return true; - const regexp = new RegExp(`^${pattern.split('*').map(escapePattern).join('.*')}$`); - const url = `${location.protocol}//${location.host}${location.pathname}`; - return url.match(regexp); -}; - -// Run the code with chrome API integrated. -const runContentScript = function (this: any, extensionId: string, url: string, code: string) { - // Assign unique world ID to each extension - const worldId = extensionWorldId[extensionId] || - (extensionWorldId[extensionId] = getIsolatedWorldIdForInstance()); - - // store extension ID for content script to read in isolated world - v8Util.setHiddenValue(global, `extension-${worldId}`, extensionId); - - webFrame.setIsolatedWorldInfo(worldId, { - name: `${extensionId} [${worldId}]` - // TODO(samuelmaddock): read `content_security_policy` from extension manifest - // csp: manifest.content_security_policy, - }); - - const sources = [{ code, url }]; - return webFrame.executeJavaScriptInIsolatedWorld(worldId, sources); -}; - -const runAllContentScript = function (scripts: Array, extensionId: string) { - for (const { url, code } of scripts) { - runContentScript.call(window, extensionId, url, code); - } -}; - -const runStylesheet = function (this: any, url: string, code: string) { - webFrame.insertCSS(code); -}; - -const runAllStylesheet = function (css: Array) { - for (const { url, code } of css) { - runStylesheet.call(window, url, code); - } -}; - -// Run injected scripts. -// https://developer.chrome.com/extensions/content_scripts -const injectContentScript = function (extensionId: string, script: Electron.ContentScript) { - if (!process.isMainFrame && !script.allFrames) return; - if (!script.matches.some(matchesPattern)) return; - - if (script.js) { - const fire = runAllContentScript.bind(window, script.js, extensionId); - if (script.runAt === 'document_start') { - process.once('document-start', fire); - } else if (script.runAt === 'document_end') { - process.once('document-end', fire); - } else { - document.addEventListener('DOMContentLoaded', fire); - } - } - - if (script.css) { - const fire = runAllStylesheet.bind(window, script.css); - if (script.runAt === 'document_start') { - process.once('document-start', fire); - } else if (script.runAt === 'document_end') { - process.once('document-end', fire); - } else { - document.addEventListener('DOMContentLoaded', fire); - } - } -}; - -// Handle the request of chrome.tabs.executeJavaScript. -ipcRendererUtils.handle('CHROME_TABS_EXECUTE_SCRIPT', function ( - event: Electron.Event, - extensionId: string, - url: string, - code: string -) { - return runContentScript.call(window, extensionId, url, code); -}); - -module.exports = (entries: Electron.ContentScriptEntry[]) => { - for (const entry of entries) { - if (entry.contentScripts) { - for (const script of entry.contentScripts) { - injectContentScript(entry.extensionId, script); - } - } - } -}; diff --git a/lib/renderer/extensions/event.ts b/lib/renderer/extensions/event.ts deleted file mode 100644 index d88800c4f93c..000000000000 --- a/lib/renderer/extensions/event.ts +++ /dev/null @@ -1,20 +0,0 @@ -export class Event { - private listeners: Function[] = [] - - addListener (callback: Function) { - this.listeners.push(callback); - } - - removeListener (callback: Function) { - const index = this.listeners.indexOf(callback); - if (index !== -1) { - this.listeners.splice(index, 1); - } - } - - emit (...args: any[]) { - for (const listener of this.listeners) { - listener(...args); - } - } -} diff --git a/lib/renderer/extensions/i18n.ts b/lib/renderer/extensions/i18n.ts deleted file mode 100644 index b979a5a06fa0..000000000000 --- a/lib/renderer/extensions/i18n.ts +++ /dev/null @@ -1,60 +0,0 @@ -// Implementation of chrome.i18n.getMessage -// https://developer.chrome.com/extensions/i18n#method-getMessage -// -// Does not implement predefined messages: -// https://developer.chrome.com/extensions/i18n#overview-predefined - -import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils'; - -interface Placeholder { - content: string; - example?: string; -} - -const getMessages = (extensionId: number) => { - try { - const data = ipcRendererUtils.invokeSync('CHROME_GET_MESSAGES', extensionId); - return JSON.parse(data) || {}; - } catch { - return {}; - } -}; - -const replaceNumberedSubstitutions = (message: string, substitutions: string[]) => { - return message.replace(/\$(\d+)/, (_, number) => { - const index = parseInt(number, 10) - 1; - return substitutions[index] || ''; - }); -}; - -const replacePlaceholders = (message: string, placeholders: Record, substitutions: string[] | string) => { - if (typeof substitutions === 'string') substitutions = [substitutions]; - if (!Array.isArray(substitutions)) substitutions = []; - - if (placeholders) { - Object.keys(placeholders).forEach((name: string) => { - let { content } = placeholders[name]; - const substitutionsArray = Array.isArray(substitutions) ? substitutions : []; - content = replaceNumberedSubstitutions(content, substitutionsArray); - message = message.replace(new RegExp(`\\$${name}\\$`, 'gi'), content); - }); - } - - return replaceNumberedSubstitutions(message, substitutions); -}; - -const getMessage = (extensionId: number, messageName: string, substitutions: string[]) => { - const messages = getMessages(extensionId); - if (Object.prototype.hasOwnProperty.call(messages, messageName)) { - const { message, placeholders } = messages[messageName]; - return replacePlaceholders(message, placeholders, substitutions); - } -}; - -exports.setup = (extensionId: number) => { - return { - getMessage (messageName: string, substitutions: string[]) { - return getMessage(extensionId, messageName, substitutions); - } - }; -}; diff --git a/lib/renderer/extensions/storage.ts b/lib/renderer/extensions/storage.ts deleted file mode 100644 index 6dbafb6e5bd8..000000000000 --- a/lib/renderer/extensions/storage.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal'; - -const getStorage = (storageType: string, extensionId: number, callback: Function) => { - if (typeof callback !== 'function') throw new TypeError('No callback provided'); - - ipcRendererInternal.invoke('CHROME_STORAGE_READ', storageType, extensionId) - .then(data => { - if (data !== null) { - callback(JSON.parse(data)); - } else { - // Disabled due to false positive in StandardJS - // eslint-disable-next-line standard/no-callback-literal - callback({}); - } - }); -}; - -const setStorage = (storageType: string, extensionId: number, storage: Record, callback: Function) => { - const json = JSON.stringify(storage); - ipcRendererInternal.invoke('CHROME_STORAGE_WRITE', storageType, extensionId, json) - .then(() => { - if (callback) callback(); - }); -}; - -const getStorageManager = (storageType: string, extensionId: number) => { - return { - get (keys: string[], callback: Function) { - getStorage(storageType, extensionId, (storage: Record) => { - if (keys == null) return callback(storage); - - let defaults: Record = {}; - switch (typeof keys) { - case 'string': - keys = [keys]; - break; - case 'object': - if (!Array.isArray(keys)) { - defaults = keys; - keys = Object.keys(keys); - } - break; - } - - // Disabled due to false positive in StandardJS - // eslint-disable-next-line standard/no-callback-literal - if (keys.length === 0) return callback({}); - - const items: Record = {}; - keys.forEach((key: string) => { - let value = storage[key]; - if (value == null) value = defaults[key]; - items[key] = value; - }); - callback(items); - }); - }, - - set (items: Record, callback: Function) { - getStorage(storageType, extensionId, (storage: Record) => { - Object.keys(items).forEach(name => { storage[name] = items[name]; }); - setStorage(storageType, extensionId, storage, callback); - }); - }, - - remove (keys: string[], callback: Function) { - getStorage(storageType, extensionId, (storage: Record) => { - if (!Array.isArray(keys)) keys = [keys]; - keys.forEach((key: string) => { - delete storage[key]; - }); - - setStorage(storageType, extensionId, storage, callback); - }); - }, - - clear (callback: Function) { - setStorage(storageType, extensionId, {}, callback); - } - }; -}; - -export const setup = (extensionId: number) => ({ - sync: getStorageManager('sync', extensionId), - local: getStorageManager('local', extensionId) -}); diff --git a/lib/renderer/extensions/web-navigation.ts b/lib/renderer/extensions/web-navigation.ts deleted file mode 100644 index 768eb342804b..000000000000 --- a/lib/renderer/extensions/web-navigation.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Event } from '@electron/internal/renderer/extensions/event'; -import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal'; - -class WebNavigation { - private onBeforeNavigate = new Event() - private onCompleted = new Event() - - constructor () { - ipcRendererInternal.on('CHROME_WEBNAVIGATION_ONBEFORENAVIGATE', (event: Electron.IpcRendererEvent, details: any) => { - this.onBeforeNavigate.emit(details); - }); - - ipcRendererInternal.on('CHROME_WEBNAVIGATION_ONCOMPLETED', (event: Electron.IpcRendererEvent, details: any) => { - this.onCompleted.emit(details); - }); - } -} - -export const setup = () => new WebNavigation(); diff --git a/shell/common/world_ids.h b/shell/common/world_ids.h index bed0a67c4fda..714e4609277d 100644 --- a/shell/common/world_ids.h +++ b/shell/common/world_ids.h @@ -16,8 +16,7 @@ enum WorldIDs : int32_t { // IDs created internally by Chrome. ISOLATED_WORLD_ID = 999, - // Numbers for isolated worlds for extensions are set in - // lib/renderer/content-script-injector.ts, and are greater than or equal to + // Numbers for isolated worlds for extensions are greater than or equal to // this number, up to ISOLATED_WORLD_ID_EXTENSIONS_END. ISOLATED_WORLD_ID_EXTENSIONS = 1 << 20,