Changeset 192270 in webkit


Ignore:
Timestamp:
Nov 10, 2015 2:19:44 PM (8 years ago)
Author:
ggaren@apple.com
Message:

alert, confirm, prompt, showModalDialog should be forbidden during page close and navigation
https://bugs.webkit.org/show_bug.cgi?id=150980

Reviewed by Chris Dumez.

Source/WebCore:

Tests: fast/events/beforeunload-alert.html

fast/events/beforeunload-confirm.html
fast/events/beforeunload-prompt.html
fast/events/beforeunload-showModalDialog.html
fast/events/pagehide-alert.html
fast/events/pagehide-confirm.html
fast/events/pagehide-prompt.html
fast/events/pagehide-showModalDialog.html
fast/events/unload-alert.html
fast/events/unload-confirm.html
fast/events/unload-prompt.html
fast/events/unload-showModalDialog.html

  • loader/FrameLoader.cpp:

(WebCore::FrameLoader::stopLoading): Factored out a helper function for
unload event processing.
(WebCore::FrameLoader::handleUnloadEvents): Forbid prompts in unload
events just like we do in beforeunload events, and for the same reasons.

(WebCore::FrameLoader::handleBeforeUnloadEvent): Updated for renames.

  • loader/FrameLoader.h:
  • page/DOMWindow.cpp:

(WebCore::DOMWindow::print):
(WebCore::DOMWindow::alert):
(WebCore::DOMWindow::confirm):
(WebCore::DOMWindow::prompt):
(WebCore::DOMWindow::showModalDialog): Updated for renames. Refactored
some of this code to handle null pages more cleanly. In particular, we
sometimes used to treat null page as "everything is permitted" -- but it
is best practice in a permissions context to treat lack of information
as no permission granted rather than all permissions granted. (I don't
know of a way to trigger this condition in practice.)

  • page/Page.cpp:

(WebCore::Page::Page):
(WebCore::Page::forbidPrompts):
(WebCore::Page::allowPrompts):
(WebCore::Page::arePromptsAllowed): Renamed to make these functions
reflect their new, broader context.

(WebCore::Page::incrementFrameHandlingBeforeUnloadEventCount): Deleted.
(WebCore::Page::decrementFrameHandlingBeforeUnloadEventCount): Deleted.
(WebCore::Page::isAnyFrameHandlingBeforeUnloadEvent): Deleted.

  • page/Page.h:

LayoutTests:

Added tests to cover the matrix of [ alert, confirm, prompt, showModalDialog ] x [ beforeunload, unload, pagehide ].

  • fast/events/beforeunload-alert-expected.txt: Added.
  • fast/events/beforeunload-alert.html: Added.
  • fast/events/beforeunload-confirm-expected.txt: Added.
  • fast/events/beforeunload-confirm.html: Added.
  • fast/events/beforeunload-prompt-expected.txt: Added.
  • fast/events/beforeunload-prompt.html: Added.
  • fast/events/beforeunload-showModalDialog-expected.txt: Added.
  • fast/events/beforeunload-showModalDialog.html: Added.
  • fast/events/onunload-expected.txt:
  • fast/events/onunload-not-on-body-expected.txt:
  • fast/events/onunload-window-property-expected.txt:
  • fast/events/pagehide-alert-expected.txt: Added.
  • fast/events/pagehide-alert.html: Added.
  • fast/events/pagehide-confirm-expected.txt: Added.
  • fast/events/pagehide-confirm.html: Added.
  • fast/events/pagehide-prompt-expected.txt: Added.
  • fast/events/pagehide-prompt.html: Added.
  • fast/events/pagehide-showModalDialog-expected.txt: Added.
  • fast/events/pagehide-showModalDialog.html: Added.
  • fast/events/pageshow-pagehide-on-back-cached-expected.txt:
  • fast/events/pageshow-pagehide-on-back-uncached-expected.txt:
  • fast/events/resources/prompt-landing-page.html: Added.
  • fast/events/unload-alert-expected.txt: Added.
  • fast/events/unload-alert.html: Added.
  • fast/events/unload-confirm-expected.txt: Added.
  • fast/events/unload-confirm.html: Added.
  • fast/events/unload-prompt-expected.txt: Added.
  • fast/events/unload-prompt.html: Added.
  • fast/events/unload-showModalDialog-expected.txt: Added.
  • fast/events/unload-showModalDialog.html: Added.
  • platform/wk2/TestExpectations: WebKit2 can't handle showModalDialog tests.
  • compositing/iframes/page-cache-layer-tree-expected.txt:
  • fast/dom/Geolocation/notimer-after-unload-expected.txt:
  • fast/history/timed-refresh-in-cached-frame-expected.txt:
  • fast/loader/frames-with-unload-handlers-in-page-cache-expected.txt:
  • fast/loader/page-dismissal-modal-dialogs-expected.txt: These were

pre-existing tests that tried to alert during unload.

Location:
trunk
Files:
25 added
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r192269 r192270  
     12015-11-10  Geoffrey Garen  <ggaren@apple.com>
     2
     3        alert, confirm, prompt, showModalDialog should be forbidden during page close and navigation
     4        https://bugs.webkit.org/show_bug.cgi?id=150980
     5
     6        Reviewed by Chris Dumez.
     7
     8        Added tests to cover the matrix of [ alert, confirm, prompt, showModalDialog ] x [ beforeunload, unload, pagehide ].
     9
     10        * fast/events/beforeunload-alert-expected.txt: Added.
     11        * fast/events/beforeunload-alert.html: Added.
     12        * fast/events/beforeunload-confirm-expected.txt: Added.
     13        * fast/events/beforeunload-confirm.html: Added.
     14        * fast/events/beforeunload-prompt-expected.txt: Added.
     15        * fast/events/beforeunload-prompt.html: Added.
     16        * fast/events/beforeunload-showModalDialog-expected.txt: Added.
     17        * fast/events/beforeunload-showModalDialog.html: Added.
     18        * fast/events/onunload-expected.txt:
     19        * fast/events/onunload-not-on-body-expected.txt:
     20        * fast/events/onunload-window-property-expected.txt:
     21        * fast/events/pagehide-alert-expected.txt: Added.
     22        * fast/events/pagehide-alert.html: Added.
     23        * fast/events/pagehide-confirm-expected.txt: Added.
     24        * fast/events/pagehide-confirm.html: Added.
     25        * fast/events/pagehide-prompt-expected.txt: Added.
     26        * fast/events/pagehide-prompt.html: Added.
     27        * fast/events/pagehide-showModalDialog-expected.txt: Added.
     28        * fast/events/pagehide-showModalDialog.html: Added.
     29        * fast/events/pageshow-pagehide-on-back-cached-expected.txt:
     30        * fast/events/pageshow-pagehide-on-back-uncached-expected.txt:
     31        * fast/events/resources/prompt-landing-page.html: Added.
     32        * fast/events/unload-alert-expected.txt: Added.
     33        * fast/events/unload-alert.html: Added.
     34        * fast/events/unload-confirm-expected.txt: Added.
     35        * fast/events/unload-confirm.html: Added.
     36        * fast/events/unload-prompt-expected.txt: Added.
     37        * fast/events/unload-prompt.html: Added.
     38        * fast/events/unload-showModalDialog-expected.txt: Added.
     39        * fast/events/unload-showModalDialog.html: Added.
     40
     41        * platform/wk2/TestExpectations: WebKit2 can't handle showModalDialog tests.
     42
     43        * compositing/iframes/page-cache-layer-tree-expected.txt:
     44        * fast/dom/Geolocation/notimer-after-unload-expected.txt:
     45        * fast/history/timed-refresh-in-cached-frame-expected.txt:
     46        * fast/loader/frames-with-unload-handlers-in-page-cache-expected.txt:
     47        * fast/loader/page-dismissal-modal-dialogs-expected.txt: These were
     48        pre-existing tests that tried to alert during unload.
     49
    1502015-11-09  David Hyatt  <hyatt@apple.com>
    251
  • trunk/LayoutTests/compositing/iframes/page-cache-layer-tree-expected.txt

    r168244 r192270  
    11ALERT: pageshow - not from cache
    2 ALERT: pagehide - entering cache
     2CONSOLE MESSAGE: line 70: Use of window.alert is not allowed while unloading a page.
    33ALERT: pageshow - from cache
    44This tests that layers are rebuilt properly after the page is restored from the page cache.
  • trunk/LayoutTests/fast/dom/Geolocation/notimer-after-unload-expected.txt

    r59859 r192270  
    11main frame - has 1 onunload handler(s)
    2 ALERT: unload-called
     2CONSOLE MESSAGE: line 15: Use of window.alert is not allowed while unloading a page.
    33You should have seen one unload alert appear.
  • trunk/LayoutTests/fast/events/onunload-expected.txt

    r36652 r192270  
    11main frame - has 1 onunload handler(s)
    2 ALERT: unload
     2CONSOLE MESSAGE: line 16: Use of window.alert is not allowed while unloading a page.
    33You should have seen an unload alert appear.
  • trunk/LayoutTests/fast/events/onunload-not-on-body-expected.txt

    r36652 r192270  
    11frame "<!--framePath //<!--frame2-->-->" - has 1 onunload handler(s)
    2 ALERT: unload
     2CONSOLE MESSAGE: line 1: Use of window.alert is not allowed while unloading a page.
    33you should only see one unload alert appear.
  • trunk/LayoutTests/fast/events/onunload-window-property-expected.txt

    r39097 r192270  
    1 ALERT: unload
     1CONSOLE MESSAGE: line 13: Use of window.alert is not allowed while unloading a page.
    22You should have seen an unload alert appear.
  • trunk/LayoutTests/fast/events/pageshow-pagehide-on-back-cached-expected.txt

    r47824 r192270  
    11ALERT: window.onload
    22ALERT: window.onpageshow, target = [object HTMLDocument], persisted = false
    3 ALERT: window.onpagehide, target = [object HTMLDocument], persisted = true
     3CONSOLE MESSAGE: line 25: Use of window.alert is not allowed while unloading a page.
    44ALERT: window.onpageshow, target = [object HTMLDocument], persisted = true
    55Test pageshow/pagehide event behavior when navigating back to an cached page.
  • trunk/LayoutTests/fast/events/pageshow-pagehide-on-back-uncached-expected.txt

    r47824 r192270  
    22ALERT: window.onload
    33ALERT: window.onpageshow, target = [object HTMLDocument], persisted = false
    4 ALERT: window.onpagehide, target = [object HTMLDocument], persisted = false
     4CONSOLE MESSAGE: line 28: Use of window.alert is not allowed while unloading a page.
    55main frame "pageshow/pagehide" - has 1 onunload handler(s)
    66ALERT: window.onload
  • trunk/LayoutTests/fast/history/timed-refresh-in-cached-frame-expected.txt

    r61801 r192270  
    1 ALERT: pagehide true
     1CONSOLE MESSAGE: line 1: Use of window.alert is not allowed while unloading a page.
    22PASSED if didn't crash in two seconds.
  • trunk/LayoutTests/fast/loader/frames-with-unload-handlers-in-page-cache-expected.txt

    r48036 r192270  
    22ALERT: Subframe onload
    33ALERT: Subframe onpageshow
    4 ALERT: Main frame window.onpagehide called
    5 ALERT: Subframe onpagehide
    6 ALERT: Subframe onunload
     4CONSOLE MESSAGE: line 16: Use of window.alert is not allowed while unloading a page.
     5CONSOLE MESSAGE: line 18: Use of window.alert is not allowed while unloading a page.
     6CONSOLE MESSAGE: line 10: Use of window.alert is not allowed while unloading a page.
    77
  • trunk/LayoutTests/fast/loader/page-dismissal-modal-dialogs-expected.txt

    r178527 r192270  
    11frame "<!--framePath //<!--frame0-->-->" - has 1 onunload handler(s)
    2 CONSOLE MESSAGE: line 8: Use of window.alert is not allowed during beforeunload event dispatch.
    3 CONSOLE MESSAGE: line 9: Use of window.confirm is not allowed during beforeunload event dispatch.
    4 CONSOLE MESSAGE: line 10: Use of window.prompt is not allowed during beforeunload event dispatch.
    5 CONSOLE MESSAGE: line 8: Use of window.alert is not allowed during beforeunload event dispatch.
    6 CONSOLE MESSAGE: line 9: Use of window.confirm is not allowed during beforeunload event dispatch.
    7 CONSOLE MESSAGE: line 10: Use of window.prompt is not allowed during beforeunload event dispatch.
    8 CONSOLE MESSAGE: line 8: Use of window.alert is not allowed during beforeunload event dispatch.
    9 CONSOLE MESSAGE: line 9: Use of window.confirm is not allowed during beforeunload event dispatch.
    10 CONSOLE MESSAGE: line 10: Use of window.prompt is not allowed during beforeunload event dispatch.
    11 CONSOLE MESSAGE: line 8: Use of window.alert is not allowed during beforeunload event dispatch.
    12 CONSOLE MESSAGE: line 9: Use of window.confirm is not allowed during beforeunload event dispatch.
    13 CONSOLE MESSAGE: line 10: Use of window.prompt is not allowed during beforeunload event dispatch.
    14 ALERT: mainFrame pagehide PASS
    15 CONFIRM: mainFrame pagehide PASS
    16 PROMPT: mainFrame pagehide PASS, default text: PASS
    17 ALERT: iFrame click PASS
    18 CONFIRM: iFrame click PASS
    19 PROMPT: iFrame click PASS, default text: PASS
    20 ALERT: mainFrame unload PASS
    21 CONFIRM: mainFrame unload PASS
    22 PROMPT: mainFrame unload PASS, default text: PASS
    23 ALERT: iFrame click PASS
    24 CONFIRM: iFrame click PASS
    25 PROMPT: iFrame click PASS, default text: PASS
    26 ALERT: iFrame pagehide PASS
    27 CONFIRM: iFrame pagehide PASS
    28 PROMPT: iFrame pagehide PASS, default text: PASS
    29 ALERT: iFrame unload PASS
    30 CONFIRM: iFrame unload PASS
    31 PROMPT: iFrame unload PASS, default text: PASS
     2CONSOLE MESSAGE: line 8: Use of window.alert is not allowed while unloading a page.
     3CONSOLE MESSAGE: line 9: Use of window.confirm is not allowed while unloading a page.
     4CONSOLE MESSAGE: line 10: Use of window.prompt is not allowed while unloading a page.
     5CONSOLE MESSAGE: line 8: Use of window.alert is not allowed while unloading a page.
     6CONSOLE MESSAGE: line 9: Use of window.confirm is not allowed while unloading a page.
     7CONSOLE MESSAGE: line 10: Use of window.prompt is not allowed while unloading a page.
     8CONSOLE MESSAGE: line 8: Use of window.alert is not allowed while unloading a page.
     9CONSOLE MESSAGE: line 9: Use of window.confirm is not allowed while unloading a page.
     10CONSOLE MESSAGE: line 10: Use of window.prompt is not allowed while unloading a page.
     11CONSOLE MESSAGE: line 8: Use of window.alert is not allowed while unloading a page.
     12CONSOLE MESSAGE: line 9: Use of window.confirm is not allowed while unloading a page.
     13CONSOLE MESSAGE: line 10: Use of window.prompt is not allowed while unloading a page.
     14CONSOLE MESSAGE: line 8: Use of window.alert is not allowed while unloading a page.
     15CONSOLE MESSAGE: line 9: Use of window.confirm is not allowed while unloading a page.
     16CONSOLE MESSAGE: line 10: Use of window.prompt is not allowed while unloading a page.
     17CONSOLE MESSAGE: line 8: Use of window.alert is not allowed while unloading a page.
     18CONSOLE MESSAGE: line 9: Use of window.confirm is not allowed while unloading a page.
     19CONSOLE MESSAGE: line 10: Use of window.prompt is not allowed while unloading a page.
     20CONSOLE MESSAGE: line 8: Use of window.alert is not allowed while unloading a page.
     21CONSOLE MESSAGE: line 9: Use of window.confirm is not allowed while unloading a page.
     22CONSOLE MESSAGE: line 10: Use of window.prompt is not allowed while unloading a page.
     23CONSOLE MESSAGE: line 8: Use of window.alert is not allowed while unloading a page.
     24CONSOLE MESSAGE: line 9: Use of window.confirm is not allowed while unloading a page.
     25CONSOLE MESSAGE: line 10: Use of window.prompt is not allowed while unloading a page.
     26CONSOLE MESSAGE: line 8: Use of window.alert is not allowed while unloading a page.
     27CONSOLE MESSAGE: line 9: Use of window.confirm is not allowed while unloading a page.
     28CONSOLE MESSAGE: line 10: Use of window.prompt is not allowed while unloading a page.
     29CONSOLE MESSAGE: line 8: Use of window.alert is not allowed while unloading a page.
     30CONSOLE MESSAGE: line 9: Use of window.confirm is not allowed while unloading a page.
     31CONSOLE MESSAGE: line 10: Use of window.prompt is not allowed while unloading a page.
    3232PASS
  • trunk/LayoutTests/platform/wk2/TestExpectations

    r192007 r192270  
    139139# <https://bugs.webkit.org/show_bug.cgi?id=69548>
    140140fast/events/show-modal-dialog-onblur-onfocus.html
     141fast/events/beforeunload-showModalDialog.html
     142fast/events/pagehide-showModalDialog.html
     143fast/events/unload-showModalDialog.html
    141144
    142145# WebKitTestRunner needs testRunner.setWillSendRequestClearHeader
  • trunk/Source/WebCore/ChangeLog

    r192269 r192270  
     12015-11-10  Geoffrey Garen  <ggaren@apple.com>
     2
     3        alert, confirm, prompt, showModalDialog should be forbidden during page close and navigation
     4        https://bugs.webkit.org/show_bug.cgi?id=150980
     5
     6        Reviewed by Chris Dumez.
     7
     8        Tests: fast/events/beforeunload-alert.html
     9               fast/events/beforeunload-confirm.html
     10               fast/events/beforeunload-prompt.html
     11               fast/events/beforeunload-showModalDialog.html
     12               fast/events/pagehide-alert.html
     13               fast/events/pagehide-confirm.html
     14               fast/events/pagehide-prompt.html
     15               fast/events/pagehide-showModalDialog.html
     16               fast/events/unload-alert.html
     17               fast/events/unload-confirm.html
     18               fast/events/unload-prompt.html
     19               fast/events/unload-showModalDialog.html
     20
     21        * loader/FrameLoader.cpp:
     22        (WebCore::FrameLoader::stopLoading): Factored out a helper function for
     23        unload event processing.
     24        (WebCore::FrameLoader::handleUnloadEvents): Forbid prompts in unload
     25        events just like we do in beforeunload events, and for the same reasons.
     26
     27        (WebCore::FrameLoader::handleBeforeUnloadEvent): Updated for renames.
     28
     29        * loader/FrameLoader.h:
     30
     31        * page/DOMWindow.cpp:
     32        (WebCore::DOMWindow::print):
     33        (WebCore::DOMWindow::alert):
     34        (WebCore::DOMWindow::confirm):
     35        (WebCore::DOMWindow::prompt):
     36        (WebCore::DOMWindow::showModalDialog): Updated for renames. Refactored
     37        some of this code to handle null pages more cleanly. In particular, we
     38        sometimes used to treat null page as "everything is permitted" -- but it
     39        is best practice in a permissions context to treat lack of information
     40        as no permission granted rather than all permissions granted. (I don't
     41        know of a way to trigger this condition in practice.)
     42
     43        * page/Page.cpp:
     44        (WebCore::Page::Page):
     45        (WebCore::Page::forbidPrompts):
     46        (WebCore::Page::allowPrompts):
     47        (WebCore::Page::arePromptsAllowed): Renamed to make these functions
     48        reflect their new, broader context.
     49
     50        (WebCore::Page::incrementFrameHandlingBeforeUnloadEventCount): Deleted.
     51        (WebCore::Page::decrementFrameHandlingBeforeUnloadEventCount): Deleted.
     52        (WebCore::Page::isAnyFrameHandlingBeforeUnloadEvent): Deleted.
     53
     54        * page/Page.h:
     55
    1562015-11-09  David Hyatt  <hyatt@apple.com>
    257
  • trunk/Source/WebCore/loader/FrameLoader.cpp

    r191688 r192270  
    176176}
    177177
     178struct ForbidPromptsScope {
     179    ForbidPromptsScope(Page* page) : m_page(page)
     180    {
     181        if (!m_page)
     182            return;
     183        m_page->forbidPrompts();
     184    }
     185
     186    ~ForbidPromptsScope()
     187    {
     188        if (!m_page)
     189            return;
     190        m_page->allowPrompts();
     191    }
     192
     193    Page* m_page;
     194};
     195
    178196class FrameLoader::FrameProgressTracker {
    179197public:
     
    419437        m_frame.document()->parser()->stopParsing();
    420438
    421     if (unloadEventPolicy != UnloadEventPolicyNone) {
    422         if (m_frame.document()) {
    423             if (m_didCallImplicitClose && !m_wasUnloadEventEmitted) {
    424                 auto* currentFocusedElement = m_frame.document()->focusedElement();
    425                 if (is<HTMLInputElement>(currentFocusedElement))
    426                     downcast<HTMLInputElement>(*currentFocusedElement).endEditing();
    427                 if (m_pageDismissalEventBeingDispatched == PageDismissalType::None) {
    428                     if (unloadEventPolicy == UnloadEventPolicyUnloadAndPageHide) {
    429                         m_pageDismissalEventBeingDispatched = PageDismissalType::PageHide;
    430                         m_frame.document()->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, m_frame.document()->inPageCache()), m_frame.document());
    431                     }
    432 
    433                     // FIXME: update Page Visibility state here.
    434                     // https://bugs.webkit.org/show_bug.cgi?id=116770
    435 
    436                     if (!m_frame.document()->inPageCache()) {
    437                         RefPtr<Event> unloadEvent(Event::create(eventNames().unloadEvent, false, false));
    438                         // The DocumentLoader (and thus its DocumentLoadTiming) might get destroyed
    439                         // while dispatching the event, so protect it to prevent writing the end
    440                         // time into freed memory.
    441                         RefPtr<DocumentLoader> documentLoader = m_provisionalDocumentLoader;
    442                         m_pageDismissalEventBeingDispatched = PageDismissalType::Unload;
    443                         if (documentLoader && documentLoader->timing().navigationStart() && !documentLoader->timing().unloadEventStart() && !documentLoader->timing().unloadEventEnd()) {
    444                             auto& timing = documentLoader->timing();
    445                             timing.markUnloadEventStart();
    446                             m_frame.document()->domWindow()->dispatchEvent(unloadEvent, m_frame.document());
    447                             timing.markUnloadEventEnd();
    448                         } else
    449                             m_frame.document()->domWindow()->dispatchEvent(unloadEvent, m_frame.document());
    450                     }
    451                 }
    452                 m_pageDismissalEventBeingDispatched = PageDismissalType::None;
    453                 if (m_frame.document())
    454                     m_frame.document()->updateStyleIfNeeded();
    455                 m_wasUnloadEventEmitted = true;
    456             }
    457         }
    458 
    459         // Dispatching the unload event could have made m_frame.document() null.
    460         if (m_frame.document() && !m_frame.document()->inPageCache()) {
    461             // Don't remove event listeners from a transitional empty document (see bug 28716 for more information).
    462             bool keepEventListeners = m_stateMachine.isDisplayingInitialEmptyDocument() && m_provisionalDocumentLoader
    463                 && m_frame.document()->isSecureTransitionTo(m_provisionalDocumentLoader->url());
    464 
    465             if (!keepEventListeners)
    466                 m_frame.document()->removeAllEventListeners();
    467         }
    468     }
     439    if (unloadEventPolicy != UnloadEventPolicyNone)
     440        handleUnloadEvents(unloadEventPolicy);
    469441
    470442    m_isComplete = true; // to avoid calling completed() in finishedParsing()
     
    28662838}
    28672839
     2840void FrameLoader::handleUnloadEvents(UnloadEventPolicy unloadEventPolicy)
     2841{
     2842    if (!m_frame.document())
     2843        return;
     2844
     2845    // We store the frame's page in a local variable because the frame might get detached inside dispatchEvent.
     2846    ForbidPromptsScope forbidPrompts(m_frame.page());
     2847
     2848    if (m_didCallImplicitClose && !m_wasUnloadEventEmitted) {
     2849        auto* currentFocusedElement = m_frame.document()->focusedElement();
     2850        if (is<HTMLInputElement>(currentFocusedElement))
     2851            downcast<HTMLInputElement>(*currentFocusedElement).endEditing();
     2852        if (m_pageDismissalEventBeingDispatched == PageDismissalType::None) {
     2853            if (unloadEventPolicy == UnloadEventPolicyUnloadAndPageHide) {
     2854                m_pageDismissalEventBeingDispatched = PageDismissalType::PageHide;
     2855                m_frame.document()->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, m_frame.document()->inPageCache()), m_frame.document());
     2856            }
     2857
     2858            // FIXME: update Page Visibility state here.
     2859            // https://bugs.webkit.org/show_bug.cgi?id=116770
     2860
     2861            if (!m_frame.document()->inPageCache()) {
     2862                RefPtr<Event> unloadEvent(Event::create(eventNames().unloadEvent, false, false));
     2863                // The DocumentLoader (and thus its DocumentLoadTiming) might get destroyed
     2864                // while dispatching the event, so protect it to prevent writing the end
     2865                // time into freed memory.
     2866                RefPtr<DocumentLoader> documentLoader = m_provisionalDocumentLoader;
     2867                m_pageDismissalEventBeingDispatched = PageDismissalType::Unload;
     2868                if (documentLoader && documentLoader->timing().navigationStart() && !documentLoader->timing().unloadEventStart() && !documentLoader->timing().unloadEventEnd()) {
     2869                    auto& timing = documentLoader->timing();
     2870                    timing.markUnloadEventStart();
     2871                    m_frame.document()->domWindow()->dispatchEvent(unloadEvent, m_frame.document());
     2872                    timing.markUnloadEventEnd();
     2873                } else
     2874                    m_frame.document()->domWindow()->dispatchEvent(unloadEvent, m_frame.document());
     2875            }
     2876        }
     2877        m_pageDismissalEventBeingDispatched = PageDismissalType::None;
     2878        if (m_frame.document())
     2879            m_frame.document()->updateStyleIfNeeded();
     2880        m_wasUnloadEventEmitted = true;
     2881    }
     2882
     2883    // Dispatching the unload event could have made m_frame.document() null.
     2884    if (!m_frame.document())
     2885        return;
     2886
     2887    if (m_frame.document()->inPageCache())
     2888        return;
     2889
     2890    // Don't remove event listeners from a transitional empty document (see bug 28716 for more information).
     2891    bool keepEventListeners = m_stateMachine.isDisplayingInitialEmptyDocument() && m_provisionalDocumentLoader
     2892        && m_frame.document()->isSecureTransitionTo(m_provisionalDocumentLoader->url());
     2893
     2894    if (!keepEventListeners)
     2895        m_frame.document()->removeAllEventListeners();
     2896}
     2897
    28682898bool FrameLoader::handleBeforeUnloadEvent(Chrome& chrome, FrameLoader* frameLoaderBeingNavigated)
    28692899{
     
    28792909    m_pageDismissalEventBeingDispatched = PageDismissalType::BeforeUnload;
    28802910
    2881     // We store the frame's page in a local variable because the frame might get detached inside dispatchEvent.
    2882     Page* page = m_frame.page();
    2883     page->incrementFrameHandlingBeforeUnloadEventCount();
    2884     domWindow->dispatchEvent(beforeUnloadEvent.get(), domWindow->document());
    2885     page->decrementFrameHandlingBeforeUnloadEventCount();
     2911    {
     2912        ForbidPromptsScope forbidPrompts(m_frame.page());
     2913        domWindow->dispatchEvent(beforeUnloadEvent.get(), domWindow->document());
     2914    }
    28862915
    28872916    m_pageDismissalEventBeingDispatched = PageDismissalType::None;
  • trunk/Source/WebCore/loader/FrameLoader.h

    r191369 r192270  
    322322
    323323    bool handleBeforeUnloadEvent(Chrome&, FrameLoader* frameLoaderBeingNavigated);
     324    void handleUnloadEvents(UnloadEventPolicy);
    324325
    325326    void continueLoadAfterNavigationPolicy(const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue, AllowNavigationToInvalidURL);
  • trunk/Source/WebCore/page/DOMWindow.cpp

    r191332 r192270  
    10481048        return;
    10491049
    1050     Page* page = m_frame->page();
     1050    auto* page = m_frame->page();
    10511051    if (!page)
    10521052        return;
    10531053
    1054     // Pages are not allowed to bring up a modal print dialog during BeforeUnload dispatch.
    1055     if (page->isAnyFrameHandlingBeforeUnloadEvent()) {
    1056         printErrorMessage("Use of window.print is not allowed during beforeunload event dispatch.");
     1054    if (!page->arePromptsAllowed()) {
     1055        printErrorMessage("Use of window.print is not allowed while unloading a page.");
    10571056        return;
    10581057    }
     
    10811080        return;
    10821081
    1083     // Pages are not allowed to cause modal alerts during BeforeUnload dispatch.
    1084     if (page() && page()->isAnyFrameHandlingBeforeUnloadEvent()) {
    1085         printErrorMessage("Use of window.alert is not allowed during beforeunload event dispatch.");
     1082    auto* page = m_frame->page();
     1083    if (!page)
     1084        return;
     1085
     1086    if (!page->arePromptsAllowed()) {
     1087        printErrorMessage("Use of window.alert is not allowed while unloading a page.");
    10861088        return;
    10871089    }
    10881090
    10891091    m_frame->document()->updateStyleIfNeeded();
    1090 
    1091     Page* page = m_frame->page();
    1092     if (!page)
    1093         return;
    10941092
    10951093    page->chrome().runJavaScriptAlert(m_frame, message);
     
    11011099        return false;
    11021100   
    1103     // Pages are not allowed to cause modal alerts during BeforeUnload dispatch.
    1104     if (page() && page()->isAnyFrameHandlingBeforeUnloadEvent()) {
    1105         printErrorMessage("Use of window.confirm is not allowed during beforeunload event dispatch.");
    1106         return false;
    1107     }
    1108 
    1109     m_frame->document()->updateStyleIfNeeded();
    1110 
    1111     Page* page = m_frame->page();
     1101    auto* page = m_frame->page();
    11121102    if (!page)
    11131103        return false;
    11141104
     1105    if (!page->arePromptsAllowed()) {
     1106        printErrorMessage("Use of window.confirm is not allowed while unloading a page.");
     1107        return false;
     1108    }
     1109
     1110    m_frame->document()->updateStyleIfNeeded();
     1111
    11151112    return page->chrome().runJavaScriptConfirm(m_frame, message);
    11161113}
     
    11211118        return String();
    11221119
    1123     // Pages are not allowed to cause modal alerts during BeforeUnload dispatch.
    1124     if (page() && page()->isAnyFrameHandlingBeforeUnloadEvent()) {
    1125         printErrorMessage("Use of window.prompt is not allowed during beforeunload event dispatch.");
    1126         return String();
    1127     }
    1128 
    1129     m_frame->document()->updateStyleIfNeeded();
    1130 
    1131     Page* page = m_frame->page();
     1120    auto* page = m_frame->page();
    11321121    if (!page)
    11331122        return String();
     1123
     1124    if (!page->arePromptsAllowed()) {
     1125        printErrorMessage("Use of window.prompt is not allowed while unloading a page.");
     1126        return String();
     1127    }
     1128
     1129    m_frame->document()->updateStyleIfNeeded();
    11341130
    11351131    String returnValue;
     
    22382234        return;
    22392235
    2240     // Pages are not allowed to cause modal alerts during BeforeUnload dispatch.
    2241     if (page() && page()->isAnyFrameHandlingBeforeUnloadEvent()) {
    2242         printErrorMessage("Use of window.showModalDialog is not allowed during beforeunload event dispatch.");
     2236    auto* page = m_frame->page();
     2237    if (!page)
     2238        return;
     2239
     2240    if (!page->arePromptsAllowed()) {
     2241        printErrorMessage("Use of window.showModalDialog is not allowed while unloading a page.");
    22432242        return;
    22442243    }
  • trunk/Source/WebCore/page/Page.cpp

    r192200 r192270  
    216216#endif
    217217    , m_lastSpatialNavigationCandidatesCount(0) // NOTE: Only called from Internals for Spatial Navigation testing.
    218     , m_framesHandlingBeforeUnloadEvent(0)
     218    , m_forbidPromptsDepth(0)
    219219    , m_applicationCacheStorage(pageConfiguration.applicationCacheStorage ? *WTF::move(pageConfiguration.applicationCacheStorage) : ApplicationCacheStorage::singleton())
    220220    , m_databaseProvider(*WTF::move(pageConfiguration.databaseProvider))
     
    16141614#endif
    16151615
    1616 void Page::incrementFrameHandlingBeforeUnloadEventCount()
    1617 {
    1618     ++m_framesHandlingBeforeUnloadEvent;
    1619 }
    1620 
    1621 void Page::decrementFrameHandlingBeforeUnloadEventCount()
    1622 {
    1623     ASSERT(m_framesHandlingBeforeUnloadEvent);
    1624     --m_framesHandlingBeforeUnloadEvent;
    1625 }
    1626 
    1627 bool Page::isAnyFrameHandlingBeforeUnloadEvent()
    1628 {
    1629     return m_framesHandlingBeforeUnloadEvent;
     1616void Page::forbidPrompts()
     1617{
     1618    ++m_forbidPromptsDepth;
     1619}
     1620
     1621void Page::allowPrompts()
     1622{
     1623    ASSERT(m_forbidPromptsDepth);
     1624    --m_forbidPromptsDepth;
     1625}
     1626
     1627bool Page::arePromptsAllowed()
     1628{
     1629    return !m_forbidPromptsDepth;
    16301630}
    16311631
  • trunk/Source/WebCore/page/Page.h

    r192200 r192270  
    424424#endif
    425425
    426     void incrementFrameHandlingBeforeUnloadEventCount();
    427     void decrementFrameHandlingBeforeUnloadEventCount();
    428     bool isAnyFrameHandlingBeforeUnloadEvent();
     426    void forbidPrompts();
     427    void allowPrompts();
     428    bool arePromptsAllowed();
     429
    429430    void setLastSpatialNavigationCandidateCount(unsigned count) { m_lastSpatialNavigationCandidatesCount = count; }
    430431    unsigned lastSpatialNavigationCandidateCount() const { return m_lastSpatialNavigationCandidatesCount; }
     
    632633
    633634    unsigned m_lastSpatialNavigationCandidatesCount;
    634     unsigned m_framesHandlingBeforeUnloadEvent;
     635    unsigned m_forbidPromptsDepth;
    635636
    636637    Ref<ApplicationCacheStorage> m_applicationCacheStorage;
Note: See TracChangeset for help on using the changeset viewer.