// 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_NP_EVENT_LISTENER_H_ #define CHROME_FRAME_NP_EVENT_LISTENER_H_ #include "base/logging.h" #include "chrome_frame/utils.h" #include "chrome_frame/np_browser_functions.h" // Avoid conflicts with basictypes and the gecko sdk. // (different definitions of uint32). #define NO_NSPR_10_SUPPORT #include "third_party/xulrunner-sdk/win/include/dom/nsIDOMEventListener.h" class nsIDOMElement; class NpEventDelegate { public: virtual void OnEvent(const char* event_name) = 0; }; class NpEventListener { public: NS_IMETHOD_(nsrefcnt) AddRef() = 0; NS_IMETHOD_(nsrefcnt) Release() = 0; virtual bool Subscribe(NPP instance, const char* event_names[], int event_name_count) = 0; virtual bool Unsubscribe(NPP instance, const char* event_names[], int event_name_count) = 0; protected: virtual ~NpEventListener() {} }; // A little helper class to implement simple ref counting // and assert on single threadedness. template class NpEventListenerBase : public NpEventListener { public: explicit NpEventListenerBase(NpEventDelegate* delegate) : ref_count_(0), delegate_(delegate) { DCHECK(delegate_); thread_id_ = ::GetCurrentThreadId(); } ~NpEventListenerBase() { DCHECK(thread_id_ == ::GetCurrentThreadId()); } NS_IMETHOD_(nsrefcnt) AddRef() { DCHECK(thread_id_ == ::GetCurrentThreadId()); ref_count_++; return ref_count_; } NS_IMETHOD_(nsrefcnt) Release() { DCHECK(thread_id_ == ::GetCurrentThreadId()); ref_count_--; if (!ref_count_) { T* me = static_cast(this); delete me; return 0; } return ref_count_; } protected: nsrefcnt ref_count_; NpEventDelegate* delegate_; AddRefModule module_ref_; // used to DCHECK on expected single-threaded usage unsigned long thread_id_; }; // Implements nsIDOMEventListener in order to receive events from DOM // elements inside an HTML page. class DomEventListener : public nsIDOMEventListener, public NpEventListenerBase { public: explicit DomEventListener(NpEventDelegate* delegate); virtual ~DomEventListener(); // Implementation of NpEventListener virtual bool Subscribe(NPP instance, const char* event_names[], int event_name_count); virtual bool Unsubscribe(NPP instance, const char* event_names[], int event_name_count); protected: // We implement QueryInterface etc ourselves in order to avoid // extra dependencies brought on by the NS_IMPL_* macros. NS_IMETHOD QueryInterface(REFNSIID iid, void** ptr); NS_IMETHOD_(nsrefcnt) AddRef() { return NpEventListenerBase::AddRef(); } NS_IMETHOD_(nsrefcnt) Release() { return NpEventListenerBase::Release(); } // Implementation of nsIDOMEventListener NS_IMETHOD HandleEvent(nsIDOMEvent *event); private: static bool GetObjectElement(NPP instance, nsIDOMElement** element); private: DISALLOW_COPY_AND_ASSIGN(DomEventListener); }; class NPObjectEventListener : public NpEventListenerBase { public: explicit NPObjectEventListener(NpEventDelegate* delegate); ~NPObjectEventListener(); // Implementation of NpEventListener virtual bool Subscribe(NPP instance, const char* event_names[], int event_name_count); virtual bool Unsubscribe(NPP instance, const char* event_names[], int event_name_count); protected: // NPObject structure which is exposed by NPObjectEventListener. class Npo : public NPObject { public: explicit Npo(NPP npp) : npp_(npp), listener_(NULL) { } void Initialize(NPObjectEventListener* listener) { listener_ = listener; } inline NPObjectEventListener* listener() const { return listener_; } inline NPP npp() const { return npp_; } protected: NPP npp_; NPObjectEventListener* listener_; AddRefModule module_ref_; }; static NPClass* PluginClass(); static bool HasMethod(Npo* npo, NPIdentifier name); static bool Invoke(Npo* npo, NPIdentifier name, const NPVariant* args, uint32_t arg_count, NPVariant* result); static NPObject* AllocateObject(NPP instance, NPClass* class_name); static void DeallocateObject(Npo* npo); typedef enum { HANDLE_EVENT, TYPE, ADD_EVENT_LISTENER, REMOVE_EVENT_LISTENER, TAG_NAME, PARENT_ELEMENT, IDENTIFIER_COUNT, } CachedStringIdentifiers; static NPIdentifier* GetCachedStringIds(); void HandleEvent(Npo* npo, NPObject* event); static NPObject* GetObjectElement(NPP instance); private: // Our NPObject. ScopedNpObject npo_; DISALLOW_COPY_AND_ASSIGN(NPObjectEventListener); }; #endif // CHROME_FRAME_NP_EVENT_LISTENER_H_