[SCM] WebKit Debian packaging branch, debian/experimental, updated. debian/1.3.8-1-1049-g2e11a8e

rniwa at webkit.org rniwa at webkit.org
Fri Jan 21 15:10:00 UTC 2011


The following commit has been merged in the debian/experimental branch:
commit cf46007a6af7370674fea37ce25806b9204a8e94
Author: rniwa at webkit.org <rniwa at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Sat Jan 8 02:15:10 2011 +0000

    2011-01-06  Ryosuke Niwa  <rniwa at webkit.org>
    
            Reviewed by Adam Barth.
    
            onbeforeunload is broken for framesets
            https://bugs.webkit.org/show_bug.cgi?id=19418
    
            Added beforeunload event support for sub frames. WebKit's implementation tries to match
            that of Internet Explorer as much as possible. beforeunload event is fired for each and
            every descendent of a frame that is about to navigate.
    
            When a value other than null is returned by a beforeunload handler, a confirmation dialog
            is shown for each handler (calls chrome's runBeforeUnloadConfirmPanel) just like it is done
            for main frames.
    
            In addition, navigation is forbidden while beforeunload handlers are being called.
            Setting values to location.href, location.reload, and other means of navigations are thus
            ignored while beforeunload event handler is being ran, matching Internet Explorer's behavior.
    
            Because navigation needs to prevented globally, NavigationDisablerForBeforeUnload is added to
            NavigationScheduler.h, which is instantiated as a RAII object in FrameLoader::shouldClose.
    
            Tests: fast/events/before-unload-adopt-subframe-to-outside.html
                   fast/events/before-unload-adopt-within-subframes.html
                   fast/events/before-unload-forbidden-navigation.html
                   fast/events/before-unload-in-multiple-subframes.html
                   fast/events/before-unload-in-subframe.html
                   fast/events/before-unload-javascript-navigation.html
                   fast/events/before-unload-remove-and-add-subframe.html
                   fact/events/before-unload-remove-itself.html
                   fast/events/before-unload-with-subframes.html
    
           * loader/FrameLoader.cpp:
           (WebCore::FrameLoader::shouldClose): Calls fireBeforeUnloadEvent on m_frame and m_frame's
           descendents. Returns true only if every call to fireBeforeUnloadEvent returned true.
           (WebCore::FrameLoader::fireBeforeUnloadEvent): Fires a beforeunload event and calls
           chrome's runBeforeUnloadConfirmPanel as needed.
           (WebCore::FrameLoader::continueLoadAfterNavigationPolicy): Calls shouldClose for all frames.
           * loader/FrameLoader.h:
           * loader/NavigationScheduler.cpp:
           (WebCore::NavigationScheduler::shouldScheduleNavigation): Checks the nullity of Page and calls
           NavigationDisablerForBeforeUnload::isNavigationAllowed when url is not javascript scheme.
           (WebCore::NavigationScheduler::scheduleRedirect): Calls shouldScheduleNavigation.
           (WebCore::NavigationScheduler::scheduleLocationChange): Ditto.
           (WebCore::NavigationScheduler::scheduleRefresh): Ditto.
           (WebCore::NavigationScheduler::scheduleHistoryNavigation): Ditto.
           * loader/NavigationScheduler.h:
           (WebCore::NavigationDisablerForBeforeUnload::NavigationDisablerForBeforeUnload): Disables navigation.
           (WebCore::NavigationDisablerForBeforeUnload::~NavigationDisablerForBeforeUnload): Enables navigation
           when called on the last instance of NavigationDisablerForBeforeUnload.
           (WebCore::NavigationDisablerForBeforeUnload::isNavigationAllowed): Returns true if there are no instance
           of NavigationDisablerForBeforeUnload left on the stack.
    2011-01-06  Ryosuke Niwa  <rniwa at webkit.org>
    
            Reviewed by Adam Barth.
    
            onbeforeunload is broken for framesets
            https://bugs.webkit.org/show_bug.cgi?id=19418
    
            Added tests to ensure WebKit fires beforeunload events for subframes,
            and disallows navigation except that of javascript scheme while beforeunload event
            handlers are being called.
    
            Also added a test to ensure WebKit fires beforeunload event for subframes exactly
            once even if a subframe was moved around within a beforeunload event handler.
    
            A test that ensures beforeunload event is not fired for an iframe if the iframe
            was added or removed within a beforeunload event handler is also added.
    
            Furthermore, a test to ensure WebKit does not fire a beforeunload event to an iframe
            that has been adopted by a document outside of the unloading document is added.
    
            * fast/events/before-unload-adopt-subframe-to-outside-expected.txt: Added.
            * fast/events/before-unload-adopt-subframe-to-outside.html: Added.
            * fast/events/before-unload-adopt-within-subframes-expected.txt: Added.
            * fast/events/before-unload-adopt-within-subframes.html: Added.
            * fast/events/before-unload-forbidden-navigation-expected.txt: Added.
            * fast/events/before-unload-forbidden-navigation.html: Added.
            * fast/events/before-unload-in-multiple-subframes-expected.txt: Added.
            * fast/events/before-unload-in-multiple-subframes.html: Added.
            * fast/events/before-unload-in-subframe-expected.txt: Added.
            * fast/events/before-unload-in-subframe.html: Added.
            * fast/events/before-unload-javascript-navigation-expected.txt: Added.
            * fast/events/before-unload-javascript-navigation.html: Added.
            * fast/events/before-unload-remove-and-add-subframe-expected.txt: Added.
            * fast/events/before-unload-remove-and-add-subframe.html: Added.
            * fact/events/before-unload-remove-itself-expected.txt: Added.
            * fact/events/before-unload-remove-itself.html: Added.
            * fast/events/before-unload-with-subframes-expected.txt: Added.
            * fast/events/before-unload-with-subframes.html: Added.
            * fast/events/resources/before-unload-in-subframe-child.html: Added.
            * fast/events/resources/before-unload-in-subframe-destination.html: Added.
            * fast/events/resources/before-unload-in-subframe-fail.html: Added.
            * fast/events/resources/before-unload-with-subframes-parent.html: Added.
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@75305 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index efdc335..41bb61d 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,46 @@
+2011-01-06  Ryosuke Niwa  <rniwa at webkit.org>
+
+        Reviewed by Adam Barth.
+
+        onbeforeunload is broken for framesets
+        https://bugs.webkit.org/show_bug.cgi?id=19418
+
+        Added tests to ensure WebKit fires beforeunload events for subframes,
+        and disallows navigation except that of javascript scheme while beforeunload event
+        handlers are being called.
+
+        Also added a test to ensure WebKit fires beforeunload event for subframes exactly
+        once even if a subframe was moved around within a beforeunload event handler.
+
+        A test that ensures beforeunload event is not fired for an iframe if the iframe
+        was added or removed within a beforeunload event handler is also added.
+
+        Furthermore, a test to ensure WebKit does not fire a beforeunload event to an iframe
+        that has been adopted by a document outside of the unloading document is added.
+
+        * fast/events/before-unload-adopt-subframe-to-outside-expected.txt: Added.
+        * fast/events/before-unload-adopt-subframe-to-outside.html: Added.
+        * fast/events/before-unload-adopt-within-subframes-expected.txt: Added.
+        * fast/events/before-unload-adopt-within-subframes.html: Added.
+        * fast/events/before-unload-forbidden-navigation-expected.txt: Added.
+        * fast/events/before-unload-forbidden-navigation.html: Added.
+        * fast/events/before-unload-in-multiple-subframes-expected.txt: Added.
+        * fast/events/before-unload-in-multiple-subframes.html: Added.
+        * fast/events/before-unload-in-subframe-expected.txt: Added.
+        * fast/events/before-unload-in-subframe.html: Added.
+        * fast/events/before-unload-javascript-navigation-expected.txt: Added.
+        * fast/events/before-unload-javascript-navigation.html: Added.
+        * fast/events/before-unload-remove-and-add-subframe-expected.txt: Added.
+        * fast/events/before-unload-remove-and-add-subframe.html: Added.
+        * fact/events/before-unload-remove-itself-expected.txt: Added.
+        * fact/events/before-unload-remove-itself.html: Added.
+        * fast/events/before-unload-with-subframes-expected.txt: Added.
+        * fast/events/before-unload-with-subframes.html: Added.
+        * fast/events/resources/before-unload-in-subframe-child.html: Added.
+        * fast/events/resources/before-unload-in-subframe-destination.html: Added.
+        * fast/events/resources/before-unload-in-subframe-fail.html: Added.
+        * fast/events/resources/before-unload-with-subframes-parent.html: Added.
+
 2011-01-07  Martin Robinson  <mrobinson at igalia.com>
 
         Reviewed by Mihai Parparita.
diff --git a/LayoutTests/fast/events/before-unload-adopt-subframe-to-outside-expected.txt b/LayoutTests/fast/events/before-unload-adopt-subframe-to-outside-expected.txt
new file mode 100644
index 0000000..b2bf428
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-adopt-subframe-to-outside-expected.txt
@@ -0,0 +1,9 @@
+This test ensures beforeunload event does NOT fire for a subframe that has been adopted by a document outside of the frame hierarchy that is about to unload.
+
+PASS: fired on parent
+PASS: fired on a
+adopting
+adopted
+PASS: fired on b
+DONE
+ 
diff --git a/LayoutTests/fast/events/before-unload-adopt-subframe-to-outside.html b/LayoutTests/fast/events/before-unload-adopt-subframe-to-outside.html
new file mode 100644
index 0000000..957cb51
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-adopt-subframe-to-outside.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>This test ensures beforeunload event does NOT fire for a subframe that has been adopted by a document outside of the frame hierarchy that is about to unload.</p>
+<pre id="log"></pre>
+<script>
+
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.waitUntilDone();
+}
+
+function createFrame(id, parent) {
+    var iframe = document.createElement('iframe');
+    if (parent)
+        parent.contentDocument.body.appendChild(iframe);
+    else
+        document.body.appendChild(iframe);
+    if (!iframe.contentDocument.body)
+        iframe.contentDocument.appendChild(iframe.contentDocument.createElement('body'));
+    iframe.contentDocument.body.appendChild(iframe.contentDocument.createTextNode(id));    
+    iframe.contentDocument.body.appendChild(iframe.contentDocument.createElement('br'));
+    iframe.contentWindow.onbeforeunload = function () { fired(iframe.contentWindow, id); return null; }
+    iframe.style.width = '70%';
+    iframe.style.height = '40%';
+    return iframe;
+}
+
+function log(message) {
+    var log = document.getElementById('log');
+    log.innerHTML += message + '\n';
+}
+
+var expectedOrder = ['parent', 'a', 'b'];
+var i = 0;
+
+function fired(contentWindow, id) {
+    if (expectedOrder[i] == id)
+        log('PASS: fired on ' + id);
+    else
+        log('FAIL: fired on ' + id + ' but expected on ' + expectedOrder[i]);
+    i++;
+
+    if (contentWindow == a.contentWindow) {
+        log('adopting');
+        document.body.appendChild(document.adoptNode(adoptee));
+        log('adopted');
+    }
+}
+
+var container = createFrame('parent');
+var a = createFrame('a', container);
+var adoptee = createFrame('adoptee', a);
+var b = createFrame('b', container);
+
+container.onload = function () {
+    if (i == expectedOrder.length)
+        log('DONE');
+    else
+        log('Received ' + i + ' events but expected ' + expectedOrder.length);
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+container.src = 'resources/before-unload-in-subframe-destination.html';
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/before-unload-adopt-within-subframes-expected.txt b/LayoutTests/fast/events/before-unload-adopt-within-subframes-expected.txt
new file mode 100644
index 0000000..d4bc9a5
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-adopt-within-subframes-expected.txt
@@ -0,0 +1,10 @@
+This test ensures beforeunload event fires exactly once in a subframe even if the frame was adopted to a frame that appears later in the tree.
+
+PASS: fired on parent
+PASS: fired on a
+PASS: fired on adoptee
+adopting
+adopted
+PASS: fired on b
+DONE
+
diff --git a/LayoutTests/fast/events/before-unload-adopt-within-subframes.html b/LayoutTests/fast/events/before-unload-adopt-within-subframes.html
new file mode 100644
index 0000000..2b86f9d
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-adopt-within-subframes.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>This test ensures beforeunload event fires exactly once in a subframe even if the frame was adopted to a frame that appears later in the tree.</p>
+<pre id="log"></pre>
+<script>
+
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.waitUntilDone();
+}
+
+function createFrame(id, parent) {
+    var iframe = document.createElement('iframe');
+    if (parent)
+        parent.contentDocument.body.appendChild(iframe);
+    else
+        document.body.appendChild(iframe);
+    iframe.contentDocument.body.appendChild(iframe.contentDocument.createTextNode(id));    
+    iframe.contentDocument.body.appendChild(iframe.contentDocument.createElement('br'));
+    iframe.contentWindow.onbeforeunload = function () { fired(iframe.contentWindow, id); return null; }
+    iframe.style.width = '70%';
+    iframe.style.height = '40%';
+    return iframe;
+}
+
+function log(message) {
+    var log = document.getElementById('log');
+    log.innerHTML += message + '\n';
+}
+
+var expectedOrder = ['parent', 'a', 'adoptee', 'b'];
+var i = 0;
+
+function fired(contentWindow, id) {
+    if (expectedOrder[i] == id)
+        log('PASS: fired on ' + id);
+    else
+        log('FAIL: fired on ' + id + ' but expected on ' + expectedOrder[i]);
+    i++;
+
+    if (contentWindow == adoptee.contentWindow) {
+        log('adopting');
+        b.contentDocument.body.appendChild(b.contentDocument.adoptNode(adoptee));
+        log('adopted');
+    }
+}
+
+var container = createFrame('parent');
+var a = createFrame('a', container);
+var adoptee = createFrame('adoptee', a);
+var b = createFrame('b', container);
+
+container.onload = function () {
+    if (i == expectedOrder.length)
+        log('DONE');
+    else
+        log('Received ' + i + ' events but expected ' + expectedOrder.length);
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+container.src = 'resources/before-unload-in-subframe-destination.html';
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/before-unload-forbidden-navigation-expected.txt b/LayoutTests/fast/events/before-unload-forbidden-navigation-expected.txt
new file mode 100644
index 0000000..4f1a788
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-forbidden-navigation-expected.txt
@@ -0,0 +1,9 @@
+This test ensures navigation is forbidden while beforeunload event is being fired. You should see PASS 1/2 and PASS 2/2 below:
+
+PASS 1/2
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+PASS: 2/2
diff --git a/LayoutTests/fast/events/before-unload-forbidden-navigation.html b/LayoutTests/fast/events/before-unload-forbidden-navigation.html
new file mode 100644
index 0000000..460db30
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-forbidden-navigation.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>This test ensures navigation is forbidden while beforeunload event is being fired. You should see PASS 1/2 and PASS 2/2 below:</p>
+<pre id="log">FAIL</pre>
+<script>
+
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.dumpChildFramesAsText();
+    layoutTestController.waitUntilDone();
+}
+
+var log = document.getElementById('log');
+
+function test(iframe) {
+    if (iframe.done) {
+        if (iframe.halfPassed) {
+            iframe.contentWindow.location.href = 'resources/before-unload-in-subframe-destination.html';            
+            iframe.halfPassed = false;
+        }
+        return;
+    }
+    iframe.done = true;
+    iframe.contentWindow.location.href = 'resources/before-unload-in-subframe-child.html';
+}
+
+function fired(contentWindow) {
+    location.href = 'resources/before-unload-in-subframe-fail.html';
+    contentWindow.location.href = 'resources/before-unload-in-subframe-fail.html';
+    log.innerHTML = 'PASS 1/2';
+    contentWindow.frameElement.halfPassed = true;
+}
+
+</script>
+<iframe onload="test(this);" src="resources/before-unload-in-subframe-child.html"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/before-unload-in-multiple-subframes-expected.txt b/LayoutTests/fast/events/before-unload-in-multiple-subframes-expected.txt
new file mode 100644
index 0000000..bc3407f
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-in-multiple-subframes-expected.txt
@@ -0,0 +1,4 @@
+This tests beforeunload event in multiple subframes. You should see PASS below:
+
+PASS
+  
diff --git a/LayoutTests/fast/events/before-unload-in-multiple-subframes.html b/LayoutTests/fast/events/before-unload-in-multiple-subframes.html
new file mode 100644
index 0000000..055b4fa
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-in-multiple-subframes.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>This tests beforeunload event in multiple subframes. You should see PASS below:</p>
+<pre id="log"></pre>
+<script>
+
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.waitUntilDone();
+}
+
+var log = document.getElementById('log');
+
+function test(iframe) {
+    if (iframe.done)
+        return;
+    iframe.done = true;
+    iframe.contentWindow.location.href = 'resources/before-unload-in-subframe-child.html';
+}
+
+var numberOfBeforeUnloadInSubframes = 0;
+var numberOfFrames = 3;
+
+function logError() {
+    log.innerHTML = 'FAIL: ' + numberOfBeforeUnloadInSubframes + ' beforeunload events are fired but expected ' + numberOfFrames + ' events';
+}
+
+logError();
+
+function fired(contentWindow) {
+    numberOfBeforeUnloadInSubframes++;
+    if (numberOfBeforeUnloadInSubframes == numberOfFrames) {
+        log.innerHTML = 'PASS';
+        if (window.layoutTestController)
+            layoutTestController.notifyDone();
+    }
+    else
+        logError();
+    contentWindow.frameElement.fired = true;
+}
+
+</script>
+<iframe onload="test(this)" src="resources/before-unload-in-subframe-child.html"></iframe>
+<iframe onload="test(this)" src="resources/before-unload-in-subframe-child.html"></iframe>
+<iframe onload="test(this)" src="resources/before-unload-in-subframe-child.html"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/before-unload-in-subframe-expected.txt b/LayoutTests/fast/events/before-unload-in-subframe-expected.txt
new file mode 100644
index 0000000..d16afd4
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-in-subframe-expected.txt
@@ -0,0 +1,9 @@
+This tests beforeunload event in subframes. You should see PASS below:
+
+PASS
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+Child loaded.
diff --git a/LayoutTests/fast/events/before-unload-in-subframe.html b/LayoutTests/fast/events/before-unload-in-subframe.html
new file mode 100644
index 0000000..b868a50
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-in-subframe.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>This tests beforeunload event in subframes. You should see PASS below:</p>
+<pre id="log"></pre>
+<script>
+
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.dumpChildFramesAsText();
+    layoutTestController.waitUntilDone();
+}
+
+var log = document.getElementById('log');
+var done = false;
+
+function test() {
+    if (done) {
+        // log's not having any content implies that load event was dispatched for the second time before beforeunload is dispatched.
+        if (!log.innerHTML.length)
+            log.innerHTML = 'FAIL: beforeunload event was never dispatched.\n';
+        if (window.layoutTestController)
+            layoutTestController.notifyDone();
+        return;
+    }
+    done = true;
+    document.getElementsByTagName('iframe')[0].contentWindow.location.href = 'resources/before-unload-in-subframe-child.html';
+}
+
+function fired() {
+    if (!log.innerHTML.length)
+        log.innerHTML = 'PASS\n';
+    else
+        log.innerHTML = 'FAIL: beforeunload event was dispatched after the second load event.'
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+
+</script>
+<iframe onload="test()" src="resources/before-unload-in-subframe-child.html"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/before-unload-javascript-navigation-expected.txt b/LayoutTests/fast/events/before-unload-javascript-navigation-expected.txt
new file mode 100644
index 0000000..c21a4c3
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-javascript-navigation-expected.txt
@@ -0,0 +1,4 @@
+This test ensures setting location.href with javascript scheme properly executes the script even while beforeunload event is being fired. You should see PASS 1/2 and PASS 2/2 below:
+
+PASS
+
diff --git a/LayoutTests/fast/events/before-unload-javascript-navigation.html b/LayoutTests/fast/events/before-unload-javascript-navigation.html
new file mode 100644
index 0000000..eed8b75
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-javascript-navigation.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>This test ensures setting location.href with javascript scheme  properly executes the script even while beforeunload event is being fired. You should see PASS 1/2 and PASS 2/2 below:</p>
+<pre id="log">FAIL</pre>
+<script>
+
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.waitUntilDone();
+}
+
+var log = document.getElementById('log');
+
+function test(iframe) {
+    if (iframe.done)
+        return;
+    iframe.done = true;
+    iframe.contentWindow.location.href = 'resources/before-unload-in-subframe-child.html';
+}
+
+function done() {
+    log.innerHTML = 'PASS';
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+
+function fired(contentWindow) {
+    location.href = 'javascript:top.done()';
+}
+
+</script>
+<iframe onload="test(this);" src="resources/before-unload-in-subframe-child.html"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/before-unload-remove-and-add-subframe-expected.txt b/LayoutTests/fast/events/before-unload-remove-and-add-subframe-expected.txt
new file mode 100644
index 0000000..b21dd8c
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-remove-and-add-subframe-expected.txt
@@ -0,0 +1,7 @@
+This test ensures beforeunload event does not fire for subframes that has been removed from the DOM within a beforeunload event handler. Also ensures the event doesn't fire for subframes added within a beforeunload event handler. The latter behavior matches MSIE.
+
+PASS: fired on parent
+PASS: fired on a
+PASS: fired on c
+DONE
+
diff --git a/LayoutTests/fast/events/before-unload-remove-and-add-subframe.html b/LayoutTests/fast/events/before-unload-remove-and-add-subframe.html
new file mode 100755
index 0000000..82c8dcd
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-remove-and-add-subframe.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>This test ensures beforeunload event does not fire for subframes that has been removed from the DOM within a beforeunload event handler. Also ensures the event doesn't fire for subframes added within a beforeunload event handler. The latter behavior matches MSIE.</p>
+<pre id="log"></pre>
+<script>
+
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.waitUntilDone();
+}
+
+function createFrame(id, parent) {
+    var iframe = document.createElement('iframe');
+    iframe.id = id;
+    if (parent)
+        parent.contentDocument.body.appendChild(iframe);
+    else
+        document.body.appendChild(iframe);
+    if (!iframe.contentDocument.body)
+        iframe.contentDocument.appendChild(iframe.contentDocument.createElement('body'));
+    iframe.contentDocument.body.appendChild(iframe.contentDocument.createTextNode(id));    
+    iframe.contentDocument.body.appendChild(iframe.contentDocument.createElement('br'));
+    iframe.contentWindow.onbeforeunload = function () { fired(iframe.contentWindow, id); return null; }
+    iframe.style.width = '70%';
+    iframe.style.height = '40%';
+    return iframe;
+}
+
+function log(message) {
+    var log = document.getElementById('log');
+    log.innerHTML += message + '\n';
+}
+
+var expectedOrder = ['parent', 'a', 'c'];
+var i = 0;
+
+function fired(contentWindow, id) {
+    if (expectedOrder[i] == id)
+        log('PASS: fired on ' + id);
+    else
+        log('FAIL: fired on ' + id + ' but expected on ' + expectedOrder[i]);
+    i++;
+
+    if (contentWindow == a.contentWindow) {
+        b.parentNode.removeChild(b);
+        createFrame('d', container);
+    }
+}
+
+var container = createFrame('parent');
+var a = createFrame('a', container);
+var b = createFrame('b', container);
+var c = createFrame('c', container);
+
+container.onload = function () {
+    if (i == expectedOrder.length)
+        log('DONE');
+    else
+        log('Received ' + i + ' events but expected ' + expectedOrder.length);
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+container.src = 'resources/before-unload-in-subframe-destination.html';
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/before-unload-remove-itself-expected.txt b/LayoutTests/fast/events/before-unload-remove-itself-expected.txt
new file mode 100644
index 0000000..8fd1170
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-remove-itself-expected.txt
@@ -0,0 +1,4 @@
+This test ensures a beforeunload event handler can safely remove the frame to which the event is fired. You should see PASS below:
+
+PASS
+
diff --git a/LayoutTests/fast/events/before-unload-remove-itself.html b/LayoutTests/fast/events/before-unload-remove-itself.html
new file mode 100644
index 0000000..23a23e2
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-remove-itself.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>This test ensures a beforeunload event handler can safely remove the frame to which the event is fired. You should see PASS below:</p>
+<pre id="log"></pre>
+<script>
+
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.dumpChildFramesAsText();
+    layoutTestController.waitUntilDone();
+}
+
+var log = document.getElementById('log');
+var done = false;
+
+function test() {
+    if (done) {
+        // log's not having any content implies that load event was dispatched for the second time before beforeunload is dispatched.
+        if (!log.innerHTML.length)
+            log.innerHTML = 'FAIL: beforeunload event was never dispatched.\n';
+        else
+            log.innerHTML = 'FAIL: beforeunload event handler did not remove the frame.\n';
+        if (window.layoutTestController)
+            layoutTestController.notifyDone();
+        return;
+    }
+    done = true;
+    document.getElementsByTagName('iframe')[0].contentWindow.location.href = 'resources/before-unload-in-subframe-child.html';
+}
+
+function fired() {
+    document.body.removeChild(document.body.getElementsByTagName('iframe')[0]);
+    log.innerHTML = 'PASS\n';
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+
+</script>
+<iframe onload="test()" src="resources/before-unload-in-subframe-child.html"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/before-unload-with-subframes-expected.txt b/LayoutTests/fast/events/before-unload-with-subframes-expected.txt
new file mode 100644
index 0000000..7212540
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-with-subframes-expected.txt
@@ -0,0 +1,9 @@
+This test ensures beforeunload event fires in all subframes when a parent frame is navigated. You should see PASS 1/2 and PASS 2/2 below:
+
+PASS 1/2
+
+
+--------
+Frame: '<!--framePath //<!--frame0-->-->'
+--------
+PASS: 2/2
diff --git a/LayoutTests/fast/events/before-unload-with-subframes.html b/LayoutTests/fast/events/before-unload-with-subframes.html
new file mode 100644
index 0000000..5dad945
--- /dev/null
+++ b/LayoutTests/fast/events/before-unload-with-subframes.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>This test ensures beforeunload event fires in all subframes when a parent frame is navigated. You should see PASS 1/2 and PASS 2/2 below:</p>
+<pre id="log"></pre>
+<script>
+
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.dumpChildFramesAsText();
+    layoutTestController.waitUntilDone();
+}
+
+var log = document.getElementById('log');
+var numberOfBeforeUnloadInSubframes = 0;
+var numberOfFrames = 3;
+
+function test(iframe) {
+    if (iframe.done) {
+        if (numberOfBeforeUnloadInSubframes == numberOfFrames)
+            layoutTestController.notifyDone();
+        return;
+    }
+    iframe.done = true;
+    iframe.contentWindow.location.href = 'resources/before-unload-in-subframe-destination.html';
+}
+
+function logError() {
+    log.innerHTML = 'FAIL: ' + numberOfBeforeUnloadInSubframes + ' beforeunload events are fired but expected ' + numberOfFrames + ' events';
+}
+
+logError();
+
+function fired(contentWindow) {
+    numberOfBeforeUnloadInSubframes++;
+    if (numberOfBeforeUnloadInSubframes == numberOfFrames)
+        log.innerHTML = 'PASS 1/2\n';
+    else
+        logError();
+    contentWindow.frameElement.fired = true;
+}
+
+</script>
+<iframe onload="test(this)" src="resources/before-unload-with-subframes-parent.html"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/resources/before-unload-in-subframe-child.html b/LayoutTests/fast/events/resources/before-unload-in-subframe-child.html
new file mode 100644
index 0000000..b78dee1
--- /dev/null
+++ b/LayoutTests/fast/events/resources/before-unload-in-subframe-child.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body onbeforeunload="top.fired(window); return null;">
+Child loaded.
+<script>
+
+if (top.loaded)
+    top.loaded();
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/resources/before-unload-in-subframe-destination.html b/LayoutTests/fast/events/resources/before-unload-in-subframe-destination.html
new file mode 100644
index 0000000..7c409cc
--- /dev/null
+++ b/LayoutTests/fast/events/resources/before-unload-in-subframe-destination.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+PASS: 2/2
+<script>
+
+if (window.layoutTestController)
+    layoutTestController.notifyDone();
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/resources/before-unload-in-subframe-fail.html b/LayoutTests/fast/events/resources/before-unload-in-subframe-fail.html
new file mode 100644
index 0000000..bf339c8
--- /dev/null
+++ b/LayoutTests/fast/events/resources/before-unload-in-subframe-fail.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+FAIL
+<script>
+
+if (window.layoutTestController)
+    layoutTestController.notifyDone();
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/resources/before-unload-with-subframes-parent.html b/LayoutTests/fast/events/resources/before-unload-with-subframes-parent.html
new file mode 100644
index 0000000..f1a2542
--- /dev/null
+++ b/LayoutTests/fast/events/resources/before-unload-with-subframes-parent.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+<body>
+<iframe src="before-unload-in-subframe-child.html"></iframe>
+<iframe src="before-unload-in-subframe-child.html"></iframe>
+<iframe src="before-unload-in-subframe-child.html"></iframe>
+</body>
+</html>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 30d219d..2722ce3 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,56 @@
+2011-01-06  Ryosuke Niwa  <rniwa at webkit.org>
+
+        Reviewed by Adam Barth.
+
+        onbeforeunload is broken for framesets
+        https://bugs.webkit.org/show_bug.cgi?id=19418
+
+        Added beforeunload event support for sub frames. WebKit's implementation tries to match
+        that of Internet Explorer as much as possible. beforeunload event is fired for each and
+        every descendent of a frame that is about to navigate.
+
+        When a value other than null is returned by a beforeunload handler, a confirmation dialog
+        is shown for each handler (calls chrome's runBeforeUnloadConfirmPanel) just like it is done
+        for main frames.
+
+        In addition, navigation is forbidden while beforeunload handlers are being called.
+        Setting values to location.href, location.reload, and other means of navigations are thus
+        ignored while beforeunload event handler is being ran, matching Internet Explorer's behavior.
+
+        Because navigation needs to prevented globally, NavigationDisablerForBeforeUnload is added to
+        NavigationScheduler.h, which is instantiated as a RAII object in FrameLoader::shouldClose.
+
+        Tests: fast/events/before-unload-adopt-subframe-to-outside.html
+               fast/events/before-unload-adopt-within-subframes.html
+               fast/events/before-unload-forbidden-navigation.html
+               fast/events/before-unload-in-multiple-subframes.html
+               fast/events/before-unload-in-subframe.html
+               fast/events/before-unload-javascript-navigation.html
+               fast/events/before-unload-remove-and-add-subframe.html
+               fact/events/before-unload-remove-itself.html
+               fast/events/before-unload-with-subframes.html
+
+       * loader/FrameLoader.cpp:
+       (WebCore::FrameLoader::shouldClose): Calls fireBeforeUnloadEvent on m_frame and m_frame's
+       descendents. Returns true only if every call to fireBeforeUnloadEvent returned true.
+       (WebCore::FrameLoader::fireBeforeUnloadEvent): Fires a beforeunload event and calls
+       chrome's runBeforeUnloadConfirmPanel as needed.
+       (WebCore::FrameLoader::continueLoadAfterNavigationPolicy): Calls shouldClose for all frames.
+       * loader/FrameLoader.h:
+       * loader/NavigationScheduler.cpp:
+       (WebCore::NavigationScheduler::shouldScheduleNavigation): Checks the nullity of Page and calls
+       NavigationDisablerForBeforeUnload::isNavigationAllowed when url is not javascript scheme.
+       (WebCore::NavigationScheduler::scheduleRedirect): Calls shouldScheduleNavigation.
+       (WebCore::NavigationScheduler::scheduleLocationChange): Ditto.
+       (WebCore::NavigationScheduler::scheduleRefresh): Ditto.
+       (WebCore::NavigationScheduler::scheduleHistoryNavigation): Ditto.
+       * loader/NavigationScheduler.h:
+       (WebCore::NavigationDisablerForBeforeUnload::NavigationDisablerForBeforeUnload): Disables navigation.
+       (WebCore::NavigationDisablerForBeforeUnload::~NavigationDisablerForBeforeUnload): Enables navigation
+       when called on the last instance of NavigationDisablerForBeforeUnload.
+       (WebCore::NavigationDisablerForBeforeUnload::isNavigationAllowed): Returns true if there are no instance
+       of NavigationDisablerForBeforeUnload left on the stack.
+
 2011-01-07  Martin Robinson  <mrobinson at igalia.com>
 
         Build fix for GTK+.
diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj
index be10fe9..1d07372 100644
--- a/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -7927,8 +7927,6 @@
 		6EBF0E5312A8929800DB1709 /* WebGLExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebGLExtension.h; path = canvas/WebGLExtension.h; sourceTree = "<group>"; };
 		6EBF0E7412A9868800DB1709 /* JSOESTextureFloat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSOESTextureFloat.cpp; sourceTree = "<group>"; };
 		6EBF0E7512A9868800DB1709 /* JSOESTextureFloat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSOESTextureFloat.h; sourceTree = "<group>"; };
-		93F1D5BE12D5335600832BEC /* JSWebKitLoseContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSWebKitLoseContext.cpp; path = JSWebKitLoseContext.cpp; sourceTree = "<group>"; };
-		93F1D5BF12D5335600832BEC /* JSWebKitLoseContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSWebKitLoseContext.h; path = JSWebKitLoseContext.h; sourceTree = "<group>"; };
 		6EE8A77010F803F3005A4A24 /* JSWebGLContextAttributes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebGLContextAttributes.cpp; sourceTree = "<group>"; };
 		6EE8A77110F803F3005A4A24 /* JSWebGLContextAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebGLContextAttributes.h; sourceTree = "<group>"; };
 		72626E010EF022FE00A07E20 /* FontFastPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FontFastPath.cpp; sourceTree = "<group>"; };
@@ -9302,6 +9300,8 @@
 		93F1D5B712D532C400832BEC /* WebKitLoseContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebKitLoseContext.cpp; path = canvas/WebKitLoseContext.cpp; sourceTree = "<group>"; };
 		93F1D5B812D532C400832BEC /* WebKitLoseContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebKitLoseContext.h; path = canvas/WebKitLoseContext.h; sourceTree = "<group>"; };
 		93F1D5B912D532C400832BEC /* WebKitLoseContext.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = WebKitLoseContext.idl; path = canvas/WebKitLoseContext.idl; sourceTree = "<group>"; };
+		93F1D5BE12D5335600832BEC /* JSWebKitLoseContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebKitLoseContext.cpp; sourceTree = "<group>"; };
+		93F1D5BF12D5335600832BEC /* JSWebKitLoseContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebKitLoseContext.h; sourceTree = "<group>"; };
 		93F6F1EA127F70B10055CB06 /* WebGLContextEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebGLContextEvent.cpp; path = canvas/WebGLContextEvent.cpp; sourceTree = "<group>"; };
 		93F6F1EB127F70B10055CB06 /* WebGLContextEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebGLContextEvent.h; path = canvas/WebGLContextEvent.h; sourceTree = "<group>"; };
 		93F6F1EC127F70B10055CB06 /* WebGLContextEvent.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = WebGLContextEvent.idl; path = canvas/WebGLContextEvent.idl; sourceTree = "<group>"; };
diff --git a/WebCore/loader/FrameLoader.cpp b/WebCore/loader/FrameLoader.cpp
index 8a8061e..6dcd054 100644
--- a/WebCore/loader/FrameLoader.cpp
+++ b/WebCore/loader/FrameLoader.cpp
@@ -2862,13 +2862,39 @@ bool FrameLoader::shouldClose()
     if (!chrome || !chrome->canRunBeforeUnloadConfirmPanel())
         return true;
 
+    // Store all references to each subframe in advance since beforeunload's event handler may modify frame
+    Vector<RefPtr<Frame> > targetFrames;
+    targetFrames.append(m_frame);
+    for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame))
+        targetFrames.append(child);
+
+    bool shouldClose = false;
+    {
+        NavigationDisablerForBeforeUnload navigationDisabler;
+        size_t i;
+
+        for (i = 0; i < targetFrames.size(); i++) {
+            if (!targetFrames[i]->tree()->isDescendantOf(m_frame))
+                continue;
+            if (!targetFrames[i]->loader()->fireBeforeUnloadEvent(chrome))
+                break;
+        }
+
+        if (i == targetFrames.size())
+            shouldClose = true;
+    }
+
+    return shouldClose;
+}
+
+bool FrameLoader::fireBeforeUnloadEvent(Chrome* chrome)
+{
     DOMWindow* domWindow = m_frame->existingDOMWindow();
     if (!domWindow)
         return true;
 
     RefPtr<Document> document = m_frame->document();
-    HTMLElement* body = document->body();
-    if (!body)
+    if (!document->body())
         return true;
 
     RefPtr<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create();
@@ -2898,8 +2924,7 @@ void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest&, Pass
     //    1) Navigation policy delegate said we can't so request is nil. A primary case of this 
     //       is the user responding Cancel to the form repost nag sheet.
     //    2) User responded Cancel to an alert popped up by the before unload event handler.
-    // The "before unload" event handler runs only for the main frame.
-    bool canContinue = shouldContinue && (!isLoadingMainFrame() || shouldClose());
+    bool canContinue = shouldContinue && shouldClose();
 
     if (!canContinue) {
         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we 
diff --git a/WebCore/loader/FrameLoader.h b/WebCore/loader/FrameLoader.h
index ca78603..d843bb3 100644
--- a/WebCore/loader/FrameLoader.h
+++ b/WebCore/loader/FrameLoader.h
@@ -53,6 +53,7 @@ class AuthenticationChallenge;
 class CachedFrameBase;
 class CachedPage;
 class CachedResource;
+class Chrome;
 class DOMWrapperWorld;
 class Document;
 class DocumentLoader;
@@ -361,6 +362,8 @@ private:
     static void callContinueLoadAfterNavigationPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue);
     static void callContinueLoadAfterNewWindowPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, const NavigationAction&, bool shouldContinue);
     static void callContinueFragmentScrollAfterNavigationPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue);
+    
+    bool fireBeforeUnloadEvent(Chrome*);
 
     void continueLoadAfterNavigationPolicy(const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue);
     void continueLoadAfterNewWindowPolicy(const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, const NavigationAction&, bool shouldContinue);
diff --git a/WebCore/loader/NavigationScheduler.cpp b/WebCore/loader/NavigationScheduler.cpp
index d2d0f7f..175219c 100644
--- a/WebCore/loader/NavigationScheduler.cpp
+++ b/WebCore/loader/NavigationScheduler.cpp
@@ -51,6 +51,8 @@
 
 namespace WebCore {
 
+unsigned NavigationDisablerForBeforeUnload::s_navigationDisableCount = 0;
+
 class ScheduledNavigation : public Noncopyable {
 public:
     ScheduledNavigation(double delay, bool lockHistory, bool lockBackForwardList, bool wasDuringLoad, bool isLocationChange)
@@ -263,9 +265,19 @@ void NavigationScheduler::clear()
     m_redirect.clear();
 }
 
+inline bool NavigationScheduler::shouldScheduleNavigation() const
+{
+    return m_frame->page();
+}
+
+inline bool NavigationScheduler::shouldScheduleNavigation(const String& url) const
+{
+    return shouldScheduleNavigation() && (protocolIsJavaScript(url) || NavigationDisablerForBeforeUnload::isNavigationAllowed());
+}
+
 void NavigationScheduler::scheduleRedirect(double delay, const String& url)
 {
-    if (!m_frame->page())
+    if (!shouldScheduleNavigation(url))
         return;
     if (delay < 0 || delay > INT_MAX / 1000)
         return;
@@ -297,7 +309,7 @@ bool NavigationScheduler::mustLockBackForwardList(Frame* targetFrame)
 
 void NavigationScheduler::scheduleLocationChange(PassRefPtr<SecurityOrigin> securityOrigin, const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList)
 {
-    if (!m_frame->page())
+    if (!shouldScheduleNavigation(url))
         return;
     if (url.isEmpty())
         return;
@@ -344,7 +356,7 @@ void NavigationScheduler::scheduleFormSubmission(PassRefPtr<FormSubmission> subm
 
 void NavigationScheduler::scheduleRefresh()
 {
-    if (!m_frame->page())
+    if (!shouldScheduleNavigation())
         return;
     const KURL& url = m_frame->loader()->url();
     if (url.isEmpty())
@@ -355,7 +367,7 @@ void NavigationScheduler::scheduleRefresh()
 
 void NavigationScheduler::scheduleHistoryNavigation(int steps)
 {
-    if (!m_frame->page())
+    if (!shouldScheduleNavigation())
         return;
 
     // Invalid history navigations (such as history.forward() during a new load) have the side effect of cancelling any scheduled
diff --git a/WebCore/loader/NavigationScheduler.h b/WebCore/loader/NavigationScheduler.h
index 4f3bebc..2014ff2 100644
--- a/WebCore/loader/NavigationScheduler.h
+++ b/WebCore/loader/NavigationScheduler.h
@@ -34,6 +34,7 @@
 #include "Event.h"
 #include "Timer.h"
 #include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
 #include <wtf/OwnPtr.h>
 #include <wtf/PassOwnPtr.h>
 #include <wtf/PassRefPtr.h>
@@ -48,7 +49,28 @@ class SecurityOrigin;
 
 struct FrameLoadRequest;
 
-class NavigationScheduler : public Noncopyable {
+class NavigationDisablerForBeforeUnload {
+    WTF_MAKE_NONCOPYABLE(NavigationDisablerForBeforeUnload);
+
+public:
+    NavigationDisablerForBeforeUnload()
+    {
+        s_navigationDisableCount++;
+    }
+    ~NavigationDisablerForBeforeUnload()
+    {
+        ASSERT(s_navigationDisableCount);
+        s_navigationDisableCount--;
+    }
+    static bool isNavigationAllowed() { return !s_navigationDisableCount; }
+
+private:
+    static unsigned s_navigationDisableCount;
+};
+
+class NavigationScheduler {
+    WTF_MAKE_NONCOPYABLE(NavigationScheduler);
+
 public:
     NavigationScheduler(Frame*);
     ~NavigationScheduler();
@@ -68,6 +90,9 @@ public:
     void clear();
 
 private:
+    bool shouldScheduleNavigation() const;
+    bool shouldScheduleNavigation(const String& url) const;
+
     void timerFired(Timer<NavigationScheduler>*);
     void schedule(PassOwnPtr<ScheduledNavigation>);
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list