96 lines
3.3 KiB
CoffeeScript
96 lines
3.3 KiB
CoffeeScript
electron = require 'electron'
|
|
fs = require 'fs'
|
|
path = require 'path'
|
|
url = require 'url'
|
|
|
|
# Mapping between hostname and file path.
|
|
hostPathMap = {}
|
|
hostPathMapNextKey = 0
|
|
|
|
getHostForPath = (path) ->
|
|
key = "extension-#{++hostPathMapNextKey}"
|
|
hostPathMap[key] = path
|
|
key
|
|
|
|
getPathForHost = (host) ->
|
|
hostPathMap[host]
|
|
|
|
# Cache extensionInfo.
|
|
extensionInfoMap = {}
|
|
|
|
getExtensionInfoFromPath = (srcDirectory) ->
|
|
manifest = JSON.parse fs.readFileSync(path.join(srcDirectory, 'manifest.json'))
|
|
unless extensionInfoMap[manifest.name]?
|
|
# We can not use 'file://' directly because all resources in the extension
|
|
# will be treated as relative to the root in Chrome.
|
|
page = url.format
|
|
protocol: 'chrome-extension'
|
|
slashes: true
|
|
hostname: getHostForPath srcDirectory
|
|
pathname: manifest.devtools_page
|
|
extensionInfoMap[manifest.name] =
|
|
startPage: page
|
|
name: manifest.name
|
|
srcDirectory: srcDirectory
|
|
exposeExperimentalAPIs: true
|
|
extensionInfoMap[manifest.name]
|
|
|
|
# The loaded extensions cache and its persistent path.
|
|
loadedExtensions = null
|
|
loadedExtensionsPath = null
|
|
|
|
# Persistent loaded extensions.
|
|
{app} = electron
|
|
app.on 'will-quit', ->
|
|
try
|
|
loadedExtensions = Object.keys(extensionInfoMap).map (key) -> extensionInfoMap[key].srcDirectory
|
|
try
|
|
fs.mkdirSync path.dirname(loadedExtensionsPath)
|
|
catch e
|
|
fs.writeFileSync loadedExtensionsPath, JSON.stringify(loadedExtensions)
|
|
catch e
|
|
|
|
# We can not use protocol or BrowserWindow until app is ready.
|
|
app.once 'ready', ->
|
|
{protocol, BrowserWindow} = electron
|
|
|
|
# Load persistented extensions.
|
|
loadedExtensionsPath = path.join app.getPath('userData'), 'DevTools Extensions'
|
|
|
|
try
|
|
loadedExtensions = JSON.parse fs.readFileSync(loadedExtensionsPath)
|
|
loadedExtensions = [] unless Array.isArray loadedExtensions
|
|
# Preheat the extensionInfo cache.
|
|
getExtensionInfoFromPath srcDirectory for srcDirectory in loadedExtensions
|
|
catch e
|
|
|
|
# The chrome-extension: can map a extension URL request to real file path.
|
|
chromeExtensionHandler = (request, callback) ->
|
|
parsed = url.parse request.url
|
|
return callback() unless parsed.hostname and parsed.path?
|
|
return callback() unless /extension-\d+/.test parsed.hostname
|
|
|
|
directory = getPathForHost parsed.hostname
|
|
return callback() unless directory?
|
|
callback path.join(directory, parsed.path)
|
|
protocol.registerFileProtocol 'chrome-extension', chromeExtensionHandler, (error) ->
|
|
console.error 'Unable to register chrome-extension protocol' if error
|
|
|
|
BrowserWindow::_loadDevToolsExtensions = (extensionInfoArray) ->
|
|
@devToolsWebContents?.executeJavaScript "DevToolsAPI.addExtensions(#{JSON.stringify(extensionInfoArray)});"
|
|
|
|
BrowserWindow.addDevToolsExtension = (srcDirectory) ->
|
|
extensionInfo = getExtensionInfoFromPath srcDirectory
|
|
if extensionInfo
|
|
window._loadDevToolsExtensions [extensionInfo] for window in BrowserWindow.getAllWindows()
|
|
extensionInfo.name
|
|
|
|
BrowserWindow.removeDevToolsExtension = (name) ->
|
|
delete extensionInfoMap[name]
|
|
|
|
# Load persistented extensions when devtools is opened.
|
|
init = BrowserWindow::_init
|
|
BrowserWindow::_init = ->
|
|
init.call this
|
|
@on 'devtools-opened', ->
|
|
@_loadDevToolsExtensions Object.keys(extensionInfoMap).map (key) -> extensionInfoMap[key]
|