diff options
author | mpcomplete@google.com <mpcomplete@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-08 18:35:34 +0000 |
---|---|---|
committer | mpcomplete@google.com <mpcomplete@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-08 18:35:34 +0000 |
commit | a40caa97fbdae3760f52f95f6b265bd1f39b19ae (patch) | |
tree | b98dceab49c4efb854c9923660735cbf96addbcd /chrome/renderer/extensions | |
parent | 1b812ea42f713908a9034fcf2a26e8d4a8a86a04 (diff) | |
download | chromium_src-a40caa97fbdae3760f52f95f6b265bd1f39b19ae.zip chromium_src-a40caa97fbdae3760f52f95f6b265bd1f39b19ae.tar.gz chromium_src-a40caa97fbdae3760f52f95f6b265bd1f39b19ae.tar.bz2 |
Add aa's Event class to our javascript bindings and use it in our extension
message passing API.
Review URL: http://codereview.chromium.org/62069
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13371 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/extensions')
-rwxr-xr-x | chrome/renderer/extensions/bindings_utils.h | 28 | ||||
-rwxr-xr-x | chrome/renderer/extensions/event_bindings.cc | 119 | ||||
-rwxr-xr-x | chrome/renderer/extensions/event_bindings.h | 25 | ||||
-rwxr-xr-x | chrome/renderer/extensions/renderer_extension_bindings.cc | 118 | ||||
-rwxr-xr-x | chrome/renderer/extensions/renderer_extension_bindings.h | 1 |
5 files changed, 188 insertions, 103 deletions
diff --git a/chrome/renderer/extensions/bindings_utils.h b/chrome/renderer/extensions/bindings_utils.h new file mode 100755 index 0000000..9e7d213 --- /dev/null +++ b/chrome/renderer/extensions/bindings_utils.h @@ -0,0 +1,28 @@ +// 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_RENDERER_EXTENSIONS_BINDINGS_UTILS_H_ +#define CHROME_RENDERER_EXTENSIONS_BINDINGS_UTILS_H_ + +#include "base/singleton.h" +#include "chrome/common/resource_bundle.h" + +#include <string> + +template<int kResourceId> +struct StringResourceTemplate { + StringResourceTemplate() + : resource(ResourceBundle::GetSharedInstance().GetRawDataResource( + kResourceId).as_string()) { + } + std::string resource; +}; + +template<int kResourceId> +const char* GetStringResource() { + return + Singleton< StringResourceTemplate<kResourceId> >::get()->resource.c_str(); +} + +#endif // CHROME_RENDERER_EXTENSIONS_BINDINGS_UTILS_H_ diff --git a/chrome/renderer/extensions/event_bindings.cc b/chrome/renderer/extensions/event_bindings.cc new file mode 100755 index 0000000..0b45abba --- /dev/null +++ b/chrome/renderer/extensions/event_bindings.cc @@ -0,0 +1,119 @@ +// 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. + +#include "chrome/renderer/extensions/event_bindings.h" + +#include "base/basictypes.h" +#include "base/singleton.h" +#include "chrome/renderer/extensions/bindings_utils.h" +#include "chrome/renderer/extensions/event_bindings.h" +#include "chrome/renderer/render_thread.h" +#include "grit/renderer_resources.h" + +namespace { + +// 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; +}; +ContextList& GetRegisteredContexts() { + return Singleton<ExtensionData>::get()->contexts; +} + +class ExtensionImpl : public v8::Extension { + public: + ExtensionImpl() + : v8::Extension(EventBindings::kName, + GetStringResource<IDR_EVENT_BINDINGS_JS>()) { + } + ~ExtensionImpl() {} + + virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( + v8::Handle<v8::String> name) { + if (name->Equals(v8::String::New("AttachEvent"))) { + return v8::FunctionTemplate::New(AttachEvent); + } else if (name->Equals(v8::String::New("DetachEvent"))) { + return v8::FunctionTemplate::New(DetachEvent); + } + return v8::Handle<v8::FunctionTemplate>(); + } + + // 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) { + const char* kContextRegistered = "chromium.extension.contextRegistered"; + + v8::Persistent<v8::Context> context = + v8::Persistent<v8::Context>::New(v8::Context::GetCurrent()); + v8::Local<v8::Object> global = context->Global(); + v8::Local<v8::Value> is_registered = global->GetHiddenValue( + v8::String::New(kContextRegistered)); + if (is_registered.IsEmpty() || is_registered->IsUndefined()) { + GetRegisteredContexts().push_back(context); + context.MakeWeak(NULL, WeakContextCallback); + global->SetHiddenValue( + v8::String::New(kContextRegistered), v8::Boolean::New(true)); + } + return v8::Undefined(); + } + + // TODO(mpcomplete): Implement this. This should do the reverse of + // AttachEvent, when that actually does what we plan on. + static v8::Handle<v8::Value> DetachEvent(const v8::Arguments& args) { + return v8::Undefined(); + } + + // Called when a registered context is garbage collected. + static void WeakContextCallback(v8::Persistent<v8::Value> obj, void*) { + ContextList::iterator it = std::find(GetRegisteredContexts().begin(), + GetRegisteredContexts().end(), obj); + if (it == GetRegisteredContexts().end()) { + NOTREACHED(); + return; + } + + it->Dispose(); + it->Clear(); + GetRegisteredContexts().erase(it); + } +}; + +} // namespace + +const char* EventBindings::kName = "chrome/EventBindings"; + +v8::Extension* EventBindings::Get() { + return new ExtensionImpl(); +} + +void EventBindings::CallFunction(const std::string& function_name, + int argc, v8::Handle<v8::Value>* argv) { + for (ContextList::iterator it = GetRegisteredContexts().begin(); + it != GetRegisteredContexts().end(); ++it) { + DCHECK(!it->IsEmpty()); + v8::Context::Scope context_scope(*it); + v8::Local<v8::Object> global = (*it)->Global(); + + // Check if the window object is gone, which means this context's frame + // has been unloaded. + v8::Local<v8::Value> window = global->Get(v8::String::New("window")); + if (!window->IsObject()) + continue; + + v8::Local<v8::Script> script = v8::Script::Compile( + v8::String::New(function_name.c_str())); + v8::Local<v8::Value> function_obj = script->Run(); + if (!function_obj->IsFunction()) + continue; + + v8::Local<v8::Function> function = + v8::Local<v8::Function>::Cast(function_obj); + if (!function.IsEmpty()) + function->Call(v8::Object::New(), argc, argv); + } +} diff --git a/chrome/renderer/extensions/event_bindings.h b/chrome/renderer/extensions/event_bindings.h new file mode 100755 index 0000000..dd91811 --- /dev/null +++ b/chrome/renderer/extensions/event_bindings.h @@ -0,0 +1,25 @@ +// 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_RENDERER_EXTENSIONS_EVENT_BINDINGS_H_ +#define CHROME_RENDERER_EXTENSIONS_EVENT_BINDINGS_H_ + +#include "v8/include/v8.h" + +#include <string> + +// This class deals with the javascript bindings related to Event objects. +class EventBindings { + public: + static const char* kName; // The v8::Extension name, for dependencies. + static v8::Extension* Get(); + + // Calls the given function in each registered context which is listening + // for events. The function can be an object property, ie: + // "chromium.Event.dispatch_". + static void CallFunction(const std::string& function_name, int argc, + v8::Handle<v8::Value>* argv); +}; + +#endif // CHROME_RENDERER_EXTENSIONS_EVENT_BINDINGS_H_ diff --git a/chrome/renderer/extensions/renderer_extension_bindings.cc b/chrome/renderer/extensions/renderer_extension_bindings.cc index 8254bc6..572b00c 100755 --- a/chrome/renderer/extensions/renderer_extension_bindings.cc +++ b/chrome/renderer/extensions/renderer_extension_bindings.cc @@ -5,53 +5,38 @@ #include "chrome/renderer/extensions/renderer_extension_bindings.h" #include "base/basictypes.h" -#include "base/singleton.h" #include "chrome/common/render_messages.h" #include "chrome/common/resource_bundle.h" +#include "chrome/renderer/extensions/bindings_utils.h" +#include "chrome/renderer/extensions/event_bindings.h" #include "chrome/renderer/render_thread.h" #include "grit/renderer_resources.h" -#include "webkit/glue/webframe.h" // Message passing API example (in a content script): // var extension = // new chromium.Extension('00123456789abcdef0123456789abcdef0123456'); -// var channel = extension.openChannel(); -// channel.postMessage('Can you hear me now?'); -// channel.onMessage = function(msg, port) { +// var port = extension.connect(); +// port.postMessage('Can you hear me now?'); +// port.onmessage.addListener(function(msg, port) { // alert('response=' + msg); // port.postMessage('I got your reponse'); -// } +// }); namespace { -// 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 SingletonData { - ContextList contexts; - std::string js_source; - - SingletonData() : - js_source(ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_RENDERER_EXTENSION_BINDINGS_JS).as_string()) { - } -}; -ContextList& GetRegisteredContexts() { - return Singleton<SingletonData>::get()->contexts; -} -const char* GetSource() { - return Singleton<SingletonData>::get()->js_source.c_str(); -} - // We use the generic interface so that unit tests can inject a mock. RenderThreadBase* render_thread_ = NULL; const char* kExtensionName = "v8/RendererExtensionBindings"; -const char* kScriptAPI = "chromium.extensions.scriptAPI"; +const char* kExtensionDeps[] = { EventBindings::kName }; class ExtensionImpl : public v8::Extension { public: - ExtensionImpl() : v8::Extension(kExtensionName, GetSource()) {} + ExtensionImpl() + : v8::Extension(kExtensionName, + GetStringResource<IDR_RENDERER_EXTENSION_BINDINGS_JS>(), + arraysize(kExtensionDeps), kExtensionDeps) { + } ~ExtensionImpl() {} virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( @@ -60,8 +45,6 @@ class ExtensionImpl : public v8::Extension { return v8::FunctionTemplate::New(OpenChannelToExtension); } else if (name->Equals(v8::String::New("PostMessage"))) { return v8::FunctionTemplate::New(PostMessage); - } else if (name->Equals(v8::String::New("RegisterScriptAPI"))) { - return v8::FunctionTemplate::New(RegisterScriptAPI); } return v8::Handle<v8::FunctionTemplate>(); } @@ -89,77 +72,6 @@ class ExtensionImpl : public v8::Extension { } return v8::Undefined(); } - - // This method is internal to the extension, and fulfills a dual purpose: - // 1. Keep track of which v8::Contexts have registered event listeners. - // 2. Registers a private variable on the context that we use for dispatching - // events as they come in, by calling designated methods. - static v8::Handle<v8::Value> RegisterScriptAPI(const v8::Arguments& args) { - if (args.Length() >= 1 && args[0]->IsObject()) { - v8::Persistent<v8::Context> context = - v8::Persistent<v8::Context>::New(v8::Context::GetCurrent()); - GetRegisteredContexts().push_back(context); - context.MakeWeak(NULL, WeakContextCallback); - context->Global()->SetHiddenValue(v8::String::New(kScriptAPI), args[0]); - DCHECK(args[0]->ToObject()->Get(v8::String::New("dispatchOnConnect"))-> - IsFunction()); - DCHECK(args[0]->ToObject()->Get(v8::String::New("dispatchOnMessage"))-> - IsFunction()); - return v8::Undefined(); - } - return v8::Undefined(); - } - - // Calls the given chromiumPrivate method in each registered context. - static void CallMethod(const std::string& method_name, int argc, - v8::Handle<v8::Value>* argv) { - for (ContextList::iterator it = GetRegisteredContexts().begin(); - it != GetRegisteredContexts().end(); ++it) { - DCHECK(!it->IsEmpty()); - v8::Context::Scope context_scope(*it); - v8::Local<v8::Object> global = (*it)->Global(); - - // Check if the window object is gone, which means this context's frame - // has been unloaded. - v8::Local<v8::Value> window = global->Get(v8::String::New("window")); - if (!window->IsObject()) - continue; - - // Retrieve our hidden variable and call the method on it. - v8::Local<v8::Value> script_api = global->GetHiddenValue( - v8::String::New(kScriptAPI)); - if (!script_api->IsObject()) { - NOTREACHED(); - continue; - } - - v8::Handle<v8::Value> function_obj = script_api->ToObject()->Get( - v8::String::New(method_name.c_str())); - if (!function_obj->IsFunction()) { - NOTREACHED(); - continue; - } - - v8::Handle<v8::Function> function = - v8::Handle<v8::Function>::Cast(function_obj); - if (!function.IsEmpty()) - function->Call(v8::Object::New(), argc, argv); - } - } - - // Called when a registered context is garbage collected. - static void WeakContextCallback(v8::Persistent<v8::Value> obj, void*) { - ContextList::iterator it = std::find(GetRegisteredContexts().begin(), - GetRegisteredContexts().end(), obj); - if (it == GetRegisteredContexts().end()) { - NOTREACHED(); - return; - } - - it->Dispose(); - it->Clear(); - GetRegisteredContexts().erase(it); - } }; } // namespace @@ -175,7 +87,8 @@ void RendererExtensionBindings::HandleConnect(int port_id) { v8::HandleScope handle_scope; v8::Handle<v8::Value> argv[1]; argv[0] = v8::Integer::New(port_id); - ExtensionImpl::CallMethod("dispatchOnConnect", arraysize(argv), argv); + EventBindings::CallFunction("chromium.Port.dispatchOnConnect_", + arraysize(argv), argv); } void RendererExtensionBindings::HandleMessage(const std::string& message, @@ -184,7 +97,8 @@ void RendererExtensionBindings::HandleMessage(const std::string& message, v8::Handle<v8::Value> argv[2]; argv[0] = v8::String::New(message.c_str()); argv[1] = v8::Integer::New(port_id); - ExtensionImpl::CallMethod("dispatchOnMessage", arraysize(argv), argv); + EventBindings::CallFunction("chromium.Port.dispatchOnMessage_", + arraysize(argv), argv); } } // namespace extensions_v8 diff --git a/chrome/renderer/extensions/renderer_extension_bindings.h b/chrome/renderer/extensions/renderer_extension_bindings.h index 7c951ec..b0d04de 100755 --- a/chrome/renderer/extensions/renderer_extension_bindings.h +++ b/chrome/renderer/extensions/renderer_extension_bindings.h @@ -10,7 +10,6 @@ #include <string> class RenderThreadBase; -class WebFrame; namespace extensions_v8 { |