]> git.gir.st - VimFx.git/blob - extension/lib/message-manager.coffee
Use `vim.markPageInteraction()` instead of direct mutation
[VimFx.git] / extension / lib / message-manager.coffee
1 ###
2 # Copyright Simon Lydell 2015, 2016, 2017.
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 randomizedUri = "#{uri}?#{Math.random()}"
44 args.messageManager.loadFrameScript(randomizedUri, true)
45 args.onShutdown(->
46 args.messageManager.removeDelayedFrameScript(randomizedUri)
47 )
48
49 listen = (name, listener, options = {}) ->
50 args = Object.assign({}, defaultOptions, options)
51 namespacedName = namespace(name, args.prefix)
52 fn = (data) -> invokeListener?(listener, args, data)
53 args.messageManager.addMessageListener(namespacedName, fn)
54 args.onShutdown(->
55 args.messageManager.removeMessageListener(namespacedName, fn)
56 )
57
58 listenOnce = (name, listener, options = {}) ->
59 args = Object.assign({}, defaultOptions, options)
60 namespacedName = namespace(name, args.prefix)
61 fn = (data) ->
62 args.messageManager.removeMessageListener(namespacedName, fn)
63 return invokeListener?(listener, args, data)
64 args.messageManager.addMessageListener(namespacedName, fn)
65
66 callbackCounter = 0
67 send = (name, data = null, callback = null, options = {}) ->
68 args = Object.assign({}, defaultOptions, options)
69
70 callbackName = null
71 if callback
72 callbackName = "#{name}:callback:#{callbackCounter}"
73 callbackCounter += 1
74 listenOnce(callbackName, callback, args)
75
76 namespacedName = namespace(name, args.prefix)
77 wrappedData = {data, callbackName}
78
79 # Message Manager methods may be missing on shutdown.
80 if args.messageManager.broadcastAsyncMessage
81 args.messageManager.broadcastAsyncMessage?(namespacedName, wrappedData)
82 else
83 args.messageManager.sendAsyncMessage?(namespacedName, wrappedData)
84
85 # Unwraps the data from `send` and invokes `listener` with it.
86 invokeListener = (listener, args, {data: {data, callbackName} = {}, target}) ->
87 callback =
88 if callbackName
89 (data = null) ->
90 send(callbackName, data, null, Object.assign({}, args, {
91 messageManager: target.messageManager ? target
92 }))
93 else
94 null
95 return listener(data, callback, target)
96
97 # Note: This is a synchronous call. It should only be used when absolutely
98 # needed, such as in an event listener which needs to suppress the event based
99 # on the return value.
100 get = (name, data) ->
101 namespacedName = namespace(name, defaultOptions.prefix)
102 [result] = defaultMessageManager.sendSyncMessage(namespacedName, {data})
103 return result
104
105 module.exports = {
106 load
107 listen
108 listenOnce
109 send
110 get
111 }
Imprint / Impressum