summaryrefslogtreecommitdiffstats
path: root/chrome/renderer
diff options
context:
space:
mode:
authormpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-14 22:14:01 +0000
committermpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-14 22:14:01 +0000
commitb6ce15971b4139103635132bb9c9d3cd2224973e (patch)
tree07ac0724aed49c2adb8d8c47aadeb23a34d3e324 /chrome/renderer
parent95c3c59d275042225cda4589525cb279f66f1f2c (diff)
downloadchromium_src-b6ce15971b4139103635132bb9c9d3cd2224973e.zip
chromium_src-b6ce15971b4139103635132bb9c9d3cd2224973e.tar.gz
chromium_src-b6ce15971b4139103635132bb9c9d3cd2224973e.tar.bz2
Chrome-side of fixes for content-script messaging.
This change adds registration of content scripts, parented to a frame's context. When a frame's context goes away, we unregister it and any content script contexts for it. There's a corresponding webkit change that lets us know when a content script context is created. Filed upstream as https://bugs.webkit.org/show_bug.cgi?id=27104. BUG=16228 TEST=install an extension with a content script that communicates with a parent process. Messages should be sendable both ways. Review URL: http://codereview.chromium.org/155309 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20677 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r--chrome/renderer/extensions/bindings_utils.h10
-rw-r--r--chrome/renderer/extensions/event_bindings.cc91
-rw-r--r--chrome/renderer/render_view.cc8
-rw-r--r--chrome/renderer/render_view.h5
4 files changed, 82 insertions, 32 deletions
diff --git a/chrome/renderer/extensions/bindings_utils.h b/chrome/renderer/extensions/bindings_utils.h
index 2e8935a5..2c81b0c 100644
--- a/chrome/renderer/extensions/bindings_utils.h
+++ b/chrome/renderer/extensions/bindings_utils.h
@@ -61,9 +61,15 @@ struct ContextInfo {
v8::Persistent<v8::Context> context;
std::string extension_id; // empty if the context is not an extension
+ // If this context is a content script, parent will be the frame that it
+ // was injected in. This is empty if the context is not a content script.
+ v8::Persistent<v8::Context> parent_context;
+
ContextInfo(v8::Persistent<v8::Context> context,
- const std::string& extension_id)
- : context(context), extension_id(extension_id) {}
+ const std::string& extension_id,
+ v8::Persistent<v8::Context> parent_context)
+ : context(context), extension_id(extension_id),
+ parent_context(parent_context) {}
};
typedef std::list< linked_ptr<ContextInfo> > ContextList;
diff --git a/chrome/renderer/extensions/event_bindings.cc b/chrome/renderer/extensions/event_bindings.cc
index 03cccad..eab00fc 100644
--- a/chrome/renderer/extensions/event_bindings.cc
+++ b/chrome/renderer/extensions/event_bindings.cc
@@ -118,14 +118,61 @@ RenderThreadBase* EventBindings::GetRenderThread() {
return render_thread ? render_thread : RenderThread::current();
}
+static void HandleContextDestroyed(ContextList::iterator context_iter) {
+ // Notify the bindings that they're going away.
+ CallFunctionInContext((*context_iter)->context, "dispatchOnUnload", 0, NULL);
+
+ // Remove all pending requests for this context.
+ PendingRequestMap& pending_requests = GetPendingRequestMap();
+ for (PendingRequestMap::iterator it = pending_requests.begin();
+ it != pending_requests.end(); ) {
+ PendingRequestMap::iterator current = it++;
+ if (current->second->context == (*context_iter)->context) {
+ current->second->context.Dispose();
+ current->second->context.Clear();
+ pending_requests.erase(current);
+ }
+ }
+
+ // Unload any content script contexts for this frame.
+ for (ContextList::iterator it = GetContexts().begin();
+ it != GetContexts().end(); ) {
+ ContextList::iterator current = it++;
+ if ((*current)->parent_context == (*context_iter)->context)
+ HandleContextDestroyed(current);
+ }
+
+ // Remove it from our registered contexts.
+ (*context_iter)->context.ClearWeak();
+ (*context_iter)->context.Dispose();
+ (*context_iter)->context.Clear();
+ GetContexts().erase(context_iter);
+}
+
+static void ContextWeakReferenceCallback(v8::Persistent<v8::Value> context,
+ void*)
+{
+ for (ContextList::iterator it = GetContexts().begin();
+ it != GetContexts().end(); ++it) {
+ if ((*it)->context == context) {
+ HandleContextDestroyed(it);
+ return;
+ }
+ }
+
+ NOTREACHED();
+}
+
void EventBindings::HandleContextCreated(WebFrame* frame) {
if (!bindings_registered)
return;
v8::HandleScope handle_scope;
- v8::Local<v8::Context> context = frame->GetScriptContext();
+ ContextList& contexts = GetContexts();
+ v8::Local<v8::Context> frame_context = frame->GetScriptContext();
+ v8::Local<v8::Context> context = v8::Context::GetCurrent();
DCHECK(!context.IsEmpty());
- DCHECK(bindings_utils::FindContext(context) == GetContexts().end());
+ DCHECK(bindings_utils::FindContext(context) == contexts.end());
GURL url = frame->GetView()->GetMainFrame()->GetURL();
std::string extension_id;
@@ -134,8 +181,19 @@ void EventBindings::HandleContextCreated(WebFrame* frame) {
v8::Persistent<v8::Context> persistent_context =
v8::Persistent<v8::Context>::New(context);
- GetContexts().push_back(linked_ptr<ContextInfo>(
- new ContextInfo(persistent_context, extension_id)));
+ 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());
+ 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);
+ }
+
+ contexts.push_back(linked_ptr<ContextInfo>(
+ new ContextInfo(persistent_context, extension_id, parent_context)));
v8::Handle<v8::Value> argv[1];
argv[0] = v8::String::New(extension_id.c_str());
@@ -151,28 +209,9 @@ void EventBindings::HandleContextDestroyed(WebFrame* frame) {
v8::Local<v8::Context> context = frame->GetScriptContext();
DCHECK(!context.IsEmpty());
- ContextList::iterator it = bindings_utils::FindContext(context);
- DCHECK(it != GetContexts().end());
-
- // Notify the bindings that they're going away.
- CallFunctionInContext(context, "dispatchOnUnload", 0, NULL);
-
- // Remove all pending requests for this context.
- PendingRequestMap& pending_requests = GetPendingRequestMap();
- for (PendingRequestMap::iterator it = pending_requests.begin();
- it != pending_requests.end(); ) {
- PendingRequestMap::iterator current = it++;
- if (current->second->context == context) {
- current->second->context.Dispose();
- current->second->context.Clear();
- pending_requests.erase(current);
- }
- }
-
- // Remove it from our registered contexts.
- (*it)->context.Dispose();
- (*it)->context.Clear();
- GetContexts().erase(it);
+ ContextList::iterator context_iter = bindings_utils::FindContext(context);
+ DCHECK(context_iter != GetContexts().end());
+ ::HandleContextDestroyed(context_iter);
}
// static
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 012dc3f..436de6e 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -1461,14 +1461,18 @@ void RenderView::DocumentElementAvailable(WebFrame* frame) {
frame, UserScript::DOCUMENT_START);
}
-void RenderView::DidCreateScriptContext(WebFrame* webframe) {
+void RenderView::DidCreateScriptContextForFrame(WebFrame* webframe) {
EventBindings::HandleContextCreated(webframe);
}
-void RenderView::DidDestroyScriptContext(WebFrame* webframe) {
+void RenderView::DidDestroyScriptContextForFrame(WebFrame* webframe) {
EventBindings::HandleContextDestroyed(webframe);
}
+void RenderView::DidCreateIsolatedScriptContext(WebFrame* webframe) {
+ EventBindings::HandleContextCreated(webframe);
+}
+
WindowOpenDisposition RenderView::DispositionForNavigationAction(
WebView* webview,
WebFrame* frame,
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index bf6b6e3..ba6374d 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -218,8 +218,9 @@ class RenderView : public RenderWidget,
virtual void WindowObjectCleared(WebFrame* webframe);
virtual void DocumentElementAvailable(WebFrame* webframe);
- virtual void DidCreateScriptContext(WebFrame* webframe);
- virtual void DidDestroyScriptContext(WebFrame* webframe);
+ virtual void DidCreateScriptContextForFrame(WebFrame* webframe);
+ virtual void DidDestroyScriptContextForFrame(WebFrame* webframe);
+ virtual void DidCreateIsolatedScriptContext(WebFrame* webframe);
virtual WindowOpenDisposition DispositionForNavigationAction(
WebView* webview,