LayoutTests:
authorweinig <weinig@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Mar 2007 16:05:37 +0000 (16:05 +0000)
committerweinig <weinig@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Mar 2007 16:05:37 +0000 (16:05 +0000)
        Reviewed by Darin.

        - test for http://bugs.webkit.org/show_bug.cgi?id=9929
          REGRESSION: crash on logging in on mijnpostbank.nl

        * http/tests/misc/onload-remove-iframe-crash-2-expected.txt: Added.
        * http/tests/misc/onload-remove-iframe-crash-2.html: Added.
        * http/tests/misc/resources/onload-remove-iframe-crash-2.html: Added.
        * http/tests/misc/resources/onload-remove-iframe.html: Added.

WebCore:

        Reviewed by Darin.

        - fix http://bugs.webkit.org/show_bug.cgi?id=9929
          REGRESSION: crash on logging in on mijnpostbank.nl

        Test: http/tests/misc/onload-remove-iframe-crash-2.html

        The resulted from an iframe's load event handler removing the iframe
        from the document.

        * dom/Document.cpp:
        (WebCore::Document::implicitClose): Bail out early if an event handler
        removed the frame.
        * loader/FrameLoader.cpp:
        (WebCore::FrameLoader::FrameLoader):
        (WebCore::FrameLoader::clear):
        (WebCore::FrameLoader::checkCompleted): Protect the frame from deletion
        by event handlers.
        (WebCore::FrameLoader::checkCompletedTimerFired):
        (WebCore::FrameLoader::scheduleCheckCompleted):
        (WebCore::FrameLoader::detachFromParent): Schedule a completion check
        on the parent (in case the child is what has been keeping it from completing).
        * loader/FrameLoader.h:

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

LayoutTests/ChangeLog
LayoutTests/http/tests/misc/onload-remove-iframe-crash-2-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/misc/onload-remove-iframe-crash-2.html [new file with mode: 0644]
LayoutTests/http/tests/misc/resources/onload-remove-iframe-crash-2.html [new file with mode: 0644]
LayoutTests/http/tests/misc/resources/onload-remove-iframe.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/dom/Document.cpp
WebCore/loader/FrameLoader.cpp
WebCore/loader/FrameLoader.h

index 9fefedf..a5ee020 100644 (file)
@@ -1,3 +1,15 @@
+2007-03-09  Mitz Pettel  <mitz@webkit.org>
+
+        Reviewed by Darin.
+
+        - test for http://bugs.webkit.org/show_bug.cgi?id=9929
+          REGRESSION: crash on logging in on mijnpostbank.nl
+
+        * http/tests/misc/onload-remove-iframe-crash-2-expected.txt: Added.
+        * http/tests/misc/onload-remove-iframe-crash-2.html: Added.
+        * http/tests/misc/resources/onload-remove-iframe-crash-2.html: Added.
+        * http/tests/misc/resources/onload-remove-iframe.html: Added.
+
 2007-03-08  Justin Garcia  <justin.garcia@apple.com>
 
         Reviewed by harrison
diff --git a/LayoutTests/http/tests/misc/onload-remove-iframe-crash-2-expected.txt b/LayoutTests/http/tests/misc/onload-remove-iframe-crash-2-expected.txt
new file mode 100644 (file)
index 0000000..064737f
--- /dev/null
@@ -0,0 +1,2 @@
+ALERT: SUCCESS
+
diff --git a/LayoutTests/http/tests/misc/onload-remove-iframe-crash-2.html b/LayoutTests/http/tests/misc/onload-remove-iframe-crash-2.html
new file mode 100644 (file)
index 0000000..c0a743d
--- /dev/null
@@ -0,0 +1,28 @@
+<html>
+<head>
+    <title>http://bugs.webkit.org/show_bug.cgi?id=9929</title>
+    <script>
+        if (window.layoutTestController) {
+            layoutTestController.waitUntilDone();
+            layoutTestController.dumpAsText();
+        }
+
+        var reloaded = false;
+        function frameLoaded()
+        {
+            if (!reloaded) {
+                reloaded = true;
+                frames[0].location.reload();
+            } else {
+                if (window.layoutTestController) {
+                    alert("SUCCESS");
+                    layoutTestController.notifyDone();
+                }
+            }
+        }
+    </script>
+</head>
+<frameset cols="*">
+    <frame src="resources/onload-remove-iframe-crash-2.html">
+</frameset>
+</html>
diff --git a/LayoutTests/http/tests/misc/resources/onload-remove-iframe-crash-2.html b/LayoutTests/http/tests/misc/resources/onload-remove-iframe-crash-2.html
new file mode 100644 (file)
index 0000000..345bb1f
--- /dev/null
@@ -0,0 +1,19 @@
+<html>
+<head>
+    <title></title>
+    <script>
+        function done()
+        {
+            var f = document.getElementById("iframe");
+            f.parentNode.removeChild(f); 
+            parent.frameLoaded();
+        }
+    </script>
+</head>
+<body>
+    <div>
+        <iframe id="iframe" onload="done()" src="onload-remove-iframe.html">
+        </iframe>
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/misc/resources/onload-remove-iframe.html b/LayoutTests/http/tests/misc/resources/onload-remove-iframe.html
new file mode 100644 (file)
index 0000000..a113265
--- /dev/null
@@ -0,0 +1 @@
+<img src="../../security/resources/green250x50.png">
index a535634..8e11f67 100644 (file)
@@ -1,3 +1,29 @@
+2007-03-09  Mitz Pettel  <mitz@webkit.org>
+
+        Reviewed by Darin.
+
+        - fix http://bugs.webkit.org/show_bug.cgi?id=9929
+          REGRESSION: crash on logging in on mijnpostbank.nl
+
+        Test: http/tests/misc/onload-remove-iframe-crash-2.html
+
+        The resulted from an iframe's load event handler removing the iframe
+        from the document.
+
+        * dom/Document.cpp:
+        (WebCore::Document::implicitClose): Bail out early if an event handler
+        removed the frame.
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::FrameLoader):
+        (WebCore::FrameLoader::clear):
+        (WebCore::FrameLoader::checkCompleted): Protect the frame from deletion
+        by event handlers.
+        (WebCore::FrameLoader::checkCompletedTimerFired):
+        (WebCore::FrameLoader::scheduleCheckCompleted):
+        (WebCore::FrameLoader::detachFromParent): Schedule a completion check
+        on the parent (in case the child is what has been keeping it from completing).
+        * loader/FrameLoader.h:
+
 2007-03-08  David Kilzer  <ddkilzer@webkit.org>
 
         Reviewed by Beth.
index 326be55..ae3ff06 100644 (file)
@@ -1389,19 +1389,22 @@ void Document::implicitClose()
 
     m_processingLoadEvent = false;
 
+    // An event handler may have removed the frame
+    if (!frame())
+        return;
+
     // Make sure both the initial layout and reflow happen after the onload
     // fires. This will improve onload scores, and other browsers do it.
     // If they wanna cheat, we can too. -dwh
 
-    if (frame() && frame()->loader()->isScheduledLocationChangePending() && elapsedTime() < cLayoutScheduleThreshold) {
+    if (frame()->loader()->isScheduledLocationChangePending() && elapsedTime() < cLayoutScheduleThreshold) {
         // Just bail out. Before or during the onload we were shifted to another page.
         // The old i-Bench suite does this. When this happens don't bother painting or laying out.        
         view()->unscheduleRelayout();
         return;
     }
 
-    if (frame())
-        frame()->loader()->checkEmitLoadEvent();
+    frame()->loader()->checkEmitLoadEvent();
 
     // Now do our painting/layout, but only if we aren't in a subframe or if we're in a subframe
     // that has been sized already.  Otherwise, our view size would be incorrect, so doing any 
index d9abf39..d6f6870 100644 (file)
@@ -223,6 +223,7 @@ FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client)
     , m_encodingWasChosenByUser(false)
     , m_containsPlugIns(false)
     , m_redirectionTimer(this, &FrameLoader::redirectionTimerFired)
+    , m_checkCompletedTimer(this, &FrameLoader::checkCompletedTimerFired)
     , m_opener(0)
     , m_openedByJavaScript(false)
 {
@@ -742,6 +743,8 @@ void FrameLoader::clear(bool clearWindowProperties)
     m_redirectionTimer.stop();
     m_scheduledRedirection.clear();
 
+    m_checkCompletedTimer.stop();
+
     m_receivedData = false;
 
     if (!m_encodingWasChosenByUser)
@@ -1082,6 +1085,7 @@ void FrameLoader::checkCompleted()
     // OK, completed.
     m_isComplete = true;
 
+    RefPtr<Frame> protect(m_frame);
     checkEmitLoadEvent(); // if we didn't do it before
 
     // Do not start a redirection timer for subframes here.
@@ -1092,6 +1096,17 @@ void FrameLoader::checkCompleted()
     completed();
 }
 
+void FrameLoader::checkCompletedTimerFired(Timer<FrameLoader>*)
+{
+    checkCompleted();
+}
+
+void FrameLoader::scheduleCheckCompleted()
+{
+    if (!m_checkCompletedTimer.isActive())
+        m_checkCompletedTimer.startOneShot(0);
+}
+
 void FrameLoader::checkEmitLoadEvent()
 {
     if (m_wasLoadEventEmitted || !m_frame->document() || m_frame->document()->parsing())
@@ -2841,9 +2856,10 @@ void FrameLoader::detachFromParent()
     m_client->detachedFromParent2();
     setDocumentLoader(0);
     m_client->detachedFromParent3();
-    if (Frame* parent = m_frame->tree()->parent())
+    if (Frame* parent = m_frame->tree()->parent()) {
         parent->tree()->removeChild(m_frame);
-    else {
+        parent->loader()->scheduleCheckCompleted();
+    } else {
         m_frame->setView(0);
         m_frame->pageDestroyed();
     }
index 39ab36d..5fa2367 100644 (file)
@@ -82,8 +82,6 @@ namespace WebCore {
     struct ScheduledRedirection;
     struct WindowFeatures;
 
-    template <typename T> class Timer;
-
     bool isBackForwardLoadType(FrameLoadType);
 
     typedef void (*NavigationPolicyDecisionFunction)(void* argument,
@@ -362,6 +360,7 @@ namespace WebCore {
         void loadDone();
         void finishedParsing();
         void checkCompleted();
+        void scheduleCheckCompleted();
 
         void clearRecordedFormValues();
         void recordFormValue(const String& name, const String& value, PassRefPtr<HTMLFormElement>);
@@ -435,6 +434,7 @@ namespace WebCore {
         void updateHistoryForCommit();
     
         void redirectionTimerFired(Timer<FrameLoader>*);
+        void checkCompletedTimerFired(Timer<FrameLoader>*);
 
         void cancelRedirection(bool newLoadInProgress = false);
 
@@ -586,6 +586,7 @@ namespace WebCore {
         KURL m_submittedFormURL;
     
         Timer<FrameLoader> m_redirectionTimer;
+        Timer<FrameLoader> m_checkCompletedTimer;
 
         Frame* m_opener;
         HashSet<Frame*> m_openedFrames;