| 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();
|
|
|