summaryrefslogtreecommitdiffstats
path: root/chrome/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/renderer')
-rw-r--r--chrome/renderer/extensions/bindings_utils.h9
-rw-r--r--chrome/renderer/extensions/event_bindings.cc56
-rw-r--r--chrome/renderer/extensions/event_bindings.h13
-rw-r--r--chrome/renderer/extensions/extension_process_bindings.cc24
-rw-r--r--chrome/renderer/extensions/renderer_extension_bindings.cc5
-rw-r--r--chrome/renderer/extensions/renderer_extension_bindings.h5
-rw-r--r--chrome/renderer/render_thread.cc2
-rw-r--r--chrome/renderer/render_view.cc12
-rw-r--r--chrome/renderer/render_view.h4
-rw-r--r--chrome/renderer/renderer_resources.grd2
-rw-r--r--chrome/renderer/resources/extension_process_bindings.js14
-rw-r--r--chrome/renderer/user_script_slave.cc5
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());
}
}