diff options
Diffstat (limited to 'chrome/renderer/extensions')
6 files changed, 89 insertions, 23 deletions
diff --git a/chrome/renderer/extensions/bindings_utils.h b/chrome/renderer/extensions/bindings_utils.h index 2c81b0c..324a73c 100644 --- a/chrome/renderer/extensions/bindings_utils.h +++ b/chrome/renderer/extensions/bindings_utils.h @@ -65,11 +65,16 @@ struct ContextInfo { // was injected in. This is empty if the context is not a content script. v8::Persistent<v8::Context> parent_context; + // The RenderView that this context belongs to. This is not guaranteed to be + // a valid pointer, and is used for comparisons only. Do not dereference. + RenderView* render_view; + ContextInfo(v8::Persistent<v8::Context> context, const std::string& extension_id, - v8::Persistent<v8::Context> parent_context) + v8::Persistent<v8::Context> parent_context, + RenderView* render_view) : context(context), extension_id(extension_id), - parent_context(parent_context) {} + parent_context(parent_context), render_view(render_view) {} }; typedef std::list< linked_ptr<ContextInfo> > ContextList; diff --git a/chrome/renderer/extensions/event_bindings.cc b/chrome/renderer/extensions/event_bindings.cc index bb8df28..9d7104c 100644 --- a/chrome/renderer/extensions/event_bindings.cc +++ b/chrome/renderer/extensions/event_bindings.cc @@ -14,6 +14,8 @@ #include "chrome/renderer/render_thread.h" #include "chrome/renderer/render_view.h" #include "grit/renderer_resources.h" +#include "webkit/api/public/WebDataSource.h" +#include "webkit/api/public/WebURLRequest.h" #include "webkit/glue/webframe.h" using bindings_utils::CallFunctionInContext; @@ -29,6 +31,7 @@ namespace { // Keep a local cache of RenderThread so that we can mock it out for unit tests. static RenderThreadBase* render_thread = NULL; +static bool in_unit_tests = false; // Set to true if these bindings are registered. Will be false when extensions // are disabled. @@ -111,6 +114,7 @@ v8::Extension* EventBindings::Get() { // static void EventBindings::SetRenderThread(RenderThreadBase* thread) { render_thread = thread; + in_unit_tests = true; } // static @@ -150,12 +154,17 @@ static void HandleContextDestroyed(ContextList::iterator context_iter, (*context_iter)->context.ClearWeak(); (*context_iter)->context.Dispose(); (*context_iter)->context.Clear(); + + if (!(*context_iter)->parent_context.IsEmpty()) { + (*context_iter)->parent_context.Dispose(); + (*context_iter)->parent_context.Clear(); + } + GetContexts().erase(context_iter); } static void ContextWeakReferenceCallback(v8::Persistent<v8::Value> context, - void*) -{ + void*) { for (ContextList::iterator it = GetContexts().begin(); it != GetContexts().end(); ++it) { if ((*it)->context == context) { @@ -167,7 +176,7 @@ static void ContextWeakReferenceCallback(v8::Persistent<v8::Value> context, NOTREACHED(); } -void EventBindings::HandleContextCreated(WebFrame* frame) { +void EventBindings::HandleContextCreated(WebFrame* frame, bool content_script) { if (!bindings_registered) return; @@ -178,26 +187,46 @@ void EventBindings::HandleContextCreated(WebFrame* frame) { DCHECK(!context.IsEmpty()); DCHECK(bindings_utils::FindContext(context) == contexts.end()); - GURL url = frame->GetView()->GetMainFrame()->GetURL(); + // Figure out the URL for the toplevel frame. If the top frame is loading, + // use its provisional URL, since we get this notification before commit. + WebFrame* main_frame = frame->GetView()->GetMainFrame(); + WebKit::WebDataSource* ds = main_frame->GetProvisionalDataSource(); + if (!ds) + ds = main_frame->GetDataSource(); + GURL url = ds->request().url(); std::string extension_id; - if (url.SchemeIs(chrome::kExtensionScheme)) + if (url.SchemeIs(chrome::kExtensionScheme)) { extension_id = url.host(); + } else if (!content_script) { + // This context is a regular non-extension web page. Ignore it. We only + // care about content scripts and extension frames. + // (Unless we're in unit tests, in which case we don't care what the URL + // is). + DCHECK(frame_context == context); + if (!in_unit_tests) + return; + } v8::Persistent<v8::Context> persistent_context = v8::Persistent<v8::Context>::New(context); v8::Persistent<v8::Context> parent_context; - if (frame_context != context) { - // The new context doesn't belong to the frame: it's a content script. - DCHECK(bindings_utils::FindContext(frame_context) != contexts.end()); + if (content_script) { + DCHECK(frame_context != context); + parent_context = v8::Persistent<v8::Context>::New(frame_context); // Content script contexts can get GCed before their frame goes away, so // set up a GC callback. persistent_context.MakeWeak(NULL, &ContextWeakReferenceCallback); } + RenderView* render_view = NULL; + if (frame->GetView() && frame->GetView()->GetDelegate()) + render_view = static_cast<RenderView*>(frame->GetView()->GetDelegate()); + contexts.push_back(linked_ptr<ContextInfo>( - new ContextInfo(persistent_context, extension_id, parent_context))); + new ContextInfo(persistent_context, extension_id, parent_context, + render_view))); v8::Handle<v8::Value> argv[1]; argv[0] = v8::String::New(extension_id.c_str()); @@ -214,15 +243,18 @@ void EventBindings::HandleContextDestroyed(WebFrame* frame) { DCHECK(!context.IsEmpty()); ContextList::iterator context_iter = bindings_utils::FindContext(context); - DCHECK(context_iter != GetContexts().end()); - ::HandleContextDestroyed(context_iter, true); + if (context_iter != GetContexts().end()) + ::HandleContextDestroyed(context_iter, true); } // static void EventBindings::CallFunction(const std::string& function_name, - int argc, v8::Handle<v8::Value>* argv) { + int argc, v8::Handle<v8::Value>* argv, + RenderView* render_view) { for (ContextList::iterator it = GetContexts().begin(); it != GetContexts().end(); ++it) { + if (render_view && render_view != (*it)->render_view) + continue; CallFunctionInContext((*it)->context, function_name, argc, argv); } } diff --git a/chrome/renderer/extensions/event_bindings.h b/chrome/renderer/extensions/event_bindings.h index ea0060f..c9f81da 100644 --- a/chrome/renderer/extensions/event_bindings.h +++ b/chrome/renderer/extensions/event_bindings.h @@ -10,6 +10,7 @@ #include <string> class RenderThreadBase; +class RenderView; class WebFrame; // This class deals with the javascript bindings related to Event objects. @@ -23,14 +24,16 @@ class EventBindings { static RenderThreadBase* GetRenderThread(); // Handle a script context coming / going away. - static void HandleContextCreated(WebFrame* frame); + static void HandleContextCreated(WebFrame* frame, bool content_script); static void HandleContextDestroyed(WebFrame* frame); - // Calls the given function in each registered context which is listening - // for events. See comments on bindings_utils::CallFunctionInContext for - // more details. + // Calls the given function in each registered context which is listening for + // events. If render_view is non-NULL, only call the function in contexts + // belonging to that view. See comments on + // bindings_utils::CallFunctionInContext for more details. static void CallFunction(const std::string& function_name, int argc, - v8::Handle<v8::Value>* argv); + v8::Handle<v8::Value>* argv, + RenderView* render_view); }; #endif // CHROME_RENDERER_EXTENSIONS_EVENT_BINDINGS_H_ diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc index 35fa0a4..1e4bafe1 100644 --- a/chrome/renderer/extensions/extension_process_bindings.cc +++ b/chrome/renderer/extensions/extension_process_bindings.cc @@ -68,6 +68,8 @@ class ExtensionImpl : public ExtensionBase { return v8::FunctionTemplate::New(GetViews); } else if (name->Equals(v8::String::New("GetNextRequestId"))) { return v8::FunctionTemplate::New(GetNextRequestId); + } else if (name->Equals(v8::String::New("OpenChannelToTab"))) { + return v8::FunctionTemplate::New(OpenChannelToTab); } else if (name->Equals(v8::String::New("GetCurrentPageActions"))) { return v8::FunctionTemplate::New(GetCurrentPageActions); } else if (name->Equals(v8::String::New("StartRequest"))) { @@ -110,6 +112,28 @@ class ExtensionImpl : public ExtensionBase { return v8::Integer::New(next_request_id++); } + // Creates a new messaging channel to the tab with the given ID. + static v8::Handle<v8::Value> OpenChannelToTab(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]->IsInt32() && args[1]->IsString() && + args[2]->IsString()) { + int tab_id = args[0]->Int32Value(); + std::string extension_id = *v8::String::Utf8Value(args[1]->ToString()); + std::string channel_name = *v8::String::Utf8Value(args[2]->ToString()); + int port_id = -1; + renderview->Send(new ViewHostMsg_OpenChannelToTab( + renderview->routing_id(), tab_id, extension_id, channel_name, + &port_id)); + return v8::Integer::New(port_id); + } + return v8::Undefined(); + } + static v8::Handle<v8::Value> GetCurrentPageActions( const v8::Arguments& args) { std::string extension_id = ExtensionIdFromCurrentContext(); diff --git a/chrome/renderer/extensions/renderer_extension_bindings.cc b/chrome/renderer/extensions/renderer_extension_bindings.cc index 37767f3..9de9035 100644 --- a/chrome/renderer/extensions/renderer_extension_bindings.cc +++ b/chrome/renderer/extensions/renderer_extension_bindings.cc @@ -154,8 +154,9 @@ v8::Extension* RendererExtensionBindings::Get() { } void RendererExtensionBindings::Invoke(const std::string& function_name, - const ListValue& args) { + const ListValue& args, + RenderView* renderview) { v8::HandleScope handle_scope; std::vector< v8::Handle<v8::Value> > argv = ListValueToV8(args); - EventBindings::CallFunction(function_name, argv.size(), &argv[0]); + EventBindings::CallFunction(function_name, argv.size(), &argv[0], renderview); } diff --git a/chrome/renderer/extensions/renderer_extension_bindings.h b/chrome/renderer/extensions/renderer_extension_bindings.h index 5196807..89e903d 100644 --- a/chrome/renderer/extensions/renderer_extension_bindings.h +++ b/chrome/renderer/extensions/renderer_extension_bindings.h @@ -10,7 +10,7 @@ #include <string> class ListValue; -class RenderThreadBase; +class RenderView; // This class adds extension-related javascript bindings to a renderer. It is // used by both web renderers and extension processes. @@ -23,7 +23,8 @@ class RendererExtensionBindings { static v8::Extension* Get(); // Call the given javascript function with the specified arguments. - static void Invoke(const std::string& function_name, const ListValue& args); + static void Invoke(const std::string& function_name, const ListValue& args, + RenderView* renderview); }; #endif // CHROME_RENDERER_EXTENSIONS_RENDERER_EXTENSION_BINDINGS_H_ |