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..01d30b2685b040189b1ae0e531dda818d20ab923 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 bool serialize(ResourceRequest&, int, int&) = 0; |
virtual unsigned long long size() const = 0; |
+ virtual const AtomicString getContentType() const = 0; |
tyoshino (SeeGerritForStatus)
2016/07/28 07:21:57
BeaconString returns the type including the charse
sof
2016/07/28 08:28:19
getContentType() implements what https://fetch.spe
|
}; |
class BeaconString final : public Beacon { |
public: |
- BeaconString(const String& data) |
+ explicit BeaconString(const String& data) |
: m_data(data) |
{ |
} |
@@ -45,21 +48,23 @@ public: |
return m_data.sizeInBytes(); |
} |
- bool serialize(ResourceRequest& request, int, int&) const override |
+ bool serialize(ResourceRequest& request, int, int&) override |
{ |
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) |
{ |
} |
@@ -69,7 +74,7 @@ public: |
return m_data->size(); |
} |
- bool serialize(ResourceRequest& request, int, int&) const override |
+ bool serialize(ResourceRequest& request, int, int&) override |
{ |
ASSERT(m_data); |
RefPtr<EncodedFormData> entityBody = EncodedFormData::create(); |
@@ -81,19 +86,24 @@ public: |
request.setHTTPBody(entityBody.release()); |
const String& blobType = m_data->type(); |
- if (!blobType.isEmpty() && isValidContentType(blobType)) |
- request.setHTTPContentType(AtomicString(blobType)); |
+ if (!blobType.isEmpty() && isValidContentType(blobType)) { |
+ m_contentType = AtomicString(blobType); |
+ request.setHTTPContentType(m_contentType); |
+ } |
tyoshino (SeeGerritForStatus)
2016/07/28 07:21:57
do the extraction in the constructor and use it sa
sof
2016/07/28 08:28:20
Good idea, much better; done.
|
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) |
{ |
} |
@@ -103,7 +113,7 @@ public: |
return m_data->byteLength(); |
} |
- bool serialize(ResourceRequest& request, int, int&) const override |
+ bool serialize(ResourceRequest& request, int, int&) override |
{ |
ASSERT(m_data); |
RefPtr<EncodedFormData> entityBody = EncodedFormData::create(m_data->baseAddress(), m_data->byteLength()); |
@@ -116,13 +126,15 @@ public: |
return true; |
} |
+ const AtomicString getContentType() const { return nullAtom; } |
tyoshino (SeeGerritForStatus)
2016/07/28 07:21:57
be consistent with L123-124?
sof
2016/07/28 08:28:19
No, that would make ArrayBuffer-backed follow CORS
tyoshino (SeeGerritForStatus)
2016/07/28 12:03:20
OK
|
+ |
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) |
{ |
} |
@@ -133,7 +145,7 @@ public: |
return 0; |
} |
- bool serialize(ResourceRequest& request, int allowance, int& payloadLength) const override |
+ bool serialize(ResourceRequest& request, int allowance, int& payloadLength) override |
{ |
ASSERT(m_data); |
RefPtr<EncodedFormData> entityBody = m_data->encodeMultiPartFormData(); |
@@ -149,15 +161,17 @@ public: |
return true; |
} |
+ const AtomicString getContentType() const { return AtomicString("multipart/form-data"); } |
+ |
private: |
- const Persistent<FormData> m_data; |
+ const Member<FormData> m_data; |
}; |
} // namespace |
class BeaconLoader::Sender { |
public: |
- static bool send(LocalFrame* frame, int allowance, const KURL& beaconURL, const Beacon& beacon, int& payloadLength) |
+ static bool send(LocalFrame* frame, int allowance, const KURL& beaconURL, Beacon& beacon, int& payloadLength) |
{ |
if (!frame->document()) |
return false; |
@@ -181,11 +195,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 +234,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 +263,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(); |
tyoshino (SeeGerritForStatus)
2016/07/28 07:21:57
This is ok but I wonder if you had to add this to
sof
2016/07/28 08:28:20
It won't work without it (a longer-standing bug.)
|
return; |
} |
// FIXME: http://crbug.com/427429 is needed to correctly propagate |