blob: bb6da666dd87833a5e6c5f03ed565c06c669f94d [file] [log] [blame]
// 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 T>
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<T*>(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<DomEventListener> {
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<DomEventListener>::AddRef();
}
NS_IMETHOD_(nsrefcnt) Release() {
return NpEventListenerBase<DomEventListener>::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<NPObjectEventListener> {
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> npo_;
DISALLOW_COPY_AND_ASSIGN(NPObjectEventListener);
};
#endif // CHROME_FRAME_NP_EVENT_LISTENER_H_