// Copyright (c) 2009 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 CHROME_FRAME_CHROME_FRAME_NPAPI_H_ #define CHROME_FRAME_CHROME_FRAME_NPAPI_H_ #include #include #include #include "chrome_frame/chrome_frame_automation.h" #include "chrome_frame/chrome_frame_plugin.h" #include "chrome_frame/np_browser_functions.h" #include "chrome_frame/np_event_listener.h" #include "chrome_frame/np_proxy_service.h" #include "chrome_frame/npapi_url_request.h" class MessageLoop; // ChromeFrameNPAPI: Implementation of the NPAPI plugin, which is responsible // for hosting a chrome frame, i.e. an iframe like widget which hosts the the // chrome window. This object delegates to Chrome.exe (via the Chrome // IPC-based automation mechanism) for the actual rendering. class ChromeFrameNPAPI : public CWindowImpl, public ChromeFramePlugin, public NpEventDelegate { public: typedef ChromeFramePlugin Base; // NPObject structure which is exposed by us. struct ChromeFrameNPObject : public NPObject { NPP npp; ChromeFrameNPAPI* chrome_frame_plugin_instance; }; typedef enum { PLUGIN_PROPERTY_VERSION, PLUGIN_PROPERTY_SRC, PLUGIN_PROPERTY_ONLOAD, PLUGIN_PROPERTY_ONERROR, PLUGIN_PROPERTY_ONMESSAGE, PLUGIN_PROPERTY_READYSTATE, PLUGIN_PROPERTY_ONPRIVATEMESSAGE, PLUGIN_PROPERTY_USECHROMENETWORK, PLUGIN_PROPERTY_COUNT // must be last } PluginPropertyId; static const int kWmSwitchFocusToChromeFrame = WM_APP + 0x100; static NPClass plugin_class_; static NPClass* PluginClass() { return &plugin_class_; } ChromeFrameNPAPI(); ~ChromeFrameNPAPI(); bool Initialize(NPMIMEType mime_type, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[]); void Uninitialize(); bool SetWindow(NPWindow* window_info); void UrlNotify(const char* url, NPReason reason, void* notify_data); bool NewStream(NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stream_type); void Print(NPPrint* print_info); // NPObject functions, which ensure that the plugin object is scriptable. static bool HasMethod(NPObject* obj, NPIdentifier name); static bool Invoke(NPObject* header, NPIdentifier name, const NPVariant* args, uint32_t arg_count, NPVariant* result); static NPObject* AllocateObject(NPP instance, NPClass* class_name); static void DeallocateObject(NPObject* header); // Called by the scripting environment when the native code is shutdown. // Any attempt to message a NPObject instance after the invalidate callback // has been called will result in undefined behavior, even if the native code // is still retaining those NPObject instances. static void Invalidate(NPObject* header); // The following functions need to be implemented to ensure that FF3 // invokes methods on the plugin. If these methods are not implemented // then invokes on the plugin NPObject from the script fail with a // bad NPObject error. static bool HasProperty(NPObject* obj, NPIdentifier name); static bool GetProperty(NPObject* obj, NPIdentifier name, NPVariant *variant); static bool SetProperty(NPObject* obj, NPIdentifier name, const NPVariant *variant); // Returns the ChromeFrameNPAPI object pointer from the NPP instance structure // passed in by the browser. static ChromeFrameNPAPI* ChromeFrameInstanceFromPluginInstance(NPP instance); // Returns the ChromeFrameNPAPI object pointer from the NPObject structure // which represents our plugin class. static ChromeFrameNPAPI* ChromeFrameInstanceFromNPObject(void* object); // Return a UrlRequest instance associated with the given instance and // stream combination. static NPAPIUrlRequest* ValidateRequest(NPP instance, void* notify_data); BEGIN_MSG_MAP(ChromeFrameNPAPI) MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) CHAIN_MSG_MAP(Base) END_MSG_MAP() LRESULT OnSetFocus(UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled); // NO_LINT // Implementation of NpEventDelegate virtual void OnEvent(const char* event_name); void OnFocus(); void OnBlur(); // Implementation of SetProperty, public to allow unittesting. bool SetProperty(NPIdentifier name, const NPVariant *variant); // Implementation of GetProperty, public to allow unittesting. bool GetProperty(NPIdentifier name, NPVariant *variant); // Initialize string->identifier mapping, public to allow unittesting. static void InitializeIdentifiers(); bool HandleContextMenuCommand(UINT cmd); protected: // Handler for accelerator messages passed on from the hosted chrome // instance. virtual void OnAcceleratorPressed(int tab_handle, const MSG& accel_message); virtual void OnTabbedOut(int tab_handle, bool reverse); virtual void OnOpenURL(int tab_handle, const GURL& url, int open_disposition); virtual void OnLoad(int tab_handle, const GURL& url); virtual void OnMessageFromChromeFrame(int tab_handle, const std::string& message, const std::string& origin, const std::string& target); virtual void OnRequestStart(int tab_handle, int request_id, const IPC::AutomationURLRequest& request); virtual void OnRequestRead(int tab_handle, int request_id, int bytes_to_read); virtual void OnRequestEnd(int tab_handle, int request_id, const URLRequestStatus& status); virtual void OnSetCookieAsync(int tab_handle, const GURL& url, const std::string& cookie); // ChromeFrameDelegate overrides virtual void OnLoadFailed(int error_code, const std::string& url); virtual void OnAutomationServerReady(); virtual void OnAutomationServerLaunchFailed( AutomationLaunchResult reason, const std::string& server_version); private: void SubscribeToFocusEvents(); void UnsubscribeFromFocusEvents(); // Equivalent of: // event = window.document.createEvent("Event"); // event.initEvent(type, bubbles, cancelable); // and then returns the event object. bool CreateEvent(const std::string& type, bool bubbles, bool cancelable, NPObject** basic_event); // Creates and initializes an event object of type "message". // Used for postMessage. bool CreateMessageEvent(bool bubbles, bool cancelable, const std::string& data, const std::string& origin, NPObject** message_event); // Calls chrome_frame.dispatchEvent to fire events to event listeners. void DispatchEvent(NPObject* event); // Returns a pointer to the element in the page that // hosts the plugin. Note that this is the parent element of the // element. The element doesn't support some of the events that // we require, so we use the object element for receiving events. bool GetObjectElement(nsIDOMElement** element); // Prototype for all methods that can be invoked from script. typedef bool (ChromeFrameNPAPI::*PluginMethod)(NPObject* npobject, const NPVariant* args, uint32_t arg_count, NPVariant* result); // Implementations of scriptable methods. bool NavigateToURL(const NPVariant* args, uint32_t arg_count, NPVariant* result); bool postMessage(NPObject* npobject, const NPVariant* args, uint32_t arg_count, NPVariant* result); // This method is only available when the control is in privileged mode. bool postPrivateMessage(NPObject* npobject, const NPVariant* args, uint32_t arg_count, NPVariant* result); // Pointers to method implementations. static PluginMethod plugin_methods_[]; // NPObject method ids exposed by the plugin. static NPIdentifier plugin_method_identifiers_[]; // NPObject method names exposed by the plugin. static const NPUTF8* plugin_method_identifier_names_[]; // NPObject property ids exposed by the plugin. static NPIdentifier plugin_property_identifiers_[]; // NPObject property names exposed by the plugin. static const NPUTF8* plugin_property_identifier_names_[]; virtual void OnFinalMessage(HWND window); // Helper function to invoke a function on a NPObject. bool InvokeDefault(NPObject* object, const std::string& param, NPVariant* result); bool InvokeDefault(NPObject* object, const NPVariant& param, NPVariant* result); bool InvokeDefault(NPObject* object, unsigned param_count, const NPVariant* params, NPVariant* result); // Helper function to convert javascript code to a NPObject we can // invoke on. virtual NPObject* JavascriptToNPObject(const std::string& function_name); // Helper function to execute a script. // Returns S_OK on success. bool ExecuteScript(const std::string& script, NPVariant* result); // Returns true if the script passed in is a valid function in the DOM. bool IsValidJavascriptFunction(const std::string& script); // Converts the data parameter to an NPVariant and forwards the call to the // other FireEvent method. void FireEvent(const std::string& event_type, const std::string& data); // Creates an event object, assigns the data parameter to a |data| property // on the event object and then calls DispatchEvent to fire the event to // listeners. event_type is the name of the event being fired. void FireEvent(const std::string& event_type, const NPVariant& data); // Returns a new prefs service. Virtual to allow overriding in unittests. virtual NpProxyService* CreatePrefService(); // Returns our associated windows' location. virtual std::string GetLocation(); // Returns true iff we're successfully able to query for the browser's // incognito mode, and the browser returns true. virtual bool GetBrowserIncognitoMode(); // Returns the window script object for the page. // This function will cache the window object to avoid calling // npapi::GetValue which can cause problems in Opera. NPObject* GetWindowObject() const; virtual void SetReadyState(READYSTATE new_state) { ready_state_ = new_state; NPVariant var; INT32_TO_NPVARIANT(ready_state_, var); FireEvent("readystatechanged", var); } // Host function to compile-time asserts over members of this class. static void CompileAsserts(); // Get request from the stream notify data NPAPIUrlRequest* RequestFromNotifyData(void* notify_data) const; static LRESULT CALLBACK DropKillFocusHook(int code, WPARAM wparam, LPARAM lparam); // NO_LINT // The plugins opaque instance handle NPP instance_; // The plugin instantiation mode (NP_FULL or NP_EMBED) int16 mode_; // The plugins mime type. std::string mime_type_; // Set to true if we need a full page plugin. bool force_full_page_plugin_; scoped_refptr pref_service_; // Used to receive focus and blur events from the object element // that hosts the plugin. scoped_refptr focus_listener_; // In some cases the IPC channel proxy object is instantiated on the UI // thread in FF. It then tries to use the IPC logger, which relies on // the message loop being around. Declaring a dummy message loop // is a hack to get around this. Eventually the automation code needs to // be fixed to ensure that the channel proxy always gets created on a thread // with a message loop. static MessageLoop* message_loop_; static int instance_count_; // The following members contain the NPObject pointers representing the // onload/onerror/onmessage handlers on the page. ScopedNpObject onerror_handler_; ScopedNpObject onmessage_handler_; ScopedNpObject onprivatemessage_handler_; // As a workaround for a problem in Opera we cache the window object. // The problem stems from two things: window messages aren't always removed // from the message queue and messages can be pumped inside GetValue. // This can cause an infinite recursion of processing the same message // repeatedly. mutable ScopedNpObject window_object_; // Note since 'onload' is a registered event name, the browser will // automagically create a code block for the handling code and hook it // up to the CF object via addEventListener. // See this list of known event types: // http://www.w3.org/TR/DOM-Level-3-Events/events.html#Event-types READYSTATE ready_state_; // Popups are enabled bool enabled_popups_; // The value of src property keeping the current URL. std::string src_; }; #endif // CHROME_FRAME_CHROME_FRAME_NPAPI_H_