void NavigationScheduler::scheduleLocationChange(SecurityOrigin* securityOrigin, const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList) { if (!shouldScheduleNavigation(url)) 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. URL parsedURL(ParsedURLString, url); if (parsedURL.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(m_frame.document()->url(), parsedURL)) { loader.changeLocation(securityOrigin, m_frame.document()->completeURL(url), referrer, lockHistory, lockBackForwardList); 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.stateMachine()->committedFirstRealDocumentLoad(); schedule(std::make_unique<ScheduledLocationChange>(securityOrigin, url, referrer, lockHistory, lockBackForwardList, duringLoad)); }
void NavigationScheduler::scheduleLocationChange(Document* initiatingDocument, SecurityOrigin* securityOrigin, const URL& url, const String& referrer, LockHistory lockHistory, LockBackForwardList lockBackForwardList) { if (!shouldScheduleNavigation(url)) return; if (lockBackForwardList == LockBackForwardList::No) 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. if (url.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(m_frame.document()->url(), url)) { ResourceRequest resourceRequest(m_frame.document()->completeURL(url), referrer, UseProtocolCachePolicy); ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy = ShouldOpenExternalURLsPolicy::ShouldNotAllow; if (initiatingDocument) shouldOpenExternalURLsPolicy = initiatingDocument->shouldOpenExternalURLsPolicyToPropagate(); FrameLoadRequest frameRequest(securityOrigin, resourceRequest, "_self", lockHistory, lockBackForwardList, MaybeSendReferrer, AllowNavigationToInvalidURL::No, NewFrameOpenerPolicy::Allow, ReplaceDocumentIfJavaScriptURL, shouldOpenExternalURLsPolicy); loader.changeLocation(frameRequest); 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.stateMachine().committedFirstRealDocumentLoad(); schedule(std::make_unique<ScheduledLocationChange>(initiatingDocument, securityOrigin, url, referrer, lockHistory, lockBackForwardList, duringLoad)); }
void NavigationScheduler::scheduleLocationChange(SecurityOrigin* securityOrigin, const String& url, const String& referrer, bool lockBackForwardList) { if (!shouldScheduleNavigation(url)) return; if (url.isEmpty()) return; lockBackForwardList = lockBackForwardList || mustLockBackForwardList(m_frame); // 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. We'll skip this // optimization for cross-origin navigations to minimize the navigator's ability to // execute timing attacks. if (securityOrigin->canAccess(m_frame->document()->securityOrigin())) { KURL parsedURL(ParsedURLString, url); if (parsedURL.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(m_frame->document()->url(), parsedURL)) { FrameLoadRequest request(securityOrigin, ResourceRequest(m_frame->document()->completeURL(url), referrer), "_self"); request.setLockBackForwardList(lockBackForwardList); request.setClientRedirect(ClientRedirect); m_frame->loader().load(request); return; } } schedule(adoptPtr(new ScheduledLocationChange(securityOrigin, url, referrer, lockBackForwardList))); }
void NavigationScheduler::scheduleLocationChange(Document* originDocument, const String& url, bool replacesCurrentItem) { if (!shouldScheduleNavigation(url)) return; replacesCurrentItem = replacesCurrentItem || mustReplaceCurrentItem(m_frame); // 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. We'll skip this // optimization for cross-origin navigations to minimize the navigator's ability to // execute timing attacks. if (originDocument->securityOrigin()->canAccess(m_frame->document()->securityOrigin())) { KURL parsedURL(ParsedURLString, url); if (parsedURL.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(m_frame->document()->url(), parsedURL)) { FrameLoadRequest request(originDocument, m_frame->document()->completeURL(url), "_self"); request.setReplacesCurrentItem(replacesCurrentItem); if (replacesCurrentItem) request.setClientRedirect(ClientRedirect); m_frame->loader().load(request); return; } } schedule(ScheduledLocationChange::create(originDocument, url, replacesCurrentItem)); }
inline bool NavigationScheduler::shouldScheduleNavigation(const URL& url) const { if (!shouldScheduleNavigation()) return false; if (protocolIsJavaScript(url)) return true; return NavigationDisablerForBeforeUnload::isNavigationAllowed(); }
void NavigationScheduler::scheduleRefresh(Document* initiatingDocument) { if (!shouldScheduleNavigation()) return; const URL& url = m_frame.document()->url(); if (url.isEmpty()) return; schedule(std::make_unique<ScheduledRefresh>(initiatingDocument, m_frame.document()->securityOrigin(), url, m_frame.loader().outgoingReferrer())); }
void NavigationScheduler::scheduleRefresh() { if (!shouldScheduleNavigation()) return; const KURL& url = m_frame->loader()->url(); if (url.isEmpty()) return; schedule(adoptPtr(new ScheduledRefresh(m_frame->document()->securityOrigin(), url.string(), m_frame->loader()->outgoingReferrer()))); }
void NavigationScheduler::scheduleRedirect(double delay, const String& url) { if (!shouldScheduleNavigation(url)) return; if (delay < 0 || delay > INT_MAX / 1000) return; if (url.isEmpty()) return; // We want a new back/forward list item if the refresh timeout is > 1 second. if (!m_redirect || delay <= m_redirect->delay()) schedule(std::make_unique<ScheduledRedirect>(delay, m_frame.document()->securityOrigin(), url, true, delay <= 1)); }
void NavigationScheduler::scheduleRedirect(double delay, const String& url) { if (!shouldScheduleNavigation(url)) return; if (delay < 0 || delay > INT_MAX / 1000) return; if (url.isEmpty()) return; // We want a new back/forward list item if the refresh timeout is > 1 second. if (!m_redirect || delay <= m_redirect->delay()) schedule(ScheduledRedirect::create(delay, m_frame->document(), url, delay <= 1)); }
void NavigationScheduler::scheduleRedirect(Document* initiatingDocument, double delay, const URL& url) { if (!shouldScheduleNavigation(url)) return; if (delay < 0 || delay > INT_MAX / 1000) return; if (url.isEmpty()) return; // We want a new back/forward list item if the refresh timeout is > 1 second. if (!m_redirect || delay <= m_redirect->delay()) { LockBackForwardList lockBackForwardList = delay <= 1 ? LockBackForwardList::Yes : LockBackForwardList::No; schedule(std::make_unique<ScheduledRedirect>(initiatingDocument, delay, m_frame.document()->securityOrigin(), url, LockHistory::Yes, lockBackForwardList)); } }
void NavigationScheduler::scheduleHistoryNavigation(int steps) { if (!shouldScheduleNavigation()) return; // Invalid history navigations (such as history.forward() during a new load) have the side effect of cancelling any scheduled // redirects. We also avoid the possibility of cancelling the current load by avoiding the scheduled redirection altogether. BackForwardController& backForward = m_frame.page()->backForward(); if (steps > backForward.forwardCount() || -steps > backForward.backCount()) { cancel(); return; } // In all other cases, schedule the history traversal to occur asynchronously. schedule(std::make_unique<ScheduledHistoryNavigation>(steps)); }
void NavigationScheduler::scheduleSubstituteDataLoad(const URL& baseURL, const SubstituteData& substituteData) { if (shouldScheduleNavigation()) schedule(std::make_unique<ScheduledSubstituteDataLoad>(baseURL, substituteData)); }
inline bool NavigationScheduler::shouldScheduleNavigation(const String& url) const { return shouldScheduleNavigation() && (protocolIsJavaScript(url) || NavigationDisablerForBeforeUnload::isNavigationAllowed()); }
void NavigationScheduler::schedulePageBlock(Document& originDocument) { if (shouldScheduleNavigation()) schedule(std::make_unique<ScheduledPageBlock>(originDocument)); }