#include "config.h"
#include "core/loader/FrameLoader.h"
-#include "bindings/v8/DOMWrapperWorld.h"
-#include "bindings/v8/ScriptController.h"
-#include "bindings/v8/SerializedScriptValue.h"
+#include "bindings/core/v8/DOMWrapperWorld.h"
+#include "bindings/core/v8/ScriptController.h"
+#include "bindings/core/v8/SerializedScriptValue.h"
#include "core/HTMLNames.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/PinchViewport.h"
+#include "core/frame/Settings.h"
#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/html/HTMLFormElement.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html/parser/HTMLParserIdioms.h"
+#include "core/inspector/ConsoleMessage.h"
#include "core/inspector/InspectorController.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/loader/DocumentLoadTiming.h"
#include "core/page/EventHandler.h"
#include "core/page/FrameTree.h"
#include "core/page/Page.h"
-#include "core/frame/Settings.h"
#include "core/page/WindowFeatures.h"
#include "core/page/scrolling/ScrollingCoordinator.h"
#include "core/xml/parser/XMLDocumentParser.h"
#include "platform/Logging.h"
#include "platform/UserGestureIndicator.h"
#include "platform/geometry/FloatRect.h"
-#include "platform/network/ContentSecurityPolicyResponseHeaders.h"
#include "platform/network/HTTPParsers.h"
#include "platform/network/ResourceRequest.h"
#include "platform/scroll/ScrollAnimator.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "platform/weborigin/SecurityPolicy.h"
+#include "public/platform/WebURLRequest.h"
#include "wtf/TemporaryChange.h"
#include "wtf/text/CString.h"
#include "wtf/text/WTFString.h"
-namespace WebCore {
+using blink::WebURLRequest;
+
+namespace blink {
using namespace HTMLNames;
, m_loadType(FrameLoadTypeStandard)
, m_fetchContext(FrameFetchContext::create(frame))
, m_inStopAllLoaders(false)
- , m_isComplete(false)
, m_checkTimer(this, &FrameLoader::checkTimerFired)
- , m_shouldCallCheckCompleted(false)
, m_didAccessInitialDocument(false)
, m_didAccessInitialDocumentTimer(this, &FrameLoader::didAccessInitialDocumentTimerFired)
, m_forcedSandboxFlags(SandboxNone)
- , m_willDetachClient(false)
{
}
FrameLoader::~FrameLoader()
{
+ // Verify that this FrameLoader has been detached.
+ ASSERT(!m_progressTracker);
+}
+
+void FrameLoader::trace(Visitor* visitor)
+{
+ visitor->trace(m_frame);
+ visitor->trace(m_mixedContentChecker);
+ visitor->trace(m_progressTracker);
+ visitor->trace(m_fetchContext);
}
void FrameLoader::init()
{
- m_provisionalDocumentLoader = client()->createDocumentLoader(m_frame, ResourceRequest(KURL(ParsedURLString, emptyString())), SubstituteData());
+ ResourceRequest initialRequest(KURL(ParsedURLString, emptyString()));
+ initialRequest.setRequestContext(WebURLRequest::RequestContextInternal);
+ initialRequest.setFrameType(m_frame->isMainFrame() ? WebURLRequest::FrameTypeTopLevel : WebURLRequest::FrameTypeNested);
+ m_provisionalDocumentLoader = client()->createDocumentLoader(m_frame, initialRequest, SubstituteData());
m_provisionalDocumentLoader->startLoadingMainResource();
m_frame->document()->cancelParsing();
m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument);
m_deferredHistoryLoad = DeferredHistoryLoad();
}
m_frame->navigationScheduler().startTimer();
- startCheckCompleteTimer();
+ scheduleCheckCompleted();
}
}
void FrameLoader::stopLoading()
{
- m_isComplete = true; // to avoid calling completed() in finishedParsing()
-
if (m_frame->document() && m_frame->document()->parsing()) {
finishedParsing();
m_frame->document()->setParsing(false);
else
m_currentItem->setPinchViewportScrollPoint(FloatPoint(-1, -1));
- if (m_frame->isMainFrame() && !m_frame->page()->inspectorController().deviceEmulationEnabled())
+ if (m_frame->isMainFrame())
m_currentItem->setPageScaleFactor(m_frame->page()->pageScaleFactor());
client()->didUpdateCurrentHistoryItem();
void FrameLoader::didExplicitOpen()
{
- m_isComplete = false;
-
// Calling document.open counts as committing the first real document load.
if (!m_stateMachine.committedFirstRealDocumentLoad())
m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
void FrameLoader::clear()
{
+ // clear() is called during (Local)Frame finalization and when creating
+ // a new Document within it (DocumentLoader::createWriterFor().)
if (m_stateMachine.creatingInitialEmptyDocument())
return;
m_frame->document()->cancelParsing();
m_frame->document()->prepareForDestruction();
m_frame->document()->removeFocusedElementOfSubtree(m_frame->document());
-
m_frame->selection().prepareForDestruction();
m_frame->eventHandler().clear();
if (m_frame->view())
m_frame->script().enableEval();
- m_frame->navigationScheduler().clear();
+ m_frame->navigationScheduler().cancel();
m_checkTimer.stop();
- m_shouldCallCheckCompleted = false;
if (m_stateMachine.isDisplayingInitialEmptyDocument())
m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
}
+// This is only called by ScriptController::executeScriptIfJavaScriptURL
+// and always contains the result of evaluating a javascript: url.
+// This is the <iframe src="javascript:'html'"> case.
+void FrameLoader::replaceDocumentWhileExecutingJavaScriptURL(const String& source, Document* ownerDocument)
+{
+ if (!m_frame->document()->loader())
+ return;
+
+ // DocumentWriter::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());
+
+ UseCounter::count(*m_frame->document(), UseCounter::ReplaceDocumentViaJavaScriptURL);
+
+ // Prepare a DocumentInit before clearing the frame, because it may need to
+ // inherit an aliased security context.
+ DocumentInit init(m_frame->document()->url(), m_frame);
+ init.withNewRegistrationContext();
+
+ stopAllLoaders();
+ clear();
+
+ // clear() potentially detaches the frame from the document. The
+ // loading cannot continue in that case.
+ if (!m_frame->page())
+ return;
+
+ documentLoader->replaceDocumentWhileExecutingJavaScriptURL(init, source, ownerDocument);
+}
+
void FrameLoader::setHistoryItemStateForCommit(HistoryCommitType historyCommitType, bool isPushOrReplaceState, PassRefPtr<SerializedScriptValue> stateObject)
{
if (m_provisionalItem)
dispatchDidClearDocumentOfWindowObject();
}
-static void didFailContentSecurityPolicyCheck(FrameLoader* loader)
-{
- // load event and stopAllLoaders can detach the LocalFrame, so protect it.
- RefPtr<LocalFrame> frame(loader->frame());
-
- // Move the page to a unique origin, and cancel the load.
- frame->document()->enforceSandboxFlags(SandboxOrigin);
- loader->stopAllLoaders();
-
- // Fire a load event, as timing attacks would otherwise reveal that the
- // frame was blocked. This way, it looks like every other cross-origin
- // page.
- if (FrameOwner* frameOwner = frame->owner())
- frameOwner->dispatchLoad();
-}
-
void FrameLoader::didBeginDocument(bool dispatch)
{
- m_isComplete = false;
m_frame->document()->setReadyState(Document::Loading);
if (m_provisionalItem && m_loadType == FrameLoadTypeBackForward)
if (dispatch)
dispatchDidClearDocumentOfWindowObject();
- m_frame->document()->initContentSecurityPolicy(m_documentLoader ? ContentSecurityPolicyResponseHeaders(m_documentLoader->response()) : ContentSecurityPolicyResponseHeaders());
-
- if (!m_frame->document()->contentSecurityPolicy()->allowAncestors(m_frame)) {
- didFailContentSecurityPolicyCheck(this);
- return;
- }
+ m_frame->document()->initContentSecurityPolicy(m_documentLoader ? m_documentLoader->releaseContentSecurityPolicy() : ContentSecurityPolicy::create());
Settings* settings = m_frame->document()->settings();
if (settings) {
// This can be called from the LocalFrame's destructor, in which case we shouldn't protect ourselves
// because doing so will cause us to re-enter the destructor when protector goes out of scope.
// Null-checking the FrameView indicates whether or not we're in the destructor.
- RefPtr<LocalFrame> protector = m_frame->view() ? m_frame : 0;
+ RefPtrWillBeRawPtr<LocalFrame> protect(m_frame->view() ? m_frame.get() : nullptr);
if (client())
client()->dispatchDidFinishDocumentLoad();
bool FrameLoader::allChildrenAreComplete() const
{
for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
- if (child->isLocalFrame() && !toLocalFrame(child)->loader().m_isComplete)
+ if (!child->isLocalFrame())
+ continue;
+ LocalFrame* frame = toLocalFrame(child);
+ if (!frame->document()->isLoadCompleted() || frame->loader().m_provisionalDocumentLoader)
return false;
}
return true;
void FrameLoader::checkCompleted()
{
- RefPtr<LocalFrame> protect(m_frame);
- m_shouldCallCheckCompleted = false;
+ RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get());
if (m_frame->view())
m_frame->view()->handleLoadCompleted();
- // Have we completed before?
- if (m_isComplete)
+ if (m_frame->document()->isLoadCompleted() && m_stateMachine.committedFirstRealDocumentLoad())
return;
// Are we still parsing?
return;
// OK, completed.
- m_isComplete = true;
m_frame->document()->setReadyState(Document::Complete);
if (m_frame->document()->loadEventStillNeeded())
m_frame->document()->implicitClose();
void FrameLoader::checkTimerFired(Timer<FrameLoader>*)
{
- RefPtr<LocalFrame> protect(m_frame);
-
if (Page* page = m_frame->page()) {
if (page->defersLoading())
return;
}
- if (m_shouldCallCheckCompleted)
- checkCompleted();
-}
-
-void FrameLoader::startCheckCompleteTimer()
-{
- if (!m_shouldCallCheckCompleted)
- return;
- if (m_checkTimer.isActive())
- return;
- m_checkTimer.startOneShot(0, FROM_HERE);
+ checkCompleted();
}
void FrameLoader::scheduleCheckCompleted()
{
- m_shouldCallCheckCompleted = true;
- startCheckCompleteTimer();
+ if (!m_checkTimer.isActive())
+ m_checkTimer.startOneShot(0, FROM_HERE);
}
-LocalFrame* FrameLoader::opener()
+Frame* FrameLoader::opener()
{
- // FIXME: Temporary hack to stage converting locations that really should be Frame.
- return client() ? toLocalFrame(client()->opener()) : 0;
+ return client() ? client()->opener() : 0;
}
void FrameLoader::setOpener(LocalFrame* opener)
bool FrameLoader::allowPlugins(ReasonForCallingAllowPlugins reason)
{
+ // With Oilpan, a FrameLoader might be accessed after the
+ // FrameHost has been detached. FrameClient will not be
+ // accessible, so bail early.
+ if (!client())
+ return false;
Settings* settings = m_frame->settings();
bool allowed = client()->allowPlugins(settings && settings->pluginsEnabled());
if (!allowed && reason == AboutToInstantiatePlugin)
m_frame->view()->setWasScrolledByUser(false);
- // It's important to model this as a load that starts and immediately finishes.
- // Otherwise, the parent frame may think we never finished loading.
- started();
-
// We need to scroll to the fragment whether or not a hash change occurred, since
// the user might have scrolled since the previous navigation.
scrollToFragmentWithParentBoundary(url);
-
- m_isComplete = false;
checkCompleted();
m_frame->domWindow()->statePopped(stateObject ? stateObject : SerializedScriptValue::nullValue());
void FrameLoader::completed()
{
- RefPtr<LocalFrame> protect(m_frame);
+ RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get());
for (Frame* descendant = m_frame->tree().traverseNext(m_frame); descendant; descendant = descendant->tree().traverseNext(m_frame)) {
if (descendant->isLocalFrame())
m_frame->view()->maintainScrollPositionAtAnchor(0);
}
-void FrameLoader::started()
-{
- for (Frame* frame = m_frame; frame; frame = frame->tree().parent()) {
- if (frame->isLocalFrame())
- toLocalFrame(frame)->loader().m_isComplete = false;
- }
-}
-
void FrameLoader::setReferrerForFrameRequest(ResourceRequest& request, ShouldSendReferrer shouldSendReferrer, Document* originDocument)
{
if (shouldSendReferrer == NeverSendReferrer) {
request.setHTTPReferrer(Referrer(referrer, originDocument->referrerPolicy()));
RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer);
- addHTTPOriginIfNeeded(request, referrerOrigin->toAtomicString());
+ request.addHTTPOriginIfNeeded(referrerOrigin->toAtomicString());
}
bool FrameLoader::isScriptTriggeredFormSubmissionInChildFrame(const FrameLoadRequest& request) const
bool FrameLoader::prepareRequestForThisFrame(FrameLoadRequest& request)
{
- // If no origin Document* was specified, skip security checks and assume the caller has fully initialized the FrameLoadRequest.
+ request.resourceRequest().setFrameType(m_frame->isMainFrame() ? WebURLRequest::FrameTypeTopLevel : WebURLRequest::FrameTypeNested);
+
+ // If no origin Document* was specified, skip remaining security checks and assume the caller has fully initialized the FrameLoadRequest.
if (!request.originDocument())
return true;
return request.formState() && action.shouldOpenInNewWindow();
}
+static WebURLRequest::RequestContext determineRequestContextFromNavigationType(const NavigationType navigationType)
+{
+ switch (navigationType) {
+ case NavigationTypeLinkClicked:
+ return WebURLRequest::RequestContextHyperlink;
+
+ case NavigationTypeOther:
+ return WebURLRequest::RequestContextLocation;
+
+ case NavigationTypeFormResubmitted:
+ case NavigationTypeFormSubmitted:
+ return WebURLRequest::RequestContextForm;
+
+ case NavigationTypeBackForward:
+ case NavigationTypeReload:
+ return WebURLRequest::RequestContextInternal;
+ }
+ ASSERT_NOT_REACHED();
+ return WebURLRequest::RequestContextHyperlink;
+}
+
void FrameLoader::load(const FrameLoadRequest& passedRequest)
{
ASSERT(m_frame->document());
- RefPtr<LocalFrame> protect(m_frame);
+ RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get());
if (m_inStopAllLoaders)
return;
if (!prepareRequestForThisFrame(request))
return;
- RefPtr<LocalFrame> targetFrame = request.formState() ? 0 : findFrameForNavigation(AtomicString(request.frameName()), request.formState() ? request.formState()->sourceDocument() : m_frame->document());
- if (targetFrame && targetFrame != m_frame) {
+ RefPtrWillBeRawPtr<LocalFrame> targetFrame = request.formState() ? 0 : findFrameForNavigation(AtomicString(request.frameName()), request.formState() ? request.formState()->sourceDocument() : m_frame->document());
+ if (targetFrame && targetFrame.get() != m_frame) {
request.setFrameName("_self");
targetFrame->loader().load(request);
if (Page* page = targetFrame->page())
FrameLoadType newLoadType = determineFrameLoadType(request);
NavigationAction action(request.resourceRequest(), newLoadType, request.formState(), request.triggeringEvent());
+ if (action.resourceRequest().requestContext() == WebURLRequest::RequestContextUnspecified)
+ action.mutableResourceRequest().setRequestContext(determineRequestContextFromNavigationType(action.type()));
if (shouldOpenInNewWindow(targetFrame.get(), request, action)) {
if (action.policy() == NavigationPolicyDownload)
client()->loadURLExternally(action.resourceRequest(), NavigationPolicyDownload);
return;
}
bool sameURL = url == m_documentLoader->urlForHistory();
- loadWithNavigationAction(action, newLoadType, request.formState(), request.substituteData(), request.clientRedirect());
+ loadWithNavigationAction(action, newLoadType, request.formState(), request.substituteData(), request.shouldCheckMainWorldContentSecurityPolicy(), request.clientRedirect());
// Example of this case are sites that reload the same URL with a different cookie
// driving the generated content, or a master frame with links that drive a target
// frame, where the user has clicked on the same link repeatedly.
if (!frame)
return;
- frame->document()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Not allowed to load local resource: " + url);
+ frame->document()->addConsoleMessage(ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel, "Not allowed to load local resource: " + url));
}
-static ResourceRequest requestFromHistoryItem(HistoryItem* item, ResourceRequestCachePolicy cachePolicy)
+// static
+ResourceRequest FrameLoader::requestFromHistoryItem(HistoryItem* item, ResourceRequestCachePolicy cachePolicy)
{
RefPtr<FormData> formData = item->formData();
ResourceRequest request(item->url(), item->referrer());
request.setHTTPBody(formData);
request.setHTTPContentType(item->formContentType());
RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString(item->referrer().referrer);
- FrameLoader::addHTTPOriginIfNeeded(request, securityOrigin->toAtomicString());
+ request.addHTTPOriginIfNeeded(securityOrigin->toAtomicString());
}
return request;
}
-void FrameLoader::reload(ReloadPolicy reloadPolicy, const KURL& overrideURL, const AtomicString& overrideEncoding)
+void FrameLoader::reload(ReloadPolicy reloadPolicy, const KURL& overrideURL, const AtomicString& overrideEncoding, ClientRedirectPolicy clientRedirectPolicy)
{
if (!m_currentItem)
return;
ResourceRequestCachePolicy cachePolicy = reloadPolicy == EndToEndReload ? ReloadBypassingCache : ReloadIgnoringCacheData;
ResourceRequest request = requestFromHistoryItem(m_currentItem.get(), cachePolicy);
+ request.setFrameType(m_frame->isMainFrame() ? WebURLRequest::FrameTypeTopLevel : WebURLRequest::FrameTypeNested);
+ request.setRequestContext(WebURLRequest::RequestContextInternal);
+
+ // ClientRedirectPolicy is an indication that this load was triggered by
+ // some direct interaction with the page. If this reload is not a client
+ // redirect, we should reuse the referrer from the original load of the
+ // current document. If this reload is a client redirect (e.g., location.reload()),
+ // it was initiated by something in the current document and should
+ // therefore show the current document's url as the referrer.
+ if (clientRedirectPolicy == ClientRedirect)
+ request.setHTTPReferrer(Referrer(m_frame->document()->outgoingReferrer(), m_frame->document()->referrerPolicy()));
+
if (!overrideURL.isEmpty()) {
request.setURL(overrideURL);
request.clearHTTPReferrer();
}
+ request.setSkipServiceWorker(reloadPolicy == EndToEndReload);
FrameLoadType type = reloadPolicy == EndToEndReload ? FrameLoadTypeReloadFromOrigin : FrameLoadTypeReload;
- loadWithNavigationAction(NavigationAction(request, type), type, nullptr, SubstituteData(), NotClientRedirect, overrideEncoding);
+ loadWithNavigationAction(NavigationAction(request, type), type, nullptr, SubstituteData(), CheckContentSecurityPolicy, clientRedirectPolicy, overrideEncoding);
}
void FrameLoader::stopAllLoaders()
// Calling stopLoading() on the provisional document loader can blow away
// the frame from underneath.
- RefPtr<LocalFrame> protect(m_frame);
+ RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get());
m_inStopAllLoaders = true;
- for (RefPtr<Frame> child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
+ for (RefPtrWillBeRawPtr<Frame> child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
if (child->isLocalFrame())
toLocalFrame(child.get())->loader().stopAllLoaders();
}
void FrameLoader::didAccessInitialDocumentTimerFired(Timer<FrameLoader>*)
{
- client()->didAccessInitialDocument();
+ if (client())
+ client()->didAccessInitialDocument();
}
void FrameLoader::notifyIfInitialDocumentAccessed()
}
}
-bool FrameLoader::isLoading() const
-{
- if (m_provisionalDocumentLoader)
- return true;
- return m_documentLoader && m_documentLoader->isLoading();
-}
-
void FrameLoader::commitProvisionalLoad()
{
ASSERT(client()->hasWebView());
ASSERT(m_state == FrameStateProvisional);
RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
- RefPtr<LocalFrame> protect(m_frame);
+ RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get());
// Check if the destination page is allowed to access the previous page's timing information.
if (m_frame->document()) {
client()->dispatchWillClose();
closeURL();
}
- detachChildren();
+ m_frame->detachChildren();
if (pdl != m_provisionalDocumentLoader)
return;
if (m_documentLoader)
window->setStatus(String());
window->setDefaultStatus(String());
}
- started();
}
bool FrameLoader::isLoadingMainFrame() const
bool FrameLoader::checkLoadCompleteForThisFrame()
{
ASSERT(client()->hasWebView());
- RefPtr<LocalFrame> protect(m_frame);
+ RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get());
bool allChildrenAreDoneLoading = true;
- for (RefPtr<Frame> child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
+ for (RefPtrWillBeRawPtr<Frame> child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
if (child->isLocalFrame())
allChildrenAreDoneLoading &= toLocalFrame(child.get())->loader().checkLoadCompleteForThisFrame();
}
m_provisionalDocumentLoader = nullptr;
m_progressTracker->progressCompleted();
m_state = FrameStateComplete;
+ checkCompleted();
return true;
}
}
}
-void FrameLoader::detachChildren()
-{
- typedef Vector<RefPtr<LocalFrame> > FrameVector;
- FrameVector childrenToDetach;
- childrenToDetach.reserveCapacity(m_frame->tree().childCount());
- for (Frame* child = m_frame->tree().lastChild(); child; child = child->tree().previousSibling()) {
- if (child->isLocalFrame())
- childrenToDetach.append(toLocalFrame(child));
- }
- FrameVector::iterator end = childrenToDetach.end();
- for (FrameVector::iterator it = childrenToDetach.begin(); it != end; ++it)
- (*it)->loader().detachFromParent();
-}
-
// Called every time a resource is completely loaded or an error is received.
void FrameLoader::checkLoadComplete()
{
return userAgent;
}
-void FrameLoader::frameDetached()
-{
- // stopAllLoaders can detach the LocalFrame, so protect it.
- RefPtr<LocalFrame> protect(m_frame);
- stopAllLoaders();
- detachFromParent();
-}
-
void FrameLoader::detachFromParent()
{
- // Temporary explosions. We should never re-enter this code when this condition is true.
- RELEASE_ASSERT(!m_willDetachClient);
-
- // stopAllLoaders can detach the LocalFrame, so protect it.
- RefPtr<LocalFrame> protect(m_frame);
-
- closeURL();
- detachChildren();
- // stopAllLoaders() needs to be called after detachChildren(), because detachedChildren()
- // will trigger the unload event handlers of any child frames, and those event
- // handlers might start a new subresource load in this frame.
- stopAllLoaders();
+#if !ENABLE(OILPAN)
+ // The caller must protect a reference to m_frame.
+ ASSERT(m_frame->refCount() > 1);
+#endif
InspectorInstrumentation::frameDetachedFromParent(m_frame);
if (!client())
return;
- TemporaryChange<bool> willDetachClient(m_willDetachClient, true);
-
// FIXME: All this code belongs up in Page.
Frame* parent = m_frame->tree().parent();
if (parent && parent->isLocalFrame()) {
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 V8WindowShell.
+ // back to FrameLoaderClient via WindowProxy.
m_frame->script().clearForClose();
// client() should never be null because that means we somehow re-entered
}
}
-void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, const AtomicString& origin)
-{
- if (!request.httpOrigin().isEmpty())
- return; // Request already has an Origin header.
-
- // Don't send an Origin header for GET or HEAD to avoid privacy issues.
- // For example, if an intranet page has a hyperlink to an external web
- // site, we don't want to include the Origin of the request because it
- // will leak the internal host name. Similar privacy concerns have lead
- // to the widespread suppression of the Referer header at the network
- // layer.
- if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD")
- return;
-
- // For non-GET and non-HEAD methods, always send an Origin header so the
- // server knows we support this feature.
-
- if (origin.isEmpty()) {
- // If we don't know what origin header to attach, we attach the value
- // for an empty origin.
- request.setHTTPOrigin(SecurityOrigin::createUnique()->toAtomicString());
- return;
- }
-
- request.setHTTPOrigin(origin);
-}
-
void FrameLoader::receivedMainResourceError(const ResourceError& error)
{
// Retain because the stop may release the last reference to it.
- RefPtr<LocalFrame> protect(m_frame);
+ RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get());
if (m_frame->document()->parser())
m_frame->document()->parser()->stopParsing();
return;
// Leaking scroll position to a cross-origin ancestor would permit the so-called "framesniffing" attack.
- RefPtr<LocalFrame> boundaryFrame(url.hasFragmentIdentifier() ? m_frame->document()->findUnsafeParentScrollPropagationBoundary() : 0);
+ RefPtrWillBeRawPtr<LocalFrame> boundaryFrame = url.hasFragmentIdentifier() ? m_frame->document()->findUnsafeParentScrollPropagationBoundary() : 0;
if (boundaryFrame)
boundaryFrame->view()->setSafeToPropagateScrollToParent(false);
return true;
// Store all references to each subframe in advance since beforeunload's event handler may modify frame
- Vector<RefPtr<LocalFrame> > targetFrames;
+ WillBeHeapVector<RefPtrWillBeMember<LocalFrame> > targetFrames;
targetFrames.append(m_frame);
for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree().traverseNext(m_frame)) {
// FIXME: There is not yet any way to dispatch events to out-of-process frames.
return shouldClose;
}
-void FrameLoader::loadWithNavigationAction(const NavigationAction& action, FrameLoadType type, PassRefPtrWillBeRawPtr<FormState> formState, const SubstituteData& substituteData, ClientRedirectPolicy clientRedirect, const AtomicString& overrideEncoding)
+bool FrameLoader::validateTransitionNavigationMode()
+{
+ if (frame()->document()->inQuirksMode()) {
+ frame()->document()->addConsoleMessage(ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, "Ignoring transition elements due to quirks mode."));
+ return false;
+ }
+
+ // FIXME(oysteine): Also check for width=device-width here, to avoid zoom/scaling issues.
+ return true;
+}
+
+bool FrameLoader::dispatchNavigationTransitionData()
+{
+ Vector<Document::TransitionElementData> elementData;
+ frame()->document()->getTransitionElementData(elementData);
+ if (elementData.isEmpty() || !validateTransitionNavigationMode())
+ return false;
+
+ Vector<Document::TransitionElementData>::iterator iter = elementData.begin();
+ for (; iter != elementData.end(); ++iter)
+ client()->dispatchAddNavigationTransitionData(iter->scope, iter->selector, iter->markup);
+
+ return true;
+}
+
+void FrameLoader::loadWithNavigationAction(const NavigationAction& action, FrameLoadType type, PassRefPtrWillBeRawPtr<FormState> formState, const SubstituteData& substituteData, ContentSecurityPolicyCheck shouldCheckMainWorldContentSecurityPolicy, ClientRedirectPolicy clientRedirect, const AtomicString& overrideEncoding)
{
ASSERT(client()->hasWebView());
if (m_frame->document()->pageDismissalEventBeingDispatched() != Document::NoDismissal)
else if (m_documentLoader)
m_policyDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding());
+
+ bool isTransitionNavigation = false;
+ if (RuntimeEnabledFeatures::navigationTransitionsEnabled() && type != FrameLoadTypeReload && type != FrameLoadTypeReloadFromOrigin && type != FrameLoadTypeSame)
+ isTransitionNavigation = dispatchNavigationTransitionData();
+
// stopAllLoaders can detach the LocalFrame, so protect it.
- RefPtr<LocalFrame> protect(m_frame);
- if ((!m_policyDocumentLoader->shouldContinueForNavigationPolicy(request) || !shouldClose()) && m_policyDocumentLoader) {
+ RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get());
+ if ((!m_policyDocumentLoader->shouldContinueForNavigationPolicy(request, shouldCheckMainWorldContentSecurityPolicy, isTransitionNavigation) || !shouldClose()) && m_policyDocumentLoader) {
m_policyDocumentLoader->detachFromFrame();
m_policyDocumentLoader = nullptr;
+ checkCompleted();
return;
}
if (m_provisionalDocumentLoader->isClientRedirect())
m_provisionalDocumentLoader->appendRedirect(m_frame->document()->url());
m_provisionalDocumentLoader->appendRedirect(m_provisionalDocumentLoader->request().url());
- client()->dispatchDidStartProvisionalLoad();
+ client()->dispatchDidStartProvisionalLoad(isTransitionNavigation);
ASSERT(m_provisionalDocumentLoader);
m_provisionalDocumentLoader->startLoadingMainResource();
}
return true;
case XFrameOptionsAllowAll:
return false;
- case XFrameOptionsConflict:
- m_frame->document()->addConsoleMessageWithRequestIdentifier(JSMessageSource, ErrorMessageLevel, "Multiple 'X-Frame-Options' headers with conflicting values ('" + content + "') encountered when loading '" + url.elidedString() + "'. Falling back to 'DENY'.", requestIdentifier);
+ case XFrameOptionsConflict: {
+ RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, "Multiple 'X-Frame-Options' headers with conflicting values ('" + content + "') encountered when loading '" + url.elidedString() + "'. Falling back to 'DENY'.");
+ consoleMessage->setRequestIdentifier(requestIdentifier);
+ m_frame->document()->addConsoleMessage(consoleMessage.release());
return true;
- case XFrameOptionsInvalid:
- m_frame->document()->addConsoleMessageWithRequestIdentifier(JSMessageSource, ErrorMessageLevel, "Invalid 'X-Frame-Options' header encountered when loading '" + url.elidedString() + "': '" + content + "' is not a recognized directive. The header will be ignored.", requestIdentifier);
+ }
+ case XFrameOptionsInvalid: {
+ RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, "Invalid 'X-Frame-Options' header encountered when loading '" + url.elidedString() + "': '" + content + "' is not a recognized directive. The header will be ignored.");
+ consoleMessage->setRequestIdentifier(requestIdentifier);
+ m_frame->document()->addConsoleMessage(consoleMessage.release());
return false;
+ }
default:
ASSERT_NOT_REACHED();
return false;
void FrameLoader::loadHistoryItem(HistoryItem* item, HistoryLoadType historyLoadType, ResourceRequestCachePolicy cachePolicy)
{
- RefPtr<LocalFrame> protect(m_frame);
+ RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get());
if (m_frame->page()->defersLoading()) {
m_deferredHistoryLoad = DeferredHistoryLoad(item, historyLoadType, cachePolicy);
return;
restoreScrollPositionAndViewState();
return;
}
- loadWithNavigationAction(NavigationAction(requestFromHistoryItem(item, cachePolicy), FrameLoadTypeBackForward), FrameLoadTypeBackForward, nullptr, SubstituteData());
+
+ 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);
}
void FrameLoader::dispatchDocumentElementAvailable()
return flags;
}
-} // namespace WebCore
+} // namespace blink