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