]> git.gir.st - VimFx.git/blob - extension/lib/message-manager.coffee
Fix missing hint markers when re-entering Hints mode quickly
[VimFx.git] / extension / lib / message-manager.coffee
1 ###
2 # Copyright Simon Lydell 2015, 2016.
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, prefix) -> "#{ADDON_PATH}/#{BUILD_TIME}/#{prefix}#{name}"
26
27 defaultMessageManager =
28 if IS_FRAME_SCRIPT
29 FRAME_SCRIPT_ENVIRONMENT
30 else
31 Cc['@mozilla.org/globalmessagemanager;1']
32 .getService(Ci.nsIMessageListenerManager)
33
34 defaultOptions = {
35 messageManager: defaultMessageManager
36 onShutdown: module.onShutdown
37 prefix: ''
38 }
39
40 load = (uri, options = {}) ->
41 args = Object.assign({}, defaultOptions, options)
42 # Randomize URI to work around bug 1051238.
43 args.messageManager.loadFrameScript("#{uri}?#{Math.random()}", true)
44 args.onShutdown(->
45 args.messageManager.removeDelayedFrameScript(uri)
46 )
47
48 listen = (name, listener, options = {}) ->
49 args = Object.assign({}, defaultOptions, options)
50 namespacedName = namespace(name, args.prefix)
51 fn = (data) -> invokeListener?(listener, args, data)
52 args.messageManager.addMessageListener(namespacedName, fn)
53 args.onShutdown(->
54 args.messageManager.removeMessageListener(namespacedName, fn)
55 )
56
57 listenOnce = (name, listener, options = {}) ->
58 args = Object.assign({}, defaultOptions, options)
59 namespacedName = namespace(name, args.prefix)
60 fn = (data) ->
61 args.messageManager.removeMessageListener(namespacedName, fn)
62 return invokeListener?(listener, args, data)
63 args.messageManager.addMessageListener(namespacedName, fn)
64
65 callbackCounter = 0
66 send = (name, data = null, callback = null, options = {}) ->
67 args = Object.assign({}, defaultOptions, options)
68
69 callbackName = null
70 if callback
71 callbackName = "#{name}:callback:#{callbackCounter}"
72 callbackCounter += 1
73 listenOnce(callbackName, callback, args)
74
75 namespacedName = namespace(name, args.prefix)
76 wrappedData = {data, callbackName}
77
78 # Message Manager methods may be missing on shutdown.
79 if args.messageManager.broadcastAsyncMessage
80 args.messageManager.broadcastAsyncMessage?(namespacedName, wrappedData)
81 else
82 args.messageManager.sendAsyncMessage?(namespacedName, wrappedData)
83
84 # Unwraps the data from `send` and invokes `listener` with it.
85 invokeListener = (listener, args, {data: {data, callbackName} = {}, target}) ->
86 callback =
87 if callbackName
88 (data = null) ->
89 send(callbackName, data, null, Object.assign({}, args, {
90 messageManager: target.messageManager ? target
91 }))
92 else
93 null
94 return listener(data, callback, target)
95
96 # Note: This is a synchronous call. It should only be used when absolutely
97 # needed, such as in an event listener which needs to suppress the event based
98 # on the return value.
99 get = (name, data) ->
100 namespacedName = namespace(name, defaultOptions.prefix)
101 [result] = defaultMessageManager.sendSyncMessage(namespacedName, {data})
102 return result
103
104 module.exports = {
105 load
106 listen
107 listenOnce
108 send
109 get
110 }
Imprint / Impressum