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

Side by Side Diff: third_party/WebKit/Source/core/loader/PingLoader.cpp

Issue 2570473002: Enable the CORS preflight for sendBeacon()
Patch Set: Created 4 years 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 21 matching lines...) Expand all
32 #include "core/loader/PingLoader.h" 32 #include "core/loader/PingLoader.h"
33 33
34 #include "core/dom/DOMArrayBufferView.h" 34 #include "core/dom/DOMArrayBufferView.h"
35 #include "core/dom/Document.h" 35 #include "core/dom/Document.h"
36 #include "core/dom/SecurityContext.h" 36 #include "core/dom/SecurityContext.h"
37 #include "core/fetch/CrossOriginAccessControl.h" 37 #include "core/fetch/CrossOriginAccessControl.h"
38 #include "core/fetch/FetchContext.h" 38 #include "core/fetch/FetchContext.h"
39 #include "core/fetch/FetchInitiatorTypeNames.h" 39 #include "core/fetch/FetchInitiatorTypeNames.h"
40 #include "core/fetch/FetchUtils.h" 40 #include "core/fetch/FetchUtils.h"
41 #include "core/fetch/ResourceFetcher.h" 41 #include "core/fetch/ResourceFetcher.h"
42 #include "core/fetch/ResourceLoaderOptions.h"
42 #include "core/fetch/UniqueIdentifier.h" 43 #include "core/fetch/UniqueIdentifier.h"
43 #include "core/fileapi/File.h" 44 #include "core/fileapi/File.h"
44 #include "core/frame/FrameConsole.h" 45 #include "core/frame/FrameConsole.h"
45 #include "core/frame/LocalFrame.h" 46 #include "core/frame/LocalFrame.h"
46 #include "core/frame/csp/ContentSecurityPolicy.h" 47 #include "core/frame/csp/ContentSecurityPolicy.h"
47 #include "core/html/FormData.h" 48 #include "core/html/FormData.h"
48 #include "core/inspector/ConsoleMessage.h" 49 #include "core/inspector/ConsoleMessage.h"
49 #include "core/inspector/InspectorInstrumentation.h" 50 #include "core/inspector/InspectorInstrumentation.h"
50 #include "core/inspector/InspectorTraceEvents.h" 51 #include "core/inspector/InspectorTraceEvents.h"
51 #include "core/loader/FrameLoader.h" 52 #include "core/loader/FrameLoader.h"
52 #include "core/loader/FrameLoaderClient.h" 53 #include "core/loader/FrameLoaderClient.h"
53 #include "core/loader/MixedContentChecker.h" 54 #include "core/loader/MixedContentChecker.h"
55 #include "core/loader/ThreadableLoader.h"
56 #include "core/loader/ThreadableLoaderClient.h"
54 #include "core/page/Page.h" 57 #include "core/page/Page.h"
55 #include "platform/WebFrameScheduler.h"
56 #include "platform/exported/WrappedResourceRequest.h" 58 #include "platform/exported/WrappedResourceRequest.h"
57 #include "platform/exported/WrappedResourceResponse.h" 59 #include "platform/exported/WrappedResourceResponse.h"
58 #include "platform/network/EncodedFormData.h" 60 #include "platform/network/EncodedFormData.h"
59 #include "platform/network/ParsedContentType.h" 61 #include "platform/network/ParsedContentType.h"
60 #include "platform/network/ResourceError.h" 62 #include "platform/network/ResourceError.h"
61 #include "platform/network/ResourceRequest.h" 63 #include "platform/network/ResourceRequest.h"
62 #include "platform/network/ResourceResponse.h" 64 #include "platform/network/ResourceResponse.h"
63 #include "platform/weborigin/SecurityOrigin.h" 65 #include "platform/weborigin/SecurityOrigin.h"
64 #include "platform/weborigin/SecurityPolicy.h" 66 #include "platform/weborigin/SecurityPolicy.h"
65 #include "public/platform/Platform.h" 67 #include "public/platform/Platform.h"
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 const AtomicString getContentType() const { return m_contentType; } 183 const AtomicString getContentType() const { return m_contentType; }
182 184
183 private: 185 private:
184 const Member<FormData> m_data; 186 const Member<FormData> m_data;
185 RefPtr<EncodedFormData> m_entityBody; 187 RefPtr<EncodedFormData> m_entityBody;
186 AtomicString m_contentType; 188 AtomicString m_contentType;
187 }; 189 };
188 190
189 class PingLoaderImpl : public GarbageCollectedFinalized<PingLoaderImpl>, 191 class PingLoaderImpl : public GarbageCollectedFinalized<PingLoaderImpl>,
190 public DOMWindowProperty, 192 public DOMWindowProperty,
191 private WebURLLoaderClient { 193 private ThreadableLoaderClient {
192 USING_GARBAGE_COLLECTED_MIXIN(PingLoaderImpl); 194 USING_GARBAGE_COLLECTED_MIXIN(PingLoaderImpl);
193 WTF_MAKE_NONCOPYABLE(PingLoaderImpl); 195 WTF_MAKE_NONCOPYABLE(PingLoaderImpl);
194 196
195 public: 197 public:
196 PingLoaderImpl(LocalFrame*, 198 PingLoaderImpl(LocalFrame*,
197 ResourceRequest&, 199 ResourceRequest&,
198 const AtomicString&, 200 const AtomicString&,
199 StoredCredentials, 201 StoredCredentials);
200 bool);
201 ~PingLoaderImpl() override; 202 ~PingLoaderImpl() override;
202 203
203 DECLARE_VIRTUAL_TRACE(); 204 DECLARE_VIRTUAL_TRACE();
204 205
205 private: 206 private:
206 void dispose(); 207 void dispose();
207 208
208 // WebURLLoaderClient 209 // ThreadableLoaderClient
209 bool willFollowRedirect(WebURLRequest&, const WebURLResponse&) override; 210 void didFail(const ResourceError&) final;
210 void didReceiveResponse(const WebURLResponse&) final; 211 void didFinishLoading(unsigned long, double) final;
211 void didReceiveData(const char*, int) final;
212 void didFinishLoading(double, int64_t, int64_t) final;
213 void didFail(const WebURLError&, int64_t, int64_t) final;
214 212
215 void timeout(TimerBase*); 213 Member<ThreadableLoader> m_loader;
216
217 void didFailLoading(LocalFrame*);
218
219 std::unique_ptr<WebURLLoader> m_loader;
220 Timer<PingLoaderImpl> m_timeout;
221 String m_url; 214 String m_url;
222 unsigned long m_identifier;
223 SelfKeepAlive<PingLoaderImpl> m_keepAlive; 215 SelfKeepAlive<PingLoaderImpl> m_keepAlive;
224
225 bool m_isBeacon;
226
227 RefPtr<SecurityOrigin> m_origin;
228 CORSEnabled m_corsMode;
229 }; 216 };
230 217
231 PingLoaderImpl::PingLoaderImpl(LocalFrame* frame, 218 PingLoaderImpl::PingLoaderImpl(LocalFrame* frame,
232 ResourceRequest& request, 219 ResourceRequest& request,
233 const AtomicString& initiator, 220 const AtomicString& initiator,
234 StoredCredentials credentialsAllowed, 221 StoredCredentials credentialsAllowed)
235 bool isBeacon) 222 : DOMWindowProperty(frame), m_url(request.url()), m_keepAlive(this) {
236 : DOMWindowProperty(frame),
237 m_timeout(this, &PingLoaderImpl::timeout),
238 m_url(request.url()),
239 m_identifier(createUniqueIdentifier()),
240 m_keepAlive(this),
241 m_isBeacon(isBeacon),
242 m_origin(frame->document()->getSecurityOrigin()),
243 m_corsMode(IsCORSEnabled) {
244 const AtomicString contentType = request.httpContentType();
245 if (!contentType.isNull() &&
246 FetchUtils::isSimpleHeader(AtomicString("content-type"), contentType))
247 m_corsMode = NotCORSEnabled;
248
249 frame->loader().client()->didDispatchPingLoader(request.url()); 223 frame->loader().client()->didDispatchPingLoader(request.url());
250 224
251 FetchContext& fetchContext = frame->document()->fetcher()->context(); 225 ThreadableLoaderOptions options;
252 226 options.preflightPolicy = ConsiderPreflight;
253 fetchContext.willStartLoadingResource(m_identifier, request, Resource::Image); 227 options.crossOriginRequestPolicy = UseAccessControl;
254 228 options.initiator = initiator;
255 FetchInitiatorInfo initiatorInfo;
256 initiatorInfo.name = initiator;
257 fetchContext.dispatchWillSendRequest(m_identifier, request,
258 ResourceResponse(), initiatorInfo);
259
260 // Make sure the scheduler doesn't wait for the ping.
261 if (frame->frameScheduler())
262 frame->frameScheduler()->didStopLoading(m_identifier);
263
264 m_loader = WTF::wrapUnique(Platform::current()->createURLLoader());
265 DCHECK(m_loader);
266 WrappedResourceRequest wrappedRequest(request);
267 wrappedRequest.setAllowStoredCredentials(credentialsAllowed ==
268 AllowStoredCredentials);
269 m_loader->loadAsynchronously(wrappedRequest, this);
270
271 // If the server never responds, FrameLoader won't be able to cancel this load 229 // If the server never responds, FrameLoader won't be able to cancel this load
272 // and we'll sit here waiting forever. Set a very generous timeout, just in 230 // and we'll sit here waiting forever. Set a very generous timeout, just in
273 // case. 231 // case.
274 m_timeout.startOneShot(60000, BLINK_FROM_HERE); 232 options.timeoutMilliseconds = 60000;
233 // Make sure the scheduler doesn't wait for the ping.
234 options.schedulerWaitingPolicy = PreventSchedulerFromWaiting;
235
236 ResourceLoaderOptions resourceLoaderOptions;
237 resourceLoaderOptions.allowCredentials = AllowStoredCredentials;
238 resourceLoaderOptions.credentialsRequested = ClientRequestedCredentials;
239 resourceLoaderOptions.securityOrigin = frame->document()->getSecurityOrigin();
240 resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData;
241
242 m_loader = ThreadableLoader::create(*frame->document(), this, options,
243 resourceLoaderOptions);
244 DCHECK(m_loader);
245 m_loader->start(request);
275 } 246 }
276 247
277 PingLoaderImpl::~PingLoaderImpl() { 248 PingLoaderImpl::~PingLoaderImpl() {
278 if (m_loader)
279 m_loader->cancel();
280 } 249 }
281 250
282 void PingLoaderImpl::dispose() { 251 void PingLoaderImpl::dispose() {
283 if (m_loader) { 252 if (m_loader) {
284 m_loader->cancel(); 253 m_loader->cancel();
285 m_loader = nullptr; 254 m_loader = nullptr;
286 } 255 }
287 m_timeout.stop();
288 m_keepAlive.clear(); 256 m_keepAlive.clear();
289 } 257 }
290 258
291 bool PingLoaderImpl::willFollowRedirect( 259 void PingLoaderImpl::didFail(const ResourceError& error) {
292 WebURLRequest& passedNewRequest,
293 const WebURLResponse& passedRedirectResponse) {
294 if (!m_isBeacon)
295 return true;
296
297 if (m_corsMode == NotCORSEnabled)
298 return true;
299
300 DCHECK(passedNewRequest.allowStoredCredentials());
301
302 ResourceRequest& newRequest(passedNewRequest.toMutableResourceRequest());
303 const ResourceResponse& redirectResponse(
304 passedRedirectResponse.toResourceResponse());
305
306 DCHECK(!newRequest.isNull());
307 DCHECK(!redirectResponse.isNull());
308
309 String errorDescription;
310 ResourceLoaderOptions options;
311 // TODO(tyoshino): Save updated data in options.securityOrigin and pass it
312 // on the next time.
313 if (!CrossOriginAccessControl::handleRedirect(
314 m_origin, newRequest, redirectResponse, AllowStoredCredentials,
315 options, errorDescription)) {
316 if (LocalFrame* localFrame = frame()) {
317 if (localFrame->document()) {
318 localFrame->document()->addConsoleMessage(ConsoleMessage::create(
319 JSMessageSource, ErrorMessageLevel, errorDescription));
320 }
321 }
322 // Cancel the load and self destruct.
323 dispose();
324
325 return false;
326 }
327 // FIXME: http://crbug.com/427429 is needed to correctly propagate updates of
328 // Origin: following this successful redirect.
329
330 return true;
331 }
332
333 void PingLoaderImpl::didReceiveResponse(const WebURLResponse& response) {
334 if (LocalFrame* frame = this->frame()) {
335 TRACE_EVENT1("devtools.timeline", "ResourceFinish", "data",
336 InspectorResourceFinishEvent::data(m_identifier, 0, true));
337 const ResourceResponse& resourceResponse = response.toResourceResponse();
338 InspectorInstrumentation::didReceiveResourceResponse(frame, m_identifier, 0,
339 resourceResponse, 0);
340 didFailLoading(frame);
341 }
342 dispose(); 260 dispose();
343 } 261 }
344 262
345 void PingLoaderImpl::didReceiveData(const char*, int) { 263 void PingLoaderImpl::didFinishLoading(unsigned long, double) {
346 if (LocalFrame* frame = this->frame()) {
347 TRACE_EVENT1("devtools.timeline", "ResourceFinish", "data",
348 InspectorResourceFinishEvent::data(m_identifier, 0, true));
349 didFailLoading(frame);
350 }
351 dispose(); 264 dispose();
352 } 265 }
353 266
354 void PingLoaderImpl::didFinishLoading(double, int64_t, int64_t) {
355 if (LocalFrame* frame = this->frame()) {
356 TRACE_EVENT1("devtools.timeline", "ResourceFinish", "data",
357 InspectorResourceFinishEvent::data(m_identifier, 0, true));
358 didFailLoading(frame);
359 }
360 dispose();
361 }
362
363 void PingLoaderImpl::didFail(const WebURLError& resourceError,
364 int64_t,
365 int64_t) {
366 if (LocalFrame* frame = this->frame()) {
367 TRACE_EVENT1("devtools.timeline", "ResourceFinish", "data",
368 InspectorResourceFinishEvent::data(m_identifier, 0, true));
369 didFailLoading(frame);
370 }
371 dispose();
372 }
373
374 void PingLoaderImpl::timeout(TimerBase*) {
375 if (LocalFrame* frame = this->frame()) {
376 TRACE_EVENT1("devtools.timeline", "ResourceFinish", "data",
377 InspectorResourceFinishEvent::data(m_identifier, 0, true));
378 didFailLoading(frame);
379 }
380 dispose();
381 }
382
383 void PingLoaderImpl::didFailLoading(LocalFrame* frame) {
384 InspectorInstrumentation::didFailLoading(
385 frame, m_identifier, ResourceError::cancelledError(m_url));
386 frame->console().didFailLoading(m_identifier,
387 ResourceError::cancelledError(m_url));
388 }
389
390 DEFINE_TRACE(PingLoaderImpl) { 267 DEFINE_TRACE(PingLoaderImpl) {
268 visitor->trace(m_loader);
391 DOMWindowProperty::trace(visitor); 269 DOMWindowProperty::trace(visitor);
392 } 270 }
393 271
394 void finishPingRequestInitialization( 272 void finishPingRequestInitialization(
395 ResourceRequest& request, 273 ResourceRequest& request,
396 LocalFrame* frame, 274 LocalFrame* frame,
397 WebURLRequest::RequestContext requestContext) { 275 WebURLRequest::RequestContext requestContext) {
398 request.setRequestContext(requestContext); 276 request.setRequestContext(requestContext);
399 FetchContext& fetchContext = frame->document()->fetcher()->context(); 277 FetchContext& fetchContext = frame->document()->fetcher()->context();
400 fetchContext.addAdditionalRequestHeaders(request, FetchSubresource); 278 fetchContext.addAdditionalRequestHeaders(request, FetchSubresource);
401 fetchContext.populateRequestData(request); 279 fetchContext.populateRequestData(request);
402 } 280 }
403 281
404 bool sendPingCommon(LocalFrame* frame, 282 bool sendPingCommon(LocalFrame* frame,
405 ResourceRequest& request, 283 ResourceRequest& request,
406 const AtomicString& initiator, 284 const AtomicString& initiator,
407 StoredCredentials credentialsAllowed, 285 StoredCredentials credentialsAllowed,
408 bool isBeacon) { 286 bool isBeacon) {
409 if (MixedContentChecker::shouldBlockFetch(frame, request, request.url())) 287 if (MixedContentChecker::shouldBlockFetch(frame, request, request.url()))
410 return false; 288 return false;
411 289
412 // The loader keeps itself alive until it receives a response and disposes 290 // The loader keeps itself alive until it receives a response and disposes
413 // itself. 291 // itself.
414 PingLoaderImpl* loader = 292 PingLoaderImpl* loader =
415 new PingLoaderImpl(frame, request, initiator, credentialsAllowed, true); 293 new PingLoaderImpl(frame, request, initiator, credentialsAllowed);
416 DCHECK(loader); 294 DCHECK(loader);
417 295
418 return true; 296 return true;
419 } 297 }
420 298
421 bool sendBeaconCommon(LocalFrame* frame, 299 bool sendBeaconCommon(LocalFrame* frame,
422 int allowance, 300 int allowance,
423 const KURL& url, 301 const KURL& url,
424 const Beacon& beacon, 302 const Beacon& beacon,
425 int& payloadLength) { 303 int& payloadLength) {
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 bool PingLoader::sendBeacon(LocalFrame* frame, 431 bool PingLoader::sendBeacon(LocalFrame* frame,
554 int allowance, 432 int allowance,
555 const KURL& beaconURL, 433 const KURL& beaconURL,
556 Blob* data, 434 Blob* data,
557 int& payloadLength) { 435 int& payloadLength) {
558 BeaconBlob beacon(data); 436 BeaconBlob beacon(data);
559 return sendBeaconCommon(frame, allowance, beaconURL, beacon, payloadLength); 437 return sendBeaconCommon(frame, allowance, beaconURL, beacon, payloadLength);
560 } 438 }
561 439
562 } // namespace blink 440 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698