Remember loaded extensions.
authorCheng Zhao <zcbenz@gmail.com>
Thu, 28 Aug 2014 06:58:15 +0000 (14:58 +0800)
committerCheng Zhao <zcbenz@gmail.com>
Thu, 28 Aug 2014 07:58:36 +0000 (15:58 +0800)
atom/browser/api/lib/browser-window.coffee
atom/browser/lib/chrome-extension.coffee
atom/browser/lib/init.coffee

index d76bfbf..8af84aa 100644 (file)
@@ -36,7 +36,7 @@ BrowserWindow::openDevTools = ->
   @devToolsWebContents.once 'destroyed', => @devToolsWebContents = null
 
   # Emit devtools events.
-  @emit 'dev-tools-opened'
+  @devToolsWebContents.once 'did-finish-load', => @emit 'dev-tools-opened'
   @devToolsWebContents.once 'destroyed', => @emit 'dev-tools-closed'
 
 BrowserWindow::toggleDevTools = ->
index 6ca1bc1..98b430f 100644 (file)
@@ -15,29 +15,74 @@ getHostForPath = (path) ->
 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
+  extensionInfoMap[manifest.name]
+
+# Load persistented extensions.
+loadedExtensionsPath = path.join app.getDataPath(), '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
+
+# Persistent loaded extensions.
+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 = require 'protocol'
   BrowserWindow = require 'browser-window'
 
+  # The chrome-extension: can map a extension URL request to real file path.
   protocol.registerProtocol 'chrome-extension', (request) ->
     parsed = url.parse request.url
     return unless parsed.hostname and parsed.path?
-
     return unless /extension-\d+/.test parsed.hostname
 
     directory = getPathForHost parsed.hostname
+    return unless directory?
     return new protocol.RequestFileJob(path.join(directory, parsed.path))
 
-  BrowserWindow::loadDevToolsExtension = (srcDirectory) ->
-    manifest = JSON.parse fs.readFileSync(path.join(srcDirectory, 'manifest.json'))
+  BrowserWindow::_loadDevToolsExtensions = (extensionInfoArray) ->
+    @devToolsWebContents?.executeJavaScript "WebInspector.addExtensions(#{JSON.stringify(extensionInfoArray)});"
 
-    # 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
+  BrowserWindow.addDevToolsExtension = (srcDirectory) ->
+    extensionInfo = getExtensionInfoFromPath srcDirectory
+    window._loadDevToolsExtensions [extensionInfo] for window in BrowserWindow.getAllWindows()
+    extensionInfo.name
+
+  BrowserWindow.removeDevToolsExtension = (name) ->
+    delete extensionInfoMap[name]
 
-    extensionInfo = startPage: page, name: manifest.name
-    @devToolsWebContents?.executeJavaScript "WebInspector.addExtensions([#{JSON.stringify(extensionInfo)}]);"
+  # Load persistented extensions when devtools is opened.
+  init = BrowserWindow::_init
+  BrowserWindow::_init = ->
+    init.call this
+    @on 'dev-tools-opened', ->
+      @_loadDevToolsExtensions Object.keys(extensionInfoMap).map (key) -> extensionInfoMap[key]
index 3c5b059..e164b88 100644 (file)
@@ -52,9 +52,6 @@ setImmediate ->
       detail: message
       buttons: ['OK']
 
-  # Load the chrome extension support.
-  require './chrome-extension.js'
-
   # Load the RPC server.
   require './rpc-server.js'
 
@@ -80,5 +77,8 @@ setImmediate ->
   else if packageJson.name?
     app.setName packageJson.name
 
+  # Load the chrome extension support.
+  require './chrome-extension.js'
+
   # Finally load app's main.js and transfer control to C++.
   module._load path.join(packagePath, packageJson.main), module, true