| Index: Source/core/loader/BeaconLoader.cpp
|
| diff --git a/Source/core/loader/BeaconLoader.cpp b/Source/core/loader/BeaconLoader.cpp
|
| index 9bb44cd5aa072cabcf594910441fbe4ee2cfe647..cb20a6c0c106cfc1a2f7b37c72e9890085f16016 100644
|
| --- a/Source/core/loader/BeaconLoader.cpp
|
| +++ b/Source/core/loader/BeaconLoader.cpp
|
| @@ -15,77 +15,128 @@
|
| #include "platform/network/ParsedContentType.h"
|
| #include "platform/network/ResourceRequest.h"
|
| #include "public/platform/WebURLRequest.h"
|
| +#include "wtf/Functional.h"
|
|
|
| namespace blink {
|
|
|
| -void BeaconLoader::prepareRequest(LocalFrame* frame, ResourceRequest& request)
|
| +namespace {
|
| +
|
| +class Beacon {
|
| +public:
|
| + virtual bool serialize(ResourceRequest&, int, int&) const = 0;
|
| + virtual unsigned long long size() const = 0;
|
| +
|
| +protected:
|
| + static unsigned long long beaconSize(const String&);
|
| + static unsigned long long beaconSize(Blob*);
|
| + static unsigned long long beaconSize(PassRefPtr<DOMArrayBufferView>);
|
| + static unsigned long long beaconSize(PassRefPtrWillBeRawPtr<DOMFormData>);
|
| +
|
| + static bool serialize(const String&, ResourceRequest&, int, int&);
|
| + static bool serialize(Blob*, ResourceRequest&, int, int&);
|
| + static bool serialize(PassRefPtr<DOMArrayBufferView>, ResourceRequest&, int, int&);
|
| + static bool serialize(PassRefPtrWillBeRawPtr<DOMFormData>, ResourceRequest&, int, int&);
|
| +};
|
| +
|
| +template<typename Payload>
|
| +class BeaconData final : public Beacon {
|
| +public:
|
| + BeaconData(const Payload& data)
|
| + : m_data(data)
|
| + {
|
| + }
|
| +
|
| + bool serialize(ResourceRequest& request, int allowance, int& payloadLength) const override
|
| + {
|
| + return Beacon::serialize(m_data, request, allowance, payloadLength);
|
| + }
|
| +
|
| + unsigned long long size() const override
|
| + {
|
| + return beaconSize(m_data);
|
| + }
|
| +
|
| +private:
|
| + const typename WTF::ParamStorageTraits<Payload>::StorageType m_data;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +class BeaconLoader::Sender {
|
| +public:
|
| + static bool send(LocalFrame* frame, int allowance, const KURL& beaconURL, const Beacon& beacon, int& payloadLength)
|
| + {
|
| + unsigned long long entitySize = beacon.size();
|
| + if (allowance > 0 && static_cast<unsigned long long>(allowance) < entitySize)
|
| + return false;
|
| +
|
| + ResourceRequest request(beaconURL);
|
| + request.setRequestContext(WebURLRequest::RequestContextBeacon);
|
| + request.setHTTPMethod("POST");
|
| + request.setHTTPHeaderField("Cache-Control", "max-age=0");
|
| + request.setAllowStoredCredentials(true);
|
| + frame->loader().fetchContext().addAdditionalRequestHeaders(frame->document(), request, FetchSubresource);
|
| + frame->loader().fetchContext().setFirstPartyForCookies(request);
|
| +
|
| + payloadLength = entitySize;
|
| + if (!beacon.serialize(request, allowance, payloadLength))
|
| + return false;
|
| +
|
| + FetchInitiatorInfo initiatorInfo;
|
| + initiatorInfo.name = FetchInitiatorTypeNames::beacon;
|
| +
|
| + PingLoader::start(frame, request, initiatorInfo);
|
| + return true;
|
| + }
|
| +};
|
| +
|
| +bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beaconURL, const String& data, int& payloadLength)
|
| {
|
| - request.setRequestContext(WebURLRequest::RequestContextBeacon);
|
| - request.setHTTPMethod("POST");
|
| - request.setHTTPHeaderField("Cache-Control", "max-age=0");
|
| - request.setAllowStoredCredentials(true);
|
| - frame->loader().fetchContext().addAdditionalRequestHeaders(frame->document(), request, FetchSubresource);
|
| - frame->loader().fetchContext().setFirstPartyForCookies(request);
|
| + BeaconData<decltype(data)> beacon(data);
|
| + return Sender::send(frame, allowance, beaconURL, beacon, payloadLength);
|
| }
|
|
|
| -void BeaconLoader::issueRequest(LocalFrame* frame, ResourceRequest& request)
|
| +bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beaconURL, PassRefPtr<DOMArrayBufferView> data, int& payloadLength)
|
| {
|
| - FetchInitiatorInfo initiatorInfo;
|
| - initiatorInfo.name = FetchInitiatorTypeNames::beacon;
|
| + BeaconData<decltype(data)> beacon(data);
|
| + return Sender::send(frame, allowance, beaconURL, beacon, payloadLength);
|
| +}
|
|
|
| - PingLoader::start(frame, request, initiatorInfo);
|
| +bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beaconURL, PassRefPtrWillBeRawPtr<DOMFormData> data, int& payloadLength)
|
| +{
|
| + BeaconData<decltype(data)> beacon(data);
|
| + return Sender::send(frame, allowance, beaconURL, beacon, payloadLength);
|
| }
|
|
|
| -bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beaconURL, const String& data, int& payloadLength)
|
| +bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beaconURL, Blob* data, int& payloadLength)
|
| {
|
| - ResourceRequest request(beaconURL);
|
| - prepareRequest(frame, request);
|
| + BeaconData<decltype(data)> beacon(data);
|
| + return Sender::send(frame, allowance, beaconURL, beacon, payloadLength);
|
| +}
|
|
|
| - RefPtr<FormData> entityBody = FormData::create(data.utf8());
|
| - unsigned long long entitySize = entityBody->sizeInBytes();
|
| - if (allowance > 0 && static_cast<unsigned>(allowance) < entitySize)
|
| - return false;
|
| +namespace {
|
| +
|
| +unsigned long long Beacon::beaconSize(const String& data)
|
| +{
|
| + return data.sizeInBytes();
|
| +}
|
|
|
| +bool Beacon::serialize(const String& data, ResourceRequest& request, int, int&)
|
| +{
|
| + RefPtr<FormData> entityBody = FormData::create(data.utf8());
|
| request.setHTTPBody(entityBody);
|
| request.setHTTPContentType("text/plain;charset=UTF-8");
|
| -
|
| - issueRequest(frame, request);
|
| - payloadLength = entitySize;
|
| return true;
|
| }
|
|
|
| -bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beaconURL, PassRefPtr<DOMArrayBufferView> data, int& payloadLength)
|
| +unsigned long long Beacon::beaconSize(Blob* data)
|
| {
|
| - ASSERT(data);
|
| - unsigned long long entitySize = data->byteLength();
|
| - if (allowance > 0 && static_cast<unsigned long long>(allowance) < entitySize)
|
| - return false;
|
| -
|
| - ResourceRequest request(beaconURL);
|
| - prepareRequest(frame, request);
|
| -
|
| - RefPtr<FormData> entityBody = FormData::create(data->baseAddress(), data->byteLength());
|
| - request.setHTTPBody(entityBody.release());
|
| -
|
| - // FIXME: a reasonable choice, but not in the spec; should it give a default?
|
| - AtomicString contentType = AtomicString("application/octet-stream");
|
| - request.setHTTPContentType(contentType);
|
| -
|
| - issueRequest(frame, request);
|
| - payloadLength = entitySize;
|
| - return true;
|
| + return data->size();
|
| }
|
|
|
| -bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beaconURL, Blob* data, int& payloadLength)
|
| +bool Beacon::serialize(Blob* data, ResourceRequest& request, int, int&)
|
| {
|
| ASSERT(data);
|
| - unsigned long long entitySize = data->size();
|
| - if (allowance > 0 && static_cast<unsigned long long>(allowance) < entitySize)
|
| - return false;
|
| -
|
| - ResourceRequest request(beaconURL);
|
| - prepareRequest(frame, request);
|
| -
|
| RefPtr<FormData> entityBody = FormData::create();
|
| if (data->hasBackingFile())
|
| entityBody->appendFile(toFile(data)->path());
|
| @@ -99,19 +150,37 @@ bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
|
| if (!blobType.isEmpty() && isValidContentType(blobType))
|
| request.setHTTPContentType(AtomicString(contentType));
|
|
|
| - issueRequest(frame, request);
|
| - payloadLength = entitySize;
|
| return true;
|
| }
|
|
|
| -bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beaconURL, PassRefPtrWillBeRawPtr<DOMFormData> data, int& payloadLength)
|
| +unsigned long long Beacon::beaconSize(PassRefPtr<DOMArrayBufferView> data)
|
| +{
|
| + return data->byteLength();
|
| +}
|
| +
|
| +bool Beacon::serialize(PassRefPtr<DOMArrayBufferView> data, ResourceRequest& request, int, int&)
|
| {
|
| ASSERT(data);
|
| - ResourceRequest request(beaconURL);
|
| - prepareRequest(frame, request);
|
| + RefPtr<FormData> entityBody = FormData::create(data->baseAddress(), data->byteLength());
|
| + request.setHTTPBody(entityBody.release());
|
|
|
| - RefPtr<FormData> entityBody = data->createMultiPartFormData();
|
| + // FIXME: a reasonable choice, but not in the spec; should it give a default?
|
| + AtomicString contentType = AtomicString("application/octet-stream");
|
| + request.setHTTPContentType(contentType);
|
| +
|
| + return true;
|
| +}
|
|
|
| +unsigned long long Beacon::beaconSize(PassRefPtrWillBeRawPtr<DOMFormData> data)
|
| +{
|
| + // DOMFormData's size cannot be determined until serialized.
|
| + return 0;
|
| +}
|
| +
|
| +bool Beacon::serialize(PassRefPtrWillBeRawPtr<DOMFormData> data, ResourceRequest& request, int allowance, int& payloadLength)
|
| +{
|
| + ASSERT(data);
|
| + RefPtr<FormData> entityBody = data->createMultiPartFormData();
|
| unsigned long long entitySize = entityBody->sizeInBytes();
|
| if (allowance > 0 && static_cast<unsigned long long>(allowance) < entitySize)
|
| return false;
|
| @@ -120,9 +189,10 @@ bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
|
| request.setHTTPBody(entityBody.release());
|
| request.setHTTPContentType(contentType);
|
|
|
| - issueRequest(frame, request);
|
| payloadLength = entitySize;
|
| return true;
|
| }
|
|
|
| +} // namespace
|
| +
|
| } // namespace blink
|
|
|