summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--webkit/glue/webframeloaderclient_impl.cc15
-rw-r--r--webkit/glue/webframeloaderclient_impl.h14
-rw-r--r--webkit/glue/webview_delegate.h8
7 files changed, 111 insertions, 40 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,
diff --git a/webkit/glue/webframeloaderclient_impl.cc b/webkit/glue/webframeloaderclient_impl.cc
index c5d4901..19f1096 100644
--- a/webkit/glue/webframeloaderclient_impl.cc
+++ b/webkit/glue/webframeloaderclient_impl.cc
@@ -130,18 +130,25 @@ void WebFrameLoaderClient::documentElementAvailable() {
d->DocumentElementAvailable(webframe_);
}
-void WebFrameLoaderClient::didCreateScriptContext() {
+void WebFrameLoaderClient::didCreateScriptContextForFrame() {
WebViewImpl* webview = webframe_->GetWebViewImpl();
WebViewDelegate* d = webview->delegate();
if (d)
- d->DidCreateScriptContext(webframe_);
+ d->DidCreateScriptContextForFrame(webframe_);
}
-void WebFrameLoaderClient::didDestroyScriptContext() {
+void WebFrameLoaderClient::didDestroyScriptContextForFrame() {
WebViewImpl* webview = webframe_->GetWebViewImpl();
WebViewDelegate* d = webview->delegate();
if (d)
- d->DidDestroyScriptContext(webframe_);
+ d->DidDestroyScriptContextForFrame(webframe_);
+}
+
+void WebFrameLoaderClient::didCreateIsolatedScriptContext() {
+ WebViewImpl* webview = webframe_->GetWebViewImpl();
+ WebViewDelegate* d = webview->delegate();
+ if (d)
+ d->DidCreateIsolatedScriptContext(webframe_);
}
void WebFrameLoaderClient::didPerformFirstNavigation() const {
diff --git a/webkit/glue/webframeloaderclient_impl.h b/webkit/glue/webframeloaderclient_impl.h
index 98118dd..8532f55 100644
--- a/webkit/glue/webframeloaderclient_impl.h
+++ b/webkit/glue/webframeloaderclient_impl.h
@@ -49,8 +49,18 @@ class WebFrameLoaderClient : public WebCore::FrameLoaderClient {
virtual void windowObjectCleared();
virtual void documentElementAvailable();
- virtual void didCreateScriptContext();
- virtual void didDestroyScriptContext();
+ // TODO(mpcomplete): remove these when we pick up webkit r45871
+ virtual void didCreateScriptContext() { didCreateScriptContextForFrame(); }
+ virtual void didDestroyScriptContext() { didDestroyScriptContextForFrame(); }
+
+ // A frame's V8 context was created or destroyed.
+ virtual void didCreateScriptContextForFrame();
+ virtual void didDestroyScriptContextForFrame();
+
+ // A context untied to a frame was created (through evaluateInNewContext).
+ // This context is not tied to the lifetime of its frame, and is destroyed
+ // in garbage collection.
+ virtual void didCreateIsolatedScriptContext();
virtual bool hasWebView() const; // mainly for assertions
virtual bool hasFrameView() const; // ditto
diff --git a/webkit/glue/webview_delegate.h b/webkit/glue/webview_delegate.h
index eafd383..1ccc761 100644
--- a/webkit/glue/webview_delegate.h
+++ b/webkit/glue/webview_delegate.h
@@ -231,11 +231,15 @@ class WebViewDelegate : virtual public WebWidgetDelegate {
// Notifies that a new script context has been created for this frame.
// This is similar to WindowObjectCleared but only called once per frame
// context.
- virtual void DidCreateScriptContext(WebFrame* webframe) {
+ virtual void DidCreateScriptContextForFrame(WebFrame* webframe) {
}
// Notifies that this frame's script context has been destroyed.
- virtual void DidDestroyScriptContext(WebFrame* webframe) {
+ virtual void DidDestroyScriptContextForFrame(WebFrame* webframe) {
+ }
+
+ // Notifies that a garbage-collected context was created - content scripts.
+ virtual void DidCreateIsolatedScriptContext(WebFrame* webframe) {
}
// PolicyDelegate ----------------------------------------------------------