diff options
Diffstat (limited to 'chrome/renderer')
-rw-r--r-- | chrome/renderer/extensions/bindings_utils.h | 9 | ||||
-rw-r--r-- | chrome/renderer/extensions/event_bindings.cc | 56 | ||||
-rw-r--r-- | chrome/renderer/extensions/event_bindings.h | 13 | ||||
-rw-r--r-- | chrome/renderer/extensions/extension_process_bindings.cc | 24 | ||||
-rw-r--r-- | chrome/renderer/extensions/renderer_extension_bindings.cc | 5 | ||||
-rw-r--r-- | chrome/renderer/extensions/renderer_extension_bindings.h | 5 | ||||
-rw-r--r-- | chrome/renderer/render_thread.cc | 2 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 12 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 4 | ||||
-rw-r--r-- | chrome/renderer/renderer_resources.grd | 2 | ||||
-rw-r--r-- | chrome/renderer/resources/extension_process_bindings.js | 14 | ||||
-rw-r--r-- | chrome/renderer/user_script_slave.cc | 5 |
12 files changed, 122 insertions, 29 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_ diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index 3debfac..e35377a 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -400,7 +400,7 @@ void RenderThread::EnsureWebKitInitialized() { void RenderThread::OnExtensionMessageInvoke(const std::string& function_name, const ListValue& args) { - RendererExtensionBindings::Invoke(function_name, args); + RendererExtensionBindings::Invoke(function_name, args, NULL); } void RenderThread::OnPurgePluginListCache() { diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index a7445c0..0052e1e 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -38,6 +38,7 @@ #include "chrome/renderer/devtools_client.h" #include "chrome/renderer/extensions/event_bindings.h" #include "chrome/renderer/extensions/extension_process_bindings.h" +#include "chrome/renderer/extensions/renderer_extension_bindings.h" #include "chrome/renderer/localized_error.h" #include "chrome/renderer/media/audio_renderer_impl.h" #include "chrome/renderer/media/buffered_data_source.h" @@ -415,6 +416,8 @@ void RenderView::OnMessageReceived(const IPC::Message& message) { OnPopupNotificationVisibilityChanged) IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted) IPC_MESSAGE_HANDLER(ViewMsg_ExtensionResponse, OnExtensionResponse) + IPC_MESSAGE_HANDLER(ViewMsg_ExtensionMessageInvoke, + OnExtensionMessageInvoke) IPC_MESSAGE_HANDLER(ViewMsg_ClearFocusedNode, OnClearFocusedNode) IPC_MESSAGE_HANDLER(ViewMsg_SetBackground, OnSetBackground) IPC_MESSAGE_HANDLER(ViewMsg_EnableIntrinsicWidthChangedMode, @@ -1471,7 +1474,7 @@ void RenderView::DocumentElementAvailable(WebFrame* frame) { } void RenderView::DidCreateScriptContextForFrame(WebFrame* webframe) { - EventBindings::HandleContextCreated(webframe); + EventBindings::HandleContextCreated(webframe, false); } void RenderView::DidDestroyScriptContextForFrame(WebFrame* webframe) { @@ -1479,7 +1482,7 @@ void RenderView::DidDestroyScriptContextForFrame(WebFrame* webframe) { } void RenderView::DidCreateIsolatedScriptContext(WebFrame* webframe) { - EventBindings::HandleContextCreated(webframe); + EventBindings::HandleContextCreated(webframe, true); } WebNavigationPolicy RenderView::PolicyForNavigationAction( @@ -2855,6 +2858,11 @@ void RenderView::OnExtensionResponse(int request_id, request_id, success, response, error); } +void RenderView::OnExtensionMessageInvoke(const std::string& function_name, + const ListValue& args) { + RendererExtensionBindings::Invoke(function_name, args, this); +} + // Dump all load time histograms. // // There are 13 histograms measuring various times. diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 7cc65cf..9d8705a 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -47,6 +47,7 @@ class DevToolsAgent; class DevToolsClient; class FilePath; class GURL; +class ListValue; class NavigationState; class PrintWebViewHelper; class WebFrame; @@ -544,6 +545,9 @@ class RenderView : public RenderWidget, webkit_glue::WebAccessibility::OutParams* out_params); void OnClearAccessibilityInfo(int acc_obj_id, bool clear_all); + void OnExtensionMessageInvoke(const std::string& function_name, + const ListValue& args); + void OnMoveOrResizeStarted(); // Checks if the RenderView should close, runs the beforeunload handler and diff --git a/chrome/renderer/renderer_resources.grd b/chrome/renderer/renderer_resources.grd index 6be873d..ac2e6de 100644 --- a/chrome/renderer/renderer_resources.grd +++ b/chrome/renderer/renderer_resources.grd @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- This comment is only here because changes to resources are not picked up -without changes to the corresponding grd file. yipeee! --> +without changes to the corresponding grd file. mp2 --> <grit latest_public_release="0" current_release="1"> <outputs> <output filename="grit/renderer_resources.h" type="rc_header"> diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js index b9a0548..e702744 100644 --- a/chrome/renderer/resources/extension_process_bindings.js +++ b/chrome/renderer/resources/extension_process_bindings.js @@ -17,6 +17,7 @@ var chrome = chrome || {}; native function GetViews(); native function GetChromeHidden(); native function GetNextRequestId(); + native function OpenChannelToTab(); if (!chrome) chrome = {}; @@ -304,6 +305,17 @@ var chrome = chrome || {}; chrome.types.optFun ]; + chrome.tabs.connect = function(tabId, opt_name) { + validate(arguments, arguments.callee.params); + var portId = OpenChannelToTab(tabId, chrome.extension.id_, opt_name || ""); + return chromeHidden.Port.createPort(portId, opt_name); + }; + + chrome.tabs.connect.params = [ + chrome.types.pInt, + chrome.types.optStr + ]; + // Sends ({Tab}). // Will *NOT* be followed by tab-attached - it is implied. // *MAY* be followed by tab-selection-changed. @@ -531,7 +543,7 @@ var chrome = chrome || {}; chrome.extension = new chrome.Extension(extensionId); // TODO(mpcomplete): self.onConnect is deprecated. Remove it at 1.0. // http://code.google.com/p/chromium/issues/detail?id=16356 - chrome.self.onConnect = new chrome.Event("channel-connect:" + extensionId); + chrome.self.onConnect = chrome.extension.onConnect; setupPageActionEvents(extensionId); }); diff --git a/chrome/renderer/user_script_slave.cc b/chrome/renderer/user_script_slave.cc index 48017c1..088f409 100644 --- a/chrome/renderer/user_script_slave.cc +++ b/chrome/renderer/user_script_slave.cc @@ -160,7 +160,10 @@ bool UserScriptSlave::InjectScripts(WebFrame* frame, StringPrintf(kInitExtension, script->extension_id().c_str())))); } - frame->ExecuteScriptInNewWorld(&sources.front(), sources.size()); + // TODO(abarth): switch back to NewWorld when V8IsolatedWorld is fixed. + // https://bugs.webkit.org/show_bug.cgi?id=27397 + frame->ExecuteScriptInNewContext(&sources.front(), sources.size()); + // frame->ExecuteScriptInNewWorld(&sources.front(), sources.size()); } } |