diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/renderer/extensions/bindings_utils.cc | 9 | ||||
-rw-r--r-- | chrome/renderer/extensions/bindings_utils.h | 10 | ||||
-rw-r--r-- | chrome/renderer/extensions/event_bindings.cc | 22 |
3 files changed, 34 insertions, 7 deletions
diff --git a/chrome/renderer/extensions/bindings_utils.cc b/chrome/renderer/extensions/bindings_utils.cc index d96f8d7..ddccf2c 100644 --- a/chrome/renderer/extensions/bindings_utils.cc +++ b/chrome/renderer/extensions/bindings_utils.cc @@ -71,6 +71,15 @@ ContextList GetContextsForExtension(const std::string& extension_id) { return contexts; } +ContextInfo* GetInfoForCurrentContext() { + v8::Local<v8::Context> context = v8::Context::GetCurrent(); + ContextList::iterator context_iter = FindContext(context); + if (context_iter == GetContexts().end()) + return NULL; + else + return context_iter->get(); +} + ContextList::iterator FindContext(v8::Handle<v8::Context> context) { ContextList& all_contexts = GetContexts(); diff --git a/chrome/renderer/extensions/bindings_utils.h b/chrome/renderer/extensions/bindings_utils.h index 7354c72..b0b3f08 100644 --- a/chrome/renderer/extensions/bindings_utils.h +++ b/chrome/renderer/extensions/bindings_utils.h @@ -68,12 +68,17 @@ struct ContextInfo { // a valid pointer, and is used for comparisons only. Do not dereference. RenderView* render_view; + // A count of the number of events that are listening in this context. When + // this is zero, |context| will be a weak handle. + int num_connected_events; + ContextInfo(v8::Persistent<v8::Context> context, const std::string& extension_id, v8::Persistent<v8::Context> parent_context, RenderView* render_view) : context(context), extension_id(extension_id), - parent_context(parent_context), render_view(render_view) {} + parent_context(parent_context), render_view(render_view), + num_connected_events(0) {} }; typedef std::list< linked_ptr<ContextInfo> > ContextList; @@ -86,6 +91,9 @@ ContextList GetContextsForExtension(const std::string& extension_id); // Returns the ContextInfo item that has the given context. ContextList::iterator FindContext(v8::Handle<v8::Context> context); +// Returns the ContextInfo for the current v8 context. +ContextInfo* GetInfoForCurrentContext(); + // Contains info relevant to a pending API request. struct PendingRequest { public : diff --git a/chrome/renderer/extensions/event_bindings.cc b/chrome/renderer/extensions/event_bindings.cc index 416ab2c..c30c364 100644 --- a/chrome/renderer/extensions/event_bindings.cc +++ b/chrome/renderer/extensions/event_bindings.cc @@ -22,12 +22,16 @@ using bindings_utils::CallFunctionInContext; using bindings_utils::ContextInfo; using bindings_utils::ContextList; using bindings_utils::GetContexts; +using bindings_utils::GetInfoForCurrentContext; using bindings_utils::GetStringResource; using bindings_utils::ExtensionBase; using bindings_utils::GetPendingRequestMap; using bindings_utils::PendingRequestMap; using WebKit::WebFrame; +static void ContextWeakReferenceCallback(v8::Persistent<v8::Value> context, + void*); + namespace { // Keep a local cache of RenderThread so that we can mock it out for unit tests. @@ -79,19 +83,18 @@ class ExtensionImpl : public ExtensionBase { std::string event_name(*v8::String::AsciiValue(args[0])); bool has_permission = ExtensionProcessBindings::CurrentContextHasPermission(event_name); -#if EXTENSION_TIME_TO_BREAK_API - bool allow_api = has_permission; -#else - bool allow_api = true; -#endif // Increment the count even if the caller doesn't have permission, so that // refcounts stay balanced. - if (EventIncrementListenerCount(event_name) == 1 && allow_api) { + if (EventIncrementListenerCount(event_name) == 1 && has_permission) { EventBindings::GetRenderThread()->Send( new ViewHostMsg_ExtensionAddListener(event_name)); } + ContextInfo* current_context_info = GetInfoForCurrentContext(); + if (++current_context_info->num_connected_events == 1) + current_context_info->context.ClearWeak(); + if (!has_permission) { return ExtensionProcessBindings::ThrowPermissionDeniedException( event_name); @@ -112,6 +115,13 @@ class ExtensionImpl : public ExtensionBase { EventBindings::GetRenderThread()->Send( new ViewHostMsg_ExtensionRemoveListener(event_name)); } + + ContextInfo* current_context_info = GetInfoForCurrentContext(); + if (current_context_info && + --current_context_info->num_connected_events == 0) { + current_context_info->context.MakeWeak(NULL, + &ContextWeakReferenceCallback); + } } return v8::Undefined(); |