]> git.gir.st - VimFx.git/blob - extension/lib/message-manager.coffee
Enable the `braces_spacing` coffeelint rule
[VimFx.git] / extension / lib / message-manager.coffee
1 ###
2 # Copyright Simon Lydell 2015.
3 #
4 # This file is part of VimFx.
5 #
6 # VimFx is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # VimFx is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with VimFx. If not, see <http://www.gnu.org/licenses/>.
18 ###
19
20 # This file provides an API a bit more easy to use than the very low-level
21 # Firefox message manager APIs. “Message Management” is all about sending
22 # messages between the main process and frame scripts. There is one frame script
23 # per tab, and only them can access web page content.
24
25 namespace = (name) -> "VimFx:#{name}"
26
27 defaultMM =
28 if IS_FRAME_SCRIPT
29 FRAME_SCRIPT_ENVIRONMENT
30 else
31 Cc['@mozilla.org/globalmessagemanager;1']
32 .getService(Ci.nsIMessageListenerManager)
33
34 load = (name, messageManager = defaultMM) ->
35 # Randomize URI to work around bug 1051238.
36 url = "chrome://vimfx/content/#{name}.js?#{Math.random()}"
37 messageManager.loadFrameScript(url, true)
38 module.onShutdown(->
39 messageManager.removeDelayedFrameScript(url)
40 )
41
42 listen = (name, listener, messageManager = defaultMM) ->
43 namespacedName = namespace(name)
44 fn = invokeListener.bind(null, listener)
45 messageManager.addMessageListener(namespacedName, fn)
46 module.onShutdown(->
47 messageManager.removeMessageListener(namespacedName, fn)
48 )
49
50 listenOnce = (name, listener, messageManager = defaultMM) ->
51 namespacedName = namespace(name)
52 fn = (data) ->
53 messageManager.removeMessageListener(namespacedName, fn)
54 invokeListener(listener, data)
55 messageManager.addMessageListener(namespacedName, fn)
56
57 callbackCounter = 0
58 send = (name, data = null, messageManager = defaultMM, callback = null) ->
59 if typeof messageManager == 'function'
60 callback = messageManager
61 messageManager = defaultMM
62
63 callbackName = null
64 if callback
65 callbackName = "#{name}:callback:#{callbackCounter}"
66 callbackCounter++
67 listenOnce(callbackName, callback, messageManager)
68
69 namespacedName = namespace(name)
70 wrappedData = {data, callback: callbackName}
71 if messageManager.broadcastAsyncMessage
72 messageManager.broadcastAsyncMessage(namespacedName, wrappedData)
73 else
74 messageManager.sendAsyncMessage(namespacedName, wrappedData)
75
76 # Unwraps the data from `send` and invokes `listener` with it.
77 invokeListener = (listener, {name, data: {data, callback} = {}, target}) ->
78 listener(data, {name, target, callback})
79
80 # Note: This is a synchronous call. It should only be used when absolutely
81 # needed, such as in an event listener which needs to suppress the event based
82 # on the return value.
83 get = (name, data) ->
84 [result] = defaultMM.sendSyncMessage(namespace(name), {data})
85 return result
86
87 module.exports = {
88 load
89 listen
90 listenOnce
91 send
92 get
93 }
Imprint / Impressum