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