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 |