Mailspring/internal_packages/notification-mailto/lib/launch-services.coffee

127 lines
4.4 KiB
CoffeeScript

exec = require('child_process').exec
fs = require('fs')
bundleIdentifier = 'com.inbox.edgehill'
launchServicesPlistPath = "#{process.env.HOME}/Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist"
module.exports =
class LaunchServices
constructor: ->
@secure = false
getPlatform: ->
process.platform
available: ->
@getPlatform() is 'darwin'
isYosemiteOrGreater: (callback) ->
fs.exists launchServicesPlistPath, (exists) =>
callback(exists)
readDefaults: (callback) ->
return callback(@_defaults) if @_defaults
@isYosemiteOrGreater (result) =>
if result
@_readDefaultsSecure(callback)
else
@_readDefaultsPreYosemite(callback)
_readDefaultsSecure: (callback) ->
@secure = true
tmpPath = "#{launchServicesPlistPath}.#{Math.random()}"
exec "plutil -convert json \"#{launchServicesPlistPath}\" -o \"#{tmpPath}\"", (err, stdout, stderr) =>
return callback(err) if callback and err
fs.readFile tmpPath, (err, data) =>
return callback(err) if callback and err
try
data = JSON.parse(data)
callback(data['LSHandlers'], data)
fs.unlink(tmpPath)
catch e
callback(e) if callback and err
_readDefaultsPreYosemite: (callback) ->
@secure = false
exec "defaults read com.apple.launchservices LSHandlers", (err, stdout, stderr) =>
return callback(err) if callback and err
# Convert the defaults from Apple's plist format into
# JSON. It's nearly the same, just has different delimiters
plist = stdout.toString()
regex = /([a-zA-Z]*) = (.*);/
while (match = regex.exec(plist)) != null
[text, key, val] = match
val = "\"#{val}\"" unless val[0] is '"'
plist = plist.replace(text, "\"#{key}\":#{val},")
plist = plist.replace(/\(/g, '[')
plist = plist.replace(/\)/g, ']')
plist = plist.replace(/[\s]*,[\s]*\n[\s]*}/g, '\n}')
json = []
if plist.length > 0
json = JSON.parse(plist)
callback(json)
writeDefaults: (defaults, callback) ->
@_defaults = defaults
if @secure
@_writeDefaultsSecure(defaults, callback)
else
@_writeDefaultsPreYosemite(defaults, callback)
_writeDefaultsSecure: (newDefaults, callback) ->
@_readDefaultsSecure (currentDefaults, entireFileJSON) =>
entireFileJSON['LSHandlers'] = newDefaults
data = JSON.stringify(entireFileJSON)
tmpPath = "#{launchServicesPlistPath}.json"
fs.writeFile tmpPath, data, (err) =>
return callback(err) if callback and err
exec "plutil -convert binary1 \"#{tmpPath}\" -o \"#{launchServicesPlistPath}\"", =>
fs.unlink(tmpPath)
@triggerSystemReload(callback)
_writeDefaultsPreYosemite: (defaults, callback) ->
# Convert the defaults JSON back into Apple's json-like
# format. (I think it predates JSON?)
json = JSON.stringify(defaults)
plist = json.replace(/\[/g, '(')
plist = plist.replace(/\]/g, ')')
regex = /\"([a-zA-Z^"]*)\":\"([^"]*)\",?/
while (match = regex.exec(plist)) != null
[text, key, val] = match
plist = plist.replace(text, "#{key} = \"#{val}\";")
# Write the new defaults back to the system
exec "defaults write ~/Library/Preferences/com.apple.LaunchServices.plist LSHandlers '#{plist}'", (err, stdout, stderr) =>
return callback(err) if callback and err
@triggerSystemReload(callback)
triggerSystemReload: (callback) ->
exec "/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user", (err, stdout, stderr) ->
callback(err) if callback
isRegisteredForURLScheme: (scheme, callback) ->
throw new Error "isRegisteredForURLScheme is async, provide a callback" unless callback
@readDefaults (defaults) ->
for def in defaults
if def.LSHandlerURLScheme is scheme
return callback(def.LSHandlerRoleAll is bundleIdentifier)
callback(false)
registerForURLScheme: (scheme, callback) ->
@readDefaults (defaults) =>
# Remove anything already registered for the scheme
for ii in [defaults.length-1..0] by -1
if defaults[ii].LSHandlerURLScheme is scheme
defaults.splice(ii, 1)
# Add our scheme default
defaults.push
LSHandlerURLScheme: scheme
LSHandlerRoleAll: bundleIdentifier
@writeDefaults(defaults, callback)