[SCM] WebKit Debian packaging branch, webkit-1.2, updated. upstream/1.1.90-6072-g9a69373

beidson at apple.com beidson at apple.com
Thu Apr 8 00:33:42 UTC 2010


The following commit has been merged in the webkit-1.2 branch:
commit 1117ef470189cf1280eb4f58ca221a22506f8d9b
Author: beidson at apple.com <beidson at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Sat Dec 12 01:34:17 2009 +0000

    <rdar://problem/7342725> and https://webkit.org/b/32383
    Selecting article text at sfgate.com results in spurious back/forward entries
    
    Reviewed by Darin Adler.
    
    WebCore:
    
    If an iframe had a form and that form is submitted by javascript, IE and Opera don't add back/forward entries.
    
    In the case where the frame was added dynamically via createElement(), Firefox would like to add a back entry
    but has a bug that prevents this.
    
    Therefore by a bizarre coincidence, WebKit is the loner and the only engine affected by sfgate.com's technique.
    
    This patch changes us to willfully match IE and Opera and fixes sfgate.com in the process.
    
    Tests: http/tests/navigation/dynamic-iframe-dynamic-form-back-entry.html
           http/tests/navigation/parsed-iframe-dynamic-form-back-entry.html
    
    Capture whether the form was submitted by javascript:
    * loader/FormState.cpp:
    (WebCore::FormState::FormState):
    (WebCore::FormState::create):
    * loader/FormState.h:
    (WebCore::FormState::formSubmissionTrigger):
    
    When deciding the value of the lockBackForwardList variable, take formSubmissionTrigger() into account:
    * loader/RedirectScheduler.cpp:
    (WebCore::RedirectScheduler::scheduleFormSubmission):
    
    Rearrange the public HTMLFormElement::submit() method to be called only from DOM or JS bindings,
    and figure out the rest of the parameters for an internal submit() call including the formSubmissionTrigger:
    * bindings/js/JSHTMLFormElementCustom.cpp:
    (WebCore::JSHTMLFormElement::submit):
    * html/HTMLFormElement.cpp:
    (WebCore::HTMLFormElement::prepareSubmit):
    (WebCore::HTMLFormElement::submit):
    * html/HTMLFormElement.h:
    
    LayoutTests:
    
    * http/tests/navigation/dynamic-iframe-dynamic-form-back-entry-expected.txt: Added.
    * http/tests/navigation/dynamic-iframe-dynamic-form-back-entry.html: Added.
    * http/tests/navigation/parsed-iframe-dynamic-form-back-entry-expected.txt: Added.
    * http/tests/navigation/parsed-iframe-dynamic-form-back-entry.html: Added.
    * http/tests/navigation/resources/notify-done.html: Added.
    
    * http/tests/navigation/onload-navigation-iframe-timeout-expected.txt: Updated.
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@52033 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index d1c5cab..d0649da 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,18 @@
+2009-12-11  Brady Eidson  <beidson at apple.com>
+
+        Reviewed by Darin Adler.
+
+        <rdar://problem/7342725> and https://webkit.org/b/32383
+        Selecting article text at sfgate.com results in spurious back/forward entries
+
+        * http/tests/navigation/dynamic-iframe-dynamic-form-back-entry-expected.txt: Added.
+        * http/tests/navigation/dynamic-iframe-dynamic-form-back-entry.html: Added.
+        * http/tests/navigation/parsed-iframe-dynamic-form-back-entry-expected.txt: Added.
+        * http/tests/navigation/parsed-iframe-dynamic-form-back-entry.html: Added.
+        * http/tests/navigation/resources/notify-done.html: Added.
+
+        * http/tests/navigation/onload-navigation-iframe-timeout-expected.txt: Updated.
+
 2009-12-11  Simon Fraser  <simon.fraser at apple.com>
 
         Reviewed by Darin Adler.
diff --git a/LayoutTests/http/tests/navigation/dynamic-iframe-dynamic-form-back-entry-expected.txt b/LayoutTests/http/tests/navigation/dynamic-iframe-dynamic-form-back-entry-expected.txt
new file mode 100644
index 0000000..ca84c0f
--- /dev/null
+++ b/LayoutTests/http/tests/navigation/dynamic-iframe-dynamic-form-back-entry-expected.txt
@@ -0,0 +1,7 @@
+This test sees if dynamically creating an iframe, dynamically adding form elements to it, and dynamically submitting the form result in an extra back/forward entry. It is important that these steps run after the initial load is complete, hence the setTimeout() for running the test.
+
+
+============== Back Forward List ==============
+curr->  http://127.0.0.1:8000/navigation/dynamic-iframe-dynamic-form-back-entry.html  **nav target**
+            http://127.0.0.1:8000/navigation/resources/notify-done.html (in frame "testFrame")
+===============================================
diff --git a/LayoutTests/http/tests/navigation/dynamic-iframe-dynamic-form-back-entry.html b/LayoutTests/http/tests/navigation/dynamic-iframe-dynamic-form-back-entry.html
new file mode 100644
index 0000000..8f5fbcb
--- /dev/null
+++ b/LayoutTests/http/tests/navigation/dynamic-iframe-dynamic-form-back-entry.html
@@ -0,0 +1,35 @@
+<html>
+<script>
+
+if (window.layoutTestController) {
+    layoutTestController.waitUntilDone();
+    layoutTestController.dumpBackForwardList();
+    layoutTestController.dumpAsText();
+}
+
+function runTest()
+{
+    var iframe = document.createElement("iframe");
+    iframe.setAttribute("name", "testFrame");
+    document.body.appendChild(iframe);
+
+    var otherDocument = iframe.contentWindow.document;
+
+    var form = otherDocument.createElement("form");
+    form.setAttribute("action", "resources/notify-done.html");
+    form.setAttribute("name", "TestForm");
+    form.setAttribute("target", "testFrame");
+    form.setAttribute("method", "post");
+    var button = otherDocument.createElement("input");
+    button.setAttribute("type", "submit");
+    form.appendChild(button);
+    otherDocument.body.appendChild(form);
+
+    form.submit();
+}
+
+</script>
+<body onload="setTimeout('runTest();', 0);">
+This test sees if dynamically creating an iframe, dynamically adding form elements to it, and dynamically submitting the form result in an extra back/forward entry.  It is important that these steps run after the initial load is complete, hence the setTimeout() for running the test.<br>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/navigation/onload-navigation-iframe-timeout-expected.txt b/LayoutTests/http/tests/navigation/onload-navigation-iframe-timeout-expected.txt
index b27919c..4573572 100644
--- a/LayoutTests/http/tests/navigation/onload-navigation-iframe-timeout-expected.txt
+++ b/LayoutTests/http/tests/navigation/onload-navigation-iframe-timeout-expected.txt
@@ -2,8 +2,6 @@ In this case, Safari and Firefox adds a history item but IE doesn't.
 
 
 ============== Back Forward List ==============
-        http://127.0.0.1:8000/navigation/onload-navigation-iframe-timeout.html  **nav target**
-            about:blank (in frame "myFrame")
-curr->  http://127.0.0.1:8000/navigation/onload-navigation-iframe-timeout.html
-            http://127.0.0.1:8000/navigation/resources/blank.txt? (in frame "myFrame")  **nav target**
+curr->  http://127.0.0.1:8000/navigation/onload-navigation-iframe-timeout.html  **nav target**
+            http://127.0.0.1:8000/navigation/resources/blank.txt? (in frame "myFrame")
 ===============================================
diff --git a/LayoutTests/http/tests/navigation/parsed-iframe-dynamic-form-back-entry-expected.txt b/LayoutTests/http/tests/navigation/parsed-iframe-dynamic-form-back-entry-expected.txt
new file mode 100644
index 0000000..3c6b3d1
--- /dev/null
+++ b/LayoutTests/http/tests/navigation/parsed-iframe-dynamic-form-back-entry-expected.txt
@@ -0,0 +1,7 @@
+This test sees if starting with an empty iframe in the markup, dynamically adding form elements to it, and dynamically submitting the form result in an extra back/forward entry. It is important that these steps run after the initial load is complete, hence the setTimeout() for running the test.
+
+
+============== Back Forward List ==============
+curr->  http://127.0.0.1:8000/navigation/parsed-iframe-dynamic-form-back-entry.html  **nav target**
+            http://127.0.0.1:8000/navigation/resources/notify-done.html (in frame "testFrame")
+===============================================
diff --git a/LayoutTests/http/tests/navigation/parsed-iframe-dynamic-form-back-entry.html b/LayoutTests/http/tests/navigation/parsed-iframe-dynamic-form-back-entry.html
new file mode 100644
index 0000000..d921709
--- /dev/null
+++ b/LayoutTests/http/tests/navigation/parsed-iframe-dynamic-form-back-entry.html
@@ -0,0 +1,34 @@
+<html>
+<script>
+
+if (window.layoutTestController) {
+    layoutTestController.waitUntilDone();
+    layoutTestController.dumpBackForwardList();
+    layoutTestController.dumpAsText();
+}
+
+function runTest()
+{
+    var iframe = document.getElementById("testFrame");
+
+    var otherDocument = iframe.contentWindow.document;
+
+    var form = otherDocument.createElement("form");
+    form.setAttribute("action", "resources/notify-done.html");
+    form.setAttribute("name", "TestForm");
+    form.setAttribute("target", "testFrame");
+    form.setAttribute("method", "post");
+    var button = otherDocument.createElement("input");
+    button.setAttribute("type", "submit");
+    form.appendChild(button);
+    otherDocument.body.appendChild(form);
+
+    form.submit();
+}
+
+</script>
+<body onload="setTimeout('runTest();', 0);">
+This test sees if starting with an empty iframe in the markup, dynamically adding form elements to it, and dynamically submitting the form result in an extra back/forward entry.  It is important that these steps run after the initial load is complete, hence the setTimeout() for running the test.<br>
+<iframe id="testFrame" name="testFrame"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/navigation/resources/notify-done.html b/LayoutTests/http/tests/navigation/resources/notify-done.html
new file mode 100644
index 0000000..a320e5d
--- /dev/null
+++ b/LayoutTests/http/tests/navigation/resources/notify-done.html
@@ -0,0 +1,8 @@
+<html>
+<script>
+if (window.layoutTestController)
+    layoutTestController.notifyDone();
+</script>
+<body>
+This page calls layoutTestController.notifyDone().
+</html>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index ab18e51..7eaff6c 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,42 @@
+2009-12-11  Brady Eidson  <beidson at apple.com>
+
+        Reviewed by Darin Adler.
+
+        <rdar://problem/7342725> and https://webkit.org/b/32383
+        Selecting article text at sfgate.com results in spurious back/forward entries
+
+        If an iframe had a form and that form is submitted by javascript, IE and Opera don't add back/forward entries.
+        
+        In the case where the frame was added dynamically via createElement(), Firefox would like to add a back entry
+        but has a bug that prevents this.
+
+        Therefore by a bizarre coincidence, WebKit is the loner and the only engine affected by sfgate.com's technique.
+
+        This patch changes us to willfully match IE and Opera and fixes sfgate.com in the process.
+
+        Tests: http/tests/navigation/dynamic-iframe-dynamic-form-back-entry.html
+               http/tests/navigation/parsed-iframe-dynamic-form-back-entry.html
+
+        Capture whether the form was submitted by javascript:
+        * loader/FormState.cpp:
+        (WebCore::FormState::FormState):
+        (WebCore::FormState::create):
+        * loader/FormState.h:
+        (WebCore::FormState::formSubmissionTrigger):
+
+        When deciding the value of the lockBackForwardList variable, take formSubmissionTrigger() into account:
+        * loader/RedirectScheduler.cpp:
+        (WebCore::RedirectScheduler::scheduleFormSubmission):
+
+        Rearrange the public HTMLFormElement::submit() method to be called only from DOM or JS bindings,
+        and figure out the rest of the parameters for an internal submit() call including the formSubmissionTrigger:
+        * bindings/js/JSHTMLFormElementCustom.cpp:
+        (WebCore::JSHTMLFormElement::submit):
+        * html/HTMLFormElement.cpp:
+        (WebCore::HTMLFormElement::prepareSubmit):
+        (WebCore::HTMLFormElement::submit):
+        * html/HTMLFormElement.h:
+
 2009-12-11  Alexey Proskuryakov  <ap at apple.com>
 
         Reviewed by Darin Adler.
diff --git a/WebCore/bindings/js/JSHTMLFormElementCustom.cpp b/WebCore/bindings/js/JSHTMLFormElementCustom.cpp
index de9ec4a..c364c14 100644
--- a/WebCore/bindings/js/JSHTMLFormElementCustom.cpp
+++ b/WebCore/bindings/js/JSHTMLFormElementCustom.cpp
@@ -66,7 +66,7 @@ JSValue JSHTMLFormElement::submit(ExecState* exec, const ArgList&)
     Frame* activeFrame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame();
     if (!activeFrame)
         return jsUndefined();
-    static_cast<HTMLFormElement*>(impl())->submit(0, false, !activeFrame->script()->anyPageIsProcessingUserGesture());
+    static_cast<HTMLFormElement*>(impl())->submit(activeFrame);
     return jsUndefined();
 }
 
diff --git a/WebCore/html/HTMLFormElement.cpp b/WebCore/html/HTMLFormElement.cpp
index ace0f2f..0433c82 100644
--- a/WebCore/html/HTMLFormElement.cpp
+++ b/WebCore/html/HTMLFormElement.cpp
@@ -302,7 +302,7 @@ bool HTMLFormElement::prepareSubmit(Event* event)
     m_insubmit = false;
 
     if (m_doingsubmit)
-        submit(event, true);
+        submit(event, true, false, NotSubmittedByJavaScript);
 
     return m_doingsubmit;
 }
@@ -329,7 +329,15 @@ static void transferMailtoPostFormDataToURL(RefPtr<FormData>& data, KURL& url, c
     url.setQuery(query);
 }
 
-void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool lockHistory)
+void HTMLFormElement::submit(Frame* javaScriptActiveFrame)
+{
+    if (javaScriptActiveFrame)
+        submit(0, false, !javaScriptActiveFrame->script()->anyPageIsProcessingUserGesture(), SubmittedByJavaScript);
+    else
+        submit(0, false, false, NotSubmittedByJavaScript);
+}
+
+void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool lockHistory, FormSubmissionTrigger formSubmissionTrigger)
 {
     FrameView* view = document()->view();
     Frame* frame = document()->frame();
@@ -366,7 +374,7 @@ void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool lockH
         }
     }
 
-    RefPtr<FormState> formState = FormState::create(this, formValues, frame);
+    RefPtr<FormState> formState = FormState::create(this, formValues, frame, formSubmissionTrigger);
 
     if (needButtonActivation && firstSuccessfulSubmitButton)
         firstSuccessfulSubmitButton->setActivatedSubmit(true);
diff --git a/WebCore/html/HTMLFormElement.h b/WebCore/html/HTMLFormElement.h
index a2e9585..c0ce3e3 100644
--- a/WebCore/html/HTMLFormElement.h
+++ b/WebCore/html/HTMLFormElement.h
@@ -26,6 +26,7 @@
 
 #include "CheckedRadioButtons.h"
 #include "FormDataBuilder.h"
+#include "FormState.h"
 #include "HTMLElement.h"
 #include <wtf/OwnPtr.h>
 
@@ -78,7 +79,7 @@ public:
     void removeImgElement(HTMLImageElement*);
 
     bool prepareSubmit(Event*);
-    void submit(Event* = 0, bool activateSubmitButton = false, bool lockHistory = false);
+    void submit(Frame* javaScriptActiveFrame = 0);
     void reset();
 
     // Used to indicate a malformed state to keep from applying the bottom margin of the form.
@@ -130,6 +131,8 @@ protected:
     virtual void didMoveToNewOwnerDocument();
 
 private:
+    void submit(Event*, bool activateSubmitButton, bool lockHistory, FormSubmissionTrigger);
+
     bool isMailtoForm() const;
     TextEncoding dataEncoding() const;
     PassRefPtr<FormData> createFormData(const CString& boundary);
diff --git a/WebCore/loader/FormState.cpp b/WebCore/loader/FormState.cpp
index bd37086..552789a 100644
--- a/WebCore/loader/FormState.cpp
+++ b/WebCore/loader/FormState.cpp
@@ -34,16 +34,17 @@
 
 namespace WebCore {
 
-inline FormState::FormState(PassRefPtr<HTMLFormElement> form, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Frame> sourceFrame)
+inline FormState::FormState(PassRefPtr<HTMLFormElement> form, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Frame> sourceFrame, FormSubmissionTrigger formSubmissionTrigger)
     : m_form(form)
     , m_sourceFrame(sourceFrame)
+    , m_formSubmissionTrigger(formSubmissionTrigger)
 {
     m_textFieldValues.swap(textFieldValuesToAdopt);
 }
 
-PassRefPtr<FormState> FormState::create(PassRefPtr<HTMLFormElement> form, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Frame> sourceFrame)
+PassRefPtr<FormState> FormState::create(PassRefPtr<HTMLFormElement> form, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Frame> sourceFrame, FormSubmissionTrigger formSubmissionTrigger)
 {
-    return adoptRef(new FormState(form, textFieldValuesToAdopt, sourceFrame));
+    return adoptRef(new FormState(form, textFieldValuesToAdopt, sourceFrame, formSubmissionTrigger));
 }
 
 }
diff --git a/WebCore/loader/FormState.h b/WebCore/loader/FormState.h
index 03317b1..8f7166e 100644
--- a/WebCore/loader/FormState.h
+++ b/WebCore/loader/FormState.h
@@ -36,22 +36,29 @@ namespace WebCore {
     class Frame;
     class HTMLFormElement;
 
+    enum FormSubmissionTrigger {
+        SubmittedByJavaScript,
+        NotSubmittedByJavaScript
+    };
+    
     typedef Vector<std::pair<String, String> > StringPairVector;
 
     class FormState : public RefCounted<FormState> {
     public:
-        static PassRefPtr<FormState> create(PassRefPtr<HTMLFormElement>, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Frame>);
+        static PassRefPtr<FormState> create(PassRefPtr<HTMLFormElement>, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Frame>, FormSubmissionTrigger);
 
         HTMLFormElement* form() const { return m_form.get(); }
         const StringPairVector& textFieldValues() const { return m_textFieldValues; }
         Frame* sourceFrame() const { return m_sourceFrame.get(); }
+        FormSubmissionTrigger formSubmissionTrigger() const { return m_formSubmissionTrigger; }
 
     private:
-        FormState(PassRefPtr<HTMLFormElement>, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Frame>);
+        FormState(PassRefPtr<HTMLFormElement>, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Frame>, FormSubmissionTrigger);
 
         RefPtr<HTMLFormElement> m_form;
         StringPairVector m_textFieldValues;
         RefPtr<Frame> m_sourceFrame;
+        FormSubmissionTrigger m_formSubmissionTrigger;
     };
 
 }
diff --git a/WebCore/loader/RedirectScheduler.cpp b/WebCore/loader/RedirectScheduler.cpp
index f2202cc..e53a1db 100644
--- a/WebCore/loader/RedirectScheduler.cpp
+++ b/WebCore/loader/RedirectScheduler.cpp
@@ -39,6 +39,7 @@
 #include "FrameLoadRequest.h"
 #include "FrameLoader.h"
 #include "HTMLFormElement.h"
+#include "HTMLFrameOwnerElement.h"
 #include "Page.h"
 #include <wtf/CurrentTime.h>
 
@@ -218,7 +219,13 @@ void RedirectScheduler::scheduleFormSubmission(const FrameLoadRequest& frameRequ
     // This may happen when a frame changes the location of another frame.
     bool duringLoad = !m_frame->loader()->committedFirstRealDocumentLoad();
 
-    schedule(new ScheduledRedirection(frameRequest, lockHistory, mustLockBackForwardList(m_frame), event, formState, duringLoad));
+    // If this is a child frame and the form submission was triggered by a script, lock the back/forward list
+    // to match IE and Opera.
+    // See https://bugs.webkit.org/show_bug.cgi?id=32383 for the original motivation for this.
+
+    bool lockBackForwardList = mustLockBackForwardList(m_frame) || (formState->formSubmissionTrigger() == SubmittedByJavaScript && m_frame->tree()->parent());
+
+    schedule(new ScheduledRedirection(frameRequest, lockHistory, lockBackForwardList, event, formState, duringLoad));
 }
 
 void RedirectScheduler::scheduleRefresh(bool wasUserGesture)

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list