93F9B7A00BA6032600854064 /* JSCDATASection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93F9B79E0BA6032600854064 /* JSCDATASection.cpp */; };
93F9B7A10BA6032600854064 /* JSCDATASection.h in Headers */ = {isa = PBXBuildFile; fileRef = 93F9B79F0BA6032600854064 /* JSCDATASection.h */; };
93FDAFCA0B11307400E2746F /* EditorInsertAction.h in Headers */ = {isa = PBXBuildFile; fileRef = 93FDAFC90B11307400E2746F /* EditorInsertAction.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 979F43D31075E44A0000F83B /* RedirectScheduler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 979F43D11075E44A0000F83B /* RedirectScheduler.cpp */; };
+ 979F43D41075E44A0000F83B /* RedirectScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 979F43D21075E44A0000F83B /* RedirectScheduler.h */; };
97DD4D860FDF4D6E00ECF9A4 /* XSSAuditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97DD4D840FDF4D6D00ECF9A4 /* XSSAuditor.cpp */; };
97DD4D870FDF4D6E00ECF9A4 /* XSSAuditor.h in Headers */ = {isa = PBXBuildFile; fileRef = 97DD4D850FDF4D6E00ECF9A4 /* XSSAuditor.h */; };
A17C81220F2A5CF7005DAAEB /* HTMLElementFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A17C81200F2A5CF7005DAAEB /* HTMLElementFactory.cpp */; };
93F9B79E0BA6032600854064 /* JSCDATASection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCDATASection.cpp; sourceTree = "<group>"; };
93F9B79F0BA6032600854064 /* JSCDATASection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCDATASection.h; sourceTree = "<group>"; };
93FDAFC90B11307400E2746F /* EditorInsertAction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = EditorInsertAction.h; sourceTree = "<group>"; };
+ 979F43D11075E44A0000F83B /* RedirectScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RedirectScheduler.cpp; sourceTree = "<group>"; };
+ 979F43D21075E44A0000F83B /* RedirectScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RedirectScheduler.h; sourceTree = "<group>"; };
97DD4D840FDF4D6D00ECF9A4 /* XSSAuditor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XSSAuditor.cpp; sourceTree = "<group>"; };
97DD4D850FDF4D6E00ECF9A4 /* XSSAuditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XSSAuditor.h; sourceTree = "<group>"; };
A17C81200F2A5CF7005DAAEB /* HTMLElementFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLElementFactory.cpp; sourceTree = "<group>"; };
1AC694C60A3B1676003F5049 /* PluginDocument.h */,
1A2A68210B5BEDE70002A480 /* ProgressTracker.cpp */,
1A2A68220B5BEDE70002A480 /* ProgressTracker.h */,
+ 979F43D11075E44A0000F83B /* RedirectScheduler.cpp */,
+ 979F43D21075E44A0000F83B /* RedirectScheduler.h */,
BCB16C150979C3BD00467741 /* Request.cpp */,
BCB16C160979C3BD00467741 /* Request.h */,
93E227DE0AF589AD00D48324 /* ResourceLoader.cpp */,
BCACF3BD1072921A00C0C8A3 /* UserContentURLPattern.h in Headers */,
5DB1BC6A10715A6400EFAA49 /* TransformSource.h in Headers */,
930FC68A1072B9280045293E /* TextRenderingMode.h in Headers */,
+ 979F43D41075E44A0000F83B /* RedirectScheduler.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
7693BAD3106C2DCA007B0823 /* PluginHalter.cpp in Sources */,
BCACF3BC1072921A00C0C8A3 /* UserContentURLPattern.cpp in Sources */,
5DB1BC6B10715A6400EFAA49 /* TransformSourceLibxslt.cpp in Sources */,
+ 979F43D31075E44A0000F83B /* RedirectScheduler.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
#endif
using namespace HTMLNames;
-struct ScheduledRedirection {
- enum Type { redirection, locationChange, historyNavigation, formSubmission };
-
- const Type type;
- const double delay;
- const String url;
- const String referrer;
- const FrameLoadRequest frameRequest;
- const RefPtr<Event> event;
- const RefPtr<FormState> formState;
- const int historySteps;
- const bool lockHistory;
- const bool lockBackForwardList;
- const bool wasUserGesture;
- const bool wasRefresh;
- const bool wasDuringLoad;
- bool toldClient;
-
- ScheduledRedirection(double delay, const String& url, bool lockHistory, bool lockBackForwardList, bool wasUserGesture, bool refresh)
- : type(redirection)
- , delay(delay)
- , url(url)
- , historySteps(0)
- , lockHistory(lockHistory)
- , lockBackForwardList(lockBackForwardList)
- , wasUserGesture(wasUserGesture)
- , wasRefresh(refresh)
- , wasDuringLoad(false)
- , toldClient(false)
- {
- ASSERT(!url.isEmpty());
- }
-
- ScheduledRedirection(const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool wasUserGesture, bool refresh, bool duringLoad)
- : type(locationChange)
- , delay(0)
- , url(url)
- , referrer(referrer)
- , historySteps(0)
- , lockHistory(lockHistory)
- , lockBackForwardList(lockBackForwardList)
- , wasUserGesture(wasUserGesture)
- , wasRefresh(refresh)
- , wasDuringLoad(duringLoad)
- , toldClient(false)
- {
- ASSERT(!url.isEmpty());
- }
-
- explicit ScheduledRedirection(int historyNavigationSteps)
- : type(historyNavigation)
- , delay(0)
- , historySteps(historyNavigationSteps)
- , lockHistory(false)
- , lockBackForwardList(false)
- , wasUserGesture(false)
- , wasRefresh(false)
- , wasDuringLoad(false)
- , toldClient(false)
- {
- }
-
- ScheduledRedirection(const FrameLoadRequest& frameRequest,
- bool lockHistory, bool lockBackForwardList, PassRefPtr<Event> event, PassRefPtr<FormState> formState,
- bool duringLoad)
- : type(formSubmission)
- , delay(0)
- , frameRequest(frameRequest)
- , event(event)
- , formState(formState)
- , historySteps(0)
- , lockHistory(lockHistory)
- , lockBackForwardList(lockBackForwardList)
- , wasUserGesture(false)
- , wasRefresh(false)
- , wasDuringLoad(duringLoad)
- , toldClient(false)
- {
- ASSERT(!frameRequest.isEmpty());
- ASSERT(this->formState);
- }
-};
-
-RedirectScheduler::RedirectScheduler(Frame* frame)
- : m_frame(frame)
- , m_timer(this, &RedirectScheduler::timerFired)
-{
-}
-
-RedirectScheduler::~RedirectScheduler()
-{
-}
-
-bool RedirectScheduler::redirectScheduledDuringLoad()
-{
- return m_scheduledRedirection && m_scheduledRedirection->wasDuringLoad;
-}
-
-void RedirectScheduler::clear()
-{
- m_timer.stop();
- m_scheduledRedirection.clear();
-}
-
#if ENABLE(XHTMLMP)
static const char defaultAcceptHeader[] = "application/xml,application/vnd.wap.xhtml+xml,application/xhtml+xml;profile='http://www.wapforum.org/xhtml',text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
#else
return m_frame->document()->completeURL(url);
}
-void RedirectScheduler::scheduleRedirect(double delay, const String& url)
-{
- if (delay < 0 || delay > INT_MAX / 1000)
- return;
-
- if (!m_frame->page())
- return;
-
- if (url.isEmpty())
- return;
-
- // We want a new history item if the refresh timeout is > 1 second.
- if (!m_scheduledRedirection || delay <= m_scheduledRedirection->delay)
- schedule(new ScheduledRedirection(delay, url, true, delay <= 1, false, false));
-}
-
-bool RedirectScheduler::mustLockBackForwardList(Frame* targetFrame)
-{
- // Navigation of a subframe during loading of an ancestor frame does not create a new back/forward item.
- // The definition of "during load" is any time before all handlers for the load event have been run.
- // See https://bugs.webkit.org/show_bug.cgi?id=14957 for the original motivation for this.
-
- for (Frame* ancestor = targetFrame->tree()->parent(); ancestor; ancestor = ancestor->tree()->parent()) {
- Document* document = ancestor->document();
- if (!ancestor->loader()->isComplete() || document && document->processingLoadEvent())
- return true;
- }
- return false;
-}
-
-void RedirectScheduler::scheduleLocationChange(const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool wasUserGesture)
-{
- if (!m_frame->page())
- return;
-
- if (url.isEmpty())
- return;
-
- lockBackForwardList = lockBackForwardList || mustLockBackForwardList(m_frame);
-
- FrameLoader* loader = m_frame->loader();
-
- // If the URL we're going to navigate to is the same as the current one, except for the
- // fragment part, we don't need to schedule the location change.
- KURL parsedURL(ParsedURLString, url);
- if (parsedURL.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(loader->url(), parsedURL)) {
- loader->changeLocation(loader->completeURL(url), referrer, lockHistory, lockBackForwardList, wasUserGesture);
- return;
- }
-
- // Handle a location change of a page with no document as a special case.
- // This may happen when a frame changes the location of another frame.
- bool duringLoad = !loader->committedFirstRealDocumentLoad();
-
- schedule(new ScheduledRedirection(url, referrer, lockHistory, lockBackForwardList, wasUserGesture, false, duringLoad));
-}
-
-void RedirectScheduler::scheduleFormSubmission(const FrameLoadRequest& frameRequest,
- bool lockHistory, PassRefPtr<Event> event, PassRefPtr<FormState> formState)
-{
- ASSERT(m_frame->page());
- ASSERT(!frameRequest.isEmpty());
-
- // FIXME: Do we need special handling for form submissions where the URL is the same
- // as the current one except for the fragment part? See scheduleLocationChange above.
-
- // Handle a location change of a page with no document as a special case.
- // 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));
-}
-
-void RedirectScheduler::scheduleRefresh(bool wasUserGesture)
-{
- if (!m_frame->page())
- return;
-
- const KURL& url = m_frame->loader()->url();
-
- if (url.isEmpty())
- return;
-
- schedule(new ScheduledRedirection(url.string(), m_frame->loader()->outgoingReferrer(), true, true, wasUserGesture, true, false));
-}
-
-bool RedirectScheduler::locationChangePending()
-{
- if (!m_scheduledRedirection)
- return false;
-
- switch (m_scheduledRedirection->type) {
- case ScheduledRedirection::redirection:
- return false;
- case ScheduledRedirection::historyNavigation:
- case ScheduledRedirection::locationChange:
- case ScheduledRedirection::formSubmission:
- return true;
- }
- ASSERT_NOT_REACHED();
- return false;
-}
-
-void RedirectScheduler::scheduleHistoryNavigation(int steps)
-{
- if (!m_frame->page())
- return;
-
- schedule(new ScheduledRedirection(steps));
-}
-
void FrameLoader::goBackOrForward(int distance)
{
if (distance == 0)
page->goToItem(item, FrameLoadTypeIndexedBackForward);
}
-void RedirectScheduler::timerFired(Timer<RedirectScheduler>*)
-{
- ASSERT(m_frame->page());
-
- if (m_frame->page()->defersLoading())
- return;
-
- OwnPtr<ScheduledRedirection> redirection(m_scheduledRedirection.release());
- FrameLoader* loader = m_frame->loader();
-
- switch (redirection->type) {
- case ScheduledRedirection::redirection:
- case ScheduledRedirection::locationChange:
- loader->changeLocation(KURL(ParsedURLString, redirection->url), redirection->referrer,
- redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture, redirection->wasRefresh);
- return;
- case ScheduledRedirection::historyNavigation:
- if (redirection->historySteps == 0) {
- // Special case for go(0) from a frame -> reload only the frame
- loader->urlSelected(loader->url(), "", 0, redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture);
- return;
- }
- // go(i!=0) from a frame navigates into the history of the frame only,
- // in both IE and NS (but not in Mozilla). We can't easily do that.
- if (loader->canGoBackOrForward(redirection->historySteps))
- loader->goBackOrForward(redirection->historySteps);
- return;
- case ScheduledRedirection::formSubmission:
- // 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
- // selecting a target, in case conditions have changed. Other code paths avoid this by targeting
- // without leaving a time window. If we fail the check just silently drop the form submission.
- if (!redirection->formState->sourceFrame()->loader()->shouldAllowNavigation(m_frame))
- return;
- loader->loadFrameRequest(redirection->frameRequest, redirection->lockHistory, redirection->lockBackForwardList,
- redirection->event, redirection->formState);
- return;
- }
-
- ASSERT_NOT_REACHED();
-}
-
void FrameLoader::loadURLIntoChildFrame(const KURL& url, const String& referer, Frame* childFrame)
{
ASSERT(childFrame);
return m_isComplete;
}
-void RedirectScheduler::schedule(PassOwnPtr<ScheduledRedirection> redirection)
-{
- ASSERT(m_frame->page());
- FrameLoader* loader = m_frame->loader();
-
- // If a redirect was scheduled during a load, then stop the current load.
- // Otherwise when the current load transitions from a provisional to a
- // committed state, pending redirects may be cancelled.
- if (redirection->wasDuringLoad) {
- if (DocumentLoader* provisionalDocumentLoader = loader->provisionalDocumentLoader())
- provisionalDocumentLoader->stopLoading();
- loader->stopLoading(UnloadEventPolicyUnloadAndPageHide);
- }
-
- cancel();
- m_scheduledRedirection = redirection;
- if (!loader->isComplete() && m_scheduledRedirection->type != ScheduledRedirection::redirection)
- loader->completed();
- startTimer();
-}
-
-void RedirectScheduler::startTimer()
-{
- if (!m_scheduledRedirection)
- return;
-
- ASSERT(m_frame->page());
-
- FrameLoader* loader = m_frame->loader();
-
- if (m_timer.isActive())
- return;
-
- if (m_scheduledRedirection->type == ScheduledRedirection::redirection && !loader->allAncestorsAreComplete())
- return;
-
- m_timer.startOneShot(m_scheduledRedirection->delay);
-
- switch (m_scheduledRedirection->type) {
- case ScheduledRedirection::locationChange:
- case ScheduledRedirection::redirection:
- if (m_scheduledRedirection->toldClient)
- return;
- m_scheduledRedirection->toldClient = true;
- loader->clientRedirected(KURL(ParsedURLString, m_scheduledRedirection->url),
- m_scheduledRedirection->delay,
- currentTime() + m_timer.nextFireInterval(),
- m_scheduledRedirection->lockBackForwardList);
- return;
- case ScheduledRedirection::formSubmission:
- // FIXME: It would make sense to report form submissions as client redirects too.
- // But we didn't do that in the past when form submission used a separate delay
- // mechanism, so doing it will be a behavior change.
- return;
- case ScheduledRedirection::historyNavigation:
- // Don't report history navigations.
- return;
- }
- ASSERT_NOT_REACHED();
-}
-
-void RedirectScheduler::cancel(bool newLoadInProgress)
-{
- m_timer.stop();
-
- OwnPtr<ScheduledRedirection> redirection(m_scheduledRedirection.release());
- if (redirection && redirection->toldClient)
- m_frame->loader()->clientRedirectCancelledOrFinished(newLoadInProgress);
-}
-
void FrameLoader::completed()
{
RefPtr<Frame> protect(m_frame);