When a live iframe element is moved between pages, it still depends on the old page.
authordimich@chromium.org <dimich@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 18 Feb 2010 07:55:06 +0000 (07:55 +0000)
committerdimich@chromium.org <dimich@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 18 Feb 2010 07:55:06 +0000 (07:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=34382

Reviewed by David Levin, Darin Fisher, Simon Hausmann.

WebCore:

Test: fast/frames/iframe-reparenting-new-page.html

* html/HTMLFrameElementBase.cpp:
(WebCore::HTMLFrameElementBase::setName):
Move the code setting the frame name into a separate function.

(WebCore::HTMLFrameElementBase::setNameAndOpenURL):
(WebCore::HTMLFrameElementBase::updateOnReparenting):
Called on the frame that was just re-parented and inserted into another Document.
Simply invoke Frame::transferChildFrameToNewDocument(...);

(WebCore::HTMLFrameElementBase::insertedIntoDocument):
* html/HTMLFrameElementBase.h:
* html/HTMLFrameOwnerElement.h:
(WebCore::HTMLFrameOwnerElement::setName):
Make this a virtual function, to be able to reach it via Frame::m_ownerElement.

* loader/EmptyClients.h:
(WebCore::EmptyFrameLoaderClient::adoptFrame):
* loader/FrameLoaderClient.h:
Add a new method, didTransferChildFrameToNewDocument().
It compliments createFrame() in that a frame which was re-parented
in DOM and potentially changes Page, should notify the WebKit
implementation about potential ownership change.
Many embedders assume that Page owns all the Frames, or at least
all Frames are destroyed before 'their' Page is destroyed. Obviously, if Frame
can be transferred to another Page, the embedders should be notified.

* page/Frame.cpp:
(WebCore::Frame::transferChildFrameToNewDocument):
Added, makes actual adjustments for Frame - resets the Page,
updates the frame tree and frame name, calls to FrameLoaderClient
to update external objects and recurses into children.
Can only be used on child frames.

* page/Frame.h:

WebKit/chromium:

* src/FrameLoaderClientImpl.cpp:
(WebKit::FrameLoaderClientImpl::detachedFromParent3):
(WebKit::FrameLoaderClientImpl::didTransferChildFrameToNewDocument):
Since Chromium's WebFrameClient is destroyed once a window is closed,
if Frame moves between Pages, the client of corresponding WebFrame
should be replaced as well.

* src/FrameLoaderClientImpl.h:
* src/WebFrameImpl.h:
(WebKit::WebFrameImpl::setClient):

WebKit/gtk:

* WebCoreSupport/FrameLoaderClientGtk.cpp:
(WebKit::FrameLoaderClient::didTransferChildFrameToNewDocument):
Added empty implementation of a new virtual method.

* WebCoreSupport/FrameLoaderClientGtk.h:

WebKit/haiku:

* WebCoreSupport/FrameLoaderClientHaiku.cpp:
(WebCore::FrameLoaderClientHaiku::didTransferChildFrameToNewDocument):
Added empty implementation of a new virtual method.

* WebCoreSupport/FrameLoaderClientHaiku.h:

WebKit/mac:

* WebCoreSupport/WebFrameLoaderClient.h:
* WebCoreSupport/WebFrameLoaderClient.mm:
Added empty implementation of a new virtual method.

(WebFrameLoaderClient::didTransferChildFrameToNewDocument):

WebKit/qt:

* Api/qwebframe_p.h:
(QWebFramePrivate::setPage): Added.
* WebCoreSupport/FrameLoaderClientQt.cpp:
(WebCore::FrameLoaderClientQt::didTransferChildFrameToNewDocument):
The QWebFrame caches a QWebPage which should be replaced when Frame is re-parented.
Also, the QWebFrame is a child (in QT terms) of QWebPage - so update that relationship as well.
Emit a signal that QWebFrame moved to a different QWebPage.

* WebCoreSupport/FrameLoaderClientQt.h:

WebKit/win:

* WebCoreSupport/WebFrameLoaderClient.cpp:
(WebFrameLoaderClient::didTransferChildFrameToNewDocument):
Added empty implementation of a new virtual method.

* WebCoreSupport/WebFrameLoaderClient.h:

WebKit/wx:

* WebKitSupport/FrameLoaderClientWx.cpp:
(WebCore::FrameLoaderClientWx::didTransferChildFrameToNewDocument):
Added empty implementation of a new virtual method.

* WebKitSupport/FrameLoaderClientWx.h:

LayoutTests:

* fast/frames/iframe-reparenting-new-page-expected.txt: Added.
* fast/frames/iframe-reparenting-new-page.html: Added.
* fast/frames/resources/iframe-reparenting-new-page-1.html: Added.
* fast/frames/resources/iframe-reparenting-new-page-2.html: Added.
* fast/frames/resources/iframe-reparenting-new-page-iframe.html: Added.
* fast/frames/script-tests/TEMPLATE.html: Copied from LayoutTests/fast/canvas/script-tests/TEMPLATE.html.
* fast/frames/script-tests/iframe-reparenting-new-page.js: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@54938 268f45cc-cd09-0410-ab3c-d52691b4dbfc

41 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/frames/iframe-reparenting-new-page-expected.txt [new file with mode: 0644]
LayoutTests/fast/frames/iframe-reparenting-new-page.html [new file with mode: 0644]
LayoutTests/fast/frames/resources/iframe-reparenting-new-page-1.html [new file with mode: 0644]
LayoutTests/fast/frames/resources/iframe-reparenting-new-page-2.html [new file with mode: 0644]
LayoutTests/fast/frames/resources/iframe-reparenting-new-page-iframe.html [new file with mode: 0644]
LayoutTests/fast/frames/script-tests/TEMPLATE.html [new file with mode: 0644]
LayoutTests/fast/frames/script-tests/iframe-reparenting-new-page.js [new file with mode: 0644]
WebCore/ChangeLog
WebCore/html/HTMLFrameElementBase.cpp
WebCore/html/HTMLFrameElementBase.h
WebCore/html/HTMLFrameOwnerElement.h
WebCore/loader/EmptyClients.h
WebCore/loader/FrameLoaderClient.h
WebCore/page/Frame.cpp
WebCore/page/Frame.h
WebKit/chromium/ChangeLog
WebKit/chromium/src/FrameLoaderClientImpl.cpp
WebKit/chromium/src/FrameLoaderClientImpl.h
WebKit/chromium/src/WebFrameImpl.h
WebKit/gtk/ChangeLog
WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp
WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.h
WebKit/haiku/ChangeLog
WebKit/haiku/WebCoreSupport/FrameLoaderClientHaiku.cpp
WebKit/haiku/WebCoreSupport/FrameLoaderClientHaiku.h
WebKit/mac/ChangeLog
WebKit/mac/WebCoreSupport/WebFrameLoaderClient.h
WebKit/mac/WebCoreSupport/WebFrameLoaderClient.mm
WebKit/qt/Api/qwebframe.cpp
WebKit/qt/Api/qwebframe.h
WebKit/qt/Api/qwebframe_p.h
WebKit/qt/ChangeLog
WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp
WebKit/qt/WebCoreSupport/FrameLoaderClientQt.h
WebKit/win/ChangeLog
WebKit/win/WebCoreSupport/WebFrameLoaderClient.cpp
WebKit/win/WebCoreSupport/WebFrameLoaderClient.h
WebKit/wx/ChangeLog
WebKit/wx/WebKitSupport/FrameLoaderClientWx.cpp
WebKit/wx/WebKitSupport/FrameLoaderClientWx.h

index 64b285d..4121355 100644 (file)
@@ -1,3 +1,18 @@
+2010-02-17  Dmitry Titov  <dimich@chromium.org>
+
+        Reviewed by David Levin, Darin Fisher, Simon Hausmann.
+
+        When a live iframe element is moved between pages, it still depends on the old page.
+        https://bugs.webkit.org/show_bug.cgi?id=34382
+
+        * fast/frames/iframe-reparenting-new-page-expected.txt: Added.
+        * fast/frames/iframe-reparenting-new-page.html: Added.
+        * fast/frames/resources/iframe-reparenting-new-page-1.html: Added.
+        * fast/frames/resources/iframe-reparenting-new-page-2.html: Added.
+        * fast/frames/resources/iframe-reparenting-new-page-iframe.html: Added.
+        * fast/frames/script-tests/TEMPLATE.html: Copied from LayoutTests/fast/canvas/script-tests/TEMPLATE.html.
+        * fast/frames/script-tests/iframe-reparenting-new-page.js: Added.
+
 2010-02-17  Csaba Osztrogon√°c  <ossy@webkit.org>
 
          [Qt] DRT: Get total number of pages to be printed
diff --git a/LayoutTests/fast/frames/iframe-reparenting-new-page-expected.txt b/LayoutTests/fast/frames/iframe-reparenting-new-page-expected.txt
new file mode 100644 (file)
index 0000000..02172a4
--- /dev/null
@@ -0,0 +1,18 @@
+The test verifies that the timer in iframe continues firing after iframe is adopted into a new window and the original window was closed.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+PASS Loaded iframe in window 1.
+PASS iframe.contentWindow.counter is 1
+PASS Loaded page 2.
+PASS Page 2 adopted the iframe.
+PASS Iframe transferred.
+PASS iframe.contentWindow.counter is 2
+PASS window2.location.href is iframe.contentWindow.parent.location.href
+PASS Page 1 is closed.
+PASS Received the timer beat from the adopted iframe - exiting.
+
diff --git a/LayoutTests/fast/frames/iframe-reparenting-new-page.html b/LayoutTests/fast/frames/iframe-reparenting-new-page.html
new file mode 100644 (file)
index 0000000..758ae92
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../js/resources/js-test-style.css">
+<script src="../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/iframe-reparenting-new-page.js"></script>
+<script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/frames/resources/iframe-reparenting-new-page-1.html b/LayoutTests/fast/frames/resources/iframe-reparenting-new-page-1.html
new file mode 100644 (file)
index 0000000..52e0005
--- /dev/null
@@ -0,0 +1,6 @@
+<html>
+<body>
+Page 1<br>
+<iframe id="iframe" src="iframe-reparenting-new-page-iframe.html"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/fast/frames/resources/iframe-reparenting-new-page-2.html b/LayoutTests/fast/frames/resources/iframe-reparenting-new-page-2.html
new file mode 100644 (file)
index 0000000..3f26d08
--- /dev/null
@@ -0,0 +1,13 @@
+<html>
+<script>
+window.adoptIframe = function(iframe)
+{
+    document.adoptNode(iframe);
+    document.body.appendChild(iframe);
+    opener.testPassed("Page 2 adopted the iframe.")
+}
+</script>
+<body>
+Page 2<br>
+</body>
+</html>
diff --git a/LayoutTests/fast/frames/resources/iframe-reparenting-new-page-iframe.html b/LayoutTests/fast/frames/resources/iframe-reparenting-new-page-iframe.html
new file mode 100644 (file)
index 0000000..9179a90
--- /dev/null
@@ -0,0 +1,18 @@
+<html>
+<script>
+window.counter = 0;
+
+function tick()
+{
+    if (window.finish)
+        finish();
+}
+
+function start()
+{
+    window.setInterval(tick, 50);
+}
+</script>
+<body onload="start()">
+</body>
+</html>
diff --git a/LayoutTests/fast/frames/script-tests/TEMPLATE.html b/LayoutTests/fast/frames/script-tests/TEMPLATE.html
new file mode 100644 (file)
index 0000000..1936e0d
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../js/resources/js-test-style.css">
+<script src="../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="YOUR_JS_FILE_HERE"></script>
+<script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/frames/script-tests/iframe-reparenting-new-page.js b/LayoutTests/fast/frames/script-tests/iframe-reparenting-new-page.js
new file mode 100644 (file)
index 0000000..7e2d7d2
--- /dev/null
@@ -0,0 +1,55 @@
+description(
+"The test verifies that the timer in iframe continues firing after iframe is adopted into a new window and the original window was closed."
+);
+
+var window1, iframe, window2;
+
+function finish()
+{
+    // Timer may call this multiple times before actual shutdown, generating arbitrary number of log lines.
+    // Reset the callback to avoid this.
+    iframe.contentWindow.finish = null;
+
+    testPassed("Received the timer beat from the adopted iframe - exiting.")
+    window2.close();
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+
+function page1Unloaded()
+{
+    testPassed("Page 1 is closed.");
+    // Give the iframe a function to call from the timer.
+    iframe.contentWindow.finish = finish;
+}
+
+function transferIframe()
+{
+    testPassed("Loaded page 2.");
+    window2.adoptIframe(iframe);
+    testPassed("Iframe transferred.");
+    iframe.contentWindow.counter++;
+    shouldBe("iframe.contentWindow.counter", "2");
+    shouldBe("window2.location.href", "iframe.contentWindow.parent.location.href");
+    window1.onunload = page1Unloaded;
+    window1.close();
+}
+
+function window1Loaded()
+{
+    iframe = window1.document.getElementById("iframe");
+    testPassed("Loaded iframe in window 1.");
+    iframe.contentWindow.counter++;
+    shouldBe("iframe.contentWindow.counter", "1");
+    window2 = window.open("iframe-reparenting-new-page-2.html", "_blank");
+    window2.addEventListener("load", transferIframe, false);
+}
+
+if (window.layoutTestController) {
+    layoutTestController.waitUntilDone();
+    layoutTestController.setCanOpenWindows();
+}
+window1 = window.open("resources/iframe-reparenting-new-page-1.html", "_blank");
+window1.addEventListener("load", window1Loaded, false);
+
+var successfullyParsed = true;
index b780742..547732f 100644 (file)
@@ -1,3 +1,47 @@
+2010-02-17  Dmitry Titov  <dimich@chromium.org>
+
+        Reviewed by David Levin, Darin Fisher, Simon Hausmann.
+
+        When a live iframe element is moved between pages, it still depends on the old page.
+        https://bugs.webkit.org/show_bug.cgi?id=34382
+
+        Test: fast/frames/iframe-reparenting-new-page.html
+
+        * html/HTMLFrameElementBase.cpp:
+        (WebCore::HTMLFrameElementBase::setName):
+        Move the code setting the frame name into a separate function.
+
+        (WebCore::HTMLFrameElementBase::setNameAndOpenURL):
+        (WebCore::HTMLFrameElementBase::updateOnReparenting):
+        Called on the frame that was just re-parented and inserted into another Document.
+        Simply invoke Frame::transferChildFrameToNewDocument(...);
+
+        (WebCore::HTMLFrameElementBase::insertedIntoDocument):
+        * html/HTMLFrameElementBase.h:
+        * html/HTMLFrameOwnerElement.h:
+        (WebCore::HTMLFrameOwnerElement::setName):
+        Make this a virtual function, to be able to reach it via Frame::m_ownerElement.
+
+        * loader/EmptyClients.h:
+        (WebCore::EmptyFrameLoaderClient::adoptFrame):
+        * loader/FrameLoaderClient.h:
+        Add a new method, didTransferChildFrameToNewDocument().
+        It compliments createFrame() in that a frame which was re-parented
+        in DOM and potentially changes Page, should notify the WebKit
+        implementation about potential ownership change.
+        Many embedders assume that Page owns all the Frames, or at least
+        all Frames are destroyed before 'their' Page is destroyed. Obviously, if Frame
+        can be transferred to another Page, the embedders should be notified.
+
+        * page/Frame.cpp:
+        (WebCore::Frame::transferChildFrameToNewDocument):
+        Added, makes actual adjustments for Frame - resets the Page,
+        updates the frame tree and frame name, calls to FrameLoaderClient
+        to update external objects and recurses into children.
+        Can only be used on child frames.
+
+        * page/Frame.h:
+
 2010-02-17  Tony Chang  <tony@chromium.org>
 
         Reviewed by Eric Seidel.
index 3890850..9d84b62 100644 (file)
@@ -150,7 +150,7 @@ void HTMLFrameElementBase::parseMappedAttribute(MappedAttribute *attr)
         HTMLFrameOwnerElement::parseMappedAttribute(attr);
 }
 
-void HTMLFrameElementBase::setNameAndOpenURL()
+void HTMLFrameElementBase::setName()
 {
     m_frameName = getAttribute(nameAttr);
     if (m_frameName.isNull())
@@ -158,7 +158,11 @@ void HTMLFrameElementBase::setNameAndOpenURL()
     
     if (Frame* parentFrame = document()->frame())
         m_frameName = parentFrame->tree()->uniqueChildName(m_frameName);
-    
+}
+
+void HTMLFrameElementBase::setNameAndOpenURL()
+{
+    setName();
     openURL();
 }
 
@@ -167,6 +171,14 @@ void HTMLFrameElementBase::setNameAndOpenURLCallback(Node* n)
     static_cast<HTMLFrameElementBase*>(n)->setNameAndOpenURL();
 }
 
+void HTMLFrameElementBase::updateOnReparenting()
+{
+    ASSERT(m_remainsAliveOnRemovalFromTree);
+
+    if (Frame* frame = contentFrame())
+        frame->transferChildFrameToNewDocument();
+}
+
 void HTMLFrameElementBase::insertedIntoDocument()
 {
     HTMLFrameOwnerElement::insertedIntoDocument();
@@ -175,6 +187,9 @@ void HTMLFrameElementBase::insertedIntoDocument()
     // Othewise, a synchronous load that executed JavaScript would see incorrect 
     // (0) values for the frame's renderer-dependent properties, like width.
     m_shouldOpenURLAfterAttach = true;
+
+    if (m_remainsAliveOnRemovalFromTree)
+        updateOnReparenting();
 }
 
 void HTMLFrameElementBase::removedFromDocument()
index ea93ae7..7717df0 100644 (file)
@@ -64,8 +64,11 @@ private:
     
     virtual bool isURLAttribute(Attribute*) const;
 
+    virtual void setName();
+
     virtual void willRemove();
     void checkAttachedTimerFired(Timer<HTMLFrameElementBase>*);
+    void updateOnReparenting();
 
     bool viewSourceMode() const { return m_viewSource; }
 
index 4a56e45..804ab22 100644 (file)
@@ -59,6 +59,7 @@ protected:
 private:
     friend class Frame;
 
+    virtual void setName() { }
     virtual bool isFrameOwnerElement() const { return true; }
     virtual bool isKeyboardFocusable(KeyboardEvent*) const { return m_contentFrame; }
 
index 268b711..ead0124 100644 (file)
@@ -297,6 +297,7 @@ public:
     virtual void didDisplayInsecureContent() { }
     virtual void didRunInsecureContent(SecurityOrigin*) { }
     virtual PassRefPtr<Frame> createFrame(const KURL&, const String&, HTMLFrameOwnerElement*, const String&, bool, int, int) { return 0; }
+    virtual void didTransferChildFrameToNewDocument() { }
     virtual PassRefPtr<Widget> createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool) { return 0; }
     virtual PassRefPtr<Widget> createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL&, const Vector<String>&, const Vector<String>&) { return 0; }
 
index 4c121f4..23d13bc 100644 (file)
@@ -219,6 +219,7 @@ namespace WebCore {
 
         virtual PassRefPtr<Frame> createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
                                    const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight) = 0;
+        virtual void didTransferChildFrameToNewDocument() = 0;
         virtual PassRefPtr<Widget> createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool loadManually) = 0;
         virtual void redirectDataToPlugin(Widget* pluginWidget) = 0;
 
index f485ad6..262c56c 100644 (file)
@@ -1616,6 +1616,54 @@ void Frame::disconnectOwnerElement()
     m_ownerElement = 0;
 }
 
+// The frame is moved in DOM, potentially to another page.
+void Frame::transferChildFrameToNewDocument()
+{
+    ASSERT(m_ownerElement);
+    Frame* newParent = m_ownerElement->document()->frame();
+    bool didTransfer = false;
+
+    // Switch page.
+    Page* newPage = newParent ? newParent->page() : 0;
+    if (m_page != newPage) {
+        if (page()->focusController()->focusedFrame() == this)
+            page()->focusController()->setFocusedFrame(0);
+
+        if (m_page)
+            m_page->decrementFrameCount();
+
+        m_page = newPage;
+
+        if (newPage)
+            newPage->incrementFrameCount();
+
+        didTransfer = true;
+    }
+
+    // Update the frame tree.
+    Frame* oldParent = tree()->parent();
+    if (oldParent != newParent) {
+        if (oldParent)
+            oldParent->tree()->removeChild(this);
+        if (newParent) {
+            newParent->tree()->appendChild(this);
+            m_ownerElement->setName();
+        }
+        didTransfer = true;
+    }
+
+    // Avoid unnecessary calls to client and frame subtree if the frame ended
+    // up on the same page and under the same parent frame.
+    if (didTransfer) {
+        // Let external clients update themselves.
+        loader()->client()->didTransferChildFrameToNewDocument();
+
+        // Do the same for all the children.
+        for (Frame* child = tree()->firstChild(); child; child = child->tree()->nextSibling())
+            child->transferChildFrameToNewDocument();
+    }
+}
+
 String Frame::documentTypeString() const
 {
     if (DocumentType* doctype = document()->doctype())
index 33bb435..26d1efa 100644 (file)
@@ -76,6 +76,8 @@ namespace WebCore {
 
         Page* page() const;
         void detachFromPage();
+        void transferChildFrameToNewDocument();
+
         HTMLFrameOwnerElement* ownerElement() const;
 
         void pageDestroyed();
index d634d25..6f9a19f 100644 (file)
@@ -1,3 +1,21 @@
+2010-02-17  Dmitry Titov  <dimich@chromium.org>
+
+        Reviewed by David Levin, Darin Fisher, Simon Hausmann.
+
+        When a live iframe element is moved between pages, it still depends on the old page.
+        https://bugs.webkit.org/show_bug.cgi?id=34382
+
+        * src/FrameLoaderClientImpl.cpp:
+        (WebKit::FrameLoaderClientImpl::detachedFromParent3):
+        (WebKit::FrameLoaderClientImpl::didTransferChildFrameToNewDocument):
+        Since Chromium's WebFrameClient is destroyed once a window is closed,
+        if Frame moves between Pages, the client of corresponding WebFrame
+        should be replaced as well.
+
+        * src/FrameLoaderClientImpl.h:
+        * src/WebFrameImpl.h:
+        (WebKit::WebFrameImpl::setClient):
+
 2010-02-17  Evan Martin  <evan@chromium.org>
 
         Reviewed by Eric Seidel.
index b984308..8fb267d 100644 (file)
@@ -235,7 +235,7 @@ void FrameLoaderClientImpl::detachedFromParent3()
     
     // Stop communicating with the WebFrameClient at this point since we are no
     // longer associated with the Page.
-    m_webFrame->dropClient();
+    m_webFrame->setClient(0);
 }
 
 // This function is responsible for associating the |identifier| with a given
@@ -1332,6 +1332,19 @@ PassRefPtr<Frame> FrameLoaderClientImpl::createFrame(
     return m_webFrame->createChildFrame(frameRequest, ownerElement);
 }
 
+void FrameLoaderClientImpl::didTransferChildFrameToNewDocument()
+{
+    ASSERT(m_webFrame->frame()->ownerElement());
+
+    WebFrameImpl* newParent = static_cast<WebFrameImpl*>(m_webFrame->parent());
+    if (!newParent || !newParent->client())
+        return;
+
+    // Replace the client since the old client may be destroyed when the
+    // previous page is closed.
+    m_webFrame->setClient(newParent->client());
+}
+
 PassRefPtr<Widget> FrameLoaderClientImpl::createPlugin(
     const IntSize& size, // FIXME: how do we use this?
     HTMLPlugInElement* element,
index 901600c..8a39393 100644 (file)
@@ -174,6 +174,7 @@ public:
         WebCore::HTMLFrameOwnerElement* ownerElement,
         const WebCore::String& referrer, bool allowsScrolling,
         int marginWidth, int marginHeight);
+    virtual void didTransferChildFrameToNewDocument();
     virtual PassRefPtr<WebCore::Widget> createPlugin(
         const WebCore::IntSize&, WebCore::HTMLPlugInElement*, const WebCore::KURL&,
         const Vector<WebCore::String>&, const Vector<WebCore::String>&,
index 4608e05..f23106c 100644 (file)
@@ -221,7 +221,7 @@ public:
     WebPasswordAutocompleteListener* getPasswordListener(WebCore::HTMLInputElement*);
 
     WebFrameClient* client() const { return m_client; }
-    void dropClient() { m_client = 0; }
+    void setClient(WebFrameClient* client) { m_client = client; }
 
     static void selectWordAroundPosition(WebCore::Frame*, WebCore::VisiblePosition);
 
index 842587d..e72314f 100644 (file)
@@ -1,3 +1,16 @@
+2010-02-17  Dmitry Titov  <dimich@chromium.org>
+
+        Reviewed by David Levin, Darin Fisher, Simon Hausmann.
+
+        When a live iframe element is moved between pages, it still depends on the old page.
+        https://bugs.webkit.org/show_bug.cgi?id=34382
+
+        * WebCoreSupport/FrameLoaderClientGtk.cpp:
+        (WebKit::FrameLoaderClient::didTransferChildFrameToNewDocument):
+        Added empty implementation of a new virtual method.
+
+        * WebCoreSupport/FrameLoaderClientGtk.h:
+
 2010-02-17  Kent Tamura  <tkent@chromium.org>
 
         Reviewed by Eric Seidel.
index 46c7fcf..f900f05 100644 (file)
@@ -491,6 +491,10 @@ PassRefPtr<Frame> FrameLoaderClient::createFrame(const KURL& url, const String&
     return childFrame.release();
 }
 
+void FrameLoaderClient::didTransferChildFrameToNewDocument()
+{
+}
+
 void FrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
 {
     ASSERT(!m_pluginView);
index b364873..d5db6d0 100644 (file)
@@ -113,6 +113,7 @@ namespace WebKit {
 
         virtual PassRefPtr<WebCore::Frame> createFrame(const WebCore::KURL& url, const WebCore::String& name, WebCore::HTMLFrameOwnerElement* ownerElement,
                                    const WebCore::String& referrer, bool allowsScrolling, int marginWidth, int marginHeight);
+        virtual void didTransferChildFrameToNewDocument();
         virtual PassRefPtr<WebCore::Widget> createPlugin(const WebCore::IntSize&, WebCore::HTMLPlugInElement*, const WebCore::KURL&, const WTF::Vector<WebCore::String>&, const WTF::Vector<WebCore::String>&, const WebCore::String&, bool);
         virtual void redirectDataToPlugin(WebCore::Widget* pluginWidget);
         virtual PassRefPtr<WebCore::Widget> createJavaAppletWidget(const WebCore::IntSize&, WebCore::HTMLAppletElement*, const WebCore::KURL& baseURL, const WTF::Vector<WebCore::String>& paramNames, const WTF::Vector<WebCore::String>& paramValues);
index 03fa61b..93833fc 100644 (file)
@@ -1,3 +1,16 @@
+2010-02-17  Dmitry Titov  <dimich@chromium.org>
+
+        Reviewed by David Levin, Darin Fisher, Simon Hausmann.
+
+        When a live iframe element is moved between pages, it still depends on the old page.
+        https://bugs.webkit.org/show_bug.cgi?id=34382
+
+        * WebCoreSupport/FrameLoaderClientHaiku.cpp:
+        (WebCore::FrameLoaderClientHaiku::didTransferChildFrameToNewDocument):
+        Added empty implementation of a new virtual method.
+
+        * WebCoreSupport/FrameLoaderClientHaiku.h:
+
 2010-02-17  Kent Tamura  <tkent@chromium.org>
 
         Reviewed by Eric Seidel.
index 3a84c4f..77c7cfc 100644 (file)
@@ -745,6 +745,10 @@ PassRefPtr<Frame> FrameLoaderClientHaiku::createFrame(const KURL& url, const Str
     return 0;
 }
 
+void FrameLoaderClientHaiku::didTransferChildFrameToNewDocument()
+{
+}
+
 ObjectContentType FrameLoaderClientHaiku::objectContentType(const KURL& url, const String& mimeType)
 {
     notImplemented();
index 2ffde8f..dadda19 100644 (file)
@@ -220,6 +220,7 @@ namespace WebCore {
         virtual PassRefPtr<Frame> createFrame(const KURL& url, const String& name,
                                               HTMLFrameOwnerElement*, const String& referrer,
                                               bool allowsScrolling, int marginWidth, int marginHeight);
+        virtual void didTransferChildFrameToNewDocument();
         virtual PassRefPtr<Widget> createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&,
                                                 const Vector<String>&, const Vector<String>&, const String&,
                                                 bool loadManually);
index 1b4ba65..ec76133 100644 (file)
@@ -1,3 +1,16 @@
+2010-02-17  Dmitry Titov  <dimich@chromium.org>
+
+        Reviewed by David Levin, Darin Fisher, Simon Hausmann.
+
+        When a live iframe element is moved between pages, it still depends on the old page.
+        https://bugs.webkit.org/show_bug.cgi?id=34382
+
+        * WebCoreSupport/WebFrameLoaderClient.h:
+        * WebCoreSupport/WebFrameLoaderClient.mm:
+        Added empty implementation of a new virtual method.
+
+        (WebFrameLoaderClient::didTransferChildFrameToNewDocument):
+
 2010-02-17  Kent Tamura  <tkent@chromium.org>
 
         Reviewed by Eric Seidel.
index 2774783..988b8a6 100644 (file)
@@ -188,6 +188,7 @@ private:
 
     virtual PassRefPtr<WebCore::Frame> createFrame(const WebCore::KURL& url, const WebCore::String& name, WebCore::HTMLFrameOwnerElement*,
                                         const WebCore::String& referrer, bool allowsScrolling, int marginWidth, int marginHeight);
+    virtual void didTransferChildFrameToNewDocument();
     virtual PassRefPtr<WebCore::Widget> createPlugin(const WebCore::IntSize&, WebCore::HTMLPlugInElement*, const WebCore::KURL&, const Vector<WebCore::String>&,
                                           const Vector<WebCore::String>&, const WebCore::String&, bool);
     virtual void redirectDataToPlugin(WebCore::Widget* pluginWidget);
index 1085d9e..52a24b4 100644 (file)
@@ -1352,6 +1352,10 @@ PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& url, const Strin
     return 0;
 }
 
+void WebFrameLoaderClient::didTransferChildFrameToNewDocument()
+{
+}
+
 ObjectContentType WebFrameLoaderClient::objectContentType(const KURL& url, const String& mimeType)
 {
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
index d341c6a..15b5c00 100644 (file)
@@ -298,6 +298,21 @@ void QWebFramePrivate::init(QWebFrame *qframe, QWebFrameData *frameData)
     frame->init();
 }
 
+void QWebFramePrivate::setPage(QWebPage* newPage)
+{
+    if (page == newPage)
+        return;
+
+    // The QWebFrame is created as a child of QWebPage or a parent QWebFrame.
+    // That adds it to QObject's internal children list and ensures it will be
+    // deleted when parent QWebPage is deleted. Reparent if needed.
+    if (q->parent() == qobject_cast<QObject*>(page))
+        q->setParent(newPage);
+
+    page = newPage;
+    emit q->pageChanged();
+}
+
 WebCore::Scrollbar* QWebFramePrivate::horizontalScrollBar() const
 {
     if (!frame->view())
index 541b055..68594fd 100644 (file)
@@ -219,6 +219,8 @@ Q_SIGNALS:
     void loadStarted();
     void loadFinished(bool ok);
 
+    void pageChanged();
+
 private:
     friend class QWebPage;
     friend class QWebPagePrivate;
index ee978be..7d79474 100644 (file)
@@ -73,6 +73,7 @@ public:
         , marginHeight(-1)
         {}
     void init(QWebFrame* qframe, QWebFrameData* frameData);
+    void setPage(QWebPage*);
 
     inline QWebFrame *parentFrame() { return qobject_cast<QWebFrame*>(q->parent()); }
 
index cee97f9..d589995 100644 (file)
@@ -1,3 +1,20 @@
+2010-02-17  Dmitry Titov  <dimich@chromium.org>
+
+        Reviewed by David Levin, Darin Fisher, Simon Hausmann.
+
+        When a live iframe element is moved between pages, it still depends on the old page.
+        https://bugs.webkit.org/show_bug.cgi?id=34382
+
+        * Api/qwebframe_p.h:
+        (QWebFramePrivate::setPage): Added.
+        * WebCoreSupport/FrameLoaderClientQt.cpp:
+        (WebCore::FrameLoaderClientQt::didTransferChildFrameToNewDocument):
+        The QWebFrame caches a QWebPage which should be replaced when Frame is re-parented.
+        Also, the QWebFrame is a child (in QT terms) of QWebPage - so update that relationship as well.
+        Emit a signal that QWebFrame moved to a different QWebPage.
+
+        * WebCoreSupport/FrameLoaderClientQt.h:
+
 2010-02-17  Kent Tamura  <tkent@chromium.org>
 
         Reviewed by Eric Seidel.
index 16a6faa..2eb2761 100644 (file)
@@ -1066,6 +1066,24 @@ PassRefPtr<Frame> FrameLoaderClientQt::createFrame(const KURL& url, const String
     return frameData.frame.release();
 }
 
+void FrameLoaderClientQt::didTransferChildFrameToNewDocument()
+{
+    ASSERT(m_frame->ownerElement());
+
+    if (!m_webFrame)
+        return;
+
+    Frame* parentFrame = m_webFrame->d->frame->tree()->parent();
+    ASSERT(parentFrame);
+
+    if (QWebFrame* parent = QWebFramePrivate::kit(parentFrame)) {
+        m_webFrame->d->setPage(parent->page());
+
+        if (m_webFrame->parent() != qobject_cast<QObject*>(parent))
+            m_webFrame->setParent(parent);
+    }
+}
+
 ObjectContentType FrameLoaderClientQt::objectContentType(const KURL& url, const String& _mimeType)
 {
 //    qDebug()<<" ++++++++++++++++ url is "<<url.prettyURL()<<", mime = "<<_mimeType;
index 32b9caa..adeb31c 100644 (file)
@@ -194,6 +194,7 @@ namespace WebCore {
 
         virtual PassRefPtr<Frame> createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
                                    const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight) ;
+        virtual void didTransferChildFrameToNewDocument();
         virtual PassRefPtr<Widget> createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool);
         virtual void redirectDataToPlugin(Widget* pluginWidget);
 
index f2133aa..140592e 100644 (file)
@@ -1,3 +1,16 @@
+2010-02-17  Dmitry Titov  <dimich@chromium.org>
+
+        Reviewed by David Levin, Darin Fisher, Simon Hausmann.
+
+        When a live iframe element is moved between pages, it still depends on the old page.
+        https://bugs.webkit.org/show_bug.cgi?id=34382
+
+        * WebCoreSupport/WebFrameLoaderClient.cpp:
+        (WebFrameLoaderClient::didTransferChildFrameToNewDocument):
+        Added empty implementation of a new virtual method.
+
+        * WebCoreSupport/WebFrameLoaderClient.h:
+
 2010-02-17  Kent Tamura  <tkent@chromium.org>
 
         Reviewed by Eric Seidel.
index b927c72..6ae6c5e 100644 (file)
@@ -737,6 +737,10 @@ PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& url, const Strin
     return result.release();
 }
 
+void WebFrameLoaderClient::didTransferChildFrameToNewDocument()
+{
+}
+
 PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& URL, const String& name, HTMLFrameOwnerElement* ownerElement, const String& referrer)
 {
     Frame* coreFrame = core(m_webFrame);
index f1fb5f7..a5f2b1b 100644 (file)
@@ -112,6 +112,7 @@ public:
 
     virtual PassRefPtr<WebCore::Frame> createFrame(const WebCore::KURL& url, const WebCore::String& name, WebCore::HTMLFrameOwnerElement* ownerElement,
                                const WebCore::String& referrer, bool allowsScrolling, int marginWidth, int marginHeight);
+    virtual void didTransferChildFrameToNewDocument();
     virtual PassRefPtr<WebCore::Widget> createPlugin(const WebCore::IntSize&, WebCore::HTMLPlugInElement*, const WebCore::KURL&, const Vector<WebCore::String>&, const Vector<WebCore::String>&, const WebCore::String&, bool loadManually);
     virtual void redirectDataToPlugin(WebCore::Widget* pluginWidget);
 
index 158d620..7d6d9dd 100644 (file)
@@ -1,3 +1,16 @@
+2010-02-17  Dmitry Titov  <dimich@chromium.org>
+
+        Reviewed by David Levin, Darin Fisher, Simon Hausmann.
+
+        When a live iframe element is moved between pages, it still depends on the old page.
+        https://bugs.webkit.org/show_bug.cgi?id=34382
+
+        * WebKitSupport/FrameLoaderClientWx.cpp:
+        (WebCore::FrameLoaderClientWx::didTransferChildFrameToNewDocument):
+        Added empty implementation of a new virtual method.
+
+        * WebKitSupport/FrameLoaderClientWx.h:
+
 2010-02-17  Kent Tamura  <tkent@chromium.org>
 
         Reviewed by Eric Seidel.
index 5bb4dc1..6afdd88 100644 (file)
@@ -841,6 +841,10 @@ PassRefPtr<Frame> FrameLoaderClientWx::createFrame(const KURL& url, const String
     return childFrame.release();
 }
 
+void FrameLoaderClientWx::didTransferChildFrameToNewDocument()
+{
+}
+
 ObjectContentType FrameLoaderClientWx::objectContentType(const KURL& url, const String& mimeType)
 {
     notImplemented();
index 0c29941..62218ff 100644 (file)
@@ -201,6 +201,7 @@ namespace WebCore {
 
         virtual PassRefPtr<Frame> createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
                                    const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight);
+        virtual void didTransferChildFrameToNewDocument();
         virtual PassRefPtr<Widget> createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool loadManually) ;
         virtual void redirectDataToPlugin(Widget* pluginWidget);
         virtual ResourceError pluginWillHandleLoadError(const ResourceResponse&);