Home | History | Annotate | Download | only in cpp
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef PPAPI_CPP_INSTANCE_H_
      6 #define PPAPI_CPP_INSTANCE_H_
      7 
      8 /// @file
      9 /// This file defines the C++ wrapper for an instance.
     10 
     11 #include <map>
     12 #include <string>
     13 
     14 #include "ppapi/c/pp_instance.h"
     15 #include "ppapi/c/pp_resource.h"
     16 #include "ppapi/c/pp_stdint.h"
     17 #include "ppapi/c/ppb_console.h"
     18 #include "ppapi/cpp/instance_handle.h"
     19 #include "ppapi/cpp/view.h"
     20 
     21 // Windows defines 'PostMessage', so we have to undef it.
     22 #ifdef PostMessage
     23 #undef PostMessage
     24 #endif
     25 
     26 struct PP_InputEvent;
     27 
     28 /// The C++ interface to the Pepper API.
     29 namespace pp {
     30 
     31 class Compositor;
     32 class Graphics2D;
     33 class Graphics3D;
     34 class InputEvent;
     35 class InstanceHandle;
     36 class MessageHandler;
     37 class MessageLoop;
     38 class Rect;
     39 class URLLoader;
     40 class Var;
     41 
     42 class Instance {
     43  public:
     44   /// Default constructor. Construction of an instance should only be done in
     45   /// response to a browser request in <code>Module::CreateInstance</code>.
     46   /// Otherwise, the instance will lack the proper bookkeeping in the browser
     47   /// and in the C++ wrapper.
     48   ///
     49   /// Init() will be called immediately after the constructor. This allows you
     50   /// to perform initialization tasks that can fail and to report that failure
     51   /// to the browser.
     52   explicit Instance(PP_Instance instance);
     53 
     54   /// Destructor. When the instance is removed from the web page,
     55   /// the <code>pp::Instance</code> object will be deleted. You should never
     56   /// delete the <code>Instance</code> object yourself since the lifetime is
     57   /// handled by the C++ wrapper and is controlled by the browser's calls to
     58   /// the <code>PPP_Instance</code> interface.
     59   ///
     60   /// The <code>PP_Instance</code> identifier will still be valid during this
     61   /// call so the instance can perform cleanup-related tasks. Once this function
     62   /// returns, the <code>PP_Instance</code> handle will be invalid. This means
     63   /// that you can't do any asynchronous operations such as network requests or
     64   /// file writes from this destructor since they will be immediately canceled.
     65   ///
     66   /// <strong>Note:</strong> This function may be skipped in certain
     67   /// call so the instance can perform cleanup-related tasks. Once this function
     68   /// returns, the <code>PP_Instance</code> handle will be invalid. This means
     69   /// that you can't do any asynchronous operations such as network requests or
     70   /// file writes from this destructor since they will be immediately canceled.
     71   virtual ~Instance();
     72 
     73   /// This function returns the <code>PP_Instance</code> identifying this
     74   /// object.
     75   ///
     76   /// @return A <code>PP_Instance</code> identifying this object.
     77   PP_Instance pp_instance() const { return pp_instance_; }
     78 
     79   /// Init() initializes this instance with the provided arguments. This
     80   /// function will be called immediately after the instance object is
     81   /// constructed.
     82   ///
     83   /// @param[in] argc The number of arguments contained in <code>argn</code>
     84   /// and <code>argv</code>.
     85   ///
     86   /// @param[in] argn An array of argument names.  These argument names are
     87   /// supplied in the \<embed\> tag, for example:
     88   /// <code>\<embed id="nacl_module" dimensions="2"\></code> will produce two
     89   /// argument names: "id" and "dimensions".
     90   ///
     91   /// @param[in] argv An array of argument values.  These are the values of the
     92   /// arguments listed in the \<embed\> tag, for example
     93   /// <code>\<embed id="nacl_module" dimensions="2"\></code> will produce two
     94   /// argument values: "nacl_module" and "2".  The indices of these values
     95   /// match the indices of the corresponding names in <code>argn</code>.
     96   ///
     97   /// @return true on success. Returning false causes the instance to be
     98   /// deleted and no other functions to be called.
     99   virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
    100 
    101   /// @{
    102   /// @name PPP_Instance methods for the module to override:
    103 
    104   /// DidChangeView() is called when the view information for the Instance
    105   /// has changed. See the <code>View</code> object for information.
    106   ///
    107   /// Most implementations will want to check if the size and user visibility
    108   /// changed, and either resize themselves or start/stop generating updates.
    109   ///
    110   /// You should not call the default implementation. For
    111   /// backwards-compatibility, it will call the deprecated version of
    112   /// DidChangeView below.
    113   virtual void DidChangeView(const View& view);
    114 
    115   /// Deprecated backwards-compatible version of <code>DidChangeView()</code>.
    116   /// New code should derive from the version that takes a
    117   /// <code>ViewChanged</code> object rather than this version. This function
    118   /// is called by the default implementation of the newer
    119   /// <code>DidChangeView</code> function for source compatibility with older
    120   /// code.
    121   ///
    122   /// A typical implementation will check the size of the <code>position</code>
    123   /// argument and reallocate the graphics context when a different size is
    124   /// received. Note that this function will be called for scroll events where
    125   /// the size doesn't change, so you should always check that the size is
    126   /// actually different before doing any reallocations.
    127   ///
    128   /// @param[in] position The location on the page of the instance. The
    129   /// position is relative to the top left corner of the viewport, which changes
    130   /// as the page is scrolled. Generally the size of this value will be used to
    131   /// create a graphics device, and the position is ignored (most things are
    132   /// relative to the instance so the absolute position isn't useful in most
    133   /// cases).
    134   ///
    135   /// @param[in] clip The visible region of the instance. This is relative to
    136   /// the top left of the instance's coordinate system (not the page).  If the
    137   /// instance is invisible, <code>clip</code> will be (0, 0, 0, 0).
    138   ///
    139   /// It's recommended to check for invisible instances and to stop
    140   /// generating graphics updates in this case to save system resources. It's
    141   /// not usually worthwhile, however, to generate partial updates according to
    142   /// the clip when the instance is partially visible. Instead, update the
    143   /// entire region. The time saved doing partial paints is usually not
    144   /// significant and it can create artifacts when scrolling (this notification
    145   /// is sent asynchronously from scrolling so there can be flashes of old
    146   /// content in the exposed regions).
    147   virtual void DidChangeView(const Rect& position, const Rect& clip);
    148 
    149   /// DidChangeFocus() is called when an instance has gained or lost focus.
    150   /// Having focus means that keyboard events will be sent to the instance.
    151   /// An instance's default condition is that it will not have focus.
    152   ///
    153   /// The focus flag takes into account both browser tab and window focus as
    154   /// well as focus of the plugin element on the page. In order to be deemed
    155   /// to have focus, the browser window must be topmost, the tab must be
    156   /// selected in the window, and the instance must be the focused element on
    157   /// the page.
    158   ///
    159   /// <strong>Note:</strong>Clicks on instances will give focus only if you
    160   /// handle the click event. Return <code>true</code> from
    161   /// <code>HandleInputEvent</code> in <code>PPP_InputEvent</code> (or use
    162   /// unfiltered events) to signal that the click event was handled. Otherwise,
    163   /// the browser will bubble the event and give focus to the element on the
    164   /// page that actually did end up consuming it. If you're not getting focus,
    165   /// check to make sure you're either requesting them via
    166   /// <code>RequestInputEvents()<code> (which implicitly marks all input events
    167   /// as consumed) or via <code>RequestFilteringInputEvents()</code> and
    168   /// returning true from your event handler.
    169   ///
    170   /// @param[in] has_focus Indicates the new focused state of the instance.
    171   virtual void DidChangeFocus(bool has_focus);
    172 
    173   /// HandleInputEvent() handles input events from the browser. The default
    174   /// implementation does nothing and returns false.
    175   ///
    176   /// In order to receive input events, you must register for them by calling
    177   /// RequestInputEvents() or RequestFilteringInputEvents(). By
    178   /// default, no events are delivered.
    179   ///
    180   /// If the event was handled, it will not be forwarded to any default
    181   /// handlers. If it was not handled, it may be dispatched to a default
    182   /// handler. So it is important that an instance respond accurately with
    183   /// whether event propagation should continue.
    184   ///
    185   /// Event propagation also controls focus. If you handle an event like a mouse
    186   /// event, typically the instance will be given focus. Returning false from
    187   /// a filtered event handler or not registering for an event type means that
    188   /// the click will be given to a lower part of the page and your instance will
    189   /// not receive focus. This allows an instance to be partially transparent,
    190   /// where clicks on the transparent areas will behave like clicks to the
    191   /// underlying page.
    192   ///
    193   /// In general, you should try to keep input event handling short. Especially
    194   /// for filtered input events, the browser or page may be blocked waiting for
    195   /// you to respond.
    196   ///
    197   /// The caller of this function will maintain a reference to the input event
    198   /// resource during this call. Unless you take a reference to the resource
    199   /// to hold it for later, you don't need to release it.
    200   ///
    201   /// <strong>Note: </strong>If you're not receiving input events, make sure
    202   /// you register for the event classes you want by calling
    203   /// <code>RequestInputEvents</code> or
    204   /// <code>RequestFilteringInputEvents</code>. If you're still not receiving
    205   /// keyboard input events, make sure you're returning true (or using a
    206   /// non-filtered event handler) for mouse events. Otherwise, the instance will
    207   /// not receive focus and keyboard events will not be sent.
    208   ///
    209   /// Refer to <code>RequestInputEvents</code> and
    210   /// <code>RequestFilteringInputEvents</code> for further information.
    211   ///
    212   /// @param[in] event The event to handle.
    213   ///
    214   /// @return true if the event was handled, false if not. If you have
    215   /// registered to filter this class of events by calling
    216   /// <code>RequestFilteringInputEvents</code>, and you return false,
    217   /// the event will be forwarded to the page (and eventually the browser)
    218   /// for the default handling. For non-filtered events, the return value
    219   /// will be ignored.
    220   virtual bool HandleInputEvent(const pp::InputEvent& event);
    221 
    222   /// HandleDocumentLoad() is called after Init() for a full-frame
    223   /// instance that was instantiated based on the MIME type of a DOMWindow
    224   /// navigation. This situation only applies to modules that are
    225   /// pre-registered to handle certain MIME types. If you haven't specifically
    226   /// registered to handle a MIME type or aren't positive this applies to you,
    227   /// your implementation of this function can just return false.
    228   ///
    229   /// The given url_loader corresponds to a <code>URLLoader</code> object that
    230   /// is already opened. Its response headers may be queried using
    231   /// GetResponseInfo(). If you want to use the <code>URLLoader</code> to read
    232   /// data, you will need to save a copy of it or the underlying resource will
    233   /// be freed when this function returns and the load will be canceled.
    234   ///
    235   /// This method returns false if the module cannot handle the data. In
    236   /// response to this method, the module should call ReadResponseBody() to read
    237   /// the incoming data.
    238   ///
    239   /// @param[in] url_loader An open <code>URLLoader</code> instance.
    240   ///
    241   /// @return true if the data was handled, false otherwise.
    242   virtual bool HandleDocumentLoad(const URLLoader& url_loader);
    243 
    244   /// HandleMessage() is a function that the browser calls when PostMessage()
    245   /// is invoked on the DOM element for the instance in JavaScript. Note
    246   /// that PostMessage() in the JavaScript interface is asynchronous, meaning
    247   /// JavaScript execution will not be blocked while HandleMessage() is
    248   /// processing the message.
    249   ///
    250   /// When converting JavaScript arrays, any object properties whose name
    251   /// is not an array index are ignored. When passing arrays and objects, the
    252   /// entire reference graph will be converted and transferred. If the reference
    253   /// graph has cycles, the message will not be sent and an error will be logged
    254   /// to the console.
    255   ///
    256   /// <strong>Example:</strong>
    257   ///
    258   /// The following JavaScript code invokes <code>HandleMessage</code>, passing
    259   /// the instance on which it was invoked, with <code>message</code> being a
    260   /// string <code>Var</code> containing "Hello world!"
    261   ///
    262   /// @code{.html}
    263   ///
    264   /// <body>
    265   ///   <object id="plugin"
    266   ///           type="application/x-ppapi-postMessage-example"/>
    267   ///   <script type="text/javascript">
    268   ///     document.getElementById('plugin').postMessage("Hello world!");
    269   ///   </script>
    270   /// </body>
    271   ///
    272   /// @endcode
    273   ///
    274   /// Refer to PostMessage() for sending messages to JavaScript.
    275   ///
    276   /// @param[in] message A <code>Var</code> which has been converted from a
    277   /// JavaScript value. JavaScript array/object types are supported from Chrome
    278   /// M29 onward. All JavaScript values are copied when passing them to the
    279   /// plugin.
    280   virtual void HandleMessage(const Var& message);
    281 
    282   /// @}
    283 
    284   /// @{
    285   /// @name PPB_Instance methods for querying the browser:
    286 
    287   /// BindGraphics() binds the given graphics as the current display surface.
    288   /// The contents of this device is what will be displayed in the instance's
    289   /// area on the web page. The device must be a 2D or a 3D device.
    290   ///
    291   /// You can pass an <code>is_null()</code> (default constructed) Graphics2D
    292   /// as the device parameter to unbind all devices from the given instance.
    293   /// The instance will then appear transparent. Re-binding the same device
    294   /// will return <code>true</code> and will do nothing.
    295   ///
    296   /// Any previously-bound device will be released. It is an error to bind
    297   /// a device when it is already bound to another instance. If you want
    298   /// to move a device between instances, first unbind it from the old one, and
    299   /// then rebind it to the new one.
    300   ///
    301   /// Binding a device will invalidate that portion of the web page to flush the
    302   /// contents of the new device to the screen.
    303   ///
    304   /// @param[in] graphics A <code>Graphics2D</code> to bind.
    305   ///
    306   /// @return true if bind was successful or false if the device was not the
    307   /// correct type. On success, a reference to the device will be held by the
    308   /// instance, so the caller can release its reference if it chooses.
    309   bool BindGraphics(const Graphics2D& graphics);
    310 
    311   /// Binds the given Graphics3D as the current display surface.
    312   /// Refer to <code>BindGraphics(const Graphics2D& graphics)</code> for
    313   /// further information.
    314   ///
    315   /// @param[in] graphics A <code>Graphics3D</code> to bind.
    316   ///
    317   /// @return true if bind was successful or false if the device was not the
    318   /// correct type. On success, a reference to the device will be held by the
    319   /// instance, so the caller can release its reference if it chooses.
    320   bool BindGraphics(const Graphics3D& graphics);
    321 
    322   /// Binds the given Compositor as the current display surface.
    323   /// Refer to <code>BindGraphics(const Graphics2D& graphics)</code> for
    324   /// further information.
    325   ///
    326   /// @param[in] compositor A <code>Compositor</code> to bind.
    327   ///
    328   /// @return true if bind was successful or false if the device was not the
    329   /// correct type. On success, a reference to the device will be held by the
    330   /// instance, so the caller can release its reference if it chooses.
    331   bool BindGraphics(const Compositor& compositor);
    332 
    333   /// IsFullFrame() determines if the instance is full-frame (repr).
    334   /// Such an instance represents the entire document in a frame rather than an
    335   /// embedded resource. This can happen if the user does a top-level
    336   /// navigation or the page specifies an iframe to a resource with a MIME
    337   /// type registered by the module.
    338   ///
    339   /// @return true if the instance is full-frame, false if not.
    340   bool IsFullFrame();
    341 
    342   /// RequestInputEvents() requests that input events corresponding to the
    343   /// given input events are delivered to the instance.
    344   ///
    345   /// By default, no input events are delivered. Call this function with the
    346   /// classes of events you are interested in to have them be delivered to
    347   /// the instance. Calling this function will override any previous setting for
    348   /// each specified class of input events (for example, if you previously
    349   /// called RequestFilteringInputEvents(), this function will set those events
    350   /// to non-filtering mode).
    351   ///
    352   /// Input events may have high overhead, so you should only request input
    353   /// events that your plugin will actually handle. For example, the browser may
    354   /// do optimizations for scroll or touch events that can be processed
    355   /// substantially faster if it knows there are no non-default receivers for
    356   /// that message. Requesting that such messages be delivered, even if they are
    357   /// processed very quickly, may have a noticeable effect on the performance of
    358   /// the page.
    359   ///
    360   /// When requesting input events through this function, the events will be
    361   /// delivered and <em>not</em> bubbled to the page. This means that even if
    362   /// you aren't interested in the message, no other parts of the page will get
    363   /// the message.
    364   ///
    365   /// <strong>Example:</strong>
    366   ///
    367   /// @code
    368   ///   RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
    369   ///   RequestFilteringInputEvents(
    370   ///       PP_INPUTEVENT_CLASS_WHEEL | PP_INPUTEVENT_CLASS_KEYBOARD);
    371   ///
    372   /// @endcode
    373   ///
    374   /// @param event_classes A combination of flags from
    375   /// <code>PP_InputEvent_Class</code> that identifies the classes of events
    376   /// the instance is requesting. The flags are combined by logically ORing
    377   /// their values.
    378   ///
    379   /// @return <code>PP_OK</code> if the operation succeeded,
    380   /// <code>PP_ERROR_BADARGUMENT</code> if instance is invalid, or
    381   /// <code>PP_ERROR_NOTSUPPORTED</code> if one of the event class bits were
    382   /// illegal. In the case of an invalid bit, all valid bits will be applied
    383   /// and only the illegal bits will be ignored.
    384   int32_t RequestInputEvents(uint32_t event_classes);
    385 
    386   /// RequestFilteringInputEvents() requests that input events corresponding
    387   /// to the given input events are delivered to the instance for filtering.
    388   ///
    389   /// By default, no input events are delivered. In most cases you would
    390   /// register to receive events by calling RequestInputEvents(). In some cases,
    391   /// however, you may wish to filter events such that they can be bubbled up
    392   /// to the DOM. In this case, register for those classes of events using
    393   /// this function instead of RequestInputEvents(). Keyboard events must always
    394   /// be registered in filtering mode.
    395   ///
    396   /// Filtering input events requires significantly more overhead than just
    397   /// delivering them to the instance. As such, you should only request
    398   /// filtering in those cases where it's absolutely necessary. The reason is
    399   /// that it requires the browser to stop and block for the instance to handle
    400   /// the input event, rather than sending the input event asynchronously. This
    401   /// can have significant overhead.
    402   ///
    403   /// <strong>Example:</strong>
    404   ///
    405   /// @code
    406   ///
    407   ///   RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
    408   ///   RequestFilteringInputEvents(
    409   ///       PP_INPUTEVENT_CLASS_WHEEL | PP_INPUTEVENT_CLASS_KEYBOARD);
    410   ///
    411   /// @endcode
    412   ///
    413   /// @param event_classes A combination of flags from
    414   /// <code>PP_InputEvent_Class</code> that identifies the classes of events
    415   /// the instance is requesting. The flags are combined by logically ORing
    416   /// their values.
    417   ///
    418   /// @return <code>PP_OK</code> if the operation succeeded,
    419   /// <code>PP_ERROR_BADARGUMENT</code> if instance is invalid, or
    420   /// <code>PP_ERROR_NOTSUPPORTED</code> if one of the event class bits were
    421   /// illegal. In the case of an invalid bit, all valid bits will be applied
    422   /// and only the illegal bits will be ignored.
    423   int32_t RequestFilteringInputEvents(uint32_t event_classes);
    424 
    425   /// ClearInputEventRequest() requests that input events corresponding to the
    426   /// given input classes no longer be delivered to the instance.
    427   ///
    428   /// By default, no input events are delivered. If you have previously
    429   /// requested input events using RequestInputEvents() or
    430   /// RequestFilteringInputEvents(), this function will unregister handling
    431   /// for the given instance. This will allow greater browser performance for
    432   /// those events.
    433   ///
    434   /// <strong>Note: </strong> You may still get some input events after
    435   /// clearing the flag if they were dispatched before the request was cleared.
    436   /// For example, if there are 3 mouse move events waiting to be delivered,
    437   /// and you clear the mouse event class during the processing of the first
    438   /// one, you'll still receive the next two. You just won't get more events
    439   /// generated.
    440   ///
    441   /// @param[in] event_classes A combination of flags from
    442   /// <code>PP_InputEvent_Class</code> that identifies the classes of events the
    443   /// instance is no longer interested in.
    444   void ClearInputEventRequest(uint32_t event_classes);
    445 
    446   /// PostMessage() asynchronously invokes any listeners for message events on
    447   /// the DOM element for the given instance. A call to PostMessage() will
    448   /// not block while the message is processed.
    449   ///
    450   /// <strong>Example:</strong>
    451   ///
    452   /// @code{.html}
    453   ///
    454   /// <body>
    455   ///   <object id="plugin"
    456   ///           type="application/x-ppapi-postMessage-example"/>
    457   ///   <script type="text/javascript">
    458   ///     var plugin = document.getElementById('plugin');
    459   ///     plugin.addEventListener("message",
    460   ///                             function(message) { alert(message.data); },
    461   ///                             false);
    462   ///   </script>
    463   /// </body>
    464   ///
    465   /// @endcode
    466   ///
    467   /// The instance then invokes PostMessage() as follows:
    468   ///
    469   /// @code
    470   ///
    471   ///  PostMessage(pp::Var("Hello world!"));
    472   ///
    473   /// @endcode
    474   ///
    475   /// The browser will pop-up an alert saying "Hello world!"
    476   ///
    477   /// When passing array or dictionary <code>PP_Var</code>s, the entire
    478   /// reference graph will be converted and transferred. If the reference graph
    479   /// has cycles, the message will not be sent and an error will be logged to
    480   /// the console.
    481   ///
    482   /// Listeners for message events in JavaScript code will receive an object
    483   /// conforming to the HTML 5 <code>MessageEvent</code> interface.
    484   /// Specifically, the value of message will be contained as a property called
    485   /// data in the received <code>MessageEvent</code>.
    486   ///
    487   /// This messaging system is similar to the system used for listening for
    488   /// messages from Web Workers. Refer to
    489   /// <code>http://www.whatwg.org/specs/web-workers/current-work/</code> for
    490   /// further information.
    491   ///
    492   /// Refer to HandleMessage() for receiving events from JavaScript.
    493   ///
    494   /// @param[in] message A <code>Var</code> containing the data to be sent to
    495   /// JavaScript. Message can have a numeric, boolean, or string value.
    496   /// Array/Dictionary types are supported from Chrome M29 onward.
    497   /// All var types are copied when passing them to JavaScript.
    498   void PostMessage(const Var& message);
    499 
    500   /// Dev-Channel Only
    501   ///
    502   /// Registers a handler for receiving messages from JavaScript. If a handler
    503   /// is registered this way, it will replace the Instance's HandleMessage
    504   /// method, and all messages sent from JavaScript via postMessage and
    505   /// postMessageAndAwaitResponse will be dispatched to
    506   /// <code>message_handler</code>.
    507   ///
    508   /// The function calls will be dispatched via <code>message_loop</code>. This
    509   /// means that the functions will be invoked on the thread to which
    510   /// <code>message_loop</code> is attached, when <code>message_loop</code> is
    511   /// run. It is illegal to pass the main thread message loop;
    512   /// RegisterMessageHandler will return PP_ERROR_WRONG_THREAD in that case.
    513   /// If you quit <code>message_loop</code> before calling Unregister(),
    514   /// the browser will not be able to call functions in the plugin's message
    515   /// handler any more. That could mean missing some messages or could cause a
    516   /// leak if you depend on Destroy() to free hander data. So you should,
    517   /// whenever possible, Unregister() the handler prior to quitting its event
    518   /// loop.
    519   ///
    520   /// Attempting to register a message handler when one is already registered
    521   /// will cause the current MessageHandler to be unregistered and replaced. In
    522   /// that case, no messages will be sent to the "default" message handler
    523   /// (pp::Instance::HandleMessage()). Messages will stop arriving at the prior
    524   /// message handler and will begin to be dispatched at the new message
    525   /// handler.
    526   ///
    527   /// @param[in] message_handler The plugin-provided object for handling
    528   /// messages. The instance does not take ownership of the pointer; it is up
    529   /// to the plugin to ensure that |message_handler| lives until its
    530   /// WasUnregistered() function is invoked.
    531   /// @param[in] message_loop Represents the message loop on which
    532   /// MessageHandler's functions should be invoked.
    533   /// @return PP_OK on success, or an error from pp_errors.h.
    534   int32_t RegisterMessageHandler(MessageHandler* message_handler,
    535                                  const MessageLoop& message_loop);
    536 
    537   /// Unregisters the current message handler for this instance if one is
    538   /// registered. After this call, the message handler (if one was
    539   /// registered) will have "WasUnregistered" called on it and will receive no
    540   /// further messages. After that point, all messages sent from JavaScript
    541   /// using postMessage() will be dispatched to pp::Instance::HandleMessage()
    542   /// on the main thread. Attempts to call postMessageAndAwaitResponse() from
    543   /// JavaScript after that point will fail.
    544   ///
    545   /// Attempting to unregister a message handler when none is registered has no
    546   /// effect.
    547   void UnregisterMessageHandler();
    548 
    549   /// @}
    550 
    551   /// @{
    552   /// @name PPB_Console methods for logging to the console:
    553 
    554   /// Logs the given message to the JavaScript console associated with the
    555   /// given plugin instance with the given logging level. The name of the plugin
    556   /// issuing the log message will be automatically prepended to the message.
    557   /// The value may be any type of Var.
    558   void LogToConsole(PP_LogLevel level, const Var& value);
    559 
    560   /// Logs a message to the console with the given source information rather
    561   /// than using the internal PPAPI plugin name. The name must be a string var.
    562   ///
    563   /// The regular log function will automatically prepend the name of your
    564   /// plugin to the message as the "source" of the message. Some plugins may
    565   /// wish to override this. For example, if your plugin is a Python
    566   /// interpreter, you would want log messages to contain the source .py file
    567   /// doing the log statement rather than have "python" show up in the console.
    568   void LogToConsoleWithSource(PP_LogLevel level,
    569                               const Var& source,
    570                               const Var& value);
    571 
    572   /// @}
    573 
    574   /// AddPerInstanceObject() associates an instance with an interface,
    575   /// creating an object.
    576   ///
    577   /// Many optional interfaces are associated with a plugin instance. For
    578   /// example, the find in PPP_Find interface receives updates on a per-instance
    579   /// basis. This "per-instance" tracking allows such objects to associate
    580   /// themselves with an instance as "the" handler for that interface name.
    581   ///
    582   /// In the case of the find example, the find object registers with its
    583   /// associated instance in its constructor and unregisters in its destructor.
    584   /// Then whenever it gets updates with a PP_Instance parameter, it can
    585   /// map back to the find object corresponding to that given PP_Instance by
    586   /// calling GetPerInstanceObject.
    587   ///
    588   /// This lookup is done on a per-interface-name basis. This means you can
    589   /// only have one object of a given interface name associated with an
    590   /// instance.
    591   ///
    592   /// If you are adding a handler for an additional interface, be sure to
    593   /// register with the module (AddPluginInterface) for your interface name to
    594   /// get the C calls in the first place.
    595   ///
    596   /// Refer to RemovePerInstanceObject() and GetPerInstanceObject() for further
    597   /// information.
    598   ///
    599   /// @param[in] interface_name The name of the interface to associate with the
    600   /// instance
    601   /// @param[in] object
    602   void AddPerInstanceObject(const std::string& interface_name, void* object);
    603 
    604   // {PENDING: summarize Remove method here}
    605   ///
    606   /// Refer to AddPerInstanceObject() for further information.
    607   ///
    608   /// @param[in] interface_name The name of the interface to associate with the
    609   /// instance
    610   /// @param[in] object
    611   void RemovePerInstanceObject(const std::string& interface_name, void* object);
    612 
    613   /// Static version of AddPerInstanceObject that takes an InstanceHandle. As
    614   /// with all other instance functions, this must only be called on the main
    615   /// thread.
    616   static void RemovePerInstanceObject(const InstanceHandle& instance,
    617                                       const std::string& interface_name,
    618                                       void* object);
    619 
    620   /// Look up an object previously associated with an instance. Returns NULL
    621   /// if the instance is invalid or there is no object for the given interface
    622   /// name on the instance.
    623   ///
    624   /// Refer to AddPerInstanceObject() for further information.
    625   ///
    626   /// @param[in] instance
    627   /// @param[in] interface_name The name of the interface to associate with the
    628   /// instance.
    629   static void* GetPerInstanceObject(PP_Instance instance,
    630                                     const std::string& interface_name);
    631 
    632  private:
    633   PP_Instance pp_instance_;
    634 
    635   typedef std::map<std::string, void*> InterfaceNameToObjectMap;
    636   InterfaceNameToObjectMap interface_name_to_objects_;
    637 };
    638 
    639 }  // namespace pp
    640 
    641 #endif  // PPAPI_CPP_INSTANCE_H_
    642