diff --git a/lib/browser/chrome-extension.js b/lib/browser/chrome-extension.js index 55ab0051d9a34..f5e850bafbbdd 100644 --- a/lib/browser/chrome-extension.js +++ b/lib/browser/chrome-extension.js @@ -10,6 +10,7 @@ const { Buffer } = require('buffer') const fs = require('fs') const path = require('path') const url = require('url') +const util = require('util') // Mapping between extensionId(hostname) and manifest. const manifestMap = {} // extensionId => manifest @@ -226,6 +227,65 @@ ipcMainUtils.handleSync('CHROME_GET_MESSAGES', function (event, extensionId) { return fs.readFileSync(messagesPath) }) +const validStorageTypes = new Set(['sync', 'local']) + +const getChromeStoragePath = (storageType, extensionId) => { + if (!validStorageTypes.has(storageType)) { + throw new Error(`Invalid storageType: ${storageType}`) + } + + if (!manifestMap[extensionId]) { + throw new Error(`Invalid extensionId: ${extensionId}`) + } + + return path.join(app.getPath('userData'), `/Chrome Storage/${extensionId}-${storageType}.json`) +} + +const mkdirp = util.promisify((dir, callback) => { + fs.mkdir(dir, (error) => { + if (error && error.code === 'ENOENT') { + mkdirp(path.dirname(dir), (error) => { + if (!error) { + mkdirp(dir, callback) + } + }) + } else if (error && error.code === 'EEXIST') { + callback(null) + } else { + callback(error) + } + }) +}) + +const readFile = util.promisify(fs.readFile) +const writeFile = util.promisify(fs.writeFile) + +ipcMainUtils.handle('CHROME_STORAGE_READ', async function (event, storageType, extensionId) { + const filePath = getChromeStoragePath(storageType, extensionId) + + try { + return await readFile(filePath, 'utf8') + } catch (error) { + if (error.code === 'ENOENT') { + return null + } else { + throw error + } + } +}) + +ipcMainUtils.handle('CHROME_STORAGE_WRITE', async function (event, storageType, extensionId, data) { + const filePath = getChromeStoragePath(storageType, extensionId) + + try { + await mkdirp(path.dirname(filePath)) + } catch (error) { + // we just ignore the errors of mkdir or mkdirp + } + + return writeFile(filePath, data, 'utf8') +}) + const isChromeExtension = function (pageURL) { const { protocol } = url.parse(pageURL) return protocol === 'chrome-extension:' diff --git a/lib/renderer/extensions/storage.js b/lib/renderer/extensions/storage.js index d30888135ff83..ffd82a641da76 100644 --- a/lib/renderer/extensions/storage.js +++ b/lib/renderer/extensions/storage.js @@ -1,71 +1,28 @@ 'use strict' -const { getRemote, potentiallyRemoteRequire } = require('@electron/internal/renderer/remote') -const fs = potentiallyRemoteRequire('fs') -const path = potentiallyRemoteRequire('path') -const app = getRemote('app') +const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils') -const getChromeStoragePath = (storageType, extensionId) => { - return path.join( - app.getPath('userData'), `/Chrome Storage/${extensionId}-${storageType}.json`) -} - -const mkdirp = (dir, callback) => { - fs.mkdir(dir, (error) => { - if (error && error.code === 'ENOENT') { - mkdirp(path.dirname(dir), (error) => { - if (!error) { - mkdirp(dir, callback) - } - }) - } else if (error && error.code === 'EEXIST') { - callback(null) - } else { - callback(error) - } - }) -} - -const readChromeStorageFile = (storageType, extensionId, cb) => { - const filePath = getChromeStoragePath(storageType, extensionId) - fs.readFile(filePath, 'utf8', (err, data) => { - if (err && err.code === 'ENOENT') { - return cb(null, null) - } - cb(err, data) - }) -} +const getStorage = (storageType, extensionId, callback) => { + if (typeof callback !== 'function') throw new TypeError('No callback provided') -const writeChromeStorageFile = (storageType, extensionId, data, cb) => { - const filePath = getChromeStoragePath(storageType, extensionId) - - mkdirp(path.dirname(filePath), err => { - if (err) { /* we just ignore the errors of mkdir or mkdirp */ } - fs.writeFile(filePath, data, cb) - }) -} - -const getStorage = (storageType, extensionId, cb) => { - readChromeStorageFile(storageType, extensionId, (err, data) => { - if (err) throw err - if (!cb) throw new TypeError('No callback provided') - - if (data !== null) { - cb(JSON.parse(data)) - } else { - // Disabled due to false positive in StandardJS - // eslint-disable-next-line standard/no-callback-literal - cb({}) - } - }) + ipcRendererUtils.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, extensionId, storage, cb) => { +const setStorage = (storageType, extensionId, storage, callback) => { const json = JSON.stringify(storage) - writeChromeStorageFile(storageType, extensionId, json, err => { - if (err) throw err - if (cb) cb() - }) + ipcRendererUtils.invoke('CHROME_STORAGE_WRITE', storageType, extensionId, json) + .then(() => { + if (callback) callback() + }) } const getStorageManager = (storageType, extensionId) => { diff --git a/lib/renderer/remote.js b/lib/renderer/remote.js index 0ef98ca060e1a..579505a526f46 100644 --- a/lib/renderer/remote.js +++ b/lib/renderer/remote.js @@ -8,18 +8,3 @@ exports.getRemote = function (name) { } return remote[name] } - -exports.remoteRequire = function (name) { - if (!remote) { - throw new Error(`${name} requires remote, which is not enabled`) - } - return remote.require(name) -} - -exports.potentiallyRemoteRequire = function (name) { - if (process.sandboxed) { - return exports.remoteRequire(name) - } else { - return require(name) - } -}