| Index: third_party/WebKit/Source/core/loader/BeaconLoader.cpp
|
| diff --git a/third_party/WebKit/Source/core/loader/BeaconLoader.cpp b/third_party/WebKit/Source/core/loader/BeaconLoader.cpp
|
| index c2c137dc796bc61e6714af88876ae81f8ff663ee..ced714ce3c2d573219b01d976fb5898d5822c6f1 100644
|
| --- a/third_party/WebKit/Source/core/loader/BeaconLoader.cpp
|
| +++ b/third_party/WebKit/Source/core/loader/BeaconLoader.cpp
|
| @@ -9,6 +9,7 @@
|
| #include "core/fetch/CrossOriginAccessControl.h"
|
| #include "core/fetch/FetchContext.h"
|
| #include "core/fetch/FetchInitiatorTypeNames.h"
|
| +#include "core/fetch/FetchUtils.h"
|
| #include "core/fetch/ResourceFetcher.h"
|
| #include "core/fileapi/File.h"
|
| #include "core/frame/LocalFrame.h"
|
| @@ -28,14 +29,16 @@ namespace blink {
|
| namespace {
|
|
|
| class Beacon {
|
| + STACK_ALLOCATED();
|
| public:
|
| virtual bool serialize(ResourceRequest&, int, int&) const = 0;
|
| virtual unsigned long long size() const = 0;
|
| + virtual const AtomicString getContentType() const = 0;
|
| };
|
|
|
| class BeaconString final : public Beacon {
|
| public:
|
| - BeaconString(const String& data)
|
| + explicit BeaconString(const String& data)
|
| : m_data(data)
|
| {
|
| }
|
| @@ -49,19 +52,24 @@ public:
|
| {
|
| RefPtr<EncodedFormData> entityBody = EncodedFormData::create(m_data.utf8());
|
| request.setHTTPBody(entityBody);
|
| - request.setHTTPContentType("text/plain;charset=UTF-8");
|
| + request.setHTTPContentType(getContentType());
|
| return true;
|
| }
|
|
|
| + const AtomicString getContentType() const { return AtomicString("text/plain;charset=UTF-8"); }
|
| +
|
| private:
|
| const String m_data;
|
| };
|
|
|
| class BeaconBlob final : public Beacon {
|
| public:
|
| - BeaconBlob(Blob* data)
|
| + explicit BeaconBlob(Blob* data)
|
| : m_data(data)
|
| {
|
| + const String& blobType = m_data->type();
|
| + if (!blobType.isEmpty() && isValidContentType(blobType))
|
| + m_contentType = AtomicString(blobType);
|
| }
|
|
|
| unsigned long long size() const override
|
| @@ -80,20 +88,22 @@ public:
|
|
|
| request.setHTTPBody(entityBody.release());
|
|
|
| - const String& blobType = m_data->type();
|
| - if (!blobType.isEmpty() && isValidContentType(blobType))
|
| - request.setHTTPContentType(AtomicString(blobType));
|
| + if (!m_contentType.isEmpty())
|
| + request.setHTTPContentType(m_contentType);
|
|
|
| return true;
|
| }
|
|
|
| + const AtomicString getContentType() const { return m_contentType; }
|
| +
|
| private:
|
| - const Persistent<Blob> m_data;
|
| + const Member<Blob> m_data;
|
| + AtomicString m_contentType;
|
| };
|
|
|
| class BeaconDOMArrayBufferView final : public Beacon {
|
| public:
|
| - BeaconDOMArrayBufferView(DOMArrayBufferView* data)
|
| + explicit BeaconDOMArrayBufferView(DOMArrayBufferView* data)
|
| : m_data(data)
|
| {
|
| }
|
| @@ -116,15 +126,19 @@ public:
|
| return true;
|
| }
|
|
|
| + const AtomicString getContentType() const { return nullAtom; }
|
| +
|
| private:
|
| - const Persistent<DOMArrayBufferView> m_data;
|
| + const Member<DOMArrayBufferView> m_data;
|
| };
|
|
|
| class BeaconFormData final : public Beacon {
|
| public:
|
| - BeaconFormData(FormData* data)
|
| + explicit BeaconFormData(FormData* data)
|
| : m_data(data)
|
| + , m_entityBody(m_data->encodeMultiPartFormData())
|
| {
|
| + m_contentType = AtomicString("multipart/form-data; boundary=") + m_entityBody->boundary().data();
|
| }
|
|
|
| unsigned long long size() const override
|
| @@ -135,22 +149,23 @@ public:
|
|
|
| bool serialize(ResourceRequest& request, int allowance, int& payloadLength) const override
|
| {
|
| - ASSERT(m_data);
|
| - RefPtr<EncodedFormData> entityBody = m_data->encodeMultiPartFormData();
|
| - unsigned long long entitySize = entityBody->sizeInBytes();
|
| + unsigned long long entitySize = m_entityBody->sizeInBytes();
|
| if (allowance > 0 && static_cast<unsigned long long>(allowance) < entitySize)
|
| return false;
|
|
|
| - AtomicString contentType = AtomicString("multipart/form-data; boundary=") + entityBody->boundary().data();
|
| - request.setHTTPBody(entityBody.release());
|
| - request.setHTTPContentType(contentType);
|
| + request.setHTTPBody(m_entityBody.get());
|
| + request.setHTTPContentType(m_contentType);
|
|
|
| payloadLength = entitySize;
|
| return true;
|
| }
|
|
|
| + const AtomicString getContentType() const { return m_contentType; }
|
| +
|
| private:
|
| - const Persistent<FormData> m_data;
|
| + const Member<FormData> m_data;
|
| + RefPtr<EncodedFormData> m_entityBody;
|
| + AtomicString m_contentType;
|
| };
|
|
|
| } // namespace
|
| @@ -181,11 +196,16 @@ public:
|
| if (!beacon.serialize(request, allowance, payloadLength))
|
| return false;
|
|
|
| + const AtomicString contentType = beacon.getContentType();
|
| + CORSEnabled corsEnabled = IsCORSEnabled;
|
| + if (!contentType.isNull() && FetchUtils::isSimpleHeader(AtomicString("content-type"), contentType))
|
| + corsEnabled = NotCORSEnabled;
|
| +
|
| FetchInitiatorInfo initiatorInfo;
|
| initiatorInfo.name = FetchInitiatorTypeNames::beacon;
|
|
|
| // The loader keeps itself alive until it receives a response and disposes itself.
|
| - BeaconLoader* loader = new BeaconLoader(frame, request, initiatorInfo, AllowStoredCredentials);
|
| + BeaconLoader* loader = new BeaconLoader(frame, request, initiatorInfo, AllowStoredCredentials, corsEnabled);
|
| ASSERT_UNUSED(loader, loader);
|
| return true;
|
| }
|
| @@ -215,15 +235,19 @@ bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
|
| return Sender::send(frame, allowance, beaconURL, beacon, payloadLength);
|
| }
|
|
|
| -BeaconLoader::BeaconLoader(LocalFrame* frame, ResourceRequest& request, const FetchInitiatorInfo& initiatorInfo, StoredCredentials credentialsAllowed)
|
| +BeaconLoader::BeaconLoader(LocalFrame* frame, ResourceRequest& request, const FetchInitiatorInfo& initiatorInfo, StoredCredentials credentialsAllowed, CORSEnabled corsMode)
|
| : PingLoader(frame, request, initiatorInfo, credentialsAllowed)
|
| , m_beaconOrigin(frame->document()->getSecurityOrigin())
|
| + , m_redirectsFollowCORS(corsMode == IsCORSEnabled)
|
| {
|
| }
|
|
|
| void BeaconLoader::willFollowRedirect(WebURLLoader*, WebURLRequest& passedNewRequest, const WebURLResponse& passedRedirectResponse, int64_t encodedDataLength)
|
| {
|
| passedNewRequest.setAllowStoredCredentials(true);
|
| + if (!m_redirectsFollowCORS)
|
| + return;
|
| +
|
| ResourceRequest& newRequest(passedNewRequest.toMutableResourceRequest());
|
| const ResourceResponse& redirectResponse(passedRedirectResponse.toResourceResponse());
|
|
|
| @@ -240,6 +264,8 @@ void BeaconLoader::willFollowRedirect(WebURLLoader*, WebURLRequest& passedNewReq
|
| }
|
| // Cancel the load and self destruct.
|
| dispose();
|
| + // Signal WebURLLoader that the redirect musn't be followed.
|
| + passedNewRequest = WebURLRequest();
|
| return;
|
| }
|
| // FIXME: http://crbug.com/427429 is needed to correctly propagate
|
|
|