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 "core/loader/BeaconLoader.h" | 5 #include "core/loader/BeaconLoader.h" |
6 | 6 |
7 #include "core/dom/DOMArrayBufferView.h" | 7 #include "core/dom/DOMArrayBufferView.h" |
8 #include "core/dom/Document.h" | 8 #include "core/dom/Document.h" |
9 #include "core/fetch/CrossOriginAccessControl.h" | 9 #include "core/fetch/CrossOriginAccessControl.h" |
10 #include "core/fetch/FetchContext.h" | 10 #include "core/fetch/FetchContext.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 #include "wtf/Functional.h" | 24 #include "wtf/Functional.h" |
25 | 25 |
26 namespace blink { | 26 namespace blink { |
27 | 27 |
28 namespace { | 28 namespace { |
29 | 29 |
30 class Beacon { | 30 class Beacon { |
31 public: | 31 public: |
32 virtual bool serialize(ResourceRequest&, int, int&) const = 0; | 32 virtual bool serialize(ResourceRequest&, int, int&) const = 0; |
33 virtual unsigned long long size() const = 0; | 33 virtual unsigned long long size() const = 0; |
34 | |
35 protected: | |
36 static unsigned long long beaconSize(const String&); | |
37 static unsigned long long beaconSize(Blob*); | |
38 static unsigned long long beaconSize(DOMArrayBufferView*); | |
39 static unsigned long long beaconSize(FormData*); | |
40 | |
41 static bool serialize(const String&, ResourceRequest&, int, int&); | |
42 static bool serialize(Blob*, ResourceRequest&, int, int&); | |
43 static bool serialize(DOMArrayBufferView*, ResourceRequest&, int, int&); | |
44 static bool serialize(FormData*, ResourceRequest&, int, int&); | |
45 }; | 34 }; |
46 | 35 |
47 template<typename Payload> | 36 class BeaconString final : public Beacon { |
48 class BeaconData final : public Beacon { | |
49 public: | 37 public: |
50 BeaconData(const Payload& data) | 38 BeaconString(const String& data) |
51 : m_data(data) | 39 : m_data(data) |
52 { | 40 { |
53 } | 41 } |
54 | 42 |
55 bool serialize(ResourceRequest& request, int allowance, int& payloadLength)
const override | 43 unsigned long long size() const override |
56 { | 44 { |
57 return Beacon::serialize(m_data, request, allowance, payloadLength); | 45 return m_data.sizeInBytes(); |
| 46 } |
| 47 |
| 48 bool serialize(ResourceRequest& request, int, int&) const override |
| 49 { |
| 50 RefPtr<EncodedFormData> entityBody = EncodedFormData::create(m_data.utf8
()); |
| 51 request.setHTTPBody(entityBody); |
| 52 request.setHTTPContentType("text/plain;charset=UTF-8"); |
| 53 return true; |
| 54 } |
| 55 |
| 56 private: |
| 57 const String m_data; |
| 58 }; |
| 59 |
| 60 class BeaconBlob final : public Beacon { |
| 61 public: |
| 62 BeaconBlob(Blob* data) |
| 63 : m_data(data) |
| 64 { |
58 } | 65 } |
59 | 66 |
60 unsigned long long size() const override | 67 unsigned long long size() const override |
61 { | 68 { |
62 return beaconSize(m_data); | 69 return m_data->size(); |
| 70 } |
| 71 |
| 72 bool serialize(ResourceRequest& request, int, int&) const override |
| 73 { |
| 74 ASSERT(m_data); |
| 75 RefPtr<EncodedFormData> entityBody = EncodedFormData::create(); |
| 76 if (m_data->hasBackingFile()) |
| 77 entityBody->appendFile(toFile(m_data)->path()); |
| 78 else |
| 79 entityBody->appendBlob(m_data->uuid(), m_data->blobDataHandle()); |
| 80 |
| 81 request.setHTTPBody(entityBody.release()); |
| 82 |
| 83 const String& blobType = m_data->type(); |
| 84 if (!blobType.isEmpty() && isValidContentType(blobType)) |
| 85 request.setHTTPContentType(AtomicString(blobType)); |
| 86 |
| 87 return true; |
63 } | 88 } |
64 | 89 |
65 private: | 90 private: |
66 const typename WTF::ParamStorageTraits<Payload>::StorageType m_data; | 91 const Persistent<Blob> m_data; |
| 92 }; |
| 93 |
| 94 class BeaconDOMArrayBufferView final : public Beacon { |
| 95 public: |
| 96 BeaconDOMArrayBufferView(DOMArrayBufferView* data) |
| 97 : m_data(data) |
| 98 { |
| 99 } |
| 100 |
| 101 unsigned long long size() const override |
| 102 { |
| 103 return m_data->byteLength(); |
| 104 } |
| 105 |
| 106 bool serialize(ResourceRequest& request, int, int&) const override |
| 107 { |
| 108 ASSERT(m_data); |
| 109 RefPtr<EncodedFormData> entityBody = EncodedFormData::create(m_data->bas
eAddress(), m_data->byteLength()); |
| 110 request.setHTTPBody(entityBody.release()); |
| 111 |
| 112 // FIXME: a reasonable choice, but not in the spec; should it give a def
ault? |
| 113 AtomicString contentType = AtomicString("application/octet-stream"); |
| 114 request.setHTTPContentType(contentType); |
| 115 |
| 116 return true; |
| 117 } |
| 118 |
| 119 private: |
| 120 const Persistent<DOMArrayBufferView> m_data; |
| 121 }; |
| 122 |
| 123 class BeaconFormData final : public Beacon { |
| 124 public: |
| 125 BeaconFormData(FormData* data) |
| 126 : m_data(data) |
| 127 { |
| 128 } |
| 129 |
| 130 unsigned long long size() const override |
| 131 { |
| 132 // FormData's size cannot be determined until serialized. |
| 133 return 0; |
| 134 } |
| 135 |
| 136 bool serialize(ResourceRequest& request, int allowance, int& payloadLength)
const override |
| 137 { |
| 138 ASSERT(m_data); |
| 139 RefPtr<EncodedFormData> entityBody = m_data->encodeMultiPartFormData(); |
| 140 unsigned long long entitySize = entityBody->sizeInBytes(); |
| 141 if (allowance > 0 && static_cast<unsigned long long>(allowance) < entity
Size) |
| 142 return false; |
| 143 |
| 144 AtomicString contentType = AtomicString("multipart/form-data; boundary="
) + entityBody->boundary().data(); |
| 145 request.setHTTPBody(entityBody.release()); |
| 146 request.setHTTPContentType(contentType); |
| 147 |
| 148 payloadLength = entitySize; |
| 149 return true; |
| 150 } |
| 151 |
| 152 private: |
| 153 const Persistent<FormData> m_data; |
67 }; | 154 }; |
68 | 155 |
69 } // namespace | 156 } // namespace |
70 | 157 |
71 class BeaconLoader::Sender { | 158 class BeaconLoader::Sender { |
72 public: | 159 public: |
73 static bool send(LocalFrame* frame, int allowance, const KURL& beaconURL, co
nst Beacon& beacon, int& payloadLength) | 160 static bool send(LocalFrame* frame, int allowance, const KURL& beaconURL, co
nst Beacon& beacon, int& payloadLength) |
74 { | 161 { |
75 if (!frame->document()) | 162 if (!frame->document()) |
76 return false; | 163 return false; |
(...skipping 22 matching lines...) Expand all Loading... |
99 | 186 |
100 // The loader keeps itself alive until it receives a response and dispos
es itself. | 187 // The loader keeps itself alive until it receives a response and dispos
es itself. |
101 BeaconLoader* loader = new BeaconLoader(frame, request, initiatorInfo, A
llowStoredCredentials); | 188 BeaconLoader* loader = new BeaconLoader(frame, request, initiatorInfo, A
llowStoredCredentials); |
102 ASSERT_UNUSED(loader, loader); | 189 ASSERT_UNUSED(loader, loader); |
103 return true; | 190 return true; |
104 } | 191 } |
105 }; | 192 }; |
106 | 193 |
107 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
onURL, const String& data, int& payloadLength) | 194 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
onURL, const String& data, int& payloadLength) |
108 { | 195 { |
109 BeaconData<String> beacon(data); | 196 BeaconString beacon(data); |
110 return Sender::send(frame, allowance, beaconURL, beacon, payloadLength); | 197 return Sender::send(frame, allowance, beaconURL, beacon, payloadLength); |
111 } | 198 } |
112 | 199 |
113 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
onURL, DOMArrayBufferView* data, int& payloadLength) | 200 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
onURL, DOMArrayBufferView* data, int& payloadLength) |
114 { | 201 { |
115 BeaconData<decltype(data)> beacon(data); | 202 BeaconDOMArrayBufferView beacon(data); |
116 return Sender::send(frame, allowance, beaconURL, beacon, payloadLength); | 203 return Sender::send(frame, allowance, beaconURL, beacon, payloadLength); |
117 } | 204 } |
118 | 205 |
119 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
onURL, FormData* data, int& payloadLength) | 206 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
onURL, FormData* data, int& payloadLength) |
120 { | 207 { |
121 BeaconData<decltype(data)> beacon(data); | 208 BeaconFormData beacon(data); |
122 return Sender::send(frame, allowance, beaconURL, beacon, payloadLength); | 209 return Sender::send(frame, allowance, beaconURL, beacon, payloadLength); |
123 } | 210 } |
124 | 211 |
125 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
onURL, Blob* data, int& payloadLength) | 212 bool BeaconLoader::sendBeacon(LocalFrame* frame, int allowance, const KURL& beac
onURL, Blob* data, int& payloadLength) |
126 { | 213 { |
127 BeaconData<decltype(data)> beacon(data); | 214 BeaconBlob beacon(data); |
128 return Sender::send(frame, allowance, beaconURL, beacon, payloadLength); | 215 return Sender::send(frame, allowance, beaconURL, beacon, payloadLength); |
129 } | 216 } |
130 | 217 |
131 BeaconLoader::BeaconLoader(LocalFrame* frame, ResourceRequest& request, const Fe
tchInitiatorInfo& initiatorInfo, StoredCredentials credentialsAllowed) | 218 BeaconLoader::BeaconLoader(LocalFrame* frame, ResourceRequest& request, const Fe
tchInitiatorInfo& initiatorInfo, StoredCredentials credentialsAllowed) |
132 : PingLoader(frame, request, initiatorInfo, credentialsAllowed) | 219 : PingLoader(frame, request, initiatorInfo, credentialsAllowed) |
133 , m_beaconOrigin(frame->document()->getSecurityOrigin()) | 220 , m_beaconOrigin(frame->document()->getSecurityOrigin()) |
134 { | 221 { |
135 } | 222 } |
136 | 223 |
137 void BeaconLoader::willFollowRedirect(WebURLLoader*, WebURLRequest& passedNewReq
uest, const WebURLResponse& passedRedirectResponse) | 224 void BeaconLoader::willFollowRedirect(WebURLLoader*, WebURLRequest& passedNewReq
uest, const WebURLResponse& passedRedirectResponse) |
(...skipping 14 matching lines...) Expand all Loading... |
152 localFrame->document()->addConsoleMessage(ConsoleMessage::create
(JSMessageSource, ErrorMessageLevel, errorDescription)); | 239 localFrame->document()->addConsoleMessage(ConsoleMessage::create
(JSMessageSource, ErrorMessageLevel, errorDescription)); |
153 } | 240 } |
154 // Cancel the load and self destruct. | 241 // Cancel the load and self destruct. |
155 dispose(); | 242 dispose(); |
156 return; | 243 return; |
157 } | 244 } |
158 // FIXME: http://crbug.com/427429 is needed to correctly propagate | 245 // FIXME: http://crbug.com/427429 is needed to correctly propagate |
159 // updates of Origin: following this successful redirect. | 246 // updates of Origin: following this successful redirect. |
160 } | 247 } |
161 | 248 |
162 namespace { | |
163 | |
164 unsigned long long Beacon::beaconSize(const String& data) | |
165 { | |
166 return data.sizeInBytes(); | |
167 } | |
168 | |
169 bool Beacon::serialize(const String& data, ResourceRequest& request, int, int&) | |
170 { | |
171 RefPtr<EncodedFormData> entityBody = EncodedFormData::create(data.utf8()); | |
172 request.setHTTPBody(entityBody); | |
173 request.setHTTPContentType("text/plain;charset=UTF-8"); | |
174 return true; | |
175 } | |
176 | |
177 unsigned long long Beacon::beaconSize(Blob* data) | |
178 { | |
179 return data->size(); | |
180 } | |
181 | |
182 bool Beacon::serialize(Blob* data, ResourceRequest& request, int, int&) | |
183 { | |
184 ASSERT(data); | |
185 RefPtr<EncodedFormData> entityBody = EncodedFormData::create(); | |
186 if (data->hasBackingFile()) | |
187 entityBody->appendFile(toFile(data)->path()); | |
188 else | |
189 entityBody->appendBlob(data->uuid(), data->blobDataHandle()); | |
190 | |
191 request.setHTTPBody(entityBody.release()); | |
192 | |
193 const String& blobType = data->type(); | |
194 if (!blobType.isEmpty() && isValidContentType(blobType)) | |
195 request.setHTTPContentType(AtomicString(blobType)); | |
196 | |
197 return true; | |
198 } | |
199 | |
200 unsigned long long Beacon::beaconSize(DOMArrayBufferView* data) | |
201 { | |
202 return data->byteLength(); | |
203 } | |
204 | |
205 bool Beacon::serialize(DOMArrayBufferView* data, ResourceRequest& request, int,
int&) | |
206 { | |
207 ASSERT(data); | |
208 RefPtr<EncodedFormData> entityBody = EncodedFormData::create(data->baseAddre
ss(), data->byteLength()); | |
209 request.setHTTPBody(entityBody.release()); | |
210 | |
211 // FIXME: a reasonable choice, but not in the spec; should it give a default
? | |
212 AtomicString contentType = AtomicString("application/octet-stream"); | |
213 request.setHTTPContentType(contentType); | |
214 | |
215 return true; | |
216 } | |
217 | |
218 unsigned long long Beacon::beaconSize(FormData*) | |
219 { | |
220 // FormData's size cannot be determined until serialized. | |
221 return 0; | |
222 } | |
223 | |
224 bool Beacon::serialize(FormData* data, ResourceRequest& request, int allowance,
int& payloadLength) | |
225 { | |
226 ASSERT(data); | |
227 RefPtr<EncodedFormData> entityBody = data->encodeMultiPartFormData(); | |
228 unsigned long long entitySize = entityBody->sizeInBytes(); | |
229 if (allowance > 0 && static_cast<unsigned long long>(allowance) < entitySize
) | |
230 return false; | |
231 | |
232 AtomicString contentType = AtomicString("multipart/form-data; boundary=") +
entityBody->boundary().data(); | |
233 request.setHTTPBody(entityBody.release()); | |
234 request.setHTTPContentType(contentType); | |
235 | |
236 payloadLength = entitySize; | |
237 return true; | |
238 } | |
239 | |
240 } // namespace | |
241 | |
242 } // namespace blink | 249 } // namespace blink |
OLD | NEW |