Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Unified Diff: third_party/WebKit/Source/core/loader/BeaconLoader.cpp

Issue 2177383006: Update and fix sendBeacon() redirect behavior. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comment spelling Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698