Index: chrome/renderer/extensions/event_bindings.cc |
=================================================================== |
--- chrome/renderer/extensions/event_bindings.cc (revision 14939) |
+++ chrome/renderer/extensions/event_bindings.cc (working copy) |
@@ -6,6 +6,7 @@ |
#include "base/basictypes.h" |
#include "base/singleton.h" |
+#include "chrome/common/render_messages.h" |
#include "chrome/renderer/extensions/bindings_utils.h" |
#include "chrome/renderer/extensions/event_bindings.h" |
#include "chrome/renderer/js_only_v8_extensions.h" |
@@ -14,16 +15,33 @@ |
namespace { |
+// Keep a local cache of RenderThread so that we can mock it out for unit tests. |
+static RenderThreadBase* render_thread = NULL; |
+ |
+static RenderThreadBase* GetRenderThread() { |
+ return render_thread ? render_thread : RenderThread::current(); |
+} |
+ |
// Keep a list of contexts that have registered themselves with us. This lets |
// us know where to dispatch events when we receive them. |
typedef std::list< v8::Persistent<v8::Context> > ContextList; |
struct ExtensionData { |
ContextList contexts; |
+ std::map<std::string, int> listener_count; |
}; |
ContextList& GetRegisteredContexts() { |
return Singleton<ExtensionData>::get()->contexts; |
} |
+int EventIncrementListenerCount(const std::string& event_name) { |
+ ExtensionData *data = Singleton<ExtensionData>::get(); |
+ return ++(data->listener_count[event_name]); |
+} |
+int EventDecrementListenerCount(const std::string& event_name) { |
+ ExtensionData *data = Singleton<ExtensionData>::get(); |
+ return --(data->listener_count[event_name]); |
+} |
+ |
const char* kExtensionDeps[] = { JsonJsV8Extension::kName }; |
const char* kContextAttachCount = "chromium.attachCount"; |
@@ -47,10 +65,11 @@ |
} |
// Attach an event name to an object. |
- // TODO(mpcomplete): I'm just using this to register the v8 Context right now. |
- // The idea is to eventually notify the browser about what events are being |
- // listened to, so it can dispatch appropriately. |
static v8::Handle<v8::Value> AttachEvent(const v8::Arguments& args) { |
+ DCHECK(args.Length() == 1); |
+ // TODO(erikkay) should enforce that event name is a string in the bindings |
+ DCHECK(args[0]->IsString() || args[0]->IsUndefined()); |
+ |
v8::Persistent<v8::Context> context = |
v8::Persistent<v8::Context>::New(v8::Context::GetCurrent()); |
v8::Local<v8::Object> global = context->Global(); |
@@ -71,10 +90,22 @@ |
v8::String::New(kContextAttachCount), |
v8::Integer::New(account_count_value + 1)); |
+ if (args[0]->IsString()) { |
+ std::string event_name(*v8::String::AsciiValue(args[0])); |
+ if (EventIncrementListenerCount(event_name) == 1) { |
+ GetRenderThread()->Send( |
+ new ViewHostMsg_ExtensionAddListener(event_name)); |
+ } |
+ } |
+ |
return v8::Undefined(); |
} |
static v8::Handle<v8::Value> DetachEvent(const v8::Arguments& args) { |
+ DCHECK(args.Length() == 1); |
+ // TODO(erikkay) should enforce that event name is a string in the bindings |
+ DCHECK(args[0]->IsString() || args[0]->IsUndefined()); |
+ |
v8::Local<v8::Context> context = v8::Context::GetCurrent(); |
v8::Local<v8::Object> global = context->Global(); |
v8::Local<v8::Value> attach_count = global->GetHiddenValue( |
@@ -90,6 +121,14 @@ |
v8::String::New(kContextAttachCount), |
v8::Integer::New(account_count_value - 1)); |
+ if (args[0]->IsString()) { |
+ std::string event_name(*v8::String::AsciiValue(args[0])); |
+ if (EventDecrementListenerCount(event_name) == 0) { |
+ GetRenderThread()->Send( |
+ new ViewHostMsg_ExtensionRemoveListener(event_name)); |
+ } |
+ } |
+ |
return v8::Undefined(); |
} |
@@ -122,6 +161,11 @@ |
return new ExtensionImpl(); |
} |
+// static |
+void EventBindings::SetRenderThread(RenderThreadBase* thread) { |
+ render_thread = thread; |
+} |
+ |
void EventBindings::CallFunction(const std::string& function_name, |
int argc, v8::Handle<v8::Value>* argv) { |
for (ContextList::iterator it = GetRegisteredContexts().begin(); |