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