content/base/public/nsIMessageManager.idl

changeset 0
6474c204b198
     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 +};

mercurial