| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
| 4 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) | 4 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) |
| 5 * Copyright (C) 2009 Adam Barth. All rights reserved. | 5 * Copyright (C) 2009 Adam Barth. All rights reserved. |
| 6 * | 6 * |
| 7 * Redistribution and use in source and binary forms, with or without | 7 * Redistribution and use in source and binary forms, with or without |
| 8 * modification, are permitted provided that the following conditions | 8 * modification, are permitted provided that the following conditions |
| 9 * are met: | 9 * are met: |
| 10 * | 10 * |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 */ | 30 */ |
| 31 | 31 |
| 32 #include "config.h" | 32 #include "config.h" |
| 33 #include "RedirectScheduler.h" | 33 #include "RedirectScheduler.h" |
| 34 | 34 |
| 35 #include "BackForwardList.h" | 35 #include "BackForwardList.h" |
| 36 #include "DOMWindow.h" |
| 36 #include "DocumentLoader.h" | 37 #include "DocumentLoader.h" |
| 37 #include "Event.h" | 38 #include "Event.h" |
| 38 #include "FormState.h" | 39 #include "FormState.h" |
| 39 #include "FormSubmission.h" | 40 #include "FormSubmission.h" |
| 40 #include "Frame.h" | 41 #include "Frame.h" |
| 41 #include "FrameLoadRequest.h" | 42 #include "FrameLoadRequest.h" |
| 42 #include "FrameLoader.h" | 43 #include "FrameLoader.h" |
| 43 #include "FrameLoaderStateMachine.h" | 44 #include "FrameLoaderStateMachine.h" |
| 44 #include "HistoryItem.h" | |
| 45 #include "HTMLFormElement.h" | 45 #include "HTMLFormElement.h" |
| 46 #include "HTMLFrameOwnerElement.h" | 46 #include "HTMLFrameOwnerElement.h" |
| 47 #include "HistoryItem.h" |
| 47 #include "Page.h" | 48 #include "Page.h" |
| 48 #include "UserGestureIndicator.h" | 49 #include "UserGestureIndicator.h" |
| 49 #include <wtf/CurrentTime.h> | 50 #include <wtf/CurrentTime.h> |
| 50 | 51 |
| 51 namespace WebCore { | 52 namespace WebCore { |
| 52 | 53 |
| 53 class ScheduledNavigation : public Noncopyable { | 54 class ScheduledNavigation : public Noncopyable { |
| 54 public: | 55 public: |
| 55 ScheduledNavigation(double delay, bool lockHistory, bool lockBackForwardList
, bool wasDuringLoad, bool isLocationChange) | 56 ScheduledNavigation(double delay, bool lockHistory, bool lockBackForwardList
, bool wasDuringLoad, bool isLocationChange, bool wasUserGesture) |
| 56 : m_delay(delay) | 57 : m_delay(delay) |
| 57 , m_lockHistory(lockHistory) | 58 , m_lockHistory(lockHistory) |
| 58 , m_lockBackForwardList(lockBackForwardList) | 59 , m_lockBackForwardList(lockBackForwardList) |
| 59 , m_wasDuringLoad(wasDuringLoad) | 60 , m_wasDuringLoad(wasDuringLoad) |
| 60 , m_isLocationChange(isLocationChange) | 61 , m_isLocationChange(isLocationChange) |
| 62 , m_wasUserGesture(wasUserGesture) |
| 61 { | 63 { |
| 62 } | 64 } |
| 63 virtual ~ScheduledNavigation() { } | 65 virtual ~ScheduledNavigation() { } |
| 64 | 66 |
| 65 virtual void fire(Frame*) = 0; | 67 virtual void fire(Frame*) = 0; |
| 66 | 68 |
| 67 virtual bool shouldStartTimer(Frame*) { return true; } | 69 virtual bool shouldStartTimer(Frame*) { return true; } |
| 68 virtual void didStartTimer(Frame*, Timer<RedirectScheduler>*) { } | 70 virtual void didStartTimer(Frame*, Timer<RedirectScheduler>*) { } |
| 69 virtual void didStopTimer(Frame*, bool /* newLoadInProgress */) { } | 71 virtual void didStopTimer(Frame*, bool /* newLoadInProgress */) { } |
| 70 | 72 |
| 71 double delay() const { return m_delay; } | 73 double delay() const { return m_delay; } |
| 72 bool lockHistory() const { return m_lockHistory; } | 74 bool lockHistory() const { return m_lockHistory; } |
| 73 bool lockBackForwardList() const { return m_lockBackForwardList; } | 75 bool lockBackForwardList() const { return m_lockBackForwardList; } |
| 74 bool wasDuringLoad() const { return m_wasDuringLoad; } | 76 bool wasDuringLoad() const { return m_wasDuringLoad; } |
| 75 bool isLocationChange() const { return m_isLocationChange; } | 77 bool isLocationChange() const { return m_isLocationChange; } |
| 78 bool wasUserGesture() const { return m_wasUserGesture; } |
| 76 | 79 |
| 77 private: | 80 private: |
| 78 double m_delay; | 81 double m_delay; |
| 79 bool m_lockHistory; | 82 bool m_lockHistory; |
| 80 bool m_lockBackForwardList; | 83 bool m_lockBackForwardList; |
| 81 bool m_wasDuringLoad; | 84 bool m_wasDuringLoad; |
| 82 bool m_isLocationChange; | 85 bool m_isLocationChange; |
| 86 bool m_wasUserGesture; |
| 83 }; | 87 }; |
| 84 | 88 |
| 85 class ScheduledURLNavigation : public ScheduledNavigation { | 89 class ScheduledURLNavigation : public ScheduledNavigation { |
| 86 public: | 90 public: |
| 87 ScheduledURLNavigation(double delay, const String& url, const String& referr
er, bool lockHistory, bool lockBackForwardList, bool wasUserGesture, bool during
Load, bool isLocationChange) | 91 ScheduledURLNavigation(double delay, const String& url, const String& referr
er, bool lockHistory, bool lockBackForwardList, bool wasUserGesture, bool during
Load, bool isLocationChange) |
| 88 : ScheduledNavigation(delay, lockHistory, lockBackForwardList, duringLoa
d, isLocationChange) | 92 : ScheduledNavigation(delay, lockHistory, lockBackForwardList, duringLoa
d, isLocationChange, wasUserGesture) |
| 89 , m_url(url) | 93 , m_url(url) |
| 90 , m_referrer(referrer) | 94 , m_referrer(referrer) |
| 91 , m_wasUserGesture(wasUserGesture) | |
| 92 , m_haveToldClient(false) | 95 , m_haveToldClient(false) |
| 93 { | 96 { |
| 94 } | 97 } |
| 95 | 98 |
| 96 virtual void fire(Frame* frame) | 99 virtual void fire(Frame* frame) |
| 97 { | 100 { |
| 98 frame->loader()->changeLocation(KURL(ParsedURLString, m_url), m_referrer
, lockHistory(), lockBackForwardList(), m_wasUserGesture, false); | 101 frame->loader()->changeLocation(KURL(ParsedURLString, m_url), m_referrer
, lockHistory(), lockBackForwardList(), wasUserGesture(), false); |
| 99 } | 102 } |
| 100 | 103 |
| 101 virtual void didStartTimer(Frame* frame, Timer<RedirectScheduler>* timer) | 104 virtual void didStartTimer(Frame* frame, Timer<RedirectScheduler>* timer) |
| 102 { | 105 { |
| 103 if (m_haveToldClient) | 106 if (m_haveToldClient) |
| 104 return; | 107 return; |
| 105 m_haveToldClient = true; | 108 m_haveToldClient = true; |
| 106 frame->loader()->clientRedirected(KURL(ParsedURLString, m_url), delay(),
currentTime() + timer->nextFireInterval(), lockBackForwardList()); | 109 frame->loader()->clientRedirected(KURL(ParsedURLString, m_url), delay(),
currentTime() + timer->nextFireInterval(), lockBackForwardList()); |
| 107 } | 110 } |
| 108 | 111 |
| 109 virtual void didStopTimer(Frame* frame, bool newLoadInProgress) | 112 virtual void didStopTimer(Frame* frame, bool newLoadInProgress) |
| 110 { | 113 { |
| 111 if (!m_haveToldClient) | 114 if (!m_haveToldClient) |
| 112 return; | 115 return; |
| 113 frame->loader()->clientRedirectCancelledOrFinished(newLoadInProgress); | 116 frame->loader()->clientRedirectCancelledOrFinished(newLoadInProgress); |
| 114 } | 117 } |
| 115 | 118 |
| 116 String url() const { return m_url; } | 119 String url() const { return m_url; } |
| 117 String referrer() const { return m_referrer; } | 120 String referrer() const { return m_referrer; } |
| 118 bool wasUserGesture() const { return m_wasUserGesture; } | |
| 119 | 121 |
| 120 private: | 122 private: |
| 121 String m_url; | 123 String m_url; |
| 122 String m_referrer; | 124 String m_referrer; |
| 123 bool m_wasUserGesture; | |
| 124 bool m_haveToldClient; | 125 bool m_haveToldClient; |
| 125 }; | 126 }; |
| 126 | 127 |
| 127 class ScheduledRedirect : public ScheduledURLNavigation { | 128 class ScheduledRedirect : public ScheduledURLNavigation { |
| 128 public: | 129 public: |
| 129 ScheduledRedirect(double delay, const String& url, bool lockHistory, bool lo
ckBackForwardList, bool wasUserGesture) | 130 ScheduledRedirect(double delay, const String& url, bool lockHistory, bool lo
ckBackForwardList, bool wasUserGesture) |
| 130 : ScheduledURLNavigation(delay, url, String(), lockHistory, lockBackForw
ardList, wasUserGesture, false, false) { } | 131 : ScheduledURLNavigation(delay, url, String(), lockHistory, lockBackForw
ardList, wasUserGesture, false, false) { } |
| 131 | 132 |
| 132 virtual bool shouldStartTimer(Frame* frame) { return frame->loader()->allAnc
estorsAreComplete(); } | 133 virtual bool shouldStartTimer(Frame* frame) { return frame->loader()->allAnc
estorsAreComplete(); } |
| 133 }; | 134 }; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 144 : ScheduledURLNavigation(0.0, url, referrer, true, true, wasUserGesture,
false, true) { } | 145 : ScheduledURLNavigation(0.0, url, referrer, true, true, wasUserGesture,
false, true) { } |
| 145 | 146 |
| 146 virtual void fire(Frame* frame) | 147 virtual void fire(Frame* frame) |
| 147 { | 148 { |
| 148 frame->loader()->changeLocation(KURL(ParsedURLString, url()), referrer()
, lockHistory(), lockBackForwardList(), wasUserGesture(), true); | 149 frame->loader()->changeLocation(KURL(ParsedURLString, url()), referrer()
, lockHistory(), lockBackForwardList(), wasUserGesture(), true); |
| 149 } | 150 } |
| 150 }; | 151 }; |
| 151 | 152 |
| 152 class ScheduledHistoryNavigation : public ScheduledNavigation { | 153 class ScheduledHistoryNavigation : public ScheduledNavigation { |
| 153 public: | 154 public: |
| 154 explicit ScheduledHistoryNavigation(int historySteps) : ScheduledNavigation(
0, false, false, false, true), m_historySteps(historySteps) { } | 155 explicit ScheduledHistoryNavigation(int historySteps, bool wasUserGesture) :
ScheduledNavigation(0, false, false, false, true, wasUserGesture), m_historySte
ps(historySteps) { } |
| 155 | 156 |
| 156 virtual void fire(Frame* frame) | 157 virtual void fire(Frame* frame) |
| 157 { | 158 { |
| 159 UserGestureIndicator gestureIndicator(wasUserGesture() ? DefinitelyProce
ssingUserGesture : DefinitelyNotProcessingUserGesture); |
| 160 |
| 158 FrameLoader* loader = frame->loader(); | 161 FrameLoader* loader = frame->loader(); |
| 159 if (!m_historySteps) { | 162 if (!m_historySteps) { |
| 160 // Special case for go(0) from a frame -> reload only the frame | 163 // Special case for go(0) from a frame -> reload only the frame |
| 161 loader->urlSelected(loader->url(), "", 0, lockHistory(), lockBackFor
wardList(), false, SendReferrer); | 164 // To follow Firefox and IE's behavior, history reload can only navi
gate the self frame. |
| 165 loader->urlSelected(loader->url(), "_self", 0, lockHistory(), lockBa
ckForwardList(), wasUserGesture(), SendReferrer); |
| 162 return; | 166 return; |
| 163 } | 167 } |
| 164 // go(i!=0) from a frame navigates into the history of the frame only, | 168 // go(i!=0) from a frame navigates into the history of the frame only, |
| 165 // in both IE and NS (but not in Mozilla). We can't easily do that. | 169 // in both IE and NS (but not in Mozilla). We can't easily do that. |
| 166 frame->page()->goBackOrForward(m_historySteps); | 170 frame->page()->goBackOrForward(m_historySteps); |
| 167 } | 171 } |
| 168 | 172 |
| 169 private: | 173 private: |
| 170 int m_historySteps; | 174 int m_historySteps; |
| 171 }; | 175 }; |
| 172 | 176 |
| 173 class ScheduledFormSubmission : public ScheduledNavigation { | 177 class ScheduledFormSubmission : public ScheduledNavigation { |
| 174 public: | 178 public: |
| 175 ScheduledFormSubmission(PassRefPtr<FormSubmission> submission, bool lockBack
ForwardList, bool duringLoad, bool wasUserGesture) | 179 ScheduledFormSubmission(PassRefPtr<FormSubmission> submission, bool lockBack
ForwardList, bool duringLoad, bool wasUserGesture) |
| 176 : ScheduledNavigation(0, submission->lockHistory(), lockBackForwardList,
duringLoad, true) | 180 : ScheduledNavigation(0, submission->lockHistory(), lockBackForwardList,
duringLoad, true, wasUserGesture) |
| 177 , m_submission(submission) | 181 , m_submission(submission) |
| 178 , m_haveToldClient(false) | 182 , m_haveToldClient(false) |
| 179 , m_wasUserGesture(wasUserGesture) | |
| 180 { | 183 { |
| 181 ASSERT(m_submission->state()); | 184 ASSERT(m_submission->state()); |
| 182 } | 185 } |
| 183 | 186 |
| 184 virtual void fire(Frame* frame) | 187 virtual void fire(Frame* frame) |
| 185 { | 188 { |
| 186 UserGestureIndicator gestureIndicator(m_wasUserGesture ? DefinitelyProce
ssingUserGesture : DefinitelyNotProcessingUserGesture); | 189 UserGestureIndicator gestureIndicator(wasUserGesture() ? DefinitelyProce
ssingUserGesture : DefinitelyNotProcessingUserGesture); |
| 187 | 190 |
| 188 // The submitForm function will find a target frame before using the red
irection timer. | 191 // The submitForm function will find a target frame before using the red
irection timer. |
| 189 // Now that the timer has fired, we need to repeat the security check wh
ich normally is done when | 192 // Now that the timer has fired, we need to repeat the security check wh
ich normally is done when |
| 190 // selecting a target, in case conditions have changed. Other code paths
avoid this by targeting | 193 // selecting a target, in case conditions have changed. Other code paths
avoid this by targeting |
| 191 // without leaving a time window. If we fail the check just silently dro
p the form submission. | 194 // without leaving a time window. If we fail the check just silently dro
p the form submission. |
| 192 if (!m_submission->state()->sourceFrame()->loader()->shouldAllowNavigati
on(frame)) | 195 if (!m_submission->state()->sourceFrame()->loader()->shouldAllowNavigati
on(frame)) |
| 193 return; | 196 return; |
| 194 FrameLoadRequest frameRequest; | 197 FrameLoadRequest frameRequest; |
| 195 m_submission->populateFrameLoadRequest(frameRequest); | 198 m_submission->populateFrameLoadRequest(frameRequest); |
| 196 frame->loader()->loadFrameRequest(frameRequest, lockHistory(), lockBackF
orwardList(), m_submission->event(), m_submission->state(), SendReferrer); | 199 frame->loader()->loadFrameRequest(frameRequest, lockHistory(), lockBackF
orwardList(), m_submission->event(), m_submission->state(), SendReferrer); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 207 virtual void didStopTimer(Frame* frame, bool newLoadInProgress) | 210 virtual void didStopTimer(Frame* frame, bool newLoadInProgress) |
| 208 { | 211 { |
| 209 if (!m_haveToldClient) | 212 if (!m_haveToldClient) |
| 210 return; | 213 return; |
| 211 frame->loader()->clientRedirectCancelledOrFinished(newLoadInProgress); | 214 frame->loader()->clientRedirectCancelledOrFinished(newLoadInProgress); |
| 212 } | 215 } |
| 213 | 216 |
| 214 private: | 217 private: |
| 215 RefPtr<FormSubmission> m_submission; | 218 RefPtr<FormSubmission> m_submission; |
| 216 bool m_haveToldClient; | 219 bool m_haveToldClient; |
| 217 bool m_wasUserGesture; | |
| 218 }; | 220 }; |
| 219 | 221 |
| 220 RedirectScheduler::RedirectScheduler(Frame* frame) | 222 RedirectScheduler::RedirectScheduler(Frame* frame) |
| 221 : m_frame(frame) | 223 : m_frame(frame) |
| 222 , m_timer(this, &RedirectScheduler::timerFired) | 224 , m_timer(this, &RedirectScheduler::timerFired) |
| 223 { | 225 { |
| 224 } | 226 } |
| 225 | 227 |
| 226 RedirectScheduler::~RedirectScheduler() | 228 RedirectScheduler::~RedirectScheduler() |
| 227 { | 229 { |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 if (!m_frame->page()) | 339 if (!m_frame->page()) |
| 338 return; | 340 return; |
| 339 | 341 |
| 340 // Invalid history navigations (such as history.forward() during a new load)
have the side effect of cancelling any scheduled | 342 // Invalid history navigations (such as history.forward() during a new load)
have the side effect of cancelling any scheduled |
| 341 // redirects. We also avoid the possibility of cancelling the current load b
y avoiding the scheduled redirection altogether. | 343 // redirects. We also avoid the possibility of cancelling the current load b
y avoiding the scheduled redirection altogether. |
| 342 HistoryItem* specifiedEntry = m_frame->page()->backForwardList()->itemAtInde
x(steps); | 344 HistoryItem* specifiedEntry = m_frame->page()->backForwardList()->itemAtInde
x(steps); |
| 343 if (!specifiedEntry) { | 345 if (!specifiedEntry) { |
| 344 cancel(); | 346 cancel(); |
| 345 return; | 347 return; |
| 346 } | 348 } |
| 347 | 349 |
| 348 // In all other cases, schedule the history traversal to occur asynchronousl
y. | 350 // In all other cases, schedule the history traversal to occur asynchronousl
y. |
| 349 schedule(adoptPtr(new ScheduledHistoryNavigation(steps))); | 351 schedule(adoptPtr(new ScheduledHistoryNavigation(steps, m_frame->loader()->i
sProcessingUserGesture()))); |
| 350 } | 352 } |
| 351 | 353 |
| 352 void RedirectScheduler::timerFired(Timer<RedirectScheduler>*) | 354 void RedirectScheduler::timerFired(Timer<RedirectScheduler>*) |
| 353 { | 355 { |
| 354 if (!m_frame->page()) | 356 if (!m_frame->page()) |
| 355 return; | 357 return; |
| 356 if (m_frame->page()->defersLoading()) | 358 if (m_frame->page()->defersLoading()) |
| 357 return; | 359 return; |
| 358 | 360 |
| 359 OwnPtr<ScheduledNavigation> redirect(m_redirect.release()); | 361 OwnPtr<ScheduledNavigation> redirect(m_redirect.release()); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 void RedirectScheduler::cancel(bool newLoadInProgress) | 402 void RedirectScheduler::cancel(bool newLoadInProgress) |
| 401 { | 403 { |
| 402 m_timer.stop(); | 404 m_timer.stop(); |
| 403 | 405 |
| 404 OwnPtr<ScheduledNavigation> redirect(m_redirect.release()); | 406 OwnPtr<ScheduledNavigation> redirect(m_redirect.release()); |
| 405 if (redirect) | 407 if (redirect) |
| 406 redirect->didStopTimer(m_frame, newLoadInProgress); | 408 redirect->didStopTimer(m_frame, newLoadInProgress); |
| 407 } | 409 } |
| 408 | 410 |
| 409 } // namespace WebCore | 411 } // namespace WebCore |
| OLD | NEW |