1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/base/public/nsIMessageManager.idl Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,450 @@ 1.4 +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsISupports.idl" 1.10 + 1.11 +interface nsIDOMWindow; 1.12 +interface nsIDocShell; 1.13 +interface nsIContent; 1.14 +interface nsIPrincipal; 1.15 + 1.16 +/** 1.17 + * Message managers provide a way for chrome-privileged JS code to 1.18 + * communicate with each other, even across process boundaries. 1.19 + * 1.20 + * Message managers are separated into "parent side" and "child side". 1.21 + * These don't always correspond to process boundaries, but can. For 1.22 + * each child-side message manager, there is always exactly one 1.23 + * corresponding parent-side message manager that it sends messages 1.24 + * to. However, for each parent-side message manager, there may be 1.25 + * either one or many child-side managers it can message. 1.26 + * 1.27 + * Message managers that always have exactly one "other side" are of 1.28 + * type nsIMessageSender. Parent-side message managers that have many 1.29 + * "other sides" are of type nsIMessageBroadcaster. 1.30 + * 1.31 + * Child-side message managers can send synchronous messages to their 1.32 + * parent side, but not the other way around. 1.33 + * 1.34 + * There are two realms of message manager hierarchies. One realm 1.35 + * approximately corresponds to DOM elements, the other corresponds to 1.36 + * process boundaries. 1.37 + * 1.38 + * Message managers corresponding to DOM elements 1.39 + * ============================================== 1.40 + * 1.41 + * In this realm of message managers, there are 1.42 + * - "frame message managers" which correspond to frame elements 1.43 + * - "window message managers" which correspond to top-level chrome 1.44 + * windows 1.45 + * - the "global message manager", on the parent side. See below. 1.46 + * 1.47 + * The DOM-realm message managers can communicate in the ways shown by 1.48 + * the following diagram. The parent side and child side can 1.49 + * correspond to process boundaries, but don't always. 1.50 + * 1.51 + * Parent side Child side 1.52 + * ------------- ------------ 1.53 + * global MMg 1.54 + * | 1.55 + * +-->window MMw1 1.56 + * | | 1.57 + * | +-->frame MMp1_1<------------>frame MMc1_1 1.58 + * | | 1.59 + * | +-->frame MMp1_2<------------>frame MMc1_2 1.60 + * | ... 1.61 + * | 1.62 + * +-->window MMw2 1.63 + * ... 1.64 + * 1.65 + * For example: a message sent from MMc1_1, from the child side, is 1.66 + * sent only to MMp1_1 on the parent side. However, note that all 1.67 + * message managers in the hierarchy above MMp1_1, in this diagram 1.68 + * MMw1 and MMg, will also notify their message listeners when the 1.69 + * message arrives. 1.70 + 1.71 + * For example: a message broadcast through the global MMg on the 1.72 + * parent side would be broadcast to MMw1, which would transitively 1.73 + * broadcast it to MMp1_1, MM1p_2". The message would next be 1.74 + * broadcast to MMw2, and so on down the hierarchy. 1.75 + * 1.76 + * ***** PERFORMANCE AND SECURITY WARNING ***** 1.77 + * Messages broadcast through the global MM and window MMs can result 1.78 + * in messages being dispatched across many OS processes, and to many 1.79 + * processes with different permissions. Great care should be taken 1.80 + * when broadcasting. 1.81 + * 1.82 + * Interfaces 1.83 + * ---------- 1.84 + * 1.85 + * The global MMg and window MMw's are message broadcasters implementing 1.86 + * nsIMessageBroadcaster while the frame MMp's are simple message senders 1.87 + * (nsIMessageSender). Their counterparts in the content processes are 1.88 + * message senders implementing nsIContentFrameMessageManager. 1.89 + * 1.90 + * nsIMessageListenerManager 1.91 + * / \ 1.92 + * nsIMessageSender nsIMessageBroadcaster 1.93 + * | 1.94 + * nsISyncMessageSender (content process/in-process only) 1.95 + * | 1.96 + * nsIContentFrameMessageManager (content process/in-process only) 1.97 + * | 1.98 + * nsIInProcessContentFrameMessageManager (in-process only) 1.99 + * 1.100 + * 1.101 + * Message managers in the chrome process can also be QI'ed to nsIFrameScriptLoader. 1.102 + * 1.103 + * 1.104 + * Message managers corresponding to process boundaries 1.105 + * ==================================================== 1.106 + * 1.107 + * The second realm of message managers is the "process message 1.108 + * managers". With one exception, these always correspond to process 1.109 + * boundaries. The picture looks like 1.110 + * 1.111 + * Parent process Child processes 1.112 + * ---------------- ----------------- 1.113 + * global PPMM 1.114 + * | 1.115 + * +<----> child PPMM 1.116 + * | 1.117 + * +-->parent PMM1<------------------>child process CMM1 1.118 + * | 1.119 + * +-->parent PMM2<------------------>child process PMM2 1.120 + * ... 1.121 + * 1.122 + * For example: the parent-process PMM1 sends messages directly to 1.123 + * only the child-process CMM1. 1.124 + * 1.125 + * For example: CMM1 sends messages directly to PMM1. The global PPMM 1.126 + * will also notify their message listeners when the message arrives. 1.127 + * 1.128 + * For example: messages sent through the global PPMM will be 1.129 + * dispatched to the listeners of the same-process, "child PPMM". 1.130 + * They will also be broadcast to PPM1, PPM2, etc. 1.131 + * 1.132 + * ***** PERFORMANCE AND SECURITY WARNING ***** 1.133 + * Messages broadcast through the global PPMM can result in messages 1.134 + * being dispatched across many OS processes, and to many processes 1.135 + * with different permissions. Great care should be taken when 1.136 + * broadcasting. 1.137 + * 1.138 + * Requests sent to parent-process message listeners should usually 1.139 + * have replies scoped to the requesting CPMM. The following pattern 1.140 + * is common 1.141 + * 1.142 + * const ParentProcessListener = { 1.143 + * receiveMessage: function(aMessage) { 1.144 + * let childMM = aMessage.target.QueryInterface(Ci.nsIMessageSender); 1.145 + * switch (aMessage.name) { 1.146 + * case "Foo:Request": 1.147 + * // service request 1.148 + * childMM.sendAsyncMessage("Foo:Response", { data }); 1.149 + * } 1.150 + * } 1.151 + * }; 1.152 + */ 1.153 + 1.154 +[scriptable, function, uuid(2b44eb57-a9c6-4773-9a1e-fe0818739a4c)] 1.155 +interface nsIMessageListener : nsISupports 1.156 +{ 1.157 + /** 1.158 + * This is for JS only. 1.159 + * receiveMessage is called with one parameter, which has the following 1.160 + * properties: 1.161 + * { 1.162 + * target: %the target of the message. Either an element owning 1.163 + * the message manager, or message manager itself if no 1.164 + * element owns it% 1.165 + * name: %message name%, 1.166 + * sync: %true or false%. 1.167 + * data: %structured clone of the sent message data%, 1.168 + * json: %same as .data, deprecated%, 1.169 + * objects: %named table of jsvals/objects, or null% 1.170 + * principal: %principal for the window app 1.171 + * } 1.172 + * 1.173 + * Each listener is invoked with its own copy of the message 1.174 + * parameter. 1.175 + * 1.176 + * When the listener is called, 'this' value is the target of the message. 1.177 + * 1.178 + * If the message is synchronous, the possible return value is 1.179 + * returned as JSON (will be changed to use structured clones). 1.180 + * When there are multiple listeners to sync messages, each 1.181 + * listener's return value is sent back as an array. |undefined| 1.182 + * return values show up as undefined values in the array. 1.183 + */ 1.184 + void receiveMessage(); 1.185 +}; 1.186 + 1.187 +[scriptable, builtinclass, uuid(aae827bd-acf1-45fe-a556-ea545d4c0804)] 1.188 +interface nsIMessageListenerManager : nsISupports 1.189 +{ 1.190 + /** 1.191 + * Register |listener| to receive |messageName|. All listener 1.192 + * callbacks for a particular message are invoked when that message 1.193 + * is received. 1.194 + * 1.195 + * The message manager holds a strong ref to |listener|. 1.196 + * 1.197 + * If the same listener registers twice for the same message, the 1.198 + * second registration is ignored. 1.199 + */ 1.200 + void addMessageListener(in AString messageName, 1.201 + in nsIMessageListener listener); 1.202 + 1.203 + /** 1.204 + * Undo an |addMessageListener| call -- that is, calling this causes us to no 1.205 + * longer invoke |listener| when |messageName| is received. 1.206 + * 1.207 + * removeMessageListener does not remove a message listener added via 1.208 + * addWeakMessageListener; use removeWeakMessageListener for that. 1.209 + */ 1.210 + void removeMessageListener(in AString messageName, 1.211 + in nsIMessageListener listener); 1.212 + 1.213 + /** 1.214 + * This is just like addMessageListener, except the message manager holds a 1.215 + * weak ref to |listener|. 1.216 + * 1.217 + * If you have two weak message listeners for the same message, they may be 1.218 + * called in any order. 1.219 + */ 1.220 + void addWeakMessageListener(in AString messageName, 1.221 + in nsIMessageListener listener); 1.222 + 1.223 + /** 1.224 + * This undoes an |addWeakMessageListener| call. 1.225 + */ 1.226 + void removeWeakMessageListener(in AString messageName, 1.227 + in nsIMessageListener listener); 1.228 + 1.229 + [notxpcom] boolean markForCC(); 1.230 +}; 1.231 + 1.232 +/** 1.233 + * Message "senders" have a single "other side" to which messages are 1.234 + * sent. For example, a child-process message manager will send 1.235 + * messages that are only delivered to its one parent-process message 1.236 + * manager. 1.237 + */ 1.238 +[scriptable, builtinclass, uuid(d6b0d851-43e6-426d-9f13-054bc0198175)] 1.239 +interface nsIMessageSender : nsIMessageListenerManager 1.240 +{ 1.241 + /** 1.242 + * Send |messageName| and |obj| to the "other side" of this message 1.243 + * manager. This invokes listeners who registered for 1.244 + * |messageName|. 1.245 + * 1.246 + * See nsIMessageListener::receiveMessage() for the format of the 1.247 + * data delivered to listeners. 1.248 + * @throws NS_ERROR_NOT_INITIALIZED if the sender is not initialized. For 1.249 + * example, we will throw NS_ERROR_NOT_INITIALIZED if we try to send 1.250 + * a message to a cross-process frame but the other process has not 1.251 + * yet been set up. 1.252 + * @throws NS_ERROR_FAILURE when the message receiver cannot be found. For 1.253 + * example, we will throw NS_ERROR_FAILURE if we try to send a message 1.254 + * to a cross-process frame whose process has crashed. 1.255 + */ 1.256 + [implicit_jscontext, optional_argc] 1.257 + void sendAsyncMessage([optional] in AString messageName, 1.258 + [optional] in jsval obj, 1.259 + [optional] in jsval objects, 1.260 + [optional] in nsIPrincipal principal); 1.261 +}; 1.262 + 1.263 +/** 1.264 + * Message "broadcasters" don't have a single "other side" that they 1.265 + * send messages to, but rather a set of subordinate message managers. 1.266 + * For example, broadcasting a message through a window message 1.267 + * manager will broadcast the message to all frame message managers 1.268 + * within its window. 1.269 + */ 1.270 +[scriptable, builtinclass, uuid(d36346b9-5d3b-497d-9c28-ffbc3e4f6d0d)] 1.271 +interface nsIMessageBroadcaster : nsIMessageListenerManager 1.272 +{ 1.273 + /** 1.274 + * Like |sendAsyncMessage()|, but also broadcasts this message to 1.275 + * all "child" message managers of this message manager. See long 1.276 + * comment above for details. 1.277 + * 1.278 + * WARNING: broadcasting messages can be very expensive and leak 1.279 + * sensitive data. Use with extreme caution. 1.280 + */ 1.281 + [implicit_jscontext, optional_argc] 1.282 + void broadcastAsyncMessage([optional] in AString messageName, 1.283 + [optional] in jsval obj, 1.284 + [optional] in jsval objects); 1.285 + 1.286 + /** 1.287 + * Number of subordinate message managers. 1.288 + */ 1.289 + readonly attribute unsigned long childCount; 1.290 + 1.291 + /** 1.292 + * Return a single subordinate message manager. 1.293 + */ 1.294 + nsIMessageListenerManager getChildAt(in unsigned long aIndex); 1.295 +}; 1.296 + 1.297 +[scriptable, builtinclass, uuid(7fda0941-9dcc-448b-bd39-16373c5b4003)] 1.298 +interface nsISyncMessageSender : nsIMessageSender 1.299 +{ 1.300 + /** 1.301 + * Like |sendAsyncMessage()|, except blocks the sender until all 1.302 + * listeners of the message have been invoked. Returns an array 1.303 + * containing return values from each listener invoked. 1.304 + */ 1.305 + [implicit_jscontext, optional_argc] 1.306 + jsval sendSyncMessage([optional] in AString messageName, 1.307 + [optional] in jsval obj, 1.308 + [optional] in jsval objects, 1.309 + [optional] in nsIPrincipal principal); 1.310 + 1.311 + /** 1.312 + * Like |sendSyncMessage()|, except re-entrant. New RPC messages may be 1.313 + * issued even if, earlier on the call stack, we are waiting for a reply 1.314 + * to an earlier sendRpcMessage() call. 1.315 + * 1.316 + * Both sendSyncMessage and sendRpcMessage will block until a reply is 1.317 + * received, but they may be temporarily interrupted to process an urgent 1.318 + * incoming message (such as a CPOW request). 1.319 + */ 1.320 + [implicit_jscontext, optional_argc] 1.321 + jsval sendRpcMessage([optional] in AString messageName, 1.322 + [optional] in jsval obj, 1.323 + [optional] in jsval objects, 1.324 + [optional] in nsIPrincipal principal); 1.325 +}; 1.326 + 1.327 +[scriptable, builtinclass, uuid(894ff2d4-39a3-4df8-9d76-8ee329975488)] 1.328 +interface nsIContentFrameMessageManager : nsISyncMessageSender 1.329 +{ 1.330 + /** 1.331 + * The current top level window in the frame or null. 1.332 + */ 1.333 + readonly attribute nsIDOMWindow content; 1.334 + 1.335 + /** 1.336 + * The top level docshell or null. 1.337 + */ 1.338 + readonly attribute nsIDocShell docShell; 1.339 + 1.340 + /** 1.341 + * Print a string to stdout. 1.342 + */ 1.343 + void dump(in DOMString aStr); 1.344 + 1.345 + /** 1.346 + * If leak detection is enabled, print a note to the leak log that this 1.347 + * process will intentionally crash. 1.348 + */ 1.349 + void privateNoteIntentionalCrash(); 1.350 + 1.351 + /** 1.352 + * Ascii base64 data to binary data and vice versa 1.353 + */ 1.354 + DOMString atob(in DOMString aAsciiString); 1.355 + DOMString btoa(in DOMString aBase64Data); 1.356 +}; 1.357 + 1.358 +[uuid(a2325927-9c0c-437d-9215-749c79235031)] 1.359 +interface nsIInProcessContentFrameMessageManager : nsIContentFrameMessageManager 1.360 +{ 1.361 + [notxpcom] nsIContent getOwnerContent(); 1.362 +}; 1.363 + 1.364 +[scriptable, builtinclass, uuid(6fb78110-45ae-11e3-8f96-0800200c9a66)] 1.365 +interface nsIFrameScriptLoader : nsISupports 1.366 +{ 1.367 + /** 1.368 + * Load a script in the (remote) frame. aURL must be the absolute URL. 1.369 + * data: URLs are also supported. For example data:,dump("foo\n"); 1.370 + * If aAllowDelayedLoad is true, script will be loaded when the 1.371 + * remote frame becomes available. Otherwise the script will be loaded 1.372 + * only if the frame is already available. 1.373 + */ 1.374 + void loadFrameScript(in AString aURL, in boolean aAllowDelayedLoad, 1.375 + [optional] in boolean aRunInGlobalScope); 1.376 + 1.377 + /** 1.378 + * Removes aURL from the list of scripts which support delayed load. 1.379 + */ 1.380 + void removeDelayedFrameScript(in AString aURL); 1.381 + 1.382 + /** 1.383 + * Returns all delayed scripts that will be loaded once a (remote) 1.384 + * frame becomes available. The return value is a list of pairs 1.385 + * [<URL>, <WasLoadedInGlobalScope>]. 1.386 + */ 1.387 + [implicit_jscontext] 1.388 + jsval getDelayedFrameScripts(); 1.389 +}; 1.390 + 1.391 +[scriptable, builtinclass, uuid(ad57800b-ff21-4e2f-91d3-e68615ae8afe)] 1.392 +interface nsIProcessChecker : nsISupports 1.393 +{ 1.394 + 1.395 + /** 1.396 + * Return true if the "remote" process has |aPermission|. This is 1.397 + * intended to be used by JS implementations of cross-process DOM 1.398 + * APIs, like so 1.399 + * 1.400 + * recvFooRequest: function(message) { 1.401 + * if (!message.target.assertPermission("foo")) { 1.402 + * return false; 1.403 + * } 1.404 + * // service foo request 1.405 + * 1.406 + * This interface only returns meaningful data when our content is 1.407 + * in a separate process. If it shares the same OS process as us, 1.408 + * then applying this permission check doesn't add any security, 1.409 + * though it doesn't hurt anything either. 1.410 + * 1.411 + * Note: If the remote content process does *not* have |aPermission|, 1.412 + * it will be killed as a precaution. 1.413 + */ 1.414 + boolean assertPermission(in DOMString aPermission); 1.415 + 1.416 + /** 1.417 + * Return true if the "remote" process has |aManifestURL|. This is 1.418 + * intended to be used by JS implementations of cross-process DOM 1.419 + * APIs, like so 1.420 + * 1.421 + * recvFooRequest: function(message) { 1.422 + * if (!message.target.assertContainApp("foo")) { 1.423 + * return false; 1.424 + * } 1.425 + * // service foo request 1.426 + * 1.427 + * This interface only returns meaningful data when our content is 1.428 + * in a separate process. If it shares the same OS process as us, 1.429 + * then applying this manifest URL check doesn't add any security, 1.430 + * though it doesn't hurt anything either. 1.431 + * 1.432 + * Note: If the remote content process does *not* contain |aManifestURL|, 1.433 + * it will be killed as a precaution. 1.434 + */ 1.435 + boolean assertContainApp(in DOMString aManifestURL); 1.436 + 1.437 + boolean assertAppHasPermission(in DOMString aPermission); 1.438 + 1.439 + /** 1.440 + * Return true if the "remote" process' principal has an appStatus equal to 1.441 + * |aStatus|. 1.442 + * 1.443 + * This interface only returns meaningful data when our content is 1.444 + * in a separate process. If it shares the same OS process as us, 1.445 + * then applying this permission check doesn't add any security, 1.446 + * though it doesn't hurt anything either. 1.447 + * 1.448 + * Note: If the remote content process does *not* has the |aStatus|, 1.449 + * it will be killed as a precaution. 1.450 + */ 1.451 + boolean assertAppHasStatus(in unsigned short aStatus); 1.452 + 1.453 +};