2010-09-17 Johnny Ding <jnd@chromium.org>
authorinferno@chromium.org <inferno@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 17 Sep 2010 16:36:53 +0000 (16:36 +0000)
committerinferno@chromium.org <inferno@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 17 Sep 2010 16:36:53 +0000 (16:36 +0000)
        Reviewed by Adam Barth.

        Stop history reload navigation to bypass WebKit's popup blocker.
        Now history reload can only navigate the page in self frame, no matter
        what target frame is defined in <base> and no new window can be created.
        https://bugs.webkit.org/show_bug.cgi?id=45369

        Test: fast/events/popup-blocked-from-history-reload.html

        * loader/RedirectScheduler.cpp:
        (WebCore::ScheduledNavigation::ScheduledNavigation):
        (WebCore::ScheduledNavigation::wasUserGesture):
        Move the m_wasUserGesture to base class ScheduledNavigation. Then all
        asynchronous navigation situations can restore the correct gesture state
        during the real navigation process.
        (WebCore::ScheduledURLNavigation::ScheduledURLNavigation):
        (WebCore::ScheduledURLNavigation::fire):
        (WebCore::ScheduledURLNavigation::referrer):
        (WebCore::ScheduledHistoryNavigation::ScheduledHistoryNavigation):
        (WebCore::ScheduledHistoryNavigation::fire):
        (WebCore::ScheduledFormSubmission::ScheduledFormSubmission):
        (WebCore::ScheduledFormSubmission::fire):
        (WebCore::RedirectScheduler::scheduleHistoryNavigation):
2010-09-17  Johnny Ding  <jnd@chromium.org>

        Reviewed by Adam Barth.

        Stop history reload navigation to bypass WebKit's popup blocker.
        https://bugs.webkit.org/show_bug.cgi?id=45369

        * fast/events/popup-blocked-from-history-reload-expected.txt: Added.
        * fast/events/popup-blocked-from-history-reload.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/fast/events/popup-blocked-from-history-reload-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/popup-blocked-from-history-reload.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/loader/RedirectScheduler.cpp

index 35d3e05..ef8a347 100644 (file)
@@ -1,3 +1,13 @@
+2010-09-17  Johnny Ding  <jnd@chromium.org>
+
+        Reviewed by Adam Barth.
+
+        Stop history reload navigation to bypass WebKit's popup blocker.
+        https://bugs.webkit.org/show_bug.cgi?id=45369
+
+        * fast/events/popup-blocked-from-history-reload-expected.txt: Added.
+        * fast/events/popup-blocked-from-history-reload.html: Added.
+
 2010-09-17  Zhenyao Mo  <zmo@google.com>
 
         Unreviewed.
diff --git a/LayoutTests/fast/events/popup-blocked-from-history-reload-expected.txt b/LayoutTests/fast/events/popup-blocked-from-history-reload-expected.txt
new file mode 100644 (file)
index 0000000..1f7e740
--- /dev/null
@@ -0,0 +1,3 @@
+History reload can only navigate the page in the self frame, no matter what target frame is defined in base tag and no new window can be created. This is a test case for bug https://bugs.webkit.org/show_bug.cgi?id=45369.
+load count : 2
+PASSED
diff --git a/LayoutTests/fast/events/popup-blocked-from-history-reload.html b/LayoutTests/fast/events/popup-blocked-from-history-reload.html
new file mode 100644 (file)
index 0000000..784cbd5
--- /dev/null
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script>
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.setCanOpenWindows();
+    layoutTestController.setPopupBlockingEnabled(true);
+    layoutTestController.setCloseRemainingWindowsWhenComplete(true);
+    layoutTestController.waitUntilDone();
+    // Record current window count.
+    window.windowCount = window.layoutTestController.windowCount();
+}
+function testDone() {
+    if (window.layoutTestController && window.layoutTestController.windowCount() == window.windowCount)
+        document.getElementById("console").innerText = "PASSED";
+    // Close the test.
+    layoutTestController.notifyDone();
+}
+</script>
+</head>
+<body">
+History reload can only navigate the page in the self frame, no matter what target frame is defined in base tag and no new window can be created. This is a test case for bug https://bugs.webkit.org/show_bug.cgi?id=45369.
+<div id="loadCount"></div>
+<div id="console">FAILED</div>
+<script>
+if (!sessionStorage.loadCount)
+   sessionStorage.loadCount = 1;
+else
+   sessionStorage.loadCount = parseInt(sessionStorage.loadCount, 10) + 1;
+document.getElementById("loadCount").innerText = "load count : " + sessionStorage.loadCount;
+if (2 == sessionStorage.loadCount)
+    testDone();
+else
+    history.go();
+</script>
+</body>
+</html>
+
index 4cb8683..049529d 100644 (file)
@@ -1,3 +1,29 @@
+2010-09-17  Johnny Ding  <jnd@chromium.org>
+
+        Reviewed by Adam Barth.
+
+        Stop history reload navigation to bypass WebKit's popup blocker.
+        Now history reload can only navigate the page in self frame, no matter
+        what target frame is defined in <base> and no new window can be created.
+        https://bugs.webkit.org/show_bug.cgi?id=45369
+
+        Test: fast/events/popup-blocked-from-history-reload.html
+
+        * loader/RedirectScheduler.cpp:
+        (WebCore::ScheduledNavigation::ScheduledNavigation):
+        (WebCore::ScheduledNavigation::wasUserGesture):
+        Move the m_wasUserGesture to base class ScheduledNavigation. Then all
+        asynchronous navigation situations can restore the correct gesture state
+        during the real navigation process.
+        (WebCore::ScheduledURLNavigation::ScheduledURLNavigation):
+        (WebCore::ScheduledURLNavigation::fire):
+        (WebCore::ScheduledURLNavigation::referrer):
+        (WebCore::ScheduledHistoryNavigation::ScheduledHistoryNavigation):
+        (WebCore::ScheduledHistoryNavigation::fire):
+        (WebCore::ScheduledFormSubmission::ScheduledFormSubmission):
+        (WebCore::ScheduledFormSubmission::fire):
+        (WebCore::RedirectScheduler::scheduleHistoryNavigation):
+
 2010-09-16  Vangelis Kokkevis  <vangelis@chromium.org>
 
         Reviewed by James Robinson.
index 7cb6090..ce0e3f8 100644 (file)
@@ -33,6 +33,7 @@
 #include "RedirectScheduler.h"
 
 #include "BackForwardList.h"
+#include "DOMWindow.h"
 #include "DocumentLoader.h"
 #include "Event.h"
 #include "FormState.h"
@@ -41,9 +42,9 @@
 #include "FrameLoadRequest.h"
 #include "FrameLoader.h"
 #include "FrameLoaderStateMachine.h"
-#include "HistoryItem.h"
 #include "HTMLFormElement.h"
 #include "HTMLFrameOwnerElement.h"
+#include "HistoryItem.h"
 #include "Page.h"
 #include "UserGestureIndicator.h"
 #include <wtf/CurrentTime.h>
@@ -52,12 +53,13 @@ namespace WebCore {
 
 class ScheduledNavigation : public Noncopyable {
 public:
-    ScheduledNavigation(double delay, bool lockHistory, bool lockBackForwardList, bool wasDuringLoad, bool isLocationChange)
+    ScheduledNavigation(double delay, bool lockHistory, bool lockBackForwardList, bool wasDuringLoad, bool isLocationChange, bool wasUserGesture)
         : m_delay(delay)
         , m_lockHistory(lockHistory)
         , m_lockBackForwardList(lockBackForwardList)
         , m_wasDuringLoad(wasDuringLoad)
         , m_isLocationChange(isLocationChange)
+        , m_wasUserGesture(wasUserGesture)
     {
     }
     virtual ~ScheduledNavigation() { }
@@ -73,6 +75,7 @@ public:
     bool lockBackForwardList() const { return m_lockBackForwardList; }
     bool wasDuringLoad() const { return m_wasDuringLoad; }
     bool isLocationChange() const { return m_isLocationChange; }
+    bool wasUserGesture() const { return m_wasUserGesture; }
 
 private:
     double m_delay;
@@ -80,22 +83,22 @@ private:
     bool m_lockBackForwardList;
     bool m_wasDuringLoad;
     bool m_isLocationChange;
+    bool m_wasUserGesture;
 };
 
 class ScheduledURLNavigation : public ScheduledNavigation {
 public:
     ScheduledURLNavigation(double delay, const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool wasUserGesture, bool duringLoad, bool isLocationChange)
-        : ScheduledNavigation(delay, lockHistory, lockBackForwardList, duringLoad, isLocationChange)
+        : ScheduledNavigation(delay, lockHistory, lockBackForwardList, duringLoad, isLocationChange, wasUserGesture)
         , m_url(url)
         , m_referrer(referrer)
-        , m_wasUserGesture(wasUserGesture)
         , m_haveToldClient(false)
     {
     }
 
     virtual void fire(Frame* frame)
     {
-        frame->loader()->changeLocation(KURL(ParsedURLString, m_url), m_referrer, lockHistory(), lockBackForwardList(), m_wasUserGesture, false);
+        frame->loader()->changeLocation(KURL(ParsedURLString, m_url), m_referrer, lockHistory(), lockBackForwardList(), wasUserGesture(), false);
     }
 
     virtual void didStartTimer(Frame* frame, Timer<RedirectScheduler>* timer)
@@ -115,12 +118,10 @@ public:
 
     String url() const { return m_url; }
     String referrer() const { return m_referrer; }
-    bool wasUserGesture() const { return m_wasUserGesture; }
 
 private:
     String m_url;
     String m_referrer;
-    bool m_wasUserGesture;
     bool m_haveToldClient;
 };
 
@@ -151,14 +152,17 @@ public:
 
 class ScheduledHistoryNavigation : public ScheduledNavigation {
 public:
-    explicit ScheduledHistoryNavigation(int historySteps) : ScheduledNavigation(0, false, false, false, true), m_historySteps(historySteps) { }
+    explicit ScheduledHistoryNavigation(int historySteps, bool wasUserGesture) : ScheduledNavigation(0, false, false, false, true, wasUserGesture), m_historySteps(historySteps) { }
 
     virtual void fire(Frame* frame)
     {
+        UserGestureIndicator gestureIndicator(wasUserGesture() ? DefinitelyProcessingUserGesture : DefinitelyNotProcessingUserGesture);
+
         FrameLoader* loader = frame->loader();
         if (!m_historySteps) {
             // Special case for go(0) from a frame -> reload only the frame
-            loader->urlSelected(loader->url(), "", 0, lockHistory(), lockBackForwardList(), false, SendReferrer);
+            // To follow Firefox and IE's behavior, history reload can only navigate the self frame.
+            loader->urlSelected(loader->url(), "_self", 0, lockHistory(), lockBackForwardList(), wasUserGesture(), SendReferrer);
             return;
         }
         // go(i!=0) from a frame navigates into the history of the frame only,
@@ -173,17 +177,16 @@ private:
 class ScheduledFormSubmission : public ScheduledNavigation {
 public:
     ScheduledFormSubmission(PassRefPtr<FormSubmission> submission, bool lockBackForwardList, bool duringLoad, bool wasUserGesture)
-        : ScheduledNavigation(0, submission->lockHistory(), lockBackForwardList, duringLoad, true)
+        : ScheduledNavigation(0, submission->lockHistory(), lockBackForwardList, duringLoad, true, wasUserGesture)
         , m_submission(submission)
         , m_haveToldClient(false)
-        , m_wasUserGesture(wasUserGesture)
     {
         ASSERT(m_submission->state());
     }
 
     virtual void fire(Frame* frame)
     {
-        UserGestureIndicator gestureIndicator(m_wasUserGesture ? DefinitelyProcessingUserGesture : DefinitelyNotProcessingUserGesture);
+        UserGestureIndicator gestureIndicator(wasUserGesture() ? DefinitelyProcessingUserGesture : DefinitelyNotProcessingUserGesture);
 
         // The submitForm function will find a target frame before using the redirection timer.
         // Now that the timer has fired, we need to repeat the security check which normally is done when
@@ -214,7 +217,6 @@ public:
 private:
     RefPtr<FormSubmission> m_submission;
     bool m_haveToldClient;
-    bool m_wasUserGesture;
 };
 
 RedirectScheduler::RedirectScheduler(Frame* frame)
@@ -344,9 +346,9 @@ void RedirectScheduler::scheduleHistoryNavigation(int steps)
         cancel();
         return;
     }
-    
+
     // In all other cases, schedule the history traversal to occur asynchronously.
-    schedule(adoptPtr(new ScheduledHistoryNavigation(steps)));
+    schedule(adoptPtr(new ScheduledHistoryNavigation(steps, m_frame->loader()->isProcessingUserGesture())));
 }
 
 void RedirectScheduler::timerFired(Timer<RedirectScheduler>*)