Changeset 92982 in webkit


Ignore:
Timestamp:
Aug 12, 2011 12:56:56 PM (13 years ago)
Author:
aestes@apple.com
Message:

Cancel in onbeforeunload dialog sometime causes a button to stop working.
https://bugs.webkit.org/show_bug.cgi?id=26211

Reviewed by Alexey Proskuryakov.

Source/WebCore:

Test: fast/loader/form-submission-after-beforeunload-cancel.html

If an onbeforeunload handler cancels a navigation that was triggered by
a form submission, WebCore's multiple form submission protection
prevents the form from being submitted a second time even though no
first submission actually took place. Fix this by clearing
m_submittedFormURL if the onbeforeunload handler cancels the load. This
allows the submission to be retried.

  • loader/FrameLoader.cpp:

(WebCore::FrameLoader::shouldClose): Set m_submittedFormURL to KURL()
if shouldClose() will return false.

Tools:

Implement a new LayoutTestController method that a test can call to set
the return value of DumpRenderTree's beforeunload UI delegate.

  • DumpRenderTree/LayoutTestController.cpp:

(LayoutTestController::LayoutTestController): Initialize
m_shouldStayOnPageAfterHandlingBeforeUnload.
(setShouldStayOnPageAfterHandlingBeforeUnloadCallback): Call
LayoutTestController::setShouldStayOnPageAfterHandlingBeforeUnload().
(LayoutTestController::staticFunctions): Register
'setShouldStayOnPageAfterHandlingBeforeUnload' as a static function.

  • DumpRenderTree/LayoutTestController.h:

(LayoutTestController::shouldStayOnPageAfterHandlingBeforeUnload):
(LayoutTestController::setShouldStayOnPageAfterHandlingBeforeUnload):

  • DumpRenderTree/chromium/LayoutTestController.cpp:

(LayoutTestController::LayoutTestController): Initialize
m_shouldStayOnPageAfterHandlingBeforeUnload and bind
'setShouldStayOnPageAfterHandlingBeforeUnload' to its c++ setter.
(LayoutTestController::reset): Reset
m_shouldStayOnPageAfterHandlingBeforeUnload to false.
(LayoutTestController::setShouldStayOnPageAfterHandlingBeforeUnload):
Set m_shouldStayOnPageAfterHandlingBeforeUnload to the value passed in
from JavaScript.

  • DumpRenderTree/chromium/LayoutTestController.h:

(LayoutTestController::shouldStayOnPageAfterHandlingBeforeUnload):

  • DumpRenderTree/chromium/WebViewHost.cpp:

(WebViewHost::runModalBeforeUnloadDialog): Add the correct logging and
return the inverse of
LayoutTestController::shouldStayOnPageAfterHandlingBeforeUnload().

  • DumpRenderTree/mac/UIDelegate.mm:

(-[UIDelegate webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:]): Ditto.

  • DumpRenderTree/win/UIDelegate.cpp:

(UIDelegate::runBeforeUnloadConfirmPanelWithMessage): Ditto.

  • WebKitTestRunner/InjectedBundle/Bindings/LayoutTestController.idl:

Define setShouldStayOnPageAfterHandlingBeforeUnload().

  • WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:

(WTR::InjectedBundle::postNewBeforeUnloadReturnValue): Post a message
to the Test Controller telling it what value it should return in its
onbeforeunload UI delegate.

  • WebKitTestRunner/InjectedBundle/InjectedBundle.h:
  • WebKitTestRunner/InjectedBundle/LayoutTestController.cpp:

(WTR::LayoutTestController::setShouldStayOnPageAfterHandlingBeforeUnload):
Call InjectedBundle::postNewBeforeUnloadReturnValue().

  • WebKitTestRunner/InjectedBundle/LayoutTestController.h:
  • WebKitTestRunner/TestController.cpp:

(WTR::TestController::TestController): Initialize
m_beforeUnloadReturnValue to true.
(WTR::runBeforeUnloadConfirmPanel): Add the correct logging and return
the value of TestController::beforeUnloadReturnValue().
(WTR::TestController::resetStateToConsistentValues): Reset
m_beforeUnloadReturnValue to true.

  • WebKitTestRunner/TestController.h:

(WTR::TestController::beforeUnloadReturnValue):
(WTR::TestController::setBeforeUnloadReturnValue):

  • WebKitTestRunner/TestInvocation.cpp:

(WTR::TestInvocation::didReceiveMessageFromInjectedBundle): Handle the
message posted from the injected bundle by retrieving the message body
as a WKBoolean and calling TestController::setBeforeUnloadReturnValue().

LayoutTests:

  • fast/loader/form-submission-after-beforeunload-cancel-expected.txt: Added.
  • fast/loader/form-submission-after-beforeunload-cancel.html: Added.
Location:
trunk
Files:
2 added
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r92981 r92982  
     12011-08-12  Andy Estes  <aestes@apple.com>
     2
     3        Cancel in onbeforeunload dialog sometime causes a button to stop working.
     4        https://bugs.webkit.org/show_bug.cgi?id=26211
     5
     6        Reviewed by Alexey Proskuryakov.
     7
     8        * fast/loader/form-submission-after-beforeunload-cancel-expected.txt: Added.
     9        * fast/loader/form-submission-after-beforeunload-cancel.html: Added.
     10
    1112011-08-12  David Hyatt  <hyatt@apple.com>
    212
  • trunk/Source/WebCore/ChangeLog

    r92981 r92982  
     12011-08-12  Andy Estes  <aestes@apple.com>
     2
     3        Cancel in onbeforeunload dialog sometime causes a button to stop working.
     4        https://bugs.webkit.org/show_bug.cgi?id=26211
     5
     6        Reviewed by Alexey Proskuryakov.
     7
     8        Test: fast/loader/form-submission-after-beforeunload-cancel.html
     9
     10        If an onbeforeunload handler cancels a navigation that was triggered by
     11        a form submission, WebCore's multiple form submission protection
     12        prevents the form from being submitted a second time even though no
     13        first submission actually took place. Fix this by clearing
     14        m_submittedFormURL if the onbeforeunload handler cancels the load. This
     15        allows the submission to be retried.
     16
     17        * loader/FrameLoader.cpp:
     18        (WebCore::FrameLoader::shouldClose): Set m_submittedFormURL to KURL()
     19        if shouldClose() will return false.
     20
    1212011-08-12  David Hyatt  <hyatt@apple.com>
    222
  • trunk/Source/WebCore/loader/FrameLoader.cpp

    r92623 r92982  
    27332733    }
    27342734
     2735    if (!shouldClose)
     2736        m_submittedFormURL = KURL();
     2737
    27352738    return shouldClose;
    27362739}
  • trunk/Tools/ChangeLog

    r92974 r92982  
     12011-08-12  Andy Estes  <aestes@apple.com>
     2
     3        Cancel in onbeforeunload dialog sometime causes a button to stop working.
     4        https://bugs.webkit.org/show_bug.cgi?id=26211
     5
     6        Reviewed by Alexey Proskuryakov.
     7
     8        Implement a new LayoutTestController method that a test can call to set
     9        the return value of DumpRenderTree's beforeunload UI delegate.
     10
     11        * DumpRenderTree/LayoutTestController.cpp:
     12        (LayoutTestController::LayoutTestController): Initialize
     13        m_shouldStayOnPageAfterHandlingBeforeUnload.
     14        (setShouldStayOnPageAfterHandlingBeforeUnloadCallback): Call
     15        LayoutTestController::setShouldStayOnPageAfterHandlingBeforeUnload().
     16        (LayoutTestController::staticFunctions): Register
     17        'setShouldStayOnPageAfterHandlingBeforeUnload' as a static function.
     18        * DumpRenderTree/LayoutTestController.h:
     19        (LayoutTestController::shouldStayOnPageAfterHandlingBeforeUnload):
     20        (LayoutTestController::setShouldStayOnPageAfterHandlingBeforeUnload):
     21        * DumpRenderTree/chromium/LayoutTestController.cpp:
     22        (LayoutTestController::LayoutTestController): Initialize
     23        m_shouldStayOnPageAfterHandlingBeforeUnload and bind
     24        'setShouldStayOnPageAfterHandlingBeforeUnload' to its c++ setter.
     25        (LayoutTestController::reset): Reset
     26        m_shouldStayOnPageAfterHandlingBeforeUnload to false.
     27        (LayoutTestController::setShouldStayOnPageAfterHandlingBeforeUnload):
     28        Set m_shouldStayOnPageAfterHandlingBeforeUnload to the value passed in
     29        from JavaScript.
     30        * DumpRenderTree/chromium/LayoutTestController.h:
     31        (LayoutTestController::shouldStayOnPageAfterHandlingBeforeUnload):
     32        * DumpRenderTree/chromium/WebViewHost.cpp:
     33        (WebViewHost::runModalBeforeUnloadDialog): Add the correct logging and
     34        return the inverse of
     35        LayoutTestController::shouldStayOnPageAfterHandlingBeforeUnload().
     36        * DumpRenderTree/mac/UIDelegate.mm:
     37        (-[UIDelegate webView:runBeforeUnloadConfirmPanelWithMessage:initiatedByFrame:]): Ditto.
     38        * DumpRenderTree/win/UIDelegate.cpp:
     39        (UIDelegate::runBeforeUnloadConfirmPanelWithMessage): Ditto.
     40        * WebKitTestRunner/InjectedBundle/Bindings/LayoutTestController.idl:
     41        Define setShouldStayOnPageAfterHandlingBeforeUnload().
     42        * WebKitTestRunner/InjectedBundle/InjectedBundle.cpp:
     43        (WTR::InjectedBundle::postNewBeforeUnloadReturnValue): Post a message
     44        to the Test Controller telling it what value it should return in its
     45        onbeforeunload UI delegate.
     46        * WebKitTestRunner/InjectedBundle/InjectedBundle.h:
     47        * WebKitTestRunner/InjectedBundle/LayoutTestController.cpp:
     48        (WTR::LayoutTestController::setShouldStayOnPageAfterHandlingBeforeUnload):
     49        Call InjectedBundle::postNewBeforeUnloadReturnValue().
     50        * WebKitTestRunner/InjectedBundle/LayoutTestController.h:
     51        * WebKitTestRunner/TestController.cpp:
     52        (WTR::TestController::TestController): Initialize
     53        m_beforeUnloadReturnValue to true.
     54        (WTR::runBeforeUnloadConfirmPanel): Add the correct logging and return
     55        the value of TestController::beforeUnloadReturnValue().
     56        (WTR::TestController::resetStateToConsistentValues): Reset
     57        m_beforeUnloadReturnValue to true.
     58        * WebKitTestRunner/TestController.h:
     59        (WTR::TestController::beforeUnloadReturnValue):
     60        (WTR::TestController::setBeforeUnloadReturnValue):
     61        * WebKitTestRunner/TestInvocation.cpp:
     62        (WTR::TestInvocation::didReceiveMessageFromInjectedBundle): Handle the
     63        message posted from the injected bundle by retrieving the message body
     64        as a WKBoolean and calling TestController::setBeforeUnloadReturnValue().
     65
    1662011-08-12  Sam Weinig  <sam@webkit.org>
    267
  • trunk/Tools/DumpRenderTree/LayoutTestController.cpp

    r90856 r92982  
    8888    , m_deferMainResourceDataLoad(true)
    8989    , m_shouldPaintBrokenImage(true)
     90    , m_shouldStayOnPageAfterHandlingBeforeUnload(false)
    9091    , m_testPathOrURL(testPathOrURL)
    9192    , m_expectedPixelHash(expectedPixelHash)
     
    21382139
    21392140    controller->allowRoundingHacks();
     2141    return JSValueMakeUndefined(context);
     2142}
     2143
     2144static JSValueRef setShouldStayOnPageAfterHandlingBeforeUnloadCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
     2145{
     2146    LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject));
     2147   
     2148    if (argumentCount == 1)
     2149        controller->setShouldStayOnPageAfterHandlingBeforeUnload(JSValueToBoolean(context, arguments[0]));
     2150
    21402151    return JSValueMakeUndefined(context);
    21412152}
     
    24152426        { "setTextDirection", setTextDirectionCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
    24162427        { "allowRoundingHacks", allowRoundingHacksCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
     2428        { "setShouldStayOnPageAfterHandlingBeforeUnload", setShouldStayOnPageAfterHandlingBeforeUnloadCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
    24172429        { 0, 0, 0 }
    24182430    };
  • trunk/Tools/DumpRenderTree/LayoutTestController.h

    r90856 r92982  
    308308    void allowRoundingHacks();
    309309
     310    bool shouldStayOnPageAfterHandlingBeforeUnload() const { return m_shouldStayOnPageAfterHandlingBeforeUnload; }
     311    void setShouldStayOnPageAfterHandlingBeforeUnload(bool shouldStayOnPageAfterHandlingBeforeUnload) { m_shouldStayOnPageAfterHandlingBeforeUnload = shouldStayOnPageAfterHandlingBeforeUnload; }
     312
    310313    void setPOSIXLocale(JSStringRef locale);
    311314
     
    399402    bool m_deferMainResourceDataLoad;
    400403    bool m_shouldPaintBrokenImage;
     404    bool m_shouldStayOnPageAfterHandlingBeforeUnload;
    401405
    402406    std::string m_authenticationUsername;
  • trunk/Tools/DumpRenderTree/chromium/LayoutTestController.cpp

    r92219 r92982  
    7878    , m_showDebugLayerTree(false)
    7979    , m_workQueue(this)
     80    , m_shouldStayOnPageAfterHandlingBeforeUnload(false)
    8081{
    8182
     
    220221    bindMethod("observeStorageTrackerNotifications", &LayoutTestController::observeStorageTrackerNotifications);
    221222    bindMethod("syncLocalStorage", &LayoutTestController::syncLocalStorage);
     223    bindMethod("setShouldStayOnPageAfterHandlingBeforeUnload", &LayoutTestController::setShouldStayOnPageAfterHandlingBeforeUnload);
    222224   
    223225    // The fallback method is called when an unknown method is invoked.
     
    612614    m_workQueue.reset();
    613615    m_taskList.revokeAll();
     616    m_shouldStayOnPageAfterHandlingBeforeUnload = false;
    614617}
    615618
     
    18071810}
    18081811
     1812void LayoutTestController::setShouldStayOnPageAfterHandlingBeforeUnload(const CppArgumentList& arguments, CppVariant* result)
     1813{
     1814    if (arguments.size() == 1 && arguments[0].isBool())
     1815        m_shouldStayOnPageAfterHandlingBeforeUnload = arguments[0].toBoolean();
     1816
     1817    result->setNull();
     1818}
     1819
    18091820void LayoutTestController::setPluginsEnabled(const CppArgumentList& arguments, CppVariant* result)
    18101821{
  • trunk/Tools/DumpRenderTree/chromium/LayoutTestController.h

    r92219 r92982  
    394394    // Changes the direction of the focused element.
    395395    void setTextDirection(const CppArgumentList&, CppVariant*);
     396
     397    void setShouldStayOnPageAfterHandlingBeforeUnload(const CppArgumentList&, CppVariant*);
    396398
    397399public:
     
    456458    TaskList* taskList() { return &m_taskList; }
    457459
     460    bool shouldStayOnPageAfterHandlingBeforeUnload() const { return m_shouldStayOnPageAfterHandlingBeforeUnload; }
     461
    458462private:
    459463    friend class WorkItem;
     
    624628    // WAV audio data is stored here.
    625629    WebKit::WebArrayBufferView m_audioData;
     630
     631    bool m_shouldStayOnPageAfterHandlingBeforeUnload;
    626632};
    627633
  • trunk/Tools/DumpRenderTree/chromium/WebViewHost.cpp

    r92420 r92982  
    482482}
    483483
    484 bool WebViewHost::runModalBeforeUnloadDialog(WebFrame*, const WebString&)
    485 {
    486     return true; // Allow window closure.
     484bool WebViewHost::runModalBeforeUnloadDialog(WebFrame*, const WebString& message)
     485{
     486    printf("CONFIRM NAVIGATION: %s\n", message.utf8().data());
     487    return !layoutTestController()->shouldStayOnPageAfterHandlingBeforeUnload();
    487488}
    488489
  • trunk/Tools/DumpRenderTree/mac/UIDelegate.mm

    r90946 r92982  
    108108    if (!done)
    109109        printf("CONFIRM NAVIGATION: %s\n", [message UTF8String]);
    110     return YES;
     110   
     111    return !gLayoutTestController->shouldStayOnPageAfterHandlingBeforeUnload();
    111112}
    112113
  • trunk/Tools/DumpRenderTree/win/UIDelegate.cpp

    r85443 r92982  
    466466HRESULT STDMETHODCALLTYPE UIDelegate::runBeforeUnloadConfirmPanelWithMessage(
    467467    /* [in] */ IWebView* /*sender*/,
    468     /* [in] */ BSTR /*message*/,
     468    /* [in] */ BSTR message,
    469469    /* [in] */ IWebFrame* /*initiatedByFrame*/,
    470470    /* [retval][out] */ BOOL* result)
     
    472472    if (!result)
    473473        return E_POINTER;
    474     *result = TRUE;
    475     return E_NOTIMPL;
     474    printf("CONFIRM NAVIGATION: %S\n", message ? message : L"");
     475    *result = !gLayoutTestController->shouldStayOnPageAfterHandlingBeforeUnload();
     476    return S_OK;
    476477}
    477478
  • trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/LayoutTestController.idl

    r92839 r92982  
    113113
    114114        void setWillSendRequestReturnsNull(in boolean flag);
     115       
     116        void setShouldStayOnPageAfterHandlingBeforeUnload(in boolean flag);
    115117    };
    116118
  • trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp

    r90163 r92982  
    233233        m_pages[i]->dumpBackForwardList();
    234234}
     235   
     236void InjectedBundle::postNewBeforeUnloadReturnValue(bool value)
     237{
     238    WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("BeforeUnloadReturnValue"));
     239    WKRetainPtr<WKBooleanRef> messageBody(AdoptWK, WKBooleanCreate(value));
     240    WKBundlePostMessage(m_bundle, messageName.get(), messageBody.get());
     241}
    235242
    236243} // namespace WTR
  • trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.h

    r81494 r92982  
    7272
    7373    bool shouldDumpPixels() const { return m_dumpPixels; }
     74   
     75    void postNewBeforeUnloadReturnValue(bool);
    7476
    7577private:
  • trunk/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.cpp

    r92839 r92982  
    494494    return WKBundleFrameSetTextDirection(mainFrame, toWK(direction).get());
    495495}
     496   
     497void LayoutTestController::setShouldStayOnPageAfterHandlingBeforeUnload(bool shouldStayOnPage)
     498{
     499    InjectedBundle::shared().postNewBeforeUnloadReturnValue(!shouldStayOnPage);
     500}
    496501
    497502} // namespace WTR
  • trunk/Tools/WebKitTestRunner/InjectedBundle/LayoutTestController.h

    r92839 r92982  
    169169    void setTextDirection(JSStringRef);
    170170
     171    void setShouldStayOnPageAfterHandlingBeforeUnload(bool);
     172
    171173private:
    172174    static const double waitToDumpWatchdogTimerInterval;
  • trunk/Tools/WebKitTestRunner/TestController.cpp

    r91794 r92982  
    6969    , m_didPrintWebProcessCrashedMessage(false)
    7070    , m_shouldExitWhenWebProcessCrashes(true)
     71    , m_beforeUnloadReturnValue(true)
    7172{
    7273    initialize(argc, argv);
     
    106107static bool runBeforeUnloadConfirmPanel(WKPageRef page, WKStringRef message, WKFrameRef frame, const void *clientInfo)
    107108{
    108     printf("%s\n", toSTD(message).c_str());
    109     return true;
     109    TestController* testController = static_cast<TestController*>(const_cast<void*>(clientInfo));
     110    printf("CONFIRM NAVIGATION: %s\n", toSTD(message).c_str());
     111    return testController->beforeUnloadReturnValue();
    110112}
    111113
     
    359361{
    360362    m_state = Resetting;
     363   
     364    m_beforeUnloadReturnValue = true;
    361365
    362366    WKRetainPtr<WKStringRef> messageName = adoptWK(WKStringCreateWithUTF8CString("Reset"));
  • trunk/Tools/WebKitTestRunner/TestController.h

    r84534 r92982  
    5757    void runUntil(bool& done, TimeoutDuration);
    5858    void notifyDone();
     59   
     60    bool beforeUnloadReturnValue() const { return m_beforeUnloadReturnValue; }
     61    void setBeforeUnloadReturnValue(bool value) { m_beforeUnloadReturnValue = value; }
    5962
    6063private:
     
    122125    bool m_didPrintWebProcessCrashedMessage;
    123126    bool m_shouldExitWhenWebProcessCrashes;
     127   
     128    bool m_beforeUnloadReturnValue;
    124129};
    125130
  • trunk/Tools/WebKitTestRunner/TestInvocation.cpp

    r89426 r92982  
    239239        return;
    240240    }
     241   
     242    if (WKStringIsEqualToUTF8CString(messageName, "BeforeUnloadReturnValue")) {
     243        ASSERT(WKGetTypeID(messageBody) == WKBooleanGetTypeID());
     244        WKBooleanRef beforeUnloadReturnValue = static_cast<WKBooleanRef>(messageBody);
     245        TestController::shared().setBeforeUnloadReturnValue(WKBooleanGetValue(beforeUnloadReturnValue));
     246        return;
     247    }
    241248
    242249    ASSERT_NOT_REACHED();
Note: See TracChangeset for help on using the changeset viewer.