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 |