1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include "core/loader/BeaconLoader.h"
8 #include "core/FetchInitiatorTypeNames.h"
9 #include "core/fetch/CrossOriginAccessControl.h"
10 #include "core/fetch/FetchContext.h"
11 #include "core/fileapi/File.h"
12 #include "core/frame/LocalFrame.h"
13 #include "core/html/DOMFormData.h"
14 #include "platform/network/FormData.h"
15 #include "platform/network/ParsedContentType.h"
16 #include "platform/network/ResourceRequest.h"
17 #include "public/platform/WebURLRequest.h"
18 #include "wtf/ArrayBufferView.h"
22 void BeaconLoader::prepareRequest(LocalFrame* frame, ResourceRequest& request)
24 request.setRequestContext(WebURLRequest::RequestContextBeacon);
25 request.setHTTPMethod("POST");
26 request.setHTTPHeaderField("Cache-Control", "max-age=0");
27 request.setAllowStoredCredentials(true);
28 frame->loader().fetchContext().addAdditionalRequestHeaders(frame->document(), request, FetchSubresource);
29 frame->loader().fetchContext().setFirstPartyForCookies(request);
32 void BeaconLoader::issueRequest(LocalFrame* frame, ResourceRequest& request)
34 FetchInitiatorInfo initiatorInfo;
35 initiatorInfo.name = FetchInitiatorTypeNames::beacon;
37 PingLoader::start(frame, request, initiatorInfo);
40 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beaconURL, const String& data, int& payloadLength)
42 ResourceRequest request(beaconURL);
43 prepareRequest(frame, request);
45 RefPtr<FormData> entityBody = FormData::create(data.utf8());
46 unsigned long long entitySize = entityBody->sizeInBytes();
47 if (allowance > 0 && static_cast<unsigned>(allowance) < entitySize)
50 request.setHTTPBody(entityBody);
51 request.setHTTPContentType("text/plain;charset=UTF-8");
53 issueRequest(frame, request);
54 payloadLength = entitySize;
58 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beaconURL, PassRefPtr<ArrayBufferView>& data, int& payloadLength)
61 unsigned long long entitySize = data->byteLength();
62 if (allowance > 0 && static_cast<unsigned long long>(allowance) < entitySize)
65 ResourceRequest request(beaconURL);
66 prepareRequest(frame, request);
68 RefPtr<FormData> entityBody = FormData::create(data->baseAddress(), data->byteLength());
69 request.setHTTPBody(entityBody.release());
71 // FIXME: a reasonable choice, but not in the spec; should it give a default?
72 AtomicString contentType = AtomicString("application/octet-stream");
73 request.setHTTPContentType(contentType);
75 issueRequest(frame, request);
76 payloadLength = entitySize;
80 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beaconURL, PassRefPtrWillBeRawPtr<Blob>& data, int& payloadLength)
83 unsigned long long entitySize = data->size();
84 if (allowance > 0 && static_cast<unsigned long long>(allowance) < entitySize)
87 ResourceRequest request(beaconURL);
88 prepareRequest(frame, request);
90 RefPtr<FormData> entityBody = FormData::create();
91 if (data->hasBackingFile())
92 entityBody->appendFile(toFile(data.get())->path());
94 entityBody->appendBlob(data->uuid(), data->blobDataHandle());
96 request.setHTTPBody(entityBody.release());
98 AtomicString contentType;
99 const String& blobType = data->type();
100 if (!blobType.isEmpty() && isValidContentType(blobType))
101 request.setHTTPContentType(AtomicString(contentType));
103 issueRequest(frame, request);
104 payloadLength = entitySize;
108 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beaconURL, PassRefPtrWillBeRawPtr<DOMFormData>& data, int& payloadLength)
111 ResourceRequest request(beaconURL);
112 prepareRequest(frame, request);
114 RefPtr<FormData> entityBody = data->createMultiPartFormData();
116 unsigned long long entitySize = entityBody->sizeInBytes();
117 if (allowance > 0 && static_cast<unsigned long long>(allowance) < entitySize)
120 AtomicString contentType = AtomicString("multipart/form-data; boundary=", AtomicString::ConstructFromLiteral) + entityBody->boundary().data();
121 request.setHTTPBody(entityBody.release());
122 request.setHTTPContentType(contentType);
124 issueRequest(frame, request);
125 payloadLength = entitySize;