• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
pp_instance()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