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