Index: Source/web/WebFrameImpl.cpp |
diff --git a/Source/web/WebFrameImpl.cpp b/Source/web/WebFrameImpl.cpp |
index 5a53a30f4d295dcf33e9b43264495b136ca34d42..5696f5e9775ab9da1b199b15fa0058020f3578ae 100644 |
--- a/Source/web/WebFrameImpl.cpp |
+++ b/Source/web/WebFrameImpl.cpp |
@@ -50,7 +50,7 @@ |
// ref initially and it is removed when the FrameLoader is getting destroyed. |
// |
// WebFrames are created in two places, first in WebViewImpl when the root |
-// frame is created, and second in WebFrame::CreateChildFrame when sub-frames |
+// frame is created, and second in WebFrame::createChildFrame when sub-frames |
// are created. WebKit will hook up this object to the FrameLoader/Frame |
// and the refcount will be correct. |
// |
@@ -64,9 +64,12 @@ |
// in FrameLoader::detachFromParent for each subframe. |
// |
// Frame going away causes the FrameLoader to get deleted. In FrameLoader's |
-// destructor, it notifies its client with frameLoaderDestroyed. This calls |
-// WebFrame::Closing and then derefs the WebFrame and will cause it to be |
-// deleted (unless an external someone is also holding a reference). |
+// destructor, it notifies its client with frameLoaderDestroyed. This derefs |
+// the WebFrame and will cause it to be deleted (unless an external someone |
+// is also holding a reference). |
+// |
+// Thie client is expected to be set whenever the WebFrameImpl is attached to |
+// the DOM. |
#include "config.h" |
#include "WebFrameImpl.h" |
@@ -266,12 +269,6 @@ static void frameContentAsPlainText(size_t maxChars, Frame* frame, StringBuilder |
} |
} |
-static long long generateFrameIdentifier() |
-{ |
- static long long next = 0; |
- return ++next; |
-} |
- |
WebPluginContainerImpl* WebFrameImpl::pluginContainerFromFrame(Frame* frame) |
{ |
if (!frame) |
@@ -526,6 +523,12 @@ WebFrame* WebFrame::fromFrameOwnerElement(const WebElement& element) |
return WebFrameImpl::fromFrameOwnerElement(PassRefPtr<Element>(element).get()); |
} |
+void WebFrameImpl::close() |
+{ |
+ m_client = 0; |
+ deref(); // Balances ref() acquired in WebFrame::create |
+} |
+ |
WebString WebFrameImpl::uniqueName() const |
{ |
return frame()->tree()->uniqueName(); |
@@ -541,9 +544,9 @@ void WebFrameImpl::setName(const WebString& name) |
frame()->tree()->setName(name); |
} |
-long long WebFrameImpl::identifier() const |
+long long WebFrameImpl::embedderIdentifier() const |
{ |
- return m_identifier; |
+ return m_embedderIdentifier; |
} |
WebVector<WebIconURL> WebFrameImpl::iconURLs(int iconTypesMask) const |
@@ -2061,12 +2064,34 @@ WebString WebFrameImpl::layerTreeAsText(bool showDebugInfo) const |
// WebFrameImpl public --------------------------------------------------------- |
-PassRefPtr<WebFrameImpl> WebFrameImpl::create(WebFrameClient* client) |
+WebFrame* WebFrame::create(WebFrameClient* client) |
+{ |
+ return WebFrameImpl::create(client); |
+} |
+ |
+WebFrame* WebFrame::create(WebFrameClient* client, long long embedderIdentifier) |
+{ |
+ return WebFrameImpl::create(client, embedderIdentifier); |
+} |
+ |
+long long WebFrame::generateEmbedderIdentifier() |
+{ |
+ static long long next = 0; |
+ // Assume that 64-bit will not wrap to -1. |
+ return ++next; |
+} |
+ |
+WebFrameImpl* WebFrameImpl::create(WebFrameClient* client) |
{ |
- return adoptRef(new WebFrameImpl(client)); |
+ return WebFrameImpl::create(client, generateEmbedderIdentifier()); |
} |
-WebFrameImpl::WebFrameImpl(WebFrameClient* client) |
+WebFrameImpl* WebFrameImpl::create(WebFrameClient* client, long long embedderIdentifier) |
+{ |
+ return adoptRef(new WebFrameImpl(client, embedderIdentifier)).leakRef(); |
+} |
+ |
+WebFrameImpl::WebFrameImpl(WebFrameClient* client, long long embedderIdentifier) |
: FrameDestructionObserver(0) |
, m_frameLoaderClient(this) |
, m_client(client) |
@@ -2083,7 +2108,7 @@ WebFrameImpl::WebFrameImpl(WebFrameClient* client) |
, m_nextInvalidateAfter(0) |
, m_findMatchMarkersVersion(0) |
, m_findMatchRectsAreValid(false) |
- , m_identifier(generateFrameIdentifier()) |
+ , m_embedderIdentifier(embedderIdentifier) |
, m_inSameDocumentHistoryLoad(false) |
{ |
WebKit::Platform::current()->incrementStatsCounter(webFrameActiveCount); |
@@ -2109,7 +2134,7 @@ void WebFrameImpl::initializeAsMainFrame(WebCore::Page* page) |
RefPtr<Frame> mainFrame = Frame::create(page, 0, &m_frameLoaderClient); |
setWebCoreFrame(mainFrame.get()); |
- // Add reference on behalf of FrameLoader. See comments in |
+ // Add reference on behalf of FrameLoader. See comments in |
// WebFrameLoaderClient::frameLoaderDestroyed for more info. |
ref(); |
@@ -2120,7 +2145,24 @@ void WebFrameImpl::initializeAsMainFrame(WebCore::Page* page) |
PassRefPtr<Frame> WebFrameImpl::createChildFrame(const FrameLoadRequest& request, HTMLFrameOwnerElement* ownerElement) |
{ |
- RefPtr<WebFrameImpl> webframe(adoptRef(new WebFrameImpl(m_client))); |
+ ASSERT(m_client); |
+ WebFrameImpl* webframe = toWebFrameImpl(m_client->createChildFrame(this, request.frameName())); |
+ |
+ // If the embedder is returning 0 from createChildFrame(), it has not been |
+ // updated to the new ownership semantics where the embedder creates the |
+ // WebFrame. In that case, fall back to the old logic where the |
+ // WebFrameImpl is created here and published back to the embedder. To |
+ // bridge between the two ownership semantics, webframeLifetimeHack is |
+ // needeed to balance out the refcounting. |
+ // |
+ // FIXME: Remove once all embedders return non-null from createChildFrame(). |
+ RefPtr<WebFrameImpl> webframeLifetimeHack; |
+ bool mustCallDidCreateFrame = false; |
+ if (!webframe) { |
+ mustCallDidCreateFrame = true; |
+ webframeLifetimeHack = adoptRef(WebFrameImpl::create(m_client)); |
+ webframe = webframeLifetimeHack.get(); |
+ } |
// Add an extra ref on behalf of the Frame/FrameLoader, which references the |
// WebFrame via the FrameLoaderClient interface. See the comment at the top |
@@ -2134,6 +2176,10 @@ PassRefPtr<Frame> WebFrameImpl::createChildFrame(const FrameLoadRequest& request |
frame()->tree()->appendChild(childFrame); |
+ // FIXME: Remove once all embedders return non-null from createChildFrame(). |
+ if (mustCallDidCreateFrame) |
+ m_client->didCreateFrame(this, webframe); |
+ |
// Frame::init() can trigger onload event in the parent frame, |
// which may detach this frame and trigger a null-pointer access |
// in FrameTree::removeChild. Move init() after appendChild call |
@@ -2142,6 +2188,7 @@ PassRefPtr<Frame> WebFrameImpl::createChildFrame(const FrameLoadRequest& request |
// Because the event handler may set webframe->mFrame to null, |
// it is necessary to check the value after calling init() and |
// return without loading URL. |
+ // NOTE: m_client will be null if this frame has been detached. |
// (b:791612) |
childFrame->init(); // create an empty document |
if (!childFrame->tree()->parent()) |
@@ -2162,12 +2209,10 @@ PassRefPtr<Frame> WebFrameImpl::createChildFrame(const FrameLoadRequest& request |
// A synchronous navigation (about:blank) would have already processed |
// onload, so it is possible for the frame to have already been destroyed by |
// script in the page. |
+ // NOTE: m_client will be null if this frame has been detached. |
if (!childFrame->tree()->parent()) |
return 0; |
- if (m_client) |
- m_client->didCreateFrame(this, webframe.get()); |
- |
return childFrame.release(); |
} |