Cross-protocol, cross-site scripting (XPSS) using HTML forms
[WebKit-https.git] / Source / WebCore / loader / ResourceLoader.cpp
1 /*
2  * Copyright (C) 2006-2007, 2010-2011, 2016 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 (m_response.isHttpVersion0_9()) {
443         String message = "Sandboxing '" + m_response.url().string() + "' because it is using HTTP/0.9.";
444         m_frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, message, m_identifier);
445         frameLoader()->forceSandboxFlags(SandboxScripts | SandboxPlugins);
446     }
447
448     if (FormData* data = m_request.httpBody())
449         data->removeGeneratedFilesIfNeeded();
450         
451     if (m_options.sendLoadCallbacks() == SendCallbacks)
452         frameLoader()->notifier().didReceiveResponse(this, m_response);
453 }
454
455 void ResourceLoader::didReceiveData(const char* data, unsigned length, long long encodedDataLength, DataPayloadType dataPayloadType)
456 {
457     // The following assertions are not quite valid here, since a subclass
458     // might override didReceiveData in a way that invalidates them. This
459     // happens with the steps listed in 3266216
460     // ASSERT(con == connection);
461     // ASSERT(!m_reachedTerminalState);
462
463     didReceiveDataOrBuffer(data, length, 0, encodedDataLength, dataPayloadType);
464 }
465
466 void ResourceLoader::didReceiveBuffer(PassRefPtr<SharedBuffer> buffer, long long encodedDataLength, DataPayloadType dataPayloadType)
467 {
468     didReceiveDataOrBuffer(0, 0, buffer, encodedDataLength, dataPayloadType);
469 }
470
471 void ResourceLoader::didReceiveDataOrBuffer(const char* data, unsigned length, PassRefPtr<SharedBuffer> prpBuffer, long long encodedDataLength, DataPayloadType dataPayloadType)
472 {
473     // This method should only get data+length *OR* a SharedBuffer.
474     ASSERT(!prpBuffer || (!data && !length));
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> protect(*this);
479     RefPtr<SharedBuffer> buffer = prpBuffer;
480
481     addDataOrBuffer(data, length, buffer.get(), dataPayloadType);
482     
483     // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
484     // However, with today's computers and networking speeds, this won't happen in practice.
485     // Could be an issue with a giant local file.
486     if (m_options.sendLoadCallbacks() == SendCallbacks && m_frame)
487         frameLoader()->notifier().didReceiveData(this, buffer ? buffer->data() : data, buffer ? buffer->size() : length, static_cast<int>(encodedDataLength));
488 }
489
490 void ResourceLoader::didFinishLoading(double finishTime)
491 {
492     didFinishLoadingOnePart(finishTime);
493
494     // If the load has been cancelled by a delegate in response to didFinishLoad(), do not release
495     // the resources a second time, they have been released by cancel.
496     if (wasCancelled())
497         return;
498     releaseResources();
499 }
500
501 void ResourceLoader::didFinishLoadingOnePart(double finishTime)
502 {
503     // If load has been cancelled after finishing (which could happen with a
504     // JavaScript that changes the window location), do nothing.
505     if (wasCancelled())
506         return;
507     ASSERT(!m_reachedTerminalState);
508
509     if (m_notifiedLoadComplete)
510         return;
511     m_notifiedLoadComplete = true;
512     if (m_options.sendLoadCallbacks() == SendCallbacks)
513         frameLoader()->notifier().didFinishLoad(this, finishTime);
514 }
515
516 void ResourceLoader::didFail(const ResourceError& error)
517 {
518     if (wasCancelled())
519         return;
520     ASSERT(!m_reachedTerminalState);
521
522     // Protect this in this delegate method since the additional processing can do
523     // anything including possibly derefing this; one example of this is Radar 3266216.
524     Ref<ResourceLoader> protect(*this);
525
526     cleanupForError(error);
527     releaseResources();
528 }
529
530 void ResourceLoader::cleanupForError(const ResourceError& error)
531 {
532     if (FormData* data = m_request.httpBody())
533         data->removeGeneratedFilesIfNeeded();
534
535     if (m_notifiedLoadComplete)
536         return;
537     m_notifiedLoadComplete = true;
538     if (m_options.sendLoadCallbacks() == SendCallbacks && m_identifier)
539         frameLoader()->notifier().didFailToLoad(this, error);
540 }
541
542 void ResourceLoader::cancel()
543 {
544     cancel(ResourceError());
545 }
546
547 void ResourceLoader::cancel(const ResourceError& error)
548 {
549     // If the load has already completed - succeeded, failed, or previously cancelled - do nothing.
550     if (m_reachedTerminalState)
551         return;
552        
553     ResourceError nonNullError = error.isNull() ? cancelledError() : error;
554     
555     // willCancel() and didFailToLoad() both call out to clients that might do 
556     // something causing the last reference to this object to go away.
557     Ref<ResourceLoader> protect(*this);
558     
559     // If we re-enter cancel() from inside willCancel(), we want to pick up from where we left 
560     // off without re-running willCancel()
561     if (m_cancellationStatus == NotCancelled) {
562         m_cancellationStatus = CalledWillCancel;
563         
564         willCancel(nonNullError);
565     }
566
567     // If we re-enter cancel() from inside didFailToLoad(), we want to pick up from where we 
568     // left off without redoing any of this work.
569     if (m_cancellationStatus == CalledWillCancel) {
570         m_cancellationStatus = Cancelled;
571
572         if (m_handle)
573             m_handle->clearAuthentication();
574
575         m_documentLoader->cancelPendingSubstituteLoad(this);
576         if (m_handle) {
577             m_handle->cancel();
578             m_handle = nullptr;
579         }
580         cleanupForError(nonNullError);
581     }
582
583     // If cancel() completed from within the call to willCancel() or didFailToLoad(),
584     // we don't want to redo didCancel() or releasesResources().
585     if (m_reachedTerminalState)
586         return;
587
588     didCancel(nonNullError);
589
590     if (m_cancellationStatus == FinishedCancel)
591         return;
592     m_cancellationStatus = FinishedCancel;
593
594     releaseResources();
595 }
596
597 ResourceError ResourceLoader::cancelledError()
598 {
599     return frameLoader()->cancelledError(m_request);
600 }
601
602 ResourceError ResourceLoader::blockedError()
603 {
604     return frameLoader()->client().blockedError(m_request);
605 }
606
607 ResourceError ResourceLoader::cannotShowURLError()
608 {
609     return frameLoader()->client().cannotShowURLError(m_request);
610 }
611
612 void ResourceLoader::willSendRequest(ResourceHandle*, ResourceRequest& request, const ResourceResponse& redirectResponse)
613 {
614     if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForRedirect(this, request, redirectResponse))
615         return;
616     willSendRequestInternal(request, redirectResponse);
617 }
618
619 void ResourceLoader::didSendData(ResourceHandle*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
620 {
621     didSendData(bytesSent, totalBytesToBeSent);
622 }
623
624 void ResourceLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
625 {
626     if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForResponse(this, response))
627         return;
628     didReceiveResponse(response);
629 }
630
631 void ResourceLoader::didReceiveData(ResourceHandle*, const char* data, unsigned length, int encodedDataLength)
632 {
633     didReceiveData(data, length, encodedDataLength, DataPayloadBytes);
634 }
635
636 void ResourceLoader::didReceiveBuffer(ResourceHandle*, PassRefPtr<SharedBuffer> buffer, int encodedDataLength)
637 {
638     didReceiveBuffer(buffer, encodedDataLength, DataPayloadBytes);
639 }
640
641 void ResourceLoader::didFinishLoading(ResourceHandle*, double finishTime)
642 {
643     didFinishLoading(finishTime);
644 }
645
646 void ResourceLoader::didFail(ResourceHandle*, const ResourceError& error)
647 {
648     if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForError(this, error))
649         return;
650     didFail(error);
651 }
652
653 void ResourceLoader::wasBlocked(ResourceHandle*)
654 {
655     didFail(blockedError());
656 }
657
658 void ResourceLoader::cannotShowURL(ResourceHandle*)
659 {
660     didFail(cannotShowURLError());
661 }
662
663 bool ResourceLoader::shouldUseCredentialStorage()
664 {
665     if (m_options.allowCredentials() == DoNotAllowStoredCredentials)
666         return false;
667     
668     Ref<ResourceLoader> protect(*this);
669     return frameLoader()->client().shouldUseCredentialStorage(documentLoader(), identifier());
670 }
671
672 bool ResourceLoader::isAllowedToAskUserForCredentials() const
673 {
674     return m_options.clientCredentialPolicy() == AskClientForAllCredentials || (m_options.clientCredentialPolicy() == DoNotAskClientForCrossOriginCredentials && m_frame->document()->securityOrigin()->canRequest(originalRequest().url()));
675 }
676
677 void ResourceLoader::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge)
678 {
679     ASSERT(m_handle->hasAuthenticationChallenge());
680
681     // Protect this in this delegate method since the additional processing can do
682     // anything including possibly derefing this; one example of this is Radar 3266216.
683     Ref<ResourceLoader> protect(*this);
684
685     if (m_options.allowCredentials() == AllowStoredCredentials) {
686         if (isAllowedToAskUserForCredentials()) {
687             frameLoader()->notifier().didReceiveAuthenticationChallenge(this, challenge);
688             return;
689         }
690     }
691     // Only these platforms provide a way to continue without credentials.
692     // If we can't continue with credentials, we need to cancel the load altogether.
693 #if PLATFORM(COCOA) || USE(CFNETWORK) || USE(CURL) || PLATFORM(GTK) || PLATFORM(EFL)
694     challenge.authenticationClient()->receivedRequestToContinueWithoutCredential(challenge);
695     ASSERT(!m_handle || !m_handle->hasAuthenticationChallenge());
696 #else
697     didFail(blockedError());
698 #endif
699 }
700
701 void ResourceLoader::didCancelAuthenticationChallenge(const AuthenticationChallenge& challenge)
702 {
703     // Protect this in this delegate method since the additional processing can do
704     // anything including possibly derefing this; one example of this is Radar 3266216.
705     Ref<ResourceLoader> protect(*this);
706     frameLoader()->notifier().didCancelAuthenticationChallenge(this, challenge);
707 }
708
709 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
710
711 bool ResourceLoader::canAuthenticateAgainstProtectionSpace(const ProtectionSpace& protectionSpace)
712 {
713     Ref<ResourceLoader> protect(*this);
714     return frameLoader()->client().canAuthenticateAgainstProtectionSpace(documentLoader(), identifier(), protectionSpace);
715 }
716
717 #endif
718     
719 #if PLATFORM(IOS)
720
721 RetainPtr<CFDictionaryRef> ResourceLoader::connectionProperties(ResourceHandle*)
722 {
723     return frameLoader()->connectionProperties(this);
724 }
725
726 #endif
727
728 void ResourceLoader::receivedCancellation(const AuthenticationChallenge&)
729 {
730     cancel();
731 }
732
733 #if PLATFORM(COCOA) && !USE(CFNETWORK)
734
735 void ResourceLoader::schedule(SchedulePair& pair)
736 {
737     if (m_handle)
738         m_handle->schedule(pair);
739 }
740
741 void ResourceLoader::unschedule(SchedulePair& pair)
742 {
743     if (m_handle)
744         m_handle->unschedule(pair);
745 }
746
747 #endif
748
749 #if USE(QUICK_LOOK)
750 void ResourceLoader::didCreateQuickLookHandle(QuickLookHandle& handle)
751 {
752     m_isQuickLookResource = true;
753     frameLoader()->client().didCreateQuickLookHandle(handle);
754 }
755 #endif
756
757 }