diff options
author | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-30 19:52:09 +0000 |
---|---|---|
committer | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-30 19:52:09 +0000 |
commit | 4083f0521b25dfe74914421f632d18e87dad4048 (patch) | |
tree | 229a8d1e348f86906aa7341a112ad7e7e7e22ce7 /chrome/renderer/extensions/bindings_utils.cc | |
parent | 019acf33272edf63ce3f57469446042c760f924f (diff) | |
download | chromium_src-4083f0521b25dfe74914421f632d18e87dad4048.zip chromium_src-4083f0521b25dfe74914421f632d18e87dad4048.tar.gz chromium_src-4083f0521b25dfe74914421f632d18e87dad4048.tar.bz2 |
Refactor extension bindings to share code, avoid exposing hidden variables
globally, and avoid using the DOM load/unload events.
- moved callback handling into event_bindings.js (ports will use it).
- added chromeHidden, a V8 hidden value, to keep all internal variables that
need to be accessible to native code.
- changed context registration to occur always at extension load, instead of
DOM load.
- added an internal unload event that doesn't disable SuddenTermination.
This is a rework of my earlier CL http://codereview.chromium.org/125280 which was reverted because of a perf regression. I believe the perf problem was caused by the call into javascript I did on page load to handle context registration - this CL avoids that.
Review URL: http://codereview.chromium.org/147033
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19634 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/extensions/bindings_utils.cc')
-rw-r--r-- | chrome/renderer/extensions/bindings_utils.cc | 110 |
1 files changed, 106 insertions, 4 deletions
diff --git a/chrome/renderer/extensions/bindings_utils.cc b/chrome/renderer/extensions/bindings_utils.cc index 81e2058..fc9e98d 100644 --- a/chrome/renderer/extensions/bindings_utils.cc +++ b/chrome/renderer/extensions/bindings_utils.cc @@ -8,6 +8,103 @@ #include "chrome/renderer/render_view.h" #include "webkit/glue/webframe.h" +namespace bindings_utils { + +const char* kChromeHidden = "chromeHidden"; + +struct SingletonData { + ContextList contexts; + PendingRequestMap pending_requests; +}; + +// ExtensionBase + +v8::Handle<v8::FunctionTemplate> + ExtensionBase::GetNativeFunction(v8::Handle<v8::String> name) { + if (name->Equals(v8::String::New("GetChromeHidden"))) { + return v8::FunctionTemplate::New(GetChromeHidden); + } + + return v8::Handle<v8::FunctionTemplate>(); +} + +v8::Handle<v8::Value> ExtensionBase::GetChromeHidden( + const v8::Arguments& args) { + v8::Local<v8::Context> context = v8::Context::GetCurrent(); + v8::Local<v8::Object> global = context->Global(); + v8::Local<v8::Value> hidden = global->GetHiddenValue( + v8::String::New(kChromeHidden)); + + if (hidden.IsEmpty() || hidden->IsUndefined()) { + hidden = v8::Object::New(); + global->SetHiddenValue(v8::String::New(kChromeHidden), hidden); + } + + DCHECK(hidden->IsObject()); + return hidden; +} + +v8::Handle<v8::Value> ExtensionBase::StartRequest( + const v8::Arguments& args) { + // Get the current RenderView so that we can send a routed IPC message from + // the correct source. + RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext(); + if (!renderview) + return v8::Undefined(); + + if (args.Length() != 3 || !args[0]->IsString() || !args[1]->IsInt32() || + !args[2]->IsBoolean()) + return v8::Undefined(); + + std::string name = *v8::String::AsciiValue(args.Data()); + std::string json_args = *v8::String::Utf8Value(args[0]); + int request_id = args[1]->Int32Value(); + bool has_callback = args[2]->BooleanValue(); + + v8::Persistent<v8::Context> current_context = + v8::Persistent<v8::Context>::New(v8::Context::GetCurrent()); + DCHECK(!current_context.IsEmpty()); + GetPendingRequestMap()[request_id].reset(new PendingRequest( + current_context, *v8::String::AsciiValue(args.Data()))); + + renderview->SendExtensionRequest(name, json_args, request_id, has_callback); + + return v8::Undefined(); +} + +ContextList& GetContexts() { + return Singleton<SingletonData>::get()->contexts; +} + +ContextList GetContextsForExtension(const std::string& extension_id) { + ContextList& all_contexts = GetContexts(); + ContextList contexts; + + for (ContextList::iterator it = all_contexts.begin(); + it != all_contexts.end(); ++it) { + if ((*it)->extension_id == extension_id) + contexts.push_back(*it); + } + + return contexts; +} + +ContextList::iterator FindContext(v8::Handle<v8::Context> context) { + ContextList& all_contexts = GetContexts(); + + ContextList::iterator it = all_contexts.begin(); + for (; it != all_contexts.end(); ++it) { + if ((*it)->context == context) + break; + } + + return it; +} + +PendingRequestMap& GetPendingRequestMap() { + return Singleton<SingletonData>::get()->pending_requests; +} + RenderView* GetRenderViewForCurrentContext() { WebFrame* webframe = WebFrame::RetrieveFrameForCurrentContext(); DCHECK(webframe) << "RetrieveCurrentFrame called when not in a V8 context."; @@ -29,18 +126,23 @@ void CallFunctionInContext(v8::Handle<v8::Context> context, v8::Context::Scope context_scope(context); // Look up the function name, which may be a sub-property like - // "chrome.handleResponse_" in the global variable. - v8::Local<v8::Value> value = context->Global(); + // "Port.dispatchOnMessage" in the hidden global variable. + v8::Local<v8::Value> value = + context->Global()->GetHiddenValue(v8::String::New(kChromeHidden)); std::vector<std::string> components; SplitStringDontTrim(function_name, '.', &components); for (size_t i = 0; i < components.size(); ++i) { - if (value->IsObject()) + if (!value.IsEmpty() && value->IsObject()) value = value->ToObject()->Get(v8::String::New(components[i].c_str())); } - if (!value->IsFunction()) + if (value.IsEmpty() || !value->IsFunction()) { + NOTREACHED(); return; + } v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(value); if (!function.IsEmpty()) function->Call(v8::Object::New(), argc, argv); } + +} // namespace bindings_utils |