content/base/public/nsIMessageManager.idl

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "nsISupports.idl"
     8 interface nsIDOMWindow;
     9 interface nsIDocShell;
    10 interface nsIContent;
    11 interface nsIPrincipal;
    13 /**
    14  * Message managers provide a way for chrome-privileged JS code to
    15  * communicate with each other, even across process boundaries.
    16  *
    17  * Message managers are separated into "parent side" and "child side".
    18  * These don't always correspond to process boundaries, but can.  For
    19  * each child-side message manager, there is always exactly one
    20  * corresponding parent-side message manager that it sends messages
    21  * to.  However, for each parent-side message manager, there may be
    22  * either one or many child-side managers it can message.
    23  *
    24  * Message managers that always have exactly one "other side" are of
    25  * type nsIMessageSender.  Parent-side message managers that have many
    26  * "other sides" are of type nsIMessageBroadcaster.
    27  *
    28  * Child-side message managers can send synchronous messages to their
    29  * parent side, but not the other way around.
    30  *
    31  * There are two realms of message manager hierarchies.  One realm
    32  * approximately corresponds to DOM elements, the other corresponds to
    33  * process boundaries.
    34  *
    35  * Message managers corresponding to DOM elements
    36  * ==============================================
    37  *
    38  * In this realm of message managers, there are
    39  *  - "frame message managers" which correspond to frame elements
    40  *  - "window message managers" which correspond to top-level chrome
    41  *    windows
    42  *  - the "global message manager", on the parent side.  See below.
    43  *
    44  * The DOM-realm message managers can communicate in the ways shown by
    45  * the following diagram.  The parent side and child side can
    46  * correspond to process boundaries, but don't always.
    47  *
    48  *  Parent side                         Child side
    49  * -------------                       ------------
    50  *  global MMg
    51  *   |
    52  *   +-->window MMw1
    53  *   |    |
    54  *   |    +-->frame MMp1_1<------------>frame MMc1_1
    55  *   |    |
    56  *   |    +-->frame MMp1_2<------------>frame MMc1_2
    57  *   |    ...
    58  *   |
    59  *   +-->window MMw2
    60  *   ...
    61  *
    62  * For example: a message sent from MMc1_1, from the child side, is
    63  * sent only to MMp1_1 on the parent side.  However, note that all
    64  * message managers in the hierarchy above MMp1_1, in this diagram
    65  * MMw1 and MMg, will also notify their message listeners when the
    66  * message arrives.
    68  * For example: a message broadcast through the global MMg on the
    69  * parent side would be broadcast to MMw1, which would transitively
    70  * broadcast it to MMp1_1, MM1p_2".  The message would next be
    71  * broadcast to MMw2, and so on down the hierarchy.
    72  *
    73  *   ***** PERFORMANCE AND SECURITY WARNING *****
    74  * Messages broadcast through the global MM and window MMs can result
    75  * in messages being dispatched across many OS processes, and to many
    76  * processes with different permissions.  Great care should be taken
    77  * when broadcasting.
    78  *
    79  * Interfaces
    80  * ----------
    81  *
    82  * The global MMg and window MMw's are message broadcasters implementing
    83  * nsIMessageBroadcaster while the frame MMp's are simple message senders
    84  * (nsIMessageSender). Their counterparts in the content processes are
    85  * message senders implementing nsIContentFrameMessageManager.
    86  *
    87  *                    nsIMessageListenerManager
    88  *                  /                           \
    89  * nsIMessageSender                               nsIMessageBroadcaster
    90  *       |
    91  * nsISyncMessageSender (content process/in-process only)
    92  *       |
    93  * nsIContentFrameMessageManager (content process/in-process only)
    94  *       |
    95  * nsIInProcessContentFrameMessageManager (in-process only)
    96  *
    97  *
    98  * Message managers in the chrome process can also be QI'ed to nsIFrameScriptLoader.
    99  *
   100  *
   101  * Message managers corresponding to process boundaries
   102  * ====================================================
   103  *
   104  * The second realm of message managers is the "process message
   105  * managers".  With one exception, these always correspond to process
   106  * boundaries.  The picture looks like
   107  *
   108  *  Parent process                      Child processes
   109  * ----------------                    -----------------
   110  *  global PPMM
   111  *   |
   112  *   +<----> child PPMM
   113  *   |
   114  *   +-->parent PMM1<------------------>child process CMM1
   115  *   |
   116  *   +-->parent PMM2<------------------>child process PMM2
   117  *   ...
   118  *
   119  * For example: the parent-process PMM1 sends messages directly to
   120  * only the child-process CMM1.
   121  *
   122  * For example: CMM1 sends messages directly to PMM1.  The global PPMM
   123  * will also notify their message listeners when the message arrives.
   124  *
   125  * For example: messages sent through the global PPMM will be
   126  * dispatched to the listeners of the same-process, "child PPMM".
   127  * They will also be broadcast to PPM1, PPM2, etc.
   128  *
   129  *   ***** PERFORMANCE AND SECURITY WARNING *****
   130  * Messages broadcast through the global PPMM can result in messages
   131  * being dispatched across many OS processes, and to many processes
   132  * with different permissions.  Great care should be taken when
   133  * broadcasting.
   134  *
   135  * Requests sent to parent-process message listeners should usually
   136  * have replies scoped to the requesting CPMM.  The following pattern
   137  * is common
   138  *
   139  *  const ParentProcessListener = {
   140  *    receiveMessage: function(aMessage) {
   141  *      let childMM = aMessage.target.QueryInterface(Ci.nsIMessageSender);
   142  *      switch (aMessage.name) {
   143  *      case "Foo:Request":
   144  *        // service request
   145  *        childMM.sendAsyncMessage("Foo:Response", { data });
   146  *      }
   147  *    }
   148  *  };
   149  */
   151 [scriptable, function, uuid(2b44eb57-a9c6-4773-9a1e-fe0818739a4c)]
   152 interface nsIMessageListener : nsISupports
   153 {
   154   /**
   155    * This is for JS only.
   156    * receiveMessage is called with one parameter, which has the following
   157    * properties:
   158    *   {
   159    *     target:    %the target of the message. Either an element owning
   160    *                 the message manager, or message manager itself if no
   161    *                 element owns it%
   162    *     name:      %message name%,
   163    *     sync:      %true or false%.
   164    *     data:      %structured clone of the sent message data%,
   165    *     json:      %same as .data, deprecated%,
   166    *     objects:   %named table of jsvals/objects, or null%
   167    *     principal: %principal for the window app
   168    *   }
   169    *
   170    * Each listener is invoked with its own copy of the message
   171    * parameter.
   172    *
   173    * When the listener is called, 'this' value is the target of the message.
   174    *
   175    * If the message is synchronous, the possible return value is
   176    * returned as JSON (will be changed to use structured clones).
   177    * When there are multiple listeners to sync messages, each
   178    * listener's return value is sent back as an array.  |undefined|
   179    * return values show up as undefined values in the array.
   180    */
   181   void receiveMessage();
   182 };
   184 [scriptable, builtinclass, uuid(aae827bd-acf1-45fe-a556-ea545d4c0804)]
   185 interface nsIMessageListenerManager : nsISupports
   186 {
   187   /**
   188    * Register |listener| to receive |messageName|.  All listener
   189    * callbacks for a particular message are invoked when that message
   190    * is received.
   191    *
   192    * The message manager holds a strong ref to |listener|.
   193    *
   194    * If the same listener registers twice for the same message, the
   195    * second registration is ignored.
   196    */
   197   void addMessageListener(in AString messageName,
   198                           in nsIMessageListener listener);
   200   /**
   201    * Undo an |addMessageListener| call -- that is, calling this causes us to no
   202    * longer invoke |listener| when |messageName| is received.
   203    *
   204    * removeMessageListener does not remove a message listener added via
   205    * addWeakMessageListener; use removeWeakMessageListener for that.
   206    */
   207   void removeMessageListener(in AString messageName,
   208                              in nsIMessageListener listener);
   210   /**
   211    * This is just like addMessageListener, except the message manager holds a
   212    * weak ref to |listener|.
   213    *
   214    * If you have two weak message listeners for the same message, they may be
   215    * called in any order.
   216    */
   217   void addWeakMessageListener(in AString messageName,
   218                               in nsIMessageListener listener);
   220   /**
   221    * This undoes an |addWeakMessageListener| call.
   222    */
   223   void removeWeakMessageListener(in AString messageName,
   224                                  in nsIMessageListener listener);
   226   [notxpcom] boolean markForCC();
   227 };
   229 /**
   230  * Message "senders" have a single "other side" to which messages are
   231  * sent.  For example, a child-process message manager will send
   232  * messages that are only delivered to its one parent-process message
   233  * manager.
   234  */
   235 [scriptable, builtinclass, uuid(d6b0d851-43e6-426d-9f13-054bc0198175)]
   236 interface nsIMessageSender : nsIMessageListenerManager
   237 {
   238   /**
   239    * Send |messageName| and |obj| to the "other side" of this message
   240    * manager.  This invokes listeners who registered for
   241    * |messageName|.
   242    *
   243    * See nsIMessageListener::receiveMessage() for the format of the
   244    * data delivered to listeners.
   245    * @throws NS_ERROR_NOT_INITIALIZED if the sender is not initialized.  For
   246    *         example, we will throw NS_ERROR_NOT_INITIALIZED if we try to send
   247    *         a message to a cross-process frame but the other process has not
   248    *         yet been set up.
   249    * @throws NS_ERROR_FAILURE when the message receiver cannot be found.  For
   250    *         example, we will throw NS_ERROR_FAILURE if we try to send a message
   251    *         to a cross-process frame whose process has crashed.
   252    */
   253   [implicit_jscontext, optional_argc]
   254   void sendAsyncMessage([optional] in AString messageName,
   255                         [optional] in jsval obj,
   256                         [optional] in jsval objects,
   257                         [optional] in nsIPrincipal principal);
   258 };
   260 /**
   261  * Message "broadcasters" don't have a single "other side" that they
   262  * send messages to, but rather a set of subordinate message managers.
   263  * For example, broadcasting a message through a window message
   264  * manager will broadcast the message to all frame message managers
   265  * within its window.
   266  */
   267 [scriptable, builtinclass, uuid(d36346b9-5d3b-497d-9c28-ffbc3e4f6d0d)]
   268 interface nsIMessageBroadcaster : nsIMessageListenerManager
   269 {
   270   /**
   271    * Like |sendAsyncMessage()|, but also broadcasts this message to
   272    * all "child" message managers of this message manager.  See long
   273    * comment above for details.
   274    *
   275    * WARNING: broadcasting messages can be very expensive and leak
   276    * sensitive data.  Use with extreme caution.
   277    */
   278   [implicit_jscontext, optional_argc]
   279   void broadcastAsyncMessage([optional] in AString messageName,
   280                              [optional] in jsval obj,
   281                              [optional] in jsval objects);
   283   /**
   284    * Number of subordinate message managers.
   285    */
   286   readonly attribute unsigned long childCount;
   288   /**
   289    * Return a single subordinate message manager.
   290    */
   291   nsIMessageListenerManager getChildAt(in unsigned long aIndex);
   292 };
   294 [scriptable, builtinclass, uuid(7fda0941-9dcc-448b-bd39-16373c5b4003)]
   295 interface nsISyncMessageSender : nsIMessageSender
   296 {
   297   /**
   298    * Like |sendAsyncMessage()|, except blocks the sender until all
   299    * listeners of the message have been invoked.  Returns an array
   300    * containing return values from each listener invoked.
   301    */
   302   [implicit_jscontext, optional_argc]
   303   jsval sendSyncMessage([optional] in AString messageName,
   304                         [optional] in jsval obj,
   305                         [optional] in jsval objects,
   306                         [optional] in nsIPrincipal principal);
   308   /**
   309    * Like |sendSyncMessage()|, except re-entrant. New RPC messages may be
   310    * issued even if, earlier on the call stack, we are waiting for a reply
   311    * to an earlier sendRpcMessage() call.
   312    *
   313    * Both sendSyncMessage and sendRpcMessage will block until a reply is
   314    * received, but they may be temporarily interrupted to process an urgent
   315    * incoming message (such as a CPOW request).
   316    */
   317   [implicit_jscontext, optional_argc]
   318   jsval sendRpcMessage([optional] in AString messageName,
   319                        [optional] in jsval obj,
   320                        [optional] in jsval objects,
   321                        [optional] in nsIPrincipal principal);
   322 };
   324 [scriptable, builtinclass, uuid(894ff2d4-39a3-4df8-9d76-8ee329975488)]
   325 interface nsIContentFrameMessageManager : nsISyncMessageSender
   326 {
   327   /**
   328    * The current top level window in the frame or null.
   329    */
   330   readonly attribute nsIDOMWindow content;
   332   /**
   333    * The top level docshell or null.
   334    */
   335   readonly attribute nsIDocShell docShell;
   337   /**
   338    * Print a string to stdout.
   339    */
   340   void dump(in DOMString aStr);
   342   /**
   343    * If leak detection is enabled, print a note to the leak log that this
   344    * process will intentionally crash.
   345    */
   346   void privateNoteIntentionalCrash();
   348    /**
   349     * Ascii base64 data to binary data and vice versa
   350     */
   351    DOMString atob(in DOMString aAsciiString);
   352    DOMString btoa(in DOMString aBase64Data);
   353 };
   355 [uuid(a2325927-9c0c-437d-9215-749c79235031)]
   356 interface nsIInProcessContentFrameMessageManager : nsIContentFrameMessageManager
   357 {
   358   [notxpcom] nsIContent getOwnerContent();
   359 };
   361 [scriptable, builtinclass, uuid(6fb78110-45ae-11e3-8f96-0800200c9a66)]
   362 interface nsIFrameScriptLoader : nsISupports
   363 {
   364   /**
   365    * Load a script in the (remote) frame. aURL must be the absolute URL.
   366    * data: URLs are also supported. For example data:,dump("foo\n");
   367    * If aAllowDelayedLoad is true, script will be loaded when the
   368    * remote frame becomes available. Otherwise the script will be loaded
   369    * only if the frame is already available.
   370    */
   371   void loadFrameScript(in AString aURL, in boolean aAllowDelayedLoad,
   372                        [optional] in boolean aRunInGlobalScope);
   374   /**
   375    * Removes aURL from the list of scripts which support delayed load.
   376    */
   377   void removeDelayedFrameScript(in AString aURL);
   379   /**
   380    * Returns all delayed scripts that will be loaded once a (remote)
   381    * frame becomes available. The return value is a list of pairs
   382    * [<URL>, <WasLoadedInGlobalScope>].
   383    */
   384   [implicit_jscontext]
   385   jsval getDelayedFrameScripts();
   386 };
   388 [scriptable, builtinclass, uuid(ad57800b-ff21-4e2f-91d3-e68615ae8afe)]
   389 interface nsIProcessChecker : nsISupports
   390 {
   392   /**
   393    * Return true if the "remote" process has |aPermission|.  This is
   394    * intended to be used by JS implementations of cross-process DOM
   395    * APIs, like so
   396    *
   397    *   recvFooRequest: function(message) {
   398    *     if (!message.target.assertPermission("foo")) {
   399    *       return false;
   400    *     }
   401    *     // service foo request
   402    *
   403    * This interface only returns meaningful data when our content is
   404    * in a separate process.  If it shares the same OS process as us,
   405    * then applying this permission check doesn't add any security,
   406    * though it doesn't hurt anything either.
   407    *
   408    * Note: If the remote content process does *not* have |aPermission|,
   409    * it will be killed as a precaution.
   410    */
   411   boolean assertPermission(in DOMString aPermission);
   413   /**
   414    * Return true if the "remote" process has |aManifestURL|.  This is
   415    * intended to be used by JS implementations of cross-process DOM
   416    * APIs, like so
   417    *
   418    *   recvFooRequest: function(message) {
   419    *     if (!message.target.assertContainApp("foo")) {
   420    *       return false;
   421    *     }
   422    *     // service foo request
   423    *
   424    * This interface only returns meaningful data when our content is
   425    * in a separate process.  If it shares the same OS process as us,
   426    * then applying this manifest URL check doesn't add any security,
   427    * though it doesn't hurt anything either.
   428    *
   429    * Note: If the remote content process does *not* contain |aManifestURL|,
   430    * it will be killed as a precaution.
   431    */
   432   boolean assertContainApp(in DOMString aManifestURL);
   434   boolean assertAppHasPermission(in DOMString aPermission);
   436   /**
   437    * Return true if the "remote" process' principal has an appStatus equal to
   438    * |aStatus|.
   439    *
   440    * This interface only returns meaningful data when our content is
   441    * in a separate process.  If it shares the same OS process as us,
   442    * then applying this permission check doesn't add any security,
   443    * though it doesn't hurt anything either.
   444    *
   445    * Note: If the remote content process does *not* has the |aStatus|,
   446    * it will be killed as a precaution.
   447    */
   448   boolean assertAppHasStatus(in unsigned short aStatus);
   450 };

mercurial