Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / loader / ResourceLoader.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2010, 2011 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 "MainFrame.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 "Settings.h"
52 #include "SharedBuffer.h"
53 #include <wtf/Ref.h>
54
55 #if ENABLE(CONTENT_EXTENSIONS)
56 #include "ResourceLoadInfo.h"
57 #include "UserContentController.h"
58 #endif
59
60 namespace WebCore {
61
62 ResourceLoader::ResourceLoader(Frame* frame, ResourceLoaderOptions options)
63     : m_frame(frame)
64     , m_documentLoader(frame->loader().activeDocumentLoader())
65     , m_identifier(0)
66     , m_reachedTerminalState(false)
67     , m_notifiedLoadComplete(false)
68     , m_cancellationStatus(NotCancelled)
69     , m_defersLoading(options.defersLoadingPolicy() == DefersLoadingPolicy::AllowDefersLoading && frame->page()->defersLoading())
70     , m_options(options)
71     , m_isQuickLookResource(false)
72 #if ENABLE(CONTENT_EXTENSIONS)
73     , m_resourceType(ResourceType::Invalid)
74 #endif
75 {
76 }
77
78 ResourceLoader::~ResourceLoader()
79 {
80     ASSERT(m_reachedTerminalState);
81 }
82
83 void ResourceLoader::finishNetworkLoad()
84 {
85     platformStrategies()->loaderStrategy()->remove(this);
86
87     if (m_handle) {
88         ASSERT(m_handle->client() == this);
89         m_handle->clearClient();
90         m_handle = nullptr;
91     }
92 }
93
94 void ResourceLoader::releaseResources()
95 {
96     ASSERT(!m_reachedTerminalState);
97     
98     // It's possible that when we release the handle, it will be
99     // deallocated and release the last reference to this object.
100     // We need to retain to avoid accessing the object after it
101     // has been deallocated and also to avoid reentering this method.
102     Ref<ResourceLoader> protect(*this);
103
104     m_frame = nullptr;
105     m_documentLoader = nullptr;
106     
107     // We need to set reachedTerminalState to true before we release
108     // the resources to prevent a double dealloc of WebView <rdar://problem/4372628>
109     m_reachedTerminalState = true;
110
111     finishNetworkLoad();
112
113     m_identifier = 0;
114
115     m_resourceData = nullptr;
116     m_deferredRequest = ResourceRequest();
117 }
118
119 bool ResourceLoader::init(const ResourceRequest& r)
120 {
121     ASSERT(!m_handle);
122     ASSERT(m_request.isNull());
123     ASSERT(m_deferredRequest.isNull());
124     ASSERT(!m_documentLoader->isSubstituteLoadPending(this));
125     
126     ResourceRequest clientRequest(r);
127
128 #if PLATFORM(IOS)
129     // If the documentLoader was detached while this ResourceLoader was waiting its turn
130     // in ResourceLoadScheduler queue, don't continue.
131     if (!m_documentLoader->frame()) {
132         cancel();
133         return false;
134     }
135 #endif
136     
137     m_defersLoading = m_options.defersLoadingPolicy() == DefersLoadingPolicy::AllowDefersLoading && m_frame->page()->defersLoading();
138
139     if (m_options.securityCheck() == DoSecurityCheck && !m_frame->document()->securityOrigin()->canDisplay(clientRequest.url())) {
140         FrameLoader::reportLocalLoadFailed(m_frame.get(), clientRequest.url().string());
141         releaseResources();
142         return false;
143     }
144     
145     // https://bugs.webkit.org/show_bug.cgi?id=26391
146     // The various plug-in implementations call directly to ResourceLoader::load() instead of piping requests
147     // through FrameLoader. As a result, they miss the FrameLoader::addExtraFieldsToRequest() step which sets
148     // up the 1st party for cookies URL. Until plug-in implementations can be reigned in to pipe through that
149     // method, we need to make sure there is always a 1st party for cookies set.
150     if (clientRequest.firstPartyForCookies().isNull()) {
151         if (Document* document = m_frame->document())
152             clientRequest.setFirstPartyForCookies(document->firstPartyForCookies());
153     }
154
155     willSendRequestInternal(clientRequest, ResourceResponse());
156
157 #if PLATFORM(IOS)
158     // If this ResourceLoader was stopped as a result of willSendRequest, bail out.
159     if (m_reachedTerminalState)
160         return false;
161 #endif
162
163     if (clientRequest.isNull()) {
164         cancel();
165         return false;
166     }
167
168     m_originalRequest = m_request = clientRequest;
169     return true;
170 }
171
172 void ResourceLoader::deliverResponseAndData(const ResourceResponse& response, RefPtr<SharedBuffer>&& buffer)
173 {
174     Ref<ResourceLoader> protect(*this);
175
176     didReceiveResponse(response);
177     if (reachedTerminalState())
178         return;
179
180     if (buffer) {
181         unsigned size = buffer->size();
182         didReceiveBuffer(buffer.release(), size, DataPayloadWholeResource);
183         if (reachedTerminalState())
184             return;
185     }
186
187     didFinishLoading(0);
188 }
189
190 void ResourceLoader::start()
191 {
192     ASSERT(!m_handle);
193     ASSERT(!m_request.isNull());
194     ASSERT(m_deferredRequest.isNull());
195     ASSERT(frameLoader());
196
197 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
198     if (m_documentLoader->scheduleArchiveLoad(this, m_request))
199         return;
200 #endif
201
202     if (m_documentLoader->applicationCacheHost()->maybeLoadResource(this, m_request, m_request.url()))
203         return;
204
205     if (m_defersLoading) {
206         m_deferredRequest = m_request;
207         return;
208     }
209
210     if (m_reachedTerminalState)
211         return;
212
213     if (m_request.url().protocolIsData()) {
214         loadDataURL();
215         return;
216     }
217
218     m_handle = ResourceHandle::create(frameLoader()->networkingContext(), m_request, this, m_defersLoading, m_options.sniffContent() == SniffContent);
219 }
220
221 void ResourceLoader::setDefersLoading(bool defers)
222 {
223     if (m_options.defersLoadingPolicy() == DefersLoadingPolicy::DisallowDefersLoading)
224         return;
225
226     m_defersLoading = defers;
227     if (m_handle)
228         m_handle->setDefersLoading(defers);
229     if (!defers && !m_deferredRequest.isNull()) {
230         m_request = m_deferredRequest;
231         m_deferredRequest = ResourceRequest();
232         start();
233     }
234
235     platformStrategies()->loaderStrategy()->setDefersLoading(this, defers);
236 }
237
238 FrameLoader* ResourceLoader::frameLoader() const
239 {
240     if (!m_frame)
241         return nullptr;
242     return &m_frame->loader();
243 }
244
245 void ResourceLoader::loadDataURL()
246 {
247     auto url = m_request.url();
248     ASSERT(url.protocolIsData());
249
250     RefPtr<ResourceLoader> loader(this);
251     DataURLDecoder::ScheduleContext scheduleContext;
252 #if HAVE(RUNLOOP_TIMER)
253     if (auto* scheduledPairs = m_frame->page()->scheduledRunLoopPairs())
254         scheduleContext.scheduledPairs = *scheduledPairs;
255 #endif
256     DataURLDecoder::decode(url, scheduleContext, [loader, url] (Optional<DataURLDecoder::Result> decodeResult) {
257         if (loader->reachedTerminalState())
258             return;
259         if (!decodeResult) {
260             loader->didFail(ResourceError(errorDomainWebKitInternal, 0, url, "Data URL decoding failed"));
261             return;
262         }
263         if (loader->wasCancelled())
264             return;
265         auto& result = decodeResult.value();
266         auto dataSize = result.data->size();
267
268         ResourceResponse dataResponse { url, result.mimeType, dataSize, result.charset };
269         loader->didReceiveResponse(dataResponse);
270
271         if (!loader->reachedTerminalState() && dataSize)
272             loader->didReceiveBuffer(result.data.get(), dataSize, DataPayloadWholeResource);
273
274         if (!loader->reachedTerminalState())
275             loader->didFinishLoading(currentTime());
276     });
277 }
278
279 void ResourceLoader::setDataBufferingPolicy(DataBufferingPolicy dataBufferingPolicy)
280
281     m_options.setDataBufferingPolicy(dataBufferingPolicy); 
282
283     // Reset any already buffered data
284     if (dataBufferingPolicy == DoNotBufferData)
285         m_resourceData = nullptr;
286 }
287     
288 void ResourceLoader::willSwitchToSubstituteResource()
289 {
290     ASSERT(!m_documentLoader->isSubstituteLoadPending(this));
291     platformStrategies()->loaderStrategy()->remove(this);
292     if (m_handle)
293         m_handle->cancel();
294 }
295
296 void ResourceLoader::addDataOrBuffer(const char* data, unsigned length, SharedBuffer* buffer, DataPayloadType dataPayloadType)
297 {
298     if (m_options.dataBufferingPolicy() == DoNotBufferData)
299         return;
300
301     if (dataPayloadType == DataPayloadWholeResource) {
302         m_resourceData = buffer ? buffer : SharedBuffer::create(data, length);
303         return;
304     }
305         
306     if (!m_resourceData)
307         m_resourceData = buffer ? buffer : SharedBuffer::create(data, length);
308     else {
309         if (buffer)
310             m_resourceData->append(buffer);
311         else
312             m_resourceData->append(data, length);
313     }
314 }
315
316 void ResourceLoader::clearResourceData()
317 {
318     if (m_resourceData)
319         m_resourceData->clear();
320 }
321
322 bool ResourceLoader::isSubresourceLoader()
323 {
324     return false;
325 }
326
327 void ResourceLoader::willSendRequestInternal(ResourceRequest& request, const ResourceResponse& redirectResponse)
328 {
329     // Protect this in this delegate method since the additional processing can do
330     // anything including possibly derefing this; one example of this is Radar 3266216.
331     Ref<ResourceLoader> protect(*this);
332
333     ASSERT(!m_reachedTerminalState);
334 #if ENABLE(CONTENT_EXTENSIONS)
335     ASSERT(m_resourceType != ResourceType::Invalid);
336 #endif
337
338     // We need a resource identifier for all requests, even if FrameLoader is never going to see it (such as with CORS preflight requests).
339     bool createdResourceIdentifier = false;
340     if (!m_identifier) {
341         m_identifier = m_frame->page()->progress().createUniqueIdentifier();
342         createdResourceIdentifier = true;
343     }
344
345 #if ENABLE(CONTENT_EXTENSIONS)
346     if (frameLoader()) {
347         Page* page = frameLoader()->frame().page();
348         if (page && m_documentLoader) {
349             auto* userContentController = page->userContentController();
350             if (userContentController && userContentController->processContentExtensionRulesForLoad(request, m_resourceType, *m_documentLoader) == ContentExtensions::BlockedStatus::Blocked)
351                 request = { };
352         }
353     }
354 #endif
355
356     if (request.isNull()) {
357         didFail(cannotShowURLError());
358         return;
359     }
360
361     if (m_options.sendLoadCallbacks() == SendCallbacks) {
362         if (createdResourceIdentifier)
363             frameLoader()->notifier().assignIdentifierToInitialRequest(m_identifier, documentLoader(), request);
364
365 #if PLATFORM(IOS)
366         // If this ResourceLoader was stopped as a result of assignIdentifierToInitialRequest, bail out
367         if (m_reachedTerminalState)
368             return;
369 #endif
370
371         frameLoader()->notifier().willSendRequest(this, request, redirectResponse);
372     }
373     else
374         InspectorInstrumentation::willSendRequest(m_frame.get(), m_identifier, m_frame->loader().documentLoader(), request, redirectResponse);
375
376     bool isRedirect = !redirectResponse.isNull();
377     if (isRedirect)
378         platformStrategies()->loaderStrategy()->crossOriginRedirectReceived(this, request.url());
379
380     m_request = request;
381
382     if (isRedirect) {
383         auto& redirectURL = request.url();
384         if (!m_documentLoader->isCommitted())
385             frameLoader()->client().dispatchDidReceiveServerRedirectForProvisionalLoad();
386
387         if (redirectURL.protocolIsData()) {
388             // Handle data URL decoding locally.
389             finishNetworkLoad();
390             loadDataURL();
391         }
392     }
393 }
394
395 void ResourceLoader::willSendRequest(ResourceRequest&& request, const ResourceResponse& redirectResponse, std::function<void(ResourceRequest&&)>&& callback)
396 {
397     willSendRequestInternal(request, redirectResponse);
398     callback(WTFMove(request));
399 }
400
401 void ResourceLoader::didSendData(unsigned long long, unsigned long long)
402 {
403 }
404
405 static void logResourceResponseSource(Frame* frame, ResourceResponse::Source source)
406 {
407     if (!frame)
408         return;
409
410     String sourceKey;
411     switch (source) {
412     case ResourceResponse::Source::Network:
413         sourceKey = DiagnosticLoggingKeys::networkKey();
414         break;
415     case ResourceResponse::Source::DiskCache:
416         sourceKey = DiagnosticLoggingKeys::diskCacheKey();
417         break;
418     case ResourceResponse::Source::DiskCacheAfterValidation:
419         sourceKey = DiagnosticLoggingKeys::diskCacheAfterValidationKey();
420         break;
421     case ResourceResponse::Source::MemoryCache:
422     case ResourceResponse::Source::MemoryCacheAfterValidation:
423     case ResourceResponse::Source::Unknown:
424         return;
425     }
426
427     frame->mainFrame().diagnosticLoggingClient().logDiagnosticMessageWithValue(DiagnosticLoggingKeys::resourceResponseKey(), DiagnosticLoggingKeys::sourceKey(), sourceKey, ShouldSample::Yes);
428 }
429
430 void ResourceLoader::didReceiveResponse(const ResourceResponse& r)
431 {
432     ASSERT(!m_reachedTerminalState);
433
434     // Protect this in this delegate method since the additional processing can do
435     // anything including possibly derefing this; one example of this is Radar 3266216.
436     Ref<ResourceLoader> protect(*this);
437
438     logResourceResponseSource(m_frame.get(), r.source());
439
440     m_response = r;
441
442     if (FormData* data = m_request.httpBody())
443         data->removeGeneratedFilesIfNeeded();
444         
445     if (m_options.sendLoadCallbacks() == SendCallbacks)
446         frameLoader()->notifier().didReceiveResponse(this, m_response);
447 }
448
449 void ResourceLoader::didReceiveData(const char* data, unsigned length, long long encodedDataLength, DataPayloadType dataPayloadType)
450 {
451     // The following assertions are not quite valid here, since a subclass
452     // might override didReceiveData in a way that invalidates them. This
453     // happens with the steps listed in 3266216
454     // ASSERT(con == connection);
455     // ASSERT(!m_reachedTerminalState);
456
457     didReceiveDataOrBuffer(data, length, 0, encodedDataLength, dataPayloadType);
458 }
459
460 void ResourceLoader::didReceiveBuffer(PassRefPtr<SharedBuffer> buffer, long long encodedDataLength, DataPayloadType dataPayloadType)
461 {
462     didReceiveDataOrBuffer(0, 0, buffer, encodedDataLength, dataPayloadType);
463 }
464
465 void ResourceLoader::didReceiveDataOrBuffer(const char* data, unsigned length, PassRefPtr<SharedBuffer> prpBuffer, long long encodedDataLength, DataPayloadType dataPayloadType)
466 {
467     // This method should only get data+length *OR* a SharedBuffer.
468     ASSERT(!prpBuffer || (!data && !length));
469
470     // Protect this in this delegate method since the additional processing can do
471     // anything including possibly derefing this; one example of this is Radar 3266216.
472     Ref<ResourceLoader> protect(*this);
473     RefPtr<SharedBuffer> buffer = prpBuffer;
474
475     addDataOrBuffer(data, length, buffer.get(), dataPayloadType);
476     
477     // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
478     // However, with today's computers and networking speeds, this won't happen in practice.
479     // Could be an issue with a giant local file.
480     if (m_options.sendLoadCallbacks() == SendCallbacks && m_frame)
481         frameLoader()->notifier().didReceiveData(this, buffer ? buffer->data() : data, buffer ? buffer->size() : length, static_cast<int>(encodedDataLength));
482 }
483
484 void ResourceLoader::didFinishLoading(double finishTime)
485 {
486     didFinishLoadingOnePart(finishTime);
487
488     // If the load has been cancelled by a delegate in response to didFinishLoad(), do not release
489     // the resources a second time, they have been released by cancel.
490     if (wasCancelled())
491         return;
492     releaseResources();
493 }
494
495 void ResourceLoader::didFinishLoadingOnePart(double finishTime)
496 {
497     // If load has been cancelled after finishing (which could happen with a
498     // JavaScript that changes the window location), do nothing.
499     if (wasCancelled())
500         return;
501     ASSERT(!m_reachedTerminalState);
502
503     if (m_notifiedLoadComplete)
504         return;
505     m_notifiedLoadComplete = true;
506     if (m_options.sendLoadCallbacks() == SendCallbacks)
507         frameLoader()->notifier().didFinishLoad(this, finishTime);
508 }
509
510 void ResourceLoader::didFail(const ResourceError& error)
511 {
512     if (wasCancelled())
513         return;
514     ASSERT(!m_reachedTerminalState);
515
516     // Protect this in this delegate method since the additional processing can do
517     // anything including possibly derefing this; one example of this is Radar 3266216.
518     Ref<ResourceLoader> protect(*this);
519
520     cleanupForError(error);
521     releaseResources();
522 }
523
524 void ResourceLoader::cleanupForError(const ResourceError& error)
525 {
526     if (FormData* data = m_request.httpBody())
527         data->removeGeneratedFilesIfNeeded();
528
529     if (m_notifiedLoadComplete)
530         return;
531     m_notifiedLoadComplete = true;
532     if (m_options.sendLoadCallbacks() == SendCallbacks && m_identifier)
533         frameLoader()->notifier().didFailToLoad(this, error);
534 }
535
536 void ResourceLoader::cancel()
537 {
538     cancel(ResourceError());
539 }
540
541 void ResourceLoader::cancel(const ResourceError& error)
542 {
543     // If the load has already completed - succeeded, failed, or previously cancelled - do nothing.
544     if (m_reachedTerminalState)
545         return;
546        
547     ResourceError nonNullError = error.isNull() ? cancelledError() : error;
548     
549     // willCancel() and didFailToLoad() both call out to clients that might do 
550     // something causing the last reference to this object to go away.
551     Ref<ResourceLoader> protect(*this);
552     
553     // If we re-enter cancel() from inside willCancel(), we want to pick up from where we left 
554     // off without re-running willCancel()
555     if (m_cancellationStatus == NotCancelled) {
556         m_cancellationStatus = CalledWillCancel;
557         
558         willCancel(nonNullError);
559     }
560
561     // If we re-enter cancel() from inside didFailToLoad(), we want to pick up from where we 
562     // left off without redoing any of this work.
563     if (m_cancellationStatus == CalledWillCancel) {
564         m_cancellationStatus = Cancelled;
565
566         if (m_handle)
567             m_handle->clearAuthentication();
568
569         m_documentLoader->cancelPendingSubstituteLoad(this);
570         if (m_handle) {
571             m_handle->cancel();
572             m_handle = nullptr;
573         }
574         cleanupForError(nonNullError);
575     }
576
577     // If cancel() completed from within the call to willCancel() or didFailToLoad(),
578     // we don't want to redo didCancel() or releasesResources().
579     if (m_reachedTerminalState)
580         return;
581
582     didCancel(nonNullError);
583
584     if (m_cancellationStatus == FinishedCancel)
585         return;
586     m_cancellationStatus = FinishedCancel;
587
588     releaseResources();
589 }
590
591 ResourceError ResourceLoader::cancelledError()
592 {
593     return frameLoader()->cancelledError(m_request);
594 }
595
596 ResourceError ResourceLoader::blockedError()
597 {
598     return frameLoader()->client().blockedError(m_request);
599 }
600
601 ResourceError ResourceLoader::cannotShowURLError()
602 {
603     return frameLoader()->client().cannotShowURLError(m_request);
604 }
605
606 void ResourceLoader::willSendRequest(ResourceHandle*, ResourceRequest& request, const ResourceResponse& redirectResponse)
607 {
608     if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForRedirect(this, request, redirectResponse))
609         return;
610     willSendRequestInternal(request, redirectResponse);
611 }
612
613 void ResourceLoader::didSendData(ResourceHandle*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
614 {
615     didSendData(bytesSent, totalBytesToBeSent);
616 }
617
618 void ResourceLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
619 {
620     if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForResponse(this, response))
621         return;
622     didReceiveResponse(response);
623 }
624
625 void ResourceLoader::didReceiveData(ResourceHandle*, const char* data, unsigned length, int encodedDataLength)
626 {
627     didReceiveData(data, length, encodedDataLength, DataPayloadBytes);
628 }
629
630 void ResourceLoader::didReceiveBuffer(ResourceHandle*, PassRefPtr<SharedBuffer> buffer, int encodedDataLength)
631 {
632     didReceiveBuffer(buffer, encodedDataLength, DataPayloadBytes);
633 }
634
635 void ResourceLoader::didFinishLoading(ResourceHandle*, double finishTime)
636 {
637     didFinishLoading(finishTime);
638 }
639
640 void ResourceLoader::didFail(ResourceHandle*, const ResourceError& error)
641 {
642     if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForError(this, error))
643         return;
644     didFail(error);
645 }
646
647 void ResourceLoader::wasBlocked(ResourceHandle*)
648 {
649     didFail(blockedError());
650 }
651
652 void ResourceLoader::cannotShowURL(ResourceHandle*)
653 {
654     didFail(cannotShowURLError());
655 }
656
657 bool ResourceLoader::shouldUseCredentialStorage()
658 {
659     if (m_options.allowCredentials() == DoNotAllowStoredCredentials)
660         return false;
661     
662     Ref<ResourceLoader> protect(*this);
663     return frameLoader()->client().shouldUseCredentialStorage(documentLoader(), identifier());
664 }
665
666 bool ResourceLoader::isAllowedToAskUserForCredentials() const
667 {
668     return m_options.clientCredentialPolicy() == AskClientForAllCredentials || (m_options.clientCredentialPolicy() == DoNotAskClientForCrossOriginCredentials && m_frame->document()->securityOrigin()->canRequest(originalRequest().url()));
669 }
670
671 void ResourceLoader::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge)
672 {
673     ASSERT(m_handle->hasAuthenticationChallenge());
674
675     // Protect this in this delegate method since the additional processing can do
676     // anything including possibly derefing this; one example of this is Radar 3266216.
677     Ref<ResourceLoader> protect(*this);
678
679     if (m_options.allowCredentials() == AllowStoredCredentials) {
680         if (isAllowedToAskUserForCredentials()) {
681             frameLoader()->notifier().didReceiveAuthenticationChallenge(this, challenge);
682             return;
683         }
684     }
685     // Only these platforms provide a way to continue without credentials.
686     // If we can't continue with credentials, we need to cancel the load altogether.
687 #if PLATFORM(COCOA) || USE(CFNETWORK) || USE(CURL) || PLATFORM(GTK) || PLATFORM(EFL)
688     challenge.authenticationClient()->receivedRequestToContinueWithoutCredential(challenge);
689     ASSERT(!m_handle || !m_handle->hasAuthenticationChallenge());
690 #else
691     didFail(blockedError());
692 #endif
693 }
694
695 void ResourceLoader::didCancelAuthenticationChallenge(const AuthenticationChallenge& challenge)
696 {
697     // Protect this in this delegate method since the additional processing can do
698     // anything including possibly derefing this; one example of this is Radar 3266216.
699     Ref<ResourceLoader> protect(*this);
700     frameLoader()->notifier().didCancelAuthenticationChallenge(this, challenge);
701 }
702
703 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
704
705 bool ResourceLoader::canAuthenticateAgainstProtectionSpace(const ProtectionSpace& protectionSpace)
706 {
707     Ref<ResourceLoader> protect(*this);
708     return frameLoader()->client().canAuthenticateAgainstProtectionSpace(documentLoader(), identifier(), protectionSpace);
709 }
710
711 #endif
712     
713 #if PLATFORM(IOS)
714
715 RetainPtr<CFDictionaryRef> ResourceLoader::connectionProperties(ResourceHandle*)
716 {
717     return frameLoader()->connectionProperties(this);
718 }
719
720 #endif
721
722 void ResourceLoader::receivedCancellation(const AuthenticationChallenge&)
723 {
724     cancel();
725 }
726
727 #if PLATFORM(COCOA) && !USE(CFNETWORK)
728
729 void ResourceLoader::schedule(SchedulePair& pair)
730 {
731     if (m_handle)
732         m_handle->schedule(pair);
733 }
734
735 void ResourceLoader::unschedule(SchedulePair& pair)
736 {
737     if (m_handle)
738         m_handle->unschedule(pair);
739 }
740
741 #endif
742
743 #if USE(QUICK_LOOK)
744 void ResourceLoader::didCreateQuickLookHandle(QuickLookHandle& handle)
745 {
746     m_isQuickLookResource = true;
747     frameLoader()->client().didCreateQuickLookHandle(handle);
748 }
749 #endif
750
751 }