summaryrefslogtreecommitdiff
path: root/Source/WebCore/loader/PingLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/loader/PingLoader.cpp')
-rw-r--r--Source/WebCore/loader/PingLoader.cpp155
1 files changed, 106 insertions, 49 deletions
diff --git a/Source/WebCore/loader/PingLoader.cpp b/Source/WebCore/loader/PingLoader.cpp
index db7cde041..d5fff791f 100644
--- a/Source/WebCore/loader/PingLoader.cpp
+++ b/Source/WebCore/loader/PingLoader.cpp
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2015 Roopesh Chander (roop@roopc.net)
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -32,111 +34,166 @@
#include "config.h"
#include "PingLoader.h"
+#include "ContentSecurityPolicy.h"
#include "Document.h"
#include "FormData.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameLoaderClient.h"
+#include "HTTPHeaderNames.h"
#include "InspectorInstrumentation.h"
+#include "LoaderStrategy.h"
#include "Page.h"
+#include "PlatformStrategies.h"
#include "ProgressTracker.h"
#include "ResourceHandle.h"
+#include "ResourceLoadInfo.h"
#include "ResourceRequest.h"
#include "ResourceResponse.h"
#include "SecurityOrigin.h"
#include "SecurityPolicy.h"
+#include "UserContentController.h"
#include <wtf/text/CString.h>
namespace WebCore {
-void PingLoader::loadImage(Frame* frame, const URL& url)
+#if !ENABLE(CONTENT_EXTENSIONS)
+
+// Returns true if we should block the load.
+static inline bool processContentExtensionRulesForLoad(const Frame&, ResourceRequest&, ResourceType)
+{
+ return false;
+}
+
+#else
+
+// Returns true if we should block the load.
+static bool processContentExtensionRulesForLoad(const Frame& frame, ResourceRequest& request, ResourceType resourceType)
+{
+ auto* documentLoader = frame.loader().documentLoader();
+ if (!documentLoader)
+ return false;
+ auto* page = frame.page();
+ if (!page)
+ return false;
+ auto status = page->userContentProvider().processContentExtensionRulesForLoad(request.url(), resourceType, *documentLoader);
+ applyBlockedStatusToRequest(status, request);
+ return status.blockedLoad;
+}
+
+#endif
+
+void PingLoader::loadImage(Frame& frame, const URL& url)
{
- if (!frame->document()->securityOrigin()->canDisplay(url)) {
- FrameLoader::reportLocalLoadFailed(frame, url);
+ ASSERT(frame.document());
+ auto& document = *frame.document();
+
+ if (!document.securityOrigin().canDisplay(url)) {
+ FrameLoader::reportLocalLoadFailed(&frame, url);
return;
}
ResourceRequest request(url);
- request.setHTTPHeaderField("Cache-Control", "max-age=0");
- String referrer = SecurityPolicy::generateReferrerHeader(frame->document()->referrerPolicy(), request.url(), frame->loader().outgoingReferrer());
+ if (processContentExtensionRulesForLoad(frame, request, ResourceType::Image))
+ return;
+
+ document.contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(request, ContentSecurityPolicy::InsecureRequestType::Load);
+
+ request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "max-age=0");
+ String referrer = SecurityPolicy::generateReferrerHeader(document.referrerPolicy(), request.url(), frame.loader().outgoingReferrer());
if (!referrer.isEmpty())
request.setHTTPReferrer(referrer);
- frame->loader().addExtraFieldsToSubresourceRequest(request);
+ frame.loader().addExtraFieldsToSubresourceRequest(request);
- createPingLoader(frame, request);
+ startPingLoad(frame, request, ShouldFollowRedirects::Yes);
}
// http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#hyperlink-auditing
-void PingLoader::sendPing(Frame* frame, const URL& pingURL, const URL& destinationURL)
+void PingLoader::sendPing(Frame& frame, const URL& pingURL, const URL& destinationURL)
{
+ ASSERT(frame.document());
+
+ if (!pingURL.protocolIsInHTTPFamily())
+ return;
+
ResourceRequest request(pingURL);
+ if (processContentExtensionRulesForLoad(frame, request, ResourceType::Raw))
+ return;
+
+ auto& document = *frame.document();
+ document.contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(request, ContentSecurityPolicy::InsecureRequestType::Load);
+
request.setHTTPMethod("POST");
request.setHTTPContentType("text/ping");
request.setHTTPBody(FormData::create("PING"));
- request.setHTTPHeaderField("Cache-Control", "max-age=0");
- frame->loader().addExtraFieldsToSubresourceRequest(request);
-
- SecurityOrigin* sourceOrigin = frame->document()->securityOrigin();
- RefPtr<SecurityOrigin> pingOrigin = SecurityOrigin::create(pingURL);
- FrameLoader::addHTTPOriginIfNeeded(request, sourceOrigin->toString());
- request.setHTTPHeaderField("Ping-To", destinationURL);
- if (!SecurityPolicy::shouldHideReferrer(pingURL, frame->loader().outgoingReferrer())) {
- request.setHTTPHeaderField("Ping-From", frame->document()->url());
- if (!sourceOrigin->isSameSchemeHostPort(pingOrigin.get())) {
- String referrer = SecurityPolicy::generateReferrerHeader(frame->document()->referrerPolicy(), pingURL, frame->loader().outgoingReferrer());
+ request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "max-age=0");
+ frame.loader().addExtraFieldsToSubresourceRequest(request);
+
+ auto& sourceOrigin = document.securityOrigin();
+ FrameLoader::addHTTPOriginIfNeeded(request, sourceOrigin.toString());
+ request.setHTTPHeaderField(HTTPHeaderName::PingTo, destinationURL);
+ if (!SecurityPolicy::shouldHideReferrer(pingURL, frame.loader().outgoingReferrer())) {
+ request.setHTTPHeaderField(HTTPHeaderName::PingFrom, document.url());
+ if (!sourceOrigin.isSameSchemeHostPort(SecurityOrigin::create(pingURL).get())) {
+ String referrer = SecurityPolicy::generateReferrerHeader(document.referrerPolicy(), pingURL, frame.loader().outgoingReferrer());
if (!referrer.isEmpty())
request.setHTTPReferrer(referrer);
}
}
- createPingLoader(frame, request);
+ startPingLoad(frame, request, ShouldFollowRedirects::Yes);
}
-void PingLoader::sendViolationReport(Frame* frame, const URL& reportURL, PassRefPtr<FormData> report)
+void PingLoader::sendViolationReport(Frame& frame, const URL& reportURL, Ref<FormData>&& report, ViolationReportType reportType)
{
+ ASSERT(frame.document());
+
ResourceRequest request(reportURL);
- request.setHTTPMethod("POST");
- request.setHTTPContentType("application/json");
- request.setHTTPBody(report);
- request.setAllowCookies(frame->document()->securityOrigin()->isSameSchemeHostPort(SecurityOrigin::create(reportURL).get()));
- frame->loader().addExtraFieldsToSubresourceRequest(request);
+ if (processContentExtensionRulesForLoad(frame, request, ResourceType::Raw))
+ return;
+
+ auto& document = *frame.document();
+ document.contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(request, ContentSecurityPolicy::InsecureRequestType::Load);
+
+ request.setHTTPMethod(ASCIILiteral("POST"));
+ request.setHTTPBody(WTFMove(report));
+ switch (reportType) {
+ case ViolationReportType::ContentSecurityPolicy:
+ request.setHTTPContentType(ASCIILiteral("application/csp-report"));
+ break;
+ case ViolationReportType::XSSAuditor:
+ request.setHTTPContentType(ASCIILiteral("application/json"));
+ break;
+ }
- String referrer = SecurityPolicy::generateReferrerHeader(frame->document()->referrerPolicy(), reportURL, frame->loader().outgoingReferrer());
+ bool removeCookies = true;
+ if (document.securityOrigin().isSameSchemeHostPort(SecurityOrigin::create(reportURL).get()))
+ removeCookies = false;
+ if (removeCookies)
+ request.setAllowCookies(false);
+
+ frame.loader().addExtraFieldsToSubresourceRequest(request);
+
+ String referrer = SecurityPolicy::generateReferrerHeader(document.referrerPolicy(), reportURL, frame.loader().outgoingReferrer());
if (!referrer.isEmpty())
request.setHTTPReferrer(referrer);
- createPingLoader(frame, request);
-}
-
-void PingLoader::createPingLoader(Frame* frame, ResourceRequest& request)
-{
- // No need to free the PingLoader object or manage it via a smart pointer - it will kill itself as soon as it receives a response.
- new PingLoader(frame, request);
+ startPingLoad(frame, request, ShouldFollowRedirects::No);
}
-PingLoader::PingLoader(Frame* frame, ResourceRequest& request)
- : m_timeout(this, &PingLoader::timeoutTimerFired)
+void PingLoader::startPingLoad(Frame& frame, ResourceRequest& request, ShouldFollowRedirects shouldFollowRedirects)
{
- unsigned long identifier = frame->page()->progress().createUniqueIdentifier();
+ unsigned long identifier = frame.page()->progress().createUniqueIdentifier();
// FIXME: Why activeDocumentLoader? I would have expected documentLoader().
// Itseems like the PingLoader should be associated with the current
// Document in the Frame, but the activeDocumentLoader will be associated
// with the provisional DocumentLoader if there is a provisional
// DocumentLoader.
- m_shouldUseCredentialStorage = frame->loader().client().shouldUseCredentialStorage(frame->loader().activeDocumentLoader(), identifier);
- m_handle = ResourceHandle::create(frame->loader().networkingContext(), request, this, false, false);
-
- InspectorInstrumentation::continueAfterPingLoader(frame, identifier, frame->loader().activeDocumentLoader(), request, ResourceResponse());
+ bool shouldUseCredentialStorage = frame.loader().client().shouldUseCredentialStorage(frame.loader().activeDocumentLoader(), identifier);
- // If the server never responds, FrameLoader won't be able to cancel this load and
- // we'll sit here waiting forever. Set a very generous timeout, just in case.
- m_timeout.startOneShot(60000);
-}
+ InspectorInstrumentation::continueAfterPingLoader(frame, identifier, frame.loader().activeDocumentLoader(), request, ResourceResponse());
-PingLoader::~PingLoader()
-{
- if (m_handle)
- m_handle->cancel();
+ platformStrategies()->loaderStrategy()->createPingHandle(frame.loader().networkingContext(), request, shouldUseCredentialStorage, shouldFollowRedirects == ShouldFollowRedirects::Yes);
}
}