OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "core/loader/BeaconLoader.h" | 6 #include "core/loader/BeaconLoader.h" |
7 | 7 |
8 #include "core/FetchInitiatorTypeNames.h" | 8 #include "core/FetchInitiatorTypeNames.h" |
9 #include "core/dom/DOMArrayBufferView.h" | 9 #include "core/dom/DOMArrayBufferView.h" |
10 #include "core/fetch/FetchContext.h" | 10 #include "core/fetch/FetchContext.h" |
11 #include "core/fileapi/File.h" | 11 #include "core/fileapi/File.h" |
12 #include "core/frame/LocalFrame.h" | 12 #include "core/frame/LocalFrame.h" |
13 #include "core/html/DOMFormData.h" | 13 #include "core/html/DOMFormData.h" |
14 #include "platform/network/FormData.h" | 14 #include "platform/network/FormData.h" |
15 #include "platform/network/ParsedContentType.h" | 15 #include "platform/network/ParsedContentType.h" |
16 #include "platform/network/ResourceRequest.h" | 16 #include "platform/network/ResourceRequest.h" |
17 #include "public/platform/WebURLRequest.h" | 17 #include "public/platform/WebURLRequest.h" |
| 18 #include "wtf/Functional.h" |
18 | 19 |
19 namespace blink { | 20 namespace blink { |
20 | 21 |
21 void BeaconLoader::prepareRequest(LocalFrame* frame, ResourceRequest& request) | 22 namespace { |
22 { | |
23 request.setRequestContext(WebURLRequest::RequestContextBeacon); | |
24 request.setHTTPMethod("POST"); | |
25 request.setHTTPHeaderField("Cache-Control", "max-age=0"); | |
26 request.setAllowStoredCredentials(true); | |
27 frame->loader().fetchContext().addAdditionalRequestHeaders(frame->document()
, request, FetchSubresource); | |
28 frame->loader().fetchContext().setFirstPartyForCookies(request); | |
29 } | |
30 | 23 |
31 void BeaconLoader::issueRequest(LocalFrame* frame, ResourceRequest& request) | 24 class Beacon { |
32 { | 25 public: |
33 FetchInitiatorInfo initiatorInfo; | 26 virtual bool serialize(ResourceRequest&, int, int&) const = 0; |
34 initiatorInfo.name = FetchInitiatorTypeNames::beacon; | 27 virtual unsigned long long size() const = 0; |
35 | 28 |
36 PingLoader::start(frame, request, initiatorInfo); | 29 protected: |
37 } | 30 static unsigned long long beaconSize(const String&); |
| 31 static unsigned long long beaconSize(Blob*); |
| 32 static unsigned long long beaconSize(PassRefPtr<DOMArrayBufferView>); |
| 33 static unsigned long long beaconSize(PassRefPtrWillBeRawPtr<DOMFormData>); |
| 34 |
| 35 static bool serialize(const String&, ResourceRequest&, int, int&); |
| 36 static bool serialize(Blob*, ResourceRequest&, int, int&); |
| 37 static bool serialize(PassRefPtr<DOMArrayBufferView>, ResourceRequest&, int,
int&); |
| 38 static bool serialize(PassRefPtrWillBeRawPtr<DOMFormData>, ResourceRequest&,
int, int&); |
| 39 }; |
| 40 |
| 41 template<typename Payload> |
| 42 class BeaconData final : public Beacon { |
| 43 public: |
| 44 BeaconData(const Payload& data) |
| 45 : m_data(data) |
| 46 { |
| 47 } |
| 48 |
| 49 bool serialize(ResourceRequest& request, int allowance, int& payloadLength)
const override |
| 50 { |
| 51 return Beacon::serialize(m_data, request, allowance, payloadLength); |
| 52 } |
| 53 |
| 54 unsigned long long size() const override |
| 55 { |
| 56 return beaconSize(m_data); |
| 57 } |
| 58 |
| 59 private: |
| 60 const typename WTF::ParamStorageTraits<Payload>::StorageType m_data; |
| 61 }; |
| 62 |
| 63 } // namespace |
| 64 |
| 65 class BeaconLoader::Sender { |
| 66 public: |
| 67 static bool send(LocalFrame* frame, int allowance, const KURL& beaconURL, co
nst Beacon& beacon, int& payloadLength) |
| 68 { |
| 69 unsigned long long entitySize = beacon.size(); |
| 70 if (allowance > 0 && static_cast<unsigned long long>(allowance) < entity
Size) |
| 71 return false; |
| 72 |
| 73 ResourceRequest request(beaconURL); |
| 74 request.setRequestContext(WebURLRequest::RequestContextBeacon); |
| 75 request.setHTTPMethod("POST"); |
| 76 request.setHTTPHeaderField("Cache-Control", "max-age=0"); |
| 77 request.setAllowStoredCredentials(true); |
| 78 frame->loader().fetchContext().addAdditionalRequestHeaders(frame->docume
nt(), request, FetchSubresource); |
| 79 frame->loader().fetchContext().setFirstPartyForCookies(request); |
| 80 |
| 81 payloadLength = entitySize; |
| 82 if (!beacon.serialize(request, allowance, payloadLength)) |
| 83 return false; |
| 84 |
| 85 FetchInitiatorInfo initiatorInfo; |
| 86 initiatorInfo.name = FetchInitiatorTypeNames::beacon; |
| 87 |
| 88 PingLoader::start(frame, request, initiatorInfo); |
| 89 return true; |
| 90 } |
| 91 }; |
38 | 92 |
39 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
onURL, const String& data, int& payloadLength) | 93 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
onURL, const String& data, int& payloadLength) |
40 { | 94 { |
41 ResourceRequest request(beaconURL); | 95 BeaconData<decltype(data)> beacon(data); |
42 prepareRequest(frame, request); | 96 return Sender::send(frame, allowance, beaconURL, beacon, payloadLength); |
43 | |
44 RefPtr<FormData> entityBody = FormData::create(data.utf8()); | |
45 unsigned long long entitySize = entityBody->sizeInBytes(); | |
46 if (allowance > 0 && static_cast<unsigned>(allowance) < entitySize) | |
47 return false; | |
48 | |
49 request.setHTTPBody(entityBody); | |
50 request.setHTTPContentType("text/plain;charset=UTF-8"); | |
51 | |
52 issueRequest(frame, request); | |
53 payloadLength = entitySize; | |
54 return true; | |
55 } | 97 } |
56 | 98 |
57 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
onURL, PassRefPtr<DOMArrayBufferView> data, int& payloadLength) | 99 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
onURL, PassRefPtr<DOMArrayBufferView> data, int& payloadLength) |
58 { | 100 { |
59 ASSERT(data); | 101 BeaconData<decltype(data)> beacon(data); |
60 unsigned long long entitySize = data->byteLength(); | 102 return Sender::send(frame, allowance, beaconURL, beacon, payloadLength); |
61 if (allowance > 0 && static_cast<unsigned long long>(allowance) < entitySize
) | 103 } |
62 return false; | |
63 | 104 |
64 ResourceRequest request(beaconURL); | 105 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
onURL, PassRefPtrWillBeRawPtr<DOMFormData> data, int& payloadLength) |
65 prepareRequest(frame, request); | 106 { |
66 | 107 BeaconData<decltype(data)> beacon(data); |
67 RefPtr<FormData> entityBody = FormData::create(data->baseAddress(), data->by
teLength()); | 108 return Sender::send(frame, allowance, beaconURL, beacon, payloadLength); |
68 request.setHTTPBody(entityBody.release()); | |
69 | |
70 // FIXME: a reasonable choice, but not in the spec; should it give a default
? | |
71 AtomicString contentType = AtomicString("application/octet-stream"); | |
72 request.setHTTPContentType(contentType); | |
73 | |
74 issueRequest(frame, request); | |
75 payloadLength = entitySize; | |
76 return true; | |
77 } | 109 } |
78 | 110 |
79 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
onURL, Blob* data, int& payloadLength) | 111 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
onURL, Blob* data, int& payloadLength) |
80 { | 112 { |
| 113 BeaconData<decltype(data)> beacon(data); |
| 114 return Sender::send(frame, allowance, beaconURL, beacon, payloadLength); |
| 115 } |
| 116 |
| 117 namespace { |
| 118 |
| 119 unsigned long long Beacon::beaconSize(const String& data) |
| 120 { |
| 121 return data.sizeInBytes(); |
| 122 } |
| 123 |
| 124 bool Beacon::serialize(const String& data, ResourceRequest& request, int, int&) |
| 125 { |
| 126 RefPtr<FormData> entityBody = FormData::create(data.utf8()); |
| 127 request.setHTTPBody(entityBody); |
| 128 request.setHTTPContentType("text/plain;charset=UTF-8"); |
| 129 return true; |
| 130 } |
| 131 |
| 132 unsigned long long Beacon::beaconSize(Blob* data) |
| 133 { |
| 134 return data->size(); |
| 135 } |
| 136 |
| 137 bool Beacon::serialize(Blob* data, ResourceRequest& request, int, int&) |
| 138 { |
81 ASSERT(data); | 139 ASSERT(data); |
82 unsigned long long entitySize = data->size(); | |
83 if (allowance > 0 && static_cast<unsigned long long>(allowance) < entitySize
) | |
84 return false; | |
85 | |
86 ResourceRequest request(beaconURL); | |
87 prepareRequest(frame, request); | |
88 | |
89 RefPtr<FormData> entityBody = FormData::create(); | 140 RefPtr<FormData> entityBody = FormData::create(); |
90 if (data->hasBackingFile()) | 141 if (data->hasBackingFile()) |
91 entityBody->appendFile(toFile(data)->path()); | 142 entityBody->appendFile(toFile(data)->path()); |
92 else | 143 else |
93 entityBody->appendBlob(data->uuid(), data->blobDataHandle()); | 144 entityBody->appendBlob(data->uuid(), data->blobDataHandle()); |
94 | 145 |
95 request.setHTTPBody(entityBody.release()); | 146 request.setHTTPBody(entityBody.release()); |
96 | 147 |
97 AtomicString contentType; | 148 AtomicString contentType; |
98 const String& blobType = data->type(); | 149 const String& blobType = data->type(); |
99 if (!blobType.isEmpty() && isValidContentType(blobType)) | 150 if (!blobType.isEmpty() && isValidContentType(blobType)) |
100 request.setHTTPContentType(AtomicString(contentType)); | 151 request.setHTTPContentType(AtomicString(contentType)); |
101 | 152 |
102 issueRequest(frame, request); | |
103 payloadLength = entitySize; | |
104 return true; | 153 return true; |
105 } | 154 } |
106 | 155 |
107 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
onURL, PassRefPtrWillBeRawPtr<DOMFormData> data, int& payloadLength) | 156 unsigned long long Beacon::beaconSize(PassRefPtr<DOMArrayBufferView> data) |
| 157 { |
| 158 return data->byteLength(); |
| 159 } |
| 160 |
| 161 bool Beacon::serialize(PassRefPtr<DOMArrayBufferView> data, ResourceRequest& req
uest, int, int&) |
108 { | 162 { |
109 ASSERT(data); | 163 ASSERT(data); |
110 ResourceRequest request(beaconURL); | 164 RefPtr<FormData> entityBody = FormData::create(data->baseAddress(), data->by
teLength()); |
111 prepareRequest(frame, request); | 165 request.setHTTPBody(entityBody.release()); |
112 | 166 |
| 167 // FIXME: a reasonable choice, but not in the spec; should it give a default
? |
| 168 AtomicString contentType = AtomicString("application/octet-stream"); |
| 169 request.setHTTPContentType(contentType); |
| 170 |
| 171 return true; |
| 172 } |
| 173 |
| 174 unsigned long long Beacon::beaconSize(PassRefPtrWillBeRawPtr<DOMFormData> data) |
| 175 { |
| 176 // DOMFormData's size cannot be determined until serialized. |
| 177 return 0; |
| 178 } |
| 179 |
| 180 bool Beacon::serialize(PassRefPtrWillBeRawPtr<DOMFormData> data, ResourceRequest
& request, int allowance, int& payloadLength) |
| 181 { |
| 182 ASSERT(data); |
113 RefPtr<FormData> entityBody = data->createMultiPartFormData(); | 183 RefPtr<FormData> entityBody = data->createMultiPartFormData(); |
114 | |
115 unsigned long long entitySize = entityBody->sizeInBytes(); | 184 unsigned long long entitySize = entityBody->sizeInBytes(); |
116 if (allowance > 0 && static_cast<unsigned long long>(allowance) < entitySize
) | 185 if (allowance > 0 && static_cast<unsigned long long>(allowance) < entitySize
) |
117 return false; | 186 return false; |
118 | 187 |
119 AtomicString contentType = AtomicString("multipart/form-data; boundary=", At
omicString::ConstructFromLiteral) + entityBody->boundary().data(); | 188 AtomicString contentType = AtomicString("multipart/form-data; boundary=", At
omicString::ConstructFromLiteral) + entityBody->boundary().data(); |
120 request.setHTTPBody(entityBody.release()); | 189 request.setHTTPBody(entityBody.release()); |
121 request.setHTTPContentType(contentType); | 190 request.setHTTPContentType(contentType); |
122 | 191 |
123 issueRequest(frame, request); | |
124 payloadLength = entitySize; | 192 payloadLength = entitySize; |
125 return true; | 193 return true; |
126 } | 194 } |
127 | 195 |
| 196 } // namespace |
| 197 |
128 } // namespace blink | 198 } // namespace blink |
OLD | NEW |