summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/extensions/bindings_utils.cc
diff options
context:
space:
mode:
authormpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-30 19:52:09 +0000
committermpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-30 19:52:09 +0000
commit4083f0521b25dfe74914421f632d18e87dad4048 (patch)
tree229a8d1e348f86906aa7341a112ad7e7e7e22ce7 /chrome/renderer/extensions/bindings_utils.cc
parent019acf33272edf63ce3f57469446042c760f924f (diff)
downloadchromium_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.cc110
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