Mark more heap-allocated classes as fast allocated
[WebKit-https.git] / Source / WebCore / loader / ResourceLoader.cpp
1 /*
2  * Copyright (C) 2006-2018 Apple Inc. All rights reserved.
3  *           (C) 2007 Graham Dennis (graham.dennis@gmail.com)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer. 
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution. 
14  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission. 
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "ResourceLoader.h"
32
33 #include "ApplicationCacheHost.h"
34 #include "AuthenticationChallenge.h"
35 #include "DataURLDecoder.h"
36 #include "DiagnosticLoggingClient.h"
37 #include "DiagnosticLoggingKeys.h"
38 #include "DocumentLoader.h"
39 #include "Frame.h"
40 #include "FrameLoader.h"
41 #include "FrameLoaderClient.h"
42 #include "InspectorInstrumentation.h"
43 #include "LoaderStrategy.h"
44 #include "Logging.h"
45 #include "Page.h"
46 #include "PlatformStrategies.h"
47 #include "ProgressTracker.h"
48 #include "ResourceError.h"
49 #include "ResourceHandle.h"
50 #include "SecurityOrigin.h"
51 #include "SharedBuffer.h"
52 #include <wtf/CompletionHandler.h>
53 #include <wtf/Ref.h>
54
55 #if ENABLE(CONTENT_EXTENSIONS)
56 #include "UserContentController.h"
57 #endif
58
59 #if USE(QUICK_LOOK)
60 #include "PreviewConverter.h"
61 #include "PreviewLoader.h"
62 #endif
63
64 #undef RELEASE_LOG_IF_ALLOWED
65 #define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), Network, "%p - ResourceLoader::" fmt, this, ##__VA_ARGS__)
66
67 namespace WebCore {
68
69 ResourceLoader::ResourceLoader(Frame& frame, ResourceLoaderOptions options)
70     : m_frame { &frame }
71     , m_documentLoader { frame.loader().activeDocumentLoader() }
72     , m_defersLoading { options.defersLoadingPolicy == DefersLoadingPolicy::AllowDefersLoading && frame.page()->defersLoading() }
73     , m_options { options }
74 {
75 }
76
77 ResourceLoader::~ResourceLoader()
78 {
79     ASSERT(m_reachedTerminalState);
80 }
81
82 void ResourceLoader::finishNetworkLoad()
83 {
84     platformStrategies()->loaderStrategy()->remove(this);
85
86     if (m_handle) {
87         ASSERT(m_handle->client() == this);
88         m_handle->clearClient();
89         m_handle = nullptr;
90     }
91 }
92
93 void ResourceLoader::releaseResources()
94 {
95     ASSERT(!m_reachedTerminalState);
96     
97     // It's possible that when we release the handle, it will be
98     // deallocated and release the last reference to this object.
99     // We need to retain to avoid accessing the object after it
100     // has been deallocated and also to avoid reentering this method.
101     Ref<ResourceLoader> protectedThis(*this);
102
103     m_frame = nullptr;
104     m_documentLoader = nullptr;
105     
106     // We need to set reachedTerminalState to true before we release
107     // the resources to prevent a double dealloc of WebView <rdar://problem/4372628>
108     m_reachedTerminalState = true;
109
110     finishNetworkLoad();
111
112     m_identifier = 0;
113
114     m_resourceData = nullptr;
115     m_deferredRequest = ResourceRequest();
116 }
117
118 void ResourceLoader::init(ResourceRequest&& clientRequest, CompletionHandler<void(bool)>&& completionHandler)
119 {
120     ASSERT(!m_handle);
121     ASSERT(m_request.isNull());
122     ASSERT(m_deferredRequest.isNull());
123     ASSERT(!m_documentLoader->isSubstituteLoadPending(this));
124     
125     m_loadTiming.markStartTimeAndFetchStart();
126
127 #if PLATFORM(IOS_FAMILY)
128     // If the documentLoader was detached while this ResourceLoader was waiting its turn
129     // in ResourceLoadScheduler queue, don't continue.
130     if (!m_documentLoader->frame()) {
131         cancel();
132         return completionHandler(false);
133     }
134 #endif
135     
136     m_defersLoading = m_options.defersLoadingPolicy == DefersLoadingPolicy::AllowDefersLoading && m_frame->page()->defersLoading();
137
138     if (m_options.securityCheck == SecurityCheckPolicy::DoSecurityCheck && !m_frame->document()->securityOrigin().canDisplay(clientRequest.url())) {
139         FrameLoader::reportLocalLoadFailed(m_frame.get(), clientRequest.url().string());
140         releaseResources();
141         return completionHandler(false);
142     }
143
144     // The various plug-in implementations call directly to ResourceLoader::load() instead of piping requests
145     // through FrameLoader. As a result, they miss the FrameLoader::addExtraFieldsToRequest() step which sets
146     // up the 1st party for cookies URL and Same-Site info. Until plug-in implementations can be reigned in
147     // to pipe through that method, we need to make sure there is always both a 1st party for cookies set and
148     // Same-Site info. See <https://bugs.webkit.org/show_bug.cgi?id=26391>.
149     if (clientRequest.firstPartyForCookies().isNull()) {
150         if (Document* document = m_frame->document())
151             clientRequest.setFirstPartyForCookies(document->firstPartyForCookies());
152     }
153     FrameLoader::addSameSiteInfoToRequestIfNeeded(clientRequest, m_frame->document());
154
155     willSendRequestInternal(WTFMove(clientRequest), ResourceResponse(), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](ResourceRequest&& request) mutable {
156
157 #if PLATFORM(IOS_FAMILY)
158         // If this ResourceLoader was stopped as a result of willSendRequest, bail out.
159         if (m_reachedTerminalState)
160             return completionHandler(false);
161 #endif
162
163         if (request.isNull()) {
164             cancel();
165             return completionHandler(false);
166         }
167
168         m_request = WTFMove(request);
169         m_originalRequest = m_request;
170         completionHandler(true);
171     });
172 }
173
174 void ResourceLoader::deliverResponseAndData(const ResourceResponse& response, RefPtr<SharedBuffer>&& buffer)
175 {
176     didReceiveResponse(response, [this, protectedThis = makeRef(*this), buffer = WTFMove(buffer)]() mutable {
177         if (reachedTerminalState())
178             return;
179
180         if (buffer) {
181             unsigned size = buffer->size();
182             didReceiveBuffer(buffer.releaseNonNull(), size, DataPayloadWholeResource);
183             if (reachedTerminalState())
184                 return;
185         }
186
187         NetworkLoadMetrics emptyMetrics;
188         didFinishLoading(emptyMetrics);
189     });
190 }
191
192 void ResourceLoader::start()
193 {
194     ASSERT(!m_handle);
195     ASSERT(!m_request.isNull());
196     ASSERT(m_deferredRequest.isNull());
197     ASSERT(frameLoader());
198
199 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
200     if (m_documentLoader->scheduleArchiveLoad(*this, m_request))
201         return;
202 #endif
203
204     if (m_documentLoader->applicationCacheHost().maybeLoadResource(*this, m_request, m_request.url()))
205         return;
206
207     if (m_defersLoading) {
208         m_deferredRequest = m_request;
209         return;
210     }
211
212     if (m_reachedTerminalState)
213         return;
214
215     if (m_request.url().protocolIsData()) {
216         loadDataURL();
217         return;
218     }
219
220 #if USE(SOUP)
221     if (m_request.url().protocolIs("resource")) {
222         loadGResource();
223         return;
224     }
225 #endif
226
227     m_handle = ResourceHandle::create(frameLoader()->networkingContext(), m_request, this, m_defersLoading, m_options.sniffContent == ContentSniffingPolicy::SniffContent, m_options.sniffContentEncoding == ContentEncodingSniffingPolicy::Sniff);
228 }
229
230 void ResourceLoader::setDefersLoading(bool defers)
231 {
232     if (m_options.defersLoadingPolicy == DefersLoadingPolicy::DisallowDefersLoading)
233         return;
234
235     m_defersLoading = defers;
236     if (m_handle)
237         m_handle->setDefersLoading(defers);
238
239     platformStrategies()->loaderStrategy()->setDefersLoading(*this, defers);
240 }
241
242 FrameLoader* ResourceLoader::frameLoader() const
243 {
244     if (!m_frame)
245         return nullptr;
246     return &m_frame->loader();
247 }
248
249 void ResourceLoader::loadDataURL()
250 {
251     auto url = m_request.url();
252     ASSERT(url.protocolIsData());
253
254     DataURLDecoder::ScheduleContext scheduleContext;
255 #if HAVE(RUNLOOP_TIMER)
256     if (auto* scheduledPairs = m_frame->page()->scheduledRunLoopPairs())
257         scheduleContext.scheduledPairs = *scheduledPairs;
258 #endif
259     DataURLDecoder::decode(url, scheduleContext, [this, protectedThis = makeRef(*this), url](auto decodeResult) mutable {
260         if (this->reachedTerminalState())
261             return;
262         if (!decodeResult) {
263             RELEASE_LOG_IF_ALLOWED("loadDataURL: decoding of data failed (frame = %p, frameLoader = %p, resourceID = %lu)", frame(), frameLoader(), identifier());
264             protectedThis->didFail(ResourceError(errorDomainWebKitInternal, 0, url, "Data URL decoding failed"));
265             return;
266         }
267         if (this->wasCancelled())
268             return;
269         auto& result = decodeResult.value();
270         auto dataSize = result.data ? result.data->size() : 0;
271
272         ResourceResponse dataResponse { url, result.mimeType, static_cast<long long>(dataSize), result.charset };
273         dataResponse.setHTTPStatusCode(200);
274         dataResponse.setHTTPStatusText("OK"_s);
275         dataResponse.setHTTPHeaderField(HTTPHeaderName::ContentType, result.contentType);
276         dataResponse.setSource(ResourceResponse::Source::Network);
277         this->didReceiveResponse(dataResponse, [this, protectedThis = WTFMove(protectedThis), dataSize, data = result.data.releaseNonNull()]() mutable {
278             if (!this->reachedTerminalState() && dataSize)
279                 this->didReceiveBuffer(WTFMove(data), dataSize, DataPayloadWholeResource);
280
281             if (!this->reachedTerminalState()) {
282                 NetworkLoadMetrics emptyMetrics;
283                 this->didFinishLoading(emptyMetrics);
284             }
285         });
286     });
287 }
288
289 void ResourceLoader::setDataBufferingPolicy(DataBufferingPolicy dataBufferingPolicy)
290 {
291     m_options.dataBufferingPolicy = dataBufferingPolicy;
292
293     // Reset any already buffered data
294     if (dataBufferingPolicy == DataBufferingPolicy::DoNotBufferData)
295         m_resourceData = nullptr;
296 }
297
298 void ResourceLoader::willSwitchToSubstituteResource()
299 {
300     ASSERT(!m_documentLoader->isSubstituteLoadPending(this));
301     platformStrategies()->loaderStrategy()->remove(this);
302     if (m_handle)
303         m_handle->cancel();
304 }
305
306 void ResourceLoader::addDataOrBuffer(const char* data, unsigned length, SharedBuffer* buffer, DataPayloadType dataPayloadType)
307 {
308     if (m_options.dataBufferingPolicy == DataBufferingPolicy::DoNotBufferData)
309         return;
310
311     if (!m_resourceData || dataPayloadType == DataPayloadWholeResource) {
312         if (buffer)
313             m_resourceData = buffer;
314         else
315             m_resourceData = SharedBuffer::create(data, length);
316         return;
317     }
318     
319     if (buffer)
320         m_resourceData->append(*buffer);
321     else
322         m_resourceData->append(data, length);
323 }
324
325 void ResourceLoader::clearResourceData()
326 {
327     if (m_resourceData)
328         m_resourceData->clear();
329 }
330
331 bool ResourceLoader::isSubresourceLoader() const
332 {
333     return false;
334 }
335
336 void ResourceLoader::willSendRequestInternal(ResourceRequest&& request, const ResourceResponse& redirectResponse, CompletionHandler<void(ResourceRequest&&)>&& completionHandler)
337 {
338     // Protect this in this delegate method since the additional processing can do
339     // anything including possibly derefing this; one example of this is Radar 3266216.
340     Ref<ResourceLoader> protectedThis(*this);
341
342     ASSERT(!m_reachedTerminalState);
343 #if ENABLE(CONTENT_EXTENSIONS)
344     ASSERT(m_resourceType != ResourceType::Invalid);
345 #endif
346
347     // We need a resource identifier for all requests, even if FrameLoader is never going to see it (such as with CORS preflight requests).
348     bool createdResourceIdentifier = false;
349     if (!m_identifier) {
350         m_identifier = m_frame->page()->progress().createUniqueIdentifier();
351         createdResourceIdentifier = true;
352     }
353
354 #if ENABLE(CONTENT_EXTENSIONS)
355     if (!redirectResponse.isNull() && frameLoader()) {
356         Page* page = frameLoader()->frame().page();
357         if (page && m_documentLoader) {
358             auto blockedStatus = page->userContentProvider().processContentExtensionRulesForLoad(request.url(), m_resourceType, *m_documentLoader);
359             applyBlockedStatusToRequest(blockedStatus, page, request);
360             if (blockedStatus.blockedLoad) {
361                 RELEASE_LOG_IF_ALLOWED("willSendRequestinternal: resource load canceled because of content blocker (frame = %p, frameLoader = %p, resourceID = %lu)", frame(), frameLoader(), identifier());
362                 didFail(blockedByContentBlockerError());
363                 completionHandler({ });
364                 return;
365             }
366         }
367     }
368 #endif
369
370     if (request.isNull()) {
371         RELEASE_LOG_IF_ALLOWED("willSendRequestinternal: resource load canceled because of empty request (frame = %p, frameLoader = %p, resourceID = %lu)", frame(), frameLoader(), identifier());
372         didFail(cannotShowURLError());
373         completionHandler({ });
374         return;
375     }
376
377     if (m_options.sendLoadCallbacks == SendCallbackPolicy::SendCallbacks) {
378         if (createdResourceIdentifier)
379             frameLoader()->notifier().assignIdentifierToInitialRequest(m_identifier, documentLoader(), request);
380
381 #if PLATFORM(IOS_FAMILY)
382         // If this ResourceLoader was stopped as a result of assignIdentifierToInitialRequest, bail out
383         if (m_reachedTerminalState) {
384             completionHandler(WTFMove(request));
385             return;
386         }
387 #endif
388
389         frameLoader()->notifier().willSendRequest(this, request, redirectResponse);
390     }
391     else
392         InspectorInstrumentation::willSendRequest(m_frame.get(), m_identifier, m_frame->loader().documentLoader(), request, redirectResponse);
393
394 #if USE(QUICK_LOOK)
395     if (auto previewConverter = m_documentLoader->previewConverter())
396         request = previewConverter->safeRequest(request);
397 #endif
398
399     bool isRedirect = !redirectResponse.isNull();
400     if (isRedirect)
401         platformStrategies()->loaderStrategy()->crossOriginRedirectReceived(this, request.url());
402
403     m_request = request;
404
405     if (isRedirect) {
406         auto& redirectURL = request.url();
407         if (!m_documentLoader->isCommitted())
408             frameLoader()->client().dispatchDidReceiveServerRedirectForProvisionalLoad();
409
410         if (redirectURL.protocolIsData()) {
411             // Handle data URL decoding locally.
412             finishNetworkLoad();
413             loadDataURL();
414         }
415     }
416     completionHandler(WTFMove(request));
417 }
418
419 void ResourceLoader::willSendRequest(ResourceRequest&& request, const ResourceResponse& redirectResponse, CompletionHandler<void(ResourceRequest&&)>&& completionHandler)
420 {
421     willSendRequestInternal(WTFMove(request), redirectResponse, WTFMove(completionHandler));
422 }
423
424 void ResourceLoader::didSendData(unsigned long long, unsigned long long)
425 {
426 }
427
428 static void logResourceResponseSource(Frame* frame, ResourceResponse::Source source)
429 {
430     if (!frame || !frame->page())
431         return;
432
433     String sourceKey;
434     switch (source) {
435     case ResourceResponse::Source::Network:
436         sourceKey = DiagnosticLoggingKeys::networkKey();
437         break;
438     case ResourceResponse::Source::DiskCache:
439         sourceKey = DiagnosticLoggingKeys::diskCacheKey();
440         break;
441     case ResourceResponse::Source::DiskCacheAfterValidation:
442         sourceKey = DiagnosticLoggingKeys::diskCacheAfterValidationKey();
443         break;
444     case ResourceResponse::Source::ServiceWorker:
445         sourceKey = DiagnosticLoggingKeys::serviceWorkerKey();
446         break;
447     case ResourceResponse::Source::MemoryCache:
448     case ResourceResponse::Source::MemoryCacheAfterValidation:
449     case ResourceResponse::Source::ApplicationCache:
450     case ResourceResponse::Source::Unknown:
451         return;
452     }
453
454     frame->page()->diagnosticLoggingClient().logDiagnosticMessage(DiagnosticLoggingKeys::resourceResponseSourceKey(), sourceKey, ShouldSample::Yes);
455 }
456
457 bool ResourceLoader::shouldAllowResourceToAskForCredentials() const
458 {
459     return m_canCrossOriginRequestsAskUserForCredentials || m_frame->tree().top().document()->securityOrigin().canRequest(m_request.url());
460 }
461
462 void ResourceLoader::didBlockAuthenticationChallenge()
463 {
464     m_wasAuthenticationChallengeBlocked = true;
465     if (m_options.clientCredentialPolicy == ClientCredentialPolicy::CannotAskClientForCredentials)
466         return;
467     ASSERT(!shouldAllowResourceToAskForCredentials());
468     FrameLoader::reportAuthenticationChallengeBlocked(m_frame.get(), m_request.url(), "it is a cross-origin request"_s);
469 }
470
471 void ResourceLoader::didReceiveResponse(const ResourceResponse& r, CompletionHandler<void()>&& policyCompletionHandler)
472 {
473     ASSERT(!m_reachedTerminalState);
474     CompletionHandlerCallingScope completionHandlerCaller(WTFMove(policyCompletionHandler));
475
476     // Protect this in this delegate method since the additional processing can do
477     // anything including possibly derefing this; one example of this is Radar 3266216.
478     Ref<ResourceLoader> protectedThis(*this);
479
480     logResourceResponseSource(m_frame.get(), r.source());
481
482     m_response = r;
483
484     if (FormData* data = m_request.httpBody())
485         data->removeGeneratedFilesIfNeeded();
486
487     if (m_options.sendLoadCallbacks == SendCallbackPolicy::SendCallbacks)
488         frameLoader()->notifier().didReceiveResponse(this, m_response);
489 }
490
491 void ResourceLoader::didReceiveData(const char* data, unsigned length, long long encodedDataLength, DataPayloadType dataPayloadType)
492 {
493     // The following assertions are not quite valid here, since a subclass
494     // might override didReceiveData in a way that invalidates them. This
495     // happens with the steps listed in 3266216
496     // ASSERT(con == connection);
497     // ASSERT(!m_reachedTerminalState);
498
499     didReceiveDataOrBuffer(data, length, nullptr, encodedDataLength, dataPayloadType);
500 }
501
502 void ResourceLoader::didReceiveBuffer(Ref<SharedBuffer>&& buffer, long long encodedDataLength, DataPayloadType dataPayloadType)
503 {
504     didReceiveDataOrBuffer(nullptr, 0, WTFMove(buffer), encodedDataLength, dataPayloadType);
505 }
506
507 void ResourceLoader::didReceiveDataOrBuffer(const char* data, unsigned length, RefPtr<SharedBuffer>&& buffer, long long encodedDataLength, DataPayloadType dataPayloadType)
508 {
509     // This method should only get data+length *OR* a SharedBuffer.
510     ASSERT(!buffer || (!data && !length));
511
512     // Protect this in this delegate method since the additional processing can do
513     // anything including possibly derefing this; one example of this is Radar 3266216.
514     Ref<ResourceLoader> protectedThis(*this);
515
516     addDataOrBuffer(data, length, buffer.get(), dataPayloadType);
517
518     // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
519     // However, with today's computers and networking speeds, this won't happen in practice.
520     // Could be an issue with a giant local file.
521     if (m_options.sendLoadCallbacks == SendCallbackPolicy::SendCallbacks && m_frame)
522         frameLoader()->notifier().didReceiveData(this, buffer ? buffer->data() : data, buffer ? buffer->size() : length, static_cast<int>(encodedDataLength));
523 }
524
525 void ResourceLoader::didFinishLoading(const NetworkLoadMetrics& networkLoadMetrics)
526 {
527     RELEASE_LOG_IF_ALLOWED("didFinishLoading: (frame = %p, frameLoader = %p, resourceID = %lu)", frame(), frameLoader(), identifier());
528
529     didFinishLoadingOnePart(networkLoadMetrics);
530
531     // If the load has been cancelled by a delegate in response to didFinishLoad(), do not release
532     // the resources a second time, they have been released by cancel.
533     if (wasCancelled())
534         return;
535     releaseResources();
536 }
537
538 void ResourceLoader::didFinishLoadingOnePart(const NetworkLoadMetrics& networkLoadMetrics)
539 {
540     // If load has been cancelled after finishing (which could happen with a
541     // JavaScript that changes the window location), do nothing.
542     if (wasCancelled())
543         return;
544     ASSERT(!m_reachedTerminalState);
545
546     if (m_notifiedLoadComplete)
547         return;
548     m_notifiedLoadComplete = true;
549     if (m_options.sendLoadCallbacks == SendCallbackPolicy::SendCallbacks)
550         frameLoader()->notifier().didFinishLoad(this, networkLoadMetrics);
551 }
552
553 void ResourceLoader::didFail(const ResourceError& error)
554 {
555     RELEASE_LOG_IF_ALLOWED("didFail: (frame = %p, frameLoader = %p, resourceID = %lu)", frame(), frameLoader(), identifier());
556
557     if (wasCancelled())
558         return;
559     ASSERT(!m_reachedTerminalState);
560
561     // Protect this in this delegate method since the additional processing can do
562     // anything including possibly derefing this; one example of this is Radar 3266216.
563     Ref<ResourceLoader> protectedThis(*this);
564
565     cleanupForError(error);
566     releaseResources();
567 }
568
569 void ResourceLoader::cleanupForError(const ResourceError& error)
570 {
571     if (FormData* data = m_request.httpBody())
572         data->removeGeneratedFilesIfNeeded();
573
574     if (m_notifiedLoadComplete)
575         return;
576     m_notifiedLoadComplete = true;
577     if (m_options.sendLoadCallbacks == SendCallbackPolicy::SendCallbacks && m_identifier)
578         frameLoader()->notifier().didFailToLoad(this, error);
579 }
580
581 void ResourceLoader::cancel()
582 {
583     cancel(ResourceError());
584 }
585
586 void ResourceLoader::cancel(const ResourceError& error)
587 {
588     // If the load has already completed - succeeded, failed, or previously cancelled - do nothing.
589     if (m_reachedTerminalState)
590         return;
591        
592     ResourceError nonNullError = error.isNull() ? cancelledError() : error;
593     
594     // willCancel() and didFailToLoad() both call out to clients that might do 
595     // something causing the last reference to this object to go away.
596     Ref<ResourceLoader> protectedThis(*this);
597     
598     // If we re-enter cancel() from inside willCancel(), we want to pick up from where we left 
599     // off without re-running willCancel()
600     if (m_cancellationStatus == NotCancelled) {
601         m_cancellationStatus = CalledWillCancel;
602         
603         willCancel(nonNullError);
604     }
605
606     // If we re-enter cancel() from inside didFailToLoad(), we want to pick up from where we 
607     // left off without redoing any of this work.
608     if (m_cancellationStatus == CalledWillCancel) {
609         m_cancellationStatus = Cancelled;
610
611         if (m_handle)
612             m_handle->clearAuthentication();
613
614         m_documentLoader->cancelPendingSubstituteLoad(this);
615         if (m_handle) {
616             m_handle->cancel();
617             m_handle = nullptr;
618         }
619         cleanupForError(nonNullError);
620     }
621
622     // If cancel() completed from within the call to willCancel() or didFailToLoad(),
623     // we don't want to redo didCancel() or releasesResources().
624     if (m_reachedTerminalState)
625         return;
626
627     didCancel(nonNullError);
628
629     if (m_cancellationStatus == FinishedCancel)
630         return;
631     m_cancellationStatus = FinishedCancel;
632
633     releaseResources();
634 }
635
636 ResourceError ResourceLoader::cancelledError()
637 {
638     return frameLoader()->cancelledError(m_request);
639 }
640
641 ResourceError ResourceLoader::blockedError()
642 {
643     return frameLoader()->client().blockedError(m_request);
644 }
645
646 ResourceError ResourceLoader::blockedByContentBlockerError()
647 {
648     return frameLoader()->client().blockedByContentBlockerError(m_request);
649 }
650
651 ResourceError ResourceLoader::cannotShowURLError()
652 {
653     return frameLoader()->client().cannotShowURLError(m_request);
654 }
655
656 void ResourceLoader::willSendRequestAsync(ResourceHandle* handle, ResourceRequest&& request, ResourceResponse&& redirectResponse, CompletionHandler<void(ResourceRequest&&)>&& completionHandler)
657 {
658     RefPtr<ResourceHandle> protectedHandle(handle);
659     if (documentLoader()->applicationCacheHost().maybeLoadFallbackForRedirect(this, request, redirectResponse)) {
660         RELEASE_LOG_IF_ALLOWED("willSendRequestAsync: exiting early because maybeLoadFallbackForRedirect returned false (frame = %p, frameLoader = %p, resourceID = %lu)", frame(), frameLoader(), identifier());
661         completionHandler(WTFMove(request));
662         return;
663     }
664     willSendRequestInternal(WTFMove(request), redirectResponse, WTFMove(completionHandler));
665 }
666
667 void ResourceLoader::didSendData(ResourceHandle*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
668 {
669     didSendData(bytesSent, totalBytesToBeSent);
670 }
671
672 void ResourceLoader::didReceiveResponseAsync(ResourceHandle*, ResourceResponse&& response, CompletionHandler<void()>&& completionHandler)
673 {
674     if (documentLoader()->applicationCacheHost().maybeLoadFallbackForResponse(this, response)) {
675         completionHandler();
676         return;
677     }
678     didReceiveResponse(response, WTFMove(completionHandler));
679 }
680
681 void ResourceLoader::didReceiveData(ResourceHandle*, const char* data, unsigned length, int encodedDataLength)
682 {
683     didReceiveData(data, length, encodedDataLength, DataPayloadBytes);
684 }
685
686 void ResourceLoader::didReceiveBuffer(ResourceHandle*, Ref<SharedBuffer>&& buffer, int encodedDataLength)
687 {
688     didReceiveBuffer(WTFMove(buffer), encodedDataLength, DataPayloadBytes);
689 }
690
691 void ResourceLoader::didFinishLoading(ResourceHandle*)
692 {
693     NetworkLoadMetrics emptyMetrics;
694     didFinishLoading(emptyMetrics);
695 }
696
697 void ResourceLoader::didFail(ResourceHandle*, const ResourceError& error)
698 {
699     if (documentLoader()->applicationCacheHost().maybeLoadFallbackForError(this, error))
700         return;
701     didFail(error);
702 }
703
704 void ResourceLoader::wasBlocked(ResourceHandle*)
705 {
706     RELEASE_LOG_IF_ALLOWED("wasBlocked: resource load canceled because of content blocker (frame = %p, frameLoader = %p, resourceID = %lu)", frame(), frameLoader(), identifier());
707     didFail(blockedError());
708 }
709
710 void ResourceLoader::cannotShowURL(ResourceHandle*)
711 {
712     RELEASE_LOG_IF_ALLOWED("wasBlocked: resource load canceled because of invalid URL (frame = %p, frameLoader = %p, resourceID = %lu)", frame(), frameLoader(), identifier());
713     didFail(cannotShowURLError());
714 }
715
716 bool ResourceLoader::shouldUseCredentialStorage()
717 {
718     if (m_options.storedCredentialsPolicy == StoredCredentialsPolicy::DoNotUse)
719         return false;
720
721     Ref<ResourceLoader> protectedThis(*this);
722     return frameLoader()->client().shouldUseCredentialStorage(documentLoader(), identifier());
723 }
724
725 bool ResourceLoader::isAllowedToAskUserForCredentials() const
726 {
727     if (m_options.clientCredentialPolicy == ClientCredentialPolicy::CannotAskClientForCredentials)
728         return false;
729     if (!shouldAllowResourceToAskForCredentials())
730         return false;
731     return m_options.credentials == FetchOptions::Credentials::Include || (m_options.credentials == FetchOptions::Credentials::SameOrigin && m_frame->document()->securityOrigin().canRequest(originalRequest().url()));
732 }
733
734 bool ResourceLoader::shouldIncludeCertificateInfo() const
735 {
736     if (m_options.certificateInfoPolicy == CertificateInfoPolicy::IncludeCertificateInfo)
737         return true;
738     if (UNLIKELY(InspectorInstrumentation::hasFrontends()))
739         return true;
740     return false;
741 }
742
743 void ResourceLoader::didReceiveAuthenticationChallenge(ResourceHandle* handle, const AuthenticationChallenge& challenge)
744 {
745     ASSERT_UNUSED(handle, handle == m_handle);
746     ASSERT(m_handle->hasAuthenticationChallenge());
747
748     // Protect this in this delegate method since the additional processing can do
749     // anything including possibly derefing this; one example of this is Radar 3266216.
750     Ref<ResourceLoader> protectedThis(*this);
751
752     if (m_options.storedCredentialsPolicy == StoredCredentialsPolicy::Use) {
753         if (isAllowedToAskUserForCredentials()) {
754             frameLoader()->notifier().didReceiveAuthenticationChallenge(this, challenge);
755             return;
756         }
757         didBlockAuthenticationChallenge();
758     }
759     challenge.authenticationClient()->receivedRequestToContinueWithoutCredential(challenge);
760     ASSERT(!m_handle || !m_handle->hasAuthenticationChallenge());
761 }
762
763 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
764 void ResourceLoader::canAuthenticateAgainstProtectionSpaceAsync(ResourceHandle*, const ProtectionSpace& protectionSpace, CompletionHandler<void(bool)>&& completionHandler)
765 {
766     completionHandler(canAuthenticateAgainstProtectionSpace(protectionSpace));
767 }
768
769 bool ResourceLoader::canAuthenticateAgainstProtectionSpace(const ProtectionSpace& protectionSpace)
770 {
771     Ref<ResourceLoader> protectedThis(*this);
772     return frameLoader()->client().canAuthenticateAgainstProtectionSpace(documentLoader(), identifier(), protectionSpace);
773 }
774
775 #endif
776     
777 #if PLATFORM(IOS_FAMILY)
778
779 RetainPtr<CFDictionaryRef> ResourceLoader::connectionProperties(ResourceHandle*)
780 {
781     return frameLoader()->connectionProperties(this);
782 }
783
784 #endif
785
786 void ResourceLoader::receivedCancellation(const AuthenticationChallenge&)
787 {
788     cancel();
789 }
790
791 #if PLATFORM(COCOA)
792
793 void ResourceLoader::schedule(SchedulePair& pair)
794 {
795     if (m_handle)
796         m_handle->schedule(pair);
797 }
798
799 void ResourceLoader::unschedule(SchedulePair& pair)
800 {
801     if (m_handle)
802         m_handle->unschedule(pair);
803 }
804
805 #endif
806
807 #if USE(QUICK_LOOK)
808 bool ResourceLoader::isQuickLookResource() const
809 {
810     return !!m_previewLoader;
811 }
812 #endif
813
814 bool ResourceLoader::isAlwaysOnLoggingAllowed() const
815 {
816     return frameLoader() && frameLoader()->isAlwaysOnLoggingAllowed();
817 }
818
819 }