// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef PPAPI_CPP_INSTANCE_H_ #define PPAPI_CPP_INSTANCE_H_ /// @file /// Defines the C++ wrapper for a plugin instance. /// /// @addtogroup CPP /// @{ #include #include #include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_resource.h" #include "ppapi/c/pp_stdint.h" struct PP_InputEvent; /// The C++ interface to the Pepper API. namespace pp { class Graphics2D; class Graphics3D_Dev; class InputEvent; class ImageData; class Point; class Rect; class Rect; class Resource; class Surface3D_Dev; class URLLoader; class Var; class Widget_Dev; class Instance { public: /// Construction of an instance should only be done in response to a browser /// request in Module::CreateInstance. Otherwise, the instance will lack the /// proper bookkeeping in the browser and in the C++ wrapper. /// /// Init() will be called immediately after the constructor. This allows you /// to perform initialization tasks that can fail and to report that failure /// to the browser. explicit Instance(PP_Instance instance); /// When the instance is removed from the web page, the pp::Instance object /// will be deleted. You should never delete the Instance object yourself /// since the lifetime is handled by the C++ wrapper and is controlled by the /// browser's calls to the PPP_Instance interface. /// /// The PP_Instance identifier will still be valid during this call so the /// plugin can perform cleanup-related tasks. Once this function returns, the /// PP_Instance handle will be invalid. This means that you can't do any /// asynchronous operations like network requests or file writes from this /// destructor since they will be immediately canceled. /// /// Important note: This function will always be skipped on /// untrusted (Native Client) implementations. This function may be skipped /// in certain circumstances when Chrome does "fast shutdown". Fast shutdown /// will happen in some cases when all plugin instances are being deleted, /// and no cleanup functions will be called. The module will just be unloaded /// and the process terminated. virtual ~Instance(); /// Returns the PP_Instance identifying this object. When using the PPAPI C++ /// wrappers this is not normally necessary, but is required when using the /// lower-level C APIs. PP_Instance pp_instance() const { return pp_instance_; } /// Initializes this plugin with the given arguments. This will be called /// immediately after the instance object is constructed. /// /// @param[in] argc The number of arguments contained in @a argn and @a argv. /// /// @param[in] argn An array of argument names. These argument names are /// supplied in the tag, for example: /// will produce two argument /// names: "id" and "dimensions." /// /// @param[in] argv An array of argument values. These are the values of the /// arguments listed in the tag, for example /// will produce two argument /// values: "nacl_module" and "2". The indices of these values match the /// indices of the corresponding names in @a argn. /// /// @return True on success. Returning false causes the plugin /// instance to be deleted and no other functions to be called. virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]); /// @{ /// @name PPP_Instance methods for the plugin to override: /// Notification that the position, the size, or the clip rectangle of the /// element in the browser that corresponds to this instance has changed. /// /// A typical implementation will check the size of the @a position argument /// and reallocate the graphics context when a different size is received. /// Note that this function will be called for scroll events where the size /// doesn't change, so you should always check that the size is actually /// different before doing any reallocations. /// /// @param[in] position The location on the page of the instance. This is /// relative to the top left corner of the viewport, which changes as the /// page is scrolled. Generally the size of this value will be used to create /// a graphics device, and the position is ignored (most things are relative /// to the instance so the absolute position isn't useful in most cases). /// /// @param[in] clip The visible region of the instance. This is relative to /// the top left of the plugin's coordinate system (not the page). If the /// plugin is invisible, @a clip will be (0, 0, 0, 0). /// /// It's recommended to check for invisible instances and to stop /// generating graphics updates in this case to save system resources. It's /// not usually worthwhile, however, to generate partial updates according to /// the clip when the instance is partially visible. Instead, update the /// entire region. The time saved doing partial paints is usually not /// significant and it can create artifacts when scrolling (this notification /// is sent asynchronously from scolling so there can be flashes of old /// content in the exposed regions). virtual void DidChangeView(const Rect& position, const Rect& clip); /// Notification that the instance has gained or lost focus. Having focus /// means that keyboard events will be sent to the instance. An instance's /// default condition is that it will not have focus. /// /// Note: clicks on instances will give focus only if you handle the /// click event. Return @a true from HandleInputEvent to signal that the click /// event was handled. Otherwise the browser will bubble the event and give /// focus to the element on the page that actually did end up consuming it. /// If you're not getting focus, check to make sure you're returning true from /// the mouse click in HandleInputEvent. /// /// @param[in] has_focus Indicates the new focused state of the instance. virtual void DidChangeFocus(bool has_focus); /// Function for receiving input events from the browser. The default /// implementation does nothing and returns false. /// /// In order to receive input events, you must register for them by calling /// RequestInputEvents() or RequestFilteringInputEvents(). By /// default, no events are delivered. /// /// If the event was handled, it will not be forwarded to the web page or /// browser. If it was not handled, it will bubble according to the normal /// rules. So it is important that an instance respond accurately with whether /// event propagation should continue. /// /// Event propagation also controls focus. If you handle an event like a mouse /// event, typically the instance will be given focus. Returning false from /// a filtered event handler or not registering for an event type means that /// the click will be given to a lower part of the page and your instance will /// not receive focus. This allows an instance to be partially transparent, /// where clicks on the transparent areas will behave like clicks to the /// underlying page. /// /// In general, you should try to keep input event handling short. Especially /// for filtered input events, the browser or page may be blocked waiting for /// you to respond. /// /// The caller of this function will maintain a reference to the input event /// resource during this call. Unless you take a reference to the resource /// to hold it for later, you don't need to release it. /// /// \note If you're not receiving input events, make sure you register for the /// event classes you want by calling RequestInputEvents or /// RequestFilteringInputEvents. If you're still not receiving keyboard input /// events, make sure you're returning true (or using a non-filtered event /// handler) for mouse events. Otherwise, the instance will not receive focus /// and keyboard events will not be sent. /// /// \see RequestInputEvents and RequestFilteringInputEvents /// /// @return true if the event was handled, false if not. If you have /// registered to filter this class of events by calling /// RequestFilteringInputEvents, and you return false, the event will /// be forwarded to the page (and eventually the browser) for the default /// handling. For non-filtered events, the return value will be ignored. virtual bool HandleInputEvent(const pp::InputEvent& event); /// Notification of a data stream available after an instance was created /// based on the MIME type of a DOMWindow navigation. This only applies to /// modules that are pre-registered to handle certain MIME types. If you /// haven't specifically registered to handle a MIME type or aren't positive /// this applies to you, you can ignore this function. The default /// implementation just returns false. /// /// The given url_loader corresponds to a URLLoader object that is /// already opened. Its response headers may be queried using GetResponseInfo. /// If you want to use the URLLoader to read data, you will need to save a /// copy of it or the underlying resource will be freed when this function /// returns and the load will be canceled. /// /// This method returns false if the module cannot handle the data. In /// response to this method, the module should call ReadResponseBody to read /// the incoming data. /// /// @param[in] url_loader A PP_Resource an open PPB_URLLoader instance. /// /// @return true if the data was handled, false otherwise. virtual bool HandleDocumentLoad(const URLLoader& url_loader); /// HandleMessage() is a function that the browser calls when PostMessage() /// is invoked on the DOM element for the instance in JavaScript. Note /// that PostMessage() in the JavaScript interface is asynchronous, meaning /// JavaScript execution will not be blocked while HandleMessage() is /// processing the message. /// /// @param[in] message A Var containing the data sent from /// JavaScript. Message can have an int32_t, double, bool, or string value /// (objects are not supported). /// /// \see PostMessage for sending messages to JavaScript. /// /// Example: /// /// The following JavaScript code invokes HandleMessage, passing /// the instance on which it was invoked, with message being a /// string Var containing "Hello world!" /// /// @code /// /// /// /// /// /// /// @endcode virtual void HandleMessage(const Var& message); /// @} /// @{ /// @name PPB_Instance methods for querying the browser: /// BindGraphics() binds the given graphics as the current display surface. /// The contents of this device is what will be displayed in the instance's /// area on the web page. The device must be a 2D or a 3D device. /// /// You can pass an is_null() (default constructed) Graphics2D /// as the device parameter to unbind all devices from the given instance. /// The instance will then appear transparent. Re-binding the same device /// will return true and will do nothing. /// /// Any previously-bound device will be released. It is an error to bind /// a device when it is already bound to another instance. If you want /// to move a device between instances, first unbind it from the old one, and /// then rebind it to the new one. /// /// Binding a device will invalidate that portion of the web page to flush the /// contents of the new device to the screen. /// /// @param[in] graphics A Graphics2D object to bind. /// /// @return true if bind was successful or false if the device was not the /// correct type. On success, a reference to the device will be held by the /// instance, so the caller can release its reference if it chooses. bool BindGraphics(const Graphics2D& graphics); /// Binds the given Graphics3D as the current display surface. /// See BindGraphics(const Graphics2D& graphics). bool BindGraphics(const Graphics3D_Dev& graphics); /// Binds the given Surface3D as the current display surface. /// See BindGraphics(const Graphics2D& graphics). bool BindGraphics(const Surface3D_Dev& graphics); /// IsFullFrame() determines if the instance is full-frame (repr). /// Such an instance represents the entire document in a frame rather than an /// embedded resource. This can happen if the user does a top-level /// navigation or the page specifies an iframe to a resource with a MIME /// type registered by the module. /// /// @return True if the instance is full-frame, false if not. bool IsFullFrame(); /// Request that input events corresponding to the given input events are /// delivered to the instance. /// /// You can not use this function to request keyboard events /// (PP_INPUTEVENT_CLASS_KEYBOARD). You must use RequestFilteringInputEvents() /// for this class of input. /// /// By default, no input events are delivered. Call this function with the /// classes of events you are interested in to have them be delivered to /// the instance. Calling this function will override any previous setting for /// each specified class of input events (for example, if you previously /// called RequestFilteringInputEvents(), this function will set those events /// to non-filtering mode). /// /// Input events may have high overhead, so you should only request input /// events that your plugin will actually handle. For example, the browser may /// do optimizations for scroll or touch events that can be processed /// substantially faster if it knows there are no non-default receivers for /// that message. Requesting that such messages be delivered, even if they are /// processed very quickly, may have a noticable effect on the performance of /// the page. /// /// When requesting input events through this function, the events will be /// delivered and not bubbled to the page. This means that even if you /// aren't interested in the message, no other parts of the page will get /// a crack at the message. /// /// Example: /// RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE); /// RequestFilteringInputEvents( /// PP_INPUTEVENT_CLASS_WHEEL | PP_INPUTEVENT_CLASS_KEYBOARD); /// /// @param event_classes A combination of flags from PP_InputEvent_Class that /// identifies the classes of events the instance is requesting. The flags /// are combined by logically ORing their values. /// /// @return PP_OK if the operation succeeded, PP_ERROR_BADARGUMENT if instance /// is invalid, or PP_ERROR_NOTSUPPORTED if one of the event class bits were /// illegal. In the case of an invalid bit, all valid bits will be applied /// and only the illegal bits will be ignored. The most common cause of a /// PP_ERROR_NOTSUPPORTED return value is requesting keyboard events, these /// must use RequestFilteringInputEvents(). int32_t RequestInputEvents(uint32_t event_classes); /// Request that input events corresponding to the given input events are /// delivered to the instance for filtering. /// /// By default, no input events are delivered. In most cases you would /// register to receive events by calling RequestInputEvents(). In some cases, /// however, you may wish to filter events such that they can be bubbled up /// to the DOM. In this case, register for those classes of events using /// this function instead of RequestInputEvents(). Keyboard events must always /// be registered in filtering mode. /// /// Filtering input events requires significantly more overhead than just /// delivering them to the instance. As such, you should only request /// filtering in those cases where it's absolutely necessary. The reason is /// that it requires the browser to stop and block for the instance to handle /// the input event, rather than sending the input event asynchronously. This /// can have significant overhead. /// /// Example: /// RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE); /// RequestFilteringInputEvents( /// PP_INPUTEVENT_CLASS_WHEEL | PP_INPUTEVENT_CLASS_KEYBOARD); /// /// @return PP_OK if the operation succeeded, PP_ERROR_BADARGUMENT if instance /// is invalid, or PP_ERROR_NOTSUPPORTED if one of the event class bits were /// illegal. In the case of an invalid bit, all valid bits will be applied /// and only the illegal bits will be ignored. int32_t RequestFilteringInputEvents(uint32_t event_classes); /// Request that input events corresponding to the given input classes no /// longer be delivered to the instance. /// /// By default, no input events are delivered. If you have previously /// requested input events via RequestInputEvents() or /// RequestFilteringInputEvents(), this function will unregister handling /// for the given instance. This will allow greater browser performance for /// those events. /// /// Note that you may still get some input events after clearing the flag if /// they were dispatched before the request was cleared. For example, if /// there are 3 mouse move events waiting to be delivered, and you clear the /// mouse event class during the processing of the first one, you'll still /// receive the next two. You just won't get more events generated. /// /// @param event_classes A combination of flags from PP_InputEvent_Class that /// identifies the classes of events the instance is no longer interested in. void ClearInputEventRequest(uint32_t event_classes); /// PostMessage() asynchronously invokes any listeners for message events on /// the DOM element for the given instance. A call to PostMessage() will // /not block while the message is processed. /// /// @param[in] message A Var containing the data to be sent to /// JavaScript. /// Message can have a numeric, boolean, or string value; arrays and /// dictionaries are not yet supported. Ref-counted var types are copied, and /// are therefore not shared between the instance and the browser. /// /// Listeners for message events in JavaScript code will receive an object /// conforming to the HTML 5 MessageEvent interface. /// Specifically, the value of message will be contained as a property called /// data in the received MessageEvent. /// /// This messaging system is similar to the system used for listening for /// messages from Web Workers. Refer to /// http://www.whatwg.org/specs/web-workers/current-work/ for /// further information. /// /// @see HandleMessage() for receiving events from JavaScript. /// /// Example: /// /// @code /// /// /// /// /// /// /// @endcode /// /// The instance then invokes PostMessage() as follows: /// /// @code /// /// PostMessage(pp::Var("Hello world!")); /// /// @endcode /// /// The browser will pop-up an alert saying "Hello world!" void PostMessage(const Var& message); /// @} /// Associates a plugin instance with an interface, /// creating an object... {PENDING: clarify!} /// /// Many optional interfaces are associated with a plugin instance. For /// example, the find in PPP_Find interface receives updates on a per-instance /// basis. This "per-instance" tracking allows such objects to associate /// themselves with an instance as "the" handler for that interface name. /// /// In the case of the find example, the find object registers with its /// associated instance in its constructor and unregisters in its destructor. /// Then whenever it gets updates with a PP_Instance parameter, it can /// map back to the find object corresponding to that given PP_Instance by /// calling GetPerInstanceObject. /// /// This lookup is done on a per-interface-name basis. This means you can /// only have one object of a given interface name associated with an /// instance. /// /// If you are adding a handler for an additional interface, be sure to /// register with the module (AddPluginInterface) for your interface name to /// get the C calls in the first place. /// /// @see RemovePerInstanceObject /// @see GetPerInstanceObject void AddPerInstanceObject(const std::string& interface_name, void* object); /// {PENDING: summarize Remove method here} /// /// @see AddPerInstanceObject void RemovePerInstanceObject(const std::string& interface_name, void* object); /// Look up an object previously associated with an instance. Returns NULL /// if the instance is invalid or there is no object for the given interface /// name on the instance. /// /// @see AddPerInstanceObject static void* GetPerInstanceObject(PP_Instance instance, const std::string& interface_name); private: PP_Instance pp_instance_; typedef std::map InterfaceNameToObjectMap; InterfaceNameToObjectMap interface_name_to_objects_; }; } // namespace pp /// @} /// End addtogroup CPP #endif // PPAPI_CPP_INSTANCE_H_