#include "core/loader/ProgressTracker.h"
#include "core/loader/UniqueIdentifier.h"
#include "core/loader/appcache/ApplicationCacheHost.h"
-#include "core/page/BackForwardClient.h"
#include "core/page/Chrome.h"
#include "core/page/ChromeClient.h"
#include "core/page/CreateWindow.h"
bool isBackForwardLoadType(FrameLoadType type)
{
- return type == FrameLoadTypeBackForward;
+ return type == FrameLoadTypeBackForward || type == FrameLoadTypeInitialHistoryLoad;
}
static bool needsHistoryItemRestore(FrameLoadType type)
visitor->trace(m_mixedContentChecker);
visitor->trace(m_progressTracker);
visitor->trace(m_fetchContext);
+ visitor->trace(m_currentItem);
+ visitor->trace(m_provisionalItem);
+ visitor->trace(m_deferredHistoryLoad);
}
void FrameLoader::init()
if (!defers) {
if (m_deferredHistoryLoad.isValid()) {
- loadHistoryItem(m_deferredHistoryLoad.m_item.get(), m_deferredHistoryLoad.m_type, m_deferredHistoryLoad.m_cachePolicy);
+ loadHistoryItem(m_deferredHistoryLoad.m_item.get(), FrameLoadTypeBackForward,
+ m_deferredHistoryLoad.m_type, m_deferredHistoryLoad.m_cachePolicy);
m_deferredHistoryLoad = DeferredHistoryLoad();
}
m_frame->navigationScheduler().startTimer();
void FrameLoader::didExplicitOpen()
{
// Calling document.open counts as committing the first real document load.
- if (!m_stateMachine.committedFirstRealDocumentLoad())
+ if (!m_stateMachine.committedFirstRealDocumentLoad()) {
m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
+ m_progressTracker->progressStarted();
+ }
// Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results
// from a subsequent window.document.open / window.document.write call.
void FrameLoader::clear()
{
- // clear() is called during (Local)Frame finalization and when creating
- // a new Document within it (DocumentLoader::createWriterFor().)
+ // clear() is called during (Local)Frame detachment or when
+ // reusing a FrameLoader by putting a new Document within it
+ // (DocumentLoader::ensureWriter().)
if (m_stateMachine.creatingInitialEmptyDocument())
return;
if (!m_frame->document()->loader())
return;
- // DocumentWriter::replaceDocumentWhileExecutingJavaScriptURL can cause the DocumentLoader to get deref'ed and possible destroyed,
+ // DocumentLoader::replaceDocumentWhileExecutingJavaScriptURL can cause the DocumentLoader to get deref'ed and possible destroyed,
// so protect it with a RefPtr.
RefPtr<DocumentLoader> documentLoader(m_frame->document()->loader());
case FrameLoadTypeStandard:
return StandardCommit;
case FrameLoadTypeInitialInChildFrame:
+ case FrameLoadTypeInitialHistoryLoad:
return InitialCommitInChildFrame;
case FrameLoadTypeBackForward:
return BackForwardCommit;
{
m_frame->document()->setReadyState(Document::Loading);
- if (m_provisionalItem && m_loadType == FrameLoadTypeBackForward)
- m_frame->domWindow()->statePopped(m_provisionalItem->stateObject());
-
if (dispatch)
dispatchDidClearDocumentOfWindowObject();
}
}
- if (m_provisionalItem && m_loadType == FrameLoadTypeBackForward)
+ if (m_provisionalItem && (m_loadType == FrameLoadTypeBackForward || m_loadType == FrameLoadTypeInitialHistoryLoad))
m_frame->document()->setStateForNewFormElements(m_provisionalItem->documentState());
}
void FrameLoader::setReferrerForFrameRequest(ResourceRequest& request, ShouldSendReferrer shouldSendReferrer, Document* originDocument)
{
- if (shouldSendReferrer == NeverSendReferrer) {
- request.clearHTTPReferrer();
+ if (!originDocument)
+ return;
+ // FIXME: This should be an assertion, but there's some plugin code in the chromium repo
+ // that both determines its own referrer and expects to be associated with an originDocument.
+ if (!request.httpReferrer().isEmpty())
+ return;
+ if (shouldSendReferrer == NeverSendReferrer)
return;
- }
// Always use the initiating document to generate the referrer.
- // We need to generateReferrerHeader(), because we might not have enforced ReferrerPolicy or https->http
+ // We need to generateReferrer(), because we haven't enforced ReferrerPolicy or https->http
// referrer suppression yet.
- String argsReferrer(request.httpReferrer());
- if (argsReferrer.isEmpty())
- argsReferrer = originDocument->outgoingReferrer();
- String referrer = SecurityPolicy::generateReferrerHeader(originDocument->referrerPolicy(), request.url(), argsReferrer);
+ Referrer referrer = SecurityPolicy::generateReferrer(originDocument->referrerPolicy(), request.url(), originDocument->outgoingReferrer());
- request.setHTTPReferrer(Referrer(referrer, originDocument->referrerPolicy()));
- RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer);
+ request.setHTTPReferrer(referrer);
+ RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer.referrer);
request.addHTTPOriginIfNeeded(referrerOrigin->toAtomicString());
}
{
if (m_frame->tree().parent() && !m_stateMachine.committedFirstRealDocumentLoad())
return FrameLoadTypeInitialInChildFrame;
- if (!m_frame->tree().parent() && !m_frame->page()->backForward().backForwardListCount())
+ if (!m_frame->tree().parent() && !client()->backForwardLength())
return FrameLoadTypeStandard;
if (m_provisionalDocumentLoader && request.substituteData().failingURL() == m_provisionalDocumentLoader->url() && m_loadType == FrameLoadTypeBackForward)
return FrameLoadTypeBackForward;
if (!request.formState() && request.frameName().isEmpty())
request.setFrameName(m_frame->document()->baseTarget());
-
- setReferrerForFrameRequest(request.resourceRequest(), request.shouldSendReferrer(), request.originDocument());
return true;
}
return;
}
+ setReferrerForFrameRequest(request.resourceRequest(), request.shouldSendReferrer(), request.originDocument());
+
FrameLoadType newLoadType = determineFrameLoadType(request);
NavigationAction action(request.resourceRequest(), newLoadType, request.formState(), request.triggeringEvent());
if (action.resourceRequest().requestContext() == WebURLRequest::RequestContextUnspecified)
ResourceRequest FrameLoader::requestFromHistoryItem(HistoryItem* item, ResourceRequestCachePolicy cachePolicy)
{
RefPtr<FormData> formData = item->formData();
- ResourceRequest request(item->url(), item->referrer());
+ ResourceRequest request(item->url());
+ request.setHTTPReferrer(item->referrer());
request.setCachePolicy(cachePolicy);
if (formData) {
request.setHTTPMethod("POST");
return request;
}
-void FrameLoader::reload(ReloadPolicy reloadPolicy, const KURL& overrideURL, const AtomicString& overrideEncoding, ClientRedirectPolicy clientRedirectPolicy)
+void FrameLoader::reload(ReloadPolicy reloadPolicy, const KURL& overrideURL, ClientRedirectPolicy clientRedirectPolicy)
{
if (!m_currentItem)
return;
request.setSkipServiceWorker(reloadPolicy == EndToEndReload);
FrameLoadType type = reloadPolicy == EndToEndReload ? FrameLoadTypeReloadFromOrigin : FrameLoadTypeReload;
- loadWithNavigationAction(NavigationAction(request, type), type, nullptr, SubstituteData(), CheckContentSecurityPolicy, clientRedirectPolicy, overrideEncoding);
+ loadWithNavigationAction(NavigationAction(request, type), type, nullptr, SubstituteData(), CheckContentSecurityPolicy, clientRedirectPolicy);
}
void FrameLoader::stopAllLoaders()
return m_loadType;
}
+#if defined(ENABLE_LOAD_COMPLETION_HACKS)
// This function is an incomprehensible mess and is only used in checkLoadCompleteForThisFrame.
// If you're thinking of using it elsewhere, stop right now and reconsider your life.
static bool isDocumentDoneLoading(Document* document)
return true;
if (document->loader()->isLoadingMainResource())
return false;
- if (!document->loadEventFinished()) {
- if (document->loader()->isLoading() || document->isDelayingLoadEvent())
- return false;
- }
+ if (!document->loadEventFinished())
+ return false;
if (document->fetcher()->requestCount())
return false;
if (document->processingLoadEvent())
return false;
return true;
}
+#endif
bool FrameLoader::checkLoadCompleteForThisFrame()
{
return true;
if (m_provisionalDocumentLoader || !m_documentLoader)
return false;
+
+#if defined(ENABLE_LOAD_COMPLETION_HACKS)
if (!isDocumentDoneLoading(m_frame->document()) && !m_inStopAllLoaders)
return false;
+#else
+ if (m_inStopAllLoaders)
+ m_frame->document()->suppressLoadEvent();
+ if (!m_frame->document()->loadEventFinished())
+ return false;
+#endif
m_state = FrameStateComplete;
return userAgent;
}
-void FrameLoader::detachFromParent()
+void FrameLoader::detach()
{
#if !ENABLE(OILPAN)
// The caller must protect a reference to m_frame.
ASSERT(m_frame->refCount() > 1);
#endif
-
- InspectorInstrumentation::frameDetachedFromParent(m_frame);
-
if (m_documentLoader)
m_documentLoader->detachFromFrame();
m_documentLoader = nullptr;
- if (!client())
- return;
-
- // FIXME: All this code belongs up in Page.
Frame* parent = m_frame->tree().parent();
- if (parent && parent->isLocalFrame()) {
- m_frame->setView(nullptr);
- // FIXME: Shouldn't need to check if page() is null here.
- if (m_frame->owner() && m_frame->page())
- m_frame->page()->decrementSubframeCount();
- m_frame->willDetachFrameHost();
- detachClient();
+ if (parent && parent->isLocalFrame())
toLocalFrame(parent)->loader().scheduleCheckCompleted();
- } else {
- m_frame->setView(nullptr);
- m_frame->willDetachFrameHost();
- detachClient();
- }
- m_frame->detachFromFrameHost();
-}
-
-void FrameLoader::detachClient()
-{
- ASSERT(client());
-
- // Finish all cleanup work that might require talking to the embedder.
m_progressTracker->dispose();
m_progressTracker.clear();
setOpener(0);
- // Notify ScriptController that the frame is closing, since its cleanup ends up calling
- // back to FrameLoaderClient via WindowProxy.
- m_frame->script().clearForClose();
-
- // client() should never be null because that means we somehow re-entered
- // the frame detach code... but it is sometimes.
- // FIXME: Understand why this is happening so we can document this insanity.
- if (client()) {
- // After this, we must no longer talk to the client since this clears
- // its owning reference back to our owning LocalFrame.
- client()->detachedFromParent();
- m_frame->clearClient();
- }
}
void FrameLoader::receivedMainResourceError(const ResourceError& error)
bool FrameLoader::validateTransitionNavigationMode()
{
- if (frame()->document()->inQuirksMode()) {
- frame()->document()->addConsoleMessage(ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, "Ignoring transition elements due to quirks mode."));
+ if (m_frame->document()->inQuirksMode()) {
+ m_frame->document()->addConsoleMessage(ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, "Ignoring transition elements due to quirks mode."));
return false;
}
bool FrameLoader::dispatchNavigationTransitionData()
{
Vector<Document::TransitionElementData> elementData;
- frame()->document()->getTransitionElementData(elementData);
+ m_frame->document()->getTransitionElementData(elementData);
if (elementData.isEmpty() || !validateTransitionNavigationMode())
return false;
return true;
}
-void FrameLoader::loadWithNavigationAction(const NavigationAction& action, FrameLoadType type, PassRefPtrWillBeRawPtr<FormState> formState, const SubstituteData& substituteData, ContentSecurityPolicyCheck shouldCheckMainWorldContentSecurityPolicy, ClientRedirectPolicy clientRedirect, const AtomicString& overrideEncoding)
+void FrameLoader::loadWithNavigationAction(const NavigationAction& action, FrameLoadType type, PassRefPtrWillBeRawPtr<FormState> formState, const SubstituteData& substituteData, ContentSecurityPolicyCheck shouldCheckMainWorldContentSecurityPolicy, ClientRedirectPolicy clientRedirect)
{
ASSERT(client()->hasWebView());
if (m_frame->document()->pageDismissalEventBeingDispatched() != Document::NoDismissal)
m_policyDocumentLoader->setReplacesCurrentHistoryItem(replacesCurrentHistoryItem);
m_policyDocumentLoader->setIsClientRedirect(clientRedirect == ClientRedirect);
- Frame* parent = m_frame->tree().parent();
- if (parent && parent->isLocalFrame())
- m_policyDocumentLoader->setOverrideEncoding(toLocalFrame(parent)->loader().documentLoader()->overrideEncoding());
- else if (!overrideEncoding.isEmpty())
- m_policyDocumentLoader->setOverrideEncoding(overrideEncoding);
- else if (m_documentLoader)
- m_policyDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding());
-
-
bool isTransitionNavigation = false;
if (RuntimeEnabledFeatures::navigationTransitionsEnabled() && type != FrameLoadTypeReload && type != FrameLoadTypeReloadFromOrigin && type != FrameLoadTypeSame)
isTransitionNavigation = dispatchNavigationTransitionData();
if ((!m_policyDocumentLoader->shouldContinueForNavigationPolicy(request, shouldCheckMainWorldContentSecurityPolicy, isTransitionNavigation) || !shouldClose()) && m_policyDocumentLoader) {
m_policyDocumentLoader->detachFromFrame();
m_policyDocumentLoader = nullptr;
+ if (!m_stateMachine.committedFirstRealDocumentLoad())
+ m_state = FrameStateComplete;
checkCompleted();
return;
}
return toLocalFrame(frame);
}
-void FrameLoader::loadHistoryItem(HistoryItem* item, HistoryLoadType historyLoadType, ResourceRequestCachePolicy cachePolicy)
+void FrameLoader::loadHistoryItem(HistoryItem* item, FrameLoadType frameLoadType, HistoryLoadType historyLoadType, ResourceRequestCachePolicy cachePolicy)
{
RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get());
if (m_frame->page()->defersLoading()) {
m_provisionalItem = item;
if (historyLoadType == HistorySameDocumentLoad) {
- loadInSameDocument(item->url(), item->stateObject(), FrameLoadTypeBackForward, NotClientRedirect);
+ loadInSameDocument(item->url(), item->stateObject(), frameLoadType, NotClientRedirect);
restoreScrollPositionAndViewState();
return;
}
ResourceRequest request = requestFromHistoryItem(item, cachePolicy);
request.setFrameType(m_frame->isMainFrame() ? WebURLRequest::FrameTypeTopLevel : WebURLRequest::FrameTypeNested);
request.setRequestContext(WebURLRequest::RequestContextInternal);
- loadWithNavigationAction(NavigationAction(request, FrameLoadTypeBackForward), FrameLoadTypeBackForward, nullptr, SubstituteData(), CheckContentSecurityPolicy);
+ loadWithNavigationAction(NavigationAction(request, frameLoadType), frameLoadType, nullptr, SubstituteData(), CheckContentSecurityPolicy);
}
void FrameLoader::dispatchDocumentElementAvailable()