Main resource requests need cachePartition
[WebKit-https.git] / Source / WebCore / loader / DocumentLoader.cpp
1 /*
2  * Copyright (C) 2006-2016 Apple Inc. All rights reserved.
3  * Copyright (C) 2011 Google Inc. All rights reserved.
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 "DocumentLoader.h"
32
33 #include "ApplicationCacheHost.h"
34 #include "Archive.h"
35 #include "ArchiveResourceCollection.h"
36 #include "CachedPage.h"
37 #include "CachedRawResource.h"
38 #include "CachedResourceLoader.h"
39 #include "ContentExtensionError.h"
40 #include "ContentSecurityPolicy.h"
41 #include "DOMWindow.h"
42 #include "Document.h"
43 #include "DocumentParser.h"
44 #include "DocumentWriter.h"
45 #include "ElementChildIterator.h"
46 #include "Event.h"
47 #include "EventNames.h"
48 #include "ExtensionStyleSheets.h"
49 #include "FormState.h"
50 #include "FrameLoader.h"
51 #include "FrameLoaderClient.h"
52 #include "FrameTree.h"
53 #include "HTMLFormElement.h"
54 #include "HTMLFrameOwnerElement.h"
55 #include "HTTPHeaderNames.h"
56 #include "HistoryItem.h"
57 #include "IconController.h"
58 #include "IconLoader.h"
59 #include "InspectorInstrumentation.h"
60 #include "LinkIconCollector.h"
61 #include "LinkIconType.h"
62 #include "Logging.h"
63 #include "MainFrame.h"
64 #include "MemoryCache.h"
65 #include "Page.h"
66 #include "PolicyChecker.h"
67 #include "ProgressTracker.h"
68 #include "ResourceHandle.h"
69 #include "ResourceLoadObserver.h"
70 #include "SchemeRegistry.h"
71 #include "ScriptableDocumentParser.h"
72 #include "SecurityPolicy.h"
73 #include "Settings.h"
74 #include "SubresourceLoader.h"
75 #include "TextResourceDecoder.h"
76 #include <wtf/Assertions.h>
77 #include <wtf/NeverDestroyed.h>
78 #include <wtf/Ref.h>
79 #include <wtf/text/CString.h>
80 #include <wtf/text/WTFString.h>
81
82 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
83 #include "ArchiveFactory.h"
84 #endif
85
86 #if ENABLE(CONTENT_FILTERING)
87 #include "ContentFilter.h"
88 #endif
89
90 #if USE(QUICK_LOOK)
91 #include "PreviewConverter.h"
92 #include "QuickLook.h"
93 #endif
94
95 #define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), Network, "%p - DocumentLoader::" fmt, this, ##__VA_ARGS__)
96
97 namespace WebCore {
98
99 static void cancelAll(const ResourceLoaderMap& loaders)
100 {
101     Vector<RefPtr<ResourceLoader>> loadersCopy;
102     copyValuesToVector(loaders, loadersCopy);
103     for (auto& loader : loadersCopy)
104         loader->cancel();
105 }
106
107 static void setAllDefersLoading(const ResourceLoaderMap& loaders, bool defers)
108 {
109     Vector<RefPtr<ResourceLoader>> loadersCopy;
110     copyValuesToVector(loaders, loadersCopy);
111     for (auto& loader : loadersCopy)
112         loader->setDefersLoading(defers);
113 }
114
115 static bool areAllLoadersPageCacheAcceptable(const ResourceLoaderMap& loaders)
116 {
117     Vector<RefPtr<ResourceLoader>> loadersCopy;
118     copyValuesToVector(loaders, loadersCopy);
119     for (auto& loader : loadersCopy) {
120         if (!loader->frameLoader() || !loader->frameLoader()->frame().page())
121             return false;
122
123         CachedResource* cachedResource = MemoryCache::singleton().resourceForRequest(loader->request(), loader->frameLoader()->frame().page()->sessionID());
124         if (!cachedResource)
125             return false;
126
127         // Only image and XHR loads do prevent the page from entering the PageCache.
128         // All non-image loads will prevent the page from entering the PageCache.
129         if (!cachedResource->isImage() && !cachedResource->areAllClientsXMLHttpRequests())
130             return false;
131     }
132     return true;
133 }
134
135 DocumentLoader::DocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
136     : m_cachedResourceLoader(CachedResourceLoader::create(this))
137     , m_writer(m_frame)
138     , m_originalRequest(request)
139     , m_substituteData(substituteData)
140     , m_originalRequestCopy(request)
141     , m_request(request)
142     , m_originalSubstituteDataWasValid(substituteData.isValid())
143     , m_substituteResourceDeliveryTimer(*this, &DocumentLoader::substituteResourceDeliveryTimerFired)
144     , m_dataLoadTimer(*this, &DocumentLoader::handleSubstituteDataLoadNow)
145     , m_applicationCacheHost(std::make_unique<ApplicationCacheHost>(*this))
146 {
147 }
148
149 FrameLoader* DocumentLoader::frameLoader() const
150 {
151     if (!m_frame)
152         return nullptr;
153     return &m_frame->loader();
154 }
155
156 SubresourceLoader* DocumentLoader::mainResourceLoader() const
157 {
158     if (!m_mainResource)
159         return nullptr;
160     return m_mainResource->loader();
161 }
162
163 DocumentLoader::~DocumentLoader()
164 {
165     ASSERT(!m_frame || frameLoader()->activeDocumentLoader() != this || !isLoading());
166     ASSERT_WITH_MESSAGE(!m_waitingForContentPolicy, "The content policy callback should never outlive its DocumentLoader.");
167     ASSERT_WITH_MESSAGE(!m_waitingForNavigationPolicy, "The navigation policy callback should never outlive its DocumentLoader.");
168     if (m_iconLoadDecisionCallback)
169         m_iconLoadDecisionCallback->invalidate();
170     if (m_iconDataCallback)
171         m_iconDataCallback->invalidate();
172     m_cachedResourceLoader->clearDocumentLoader();
173
174     clearMainResource();
175 }
176
177 RefPtr<SharedBuffer> DocumentLoader::mainResourceData() const
178 {
179     if (m_substituteData.isValid())
180         return m_substituteData.content()->copy();
181     if (m_mainResource)
182         return m_mainResource->resourceBuffer();
183     return nullptr;
184 }
185
186 Document* DocumentLoader::document() const
187 {
188     if (m_frame && m_frame->loader().documentLoader() == this)
189         return m_frame->document();
190     return nullptr;
191 }
192
193 void DocumentLoader::replaceRequestURLForSameDocumentNavigation(const URL& url)
194 {
195     m_originalRequestCopy.setURL(url);
196     m_request.setURL(url);
197 }
198
199 void DocumentLoader::setRequest(const ResourceRequest& req)
200 {
201     // Replacing an unreachable URL with alternate content looks like a server-side
202     // redirect at this point, but we can replace a committed dataSource.
203     bool handlingUnreachableURL = false;
204
205     handlingUnreachableURL = m_substituteData.isValid() && !m_substituteData.failingURL().isEmpty();
206
207     bool shouldNotifyAboutProvisionalURLChange = false;
208     if (handlingUnreachableURL)
209         m_committed = false;
210     else if (isLoadingMainResource() && req.url() != m_request.url())
211         shouldNotifyAboutProvisionalURLChange = true;
212
213     // We should never be getting a redirect callback after the data
214     // source is committed, except in the unreachable URL case. It 
215     // would be a WebFoundation bug if it sent a redirect callback after commit.
216     ASSERT(!m_committed);
217
218     m_request = req;
219     if (shouldNotifyAboutProvisionalURLChange)
220         frameLoader()->client().dispatchDidChangeProvisionalURL();
221 }
222
223 void DocumentLoader::setMainDocumentError(const ResourceError& error)
224 {
225     m_mainDocumentError = error;    
226     frameLoader()->client().setMainDocumentError(this, error);
227 }
228
229 void DocumentLoader::mainReceivedError(const ResourceError& error)
230 {
231     ASSERT(!error.isNull());
232
233     if (!frameLoader())
234         return;
235
236     if (m_identifierForLoadWithoutResourceLoader) {
237         ASSERT(!mainResourceLoader());
238         frameLoader()->client().dispatchDidFailLoading(this, m_identifierForLoadWithoutResourceLoader, error);
239     }
240
241     // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred.
242     // See <rdar://problem/6304600> for more details.
243 #if !USE(CF)
244     ASSERT(!mainResourceLoader() || !mainResourceLoader()->defersLoading());
245 #endif
246
247     m_applicationCacheHost->failedLoadingMainResource();
248
249     setMainDocumentError(error);
250     clearMainResourceLoader();
251     frameLoader()->receivedMainResourceError(error);
252 }
253
254 // Cancels the data source's pending loads.  Conceptually, a data source only loads
255 // one document at a time, but one document may have many related resources. 
256 // stopLoading will stop all loads initiated by the data source, 
257 // but not loads initiated by child frames' data sources -- that's the WebFrame's job.
258 void DocumentLoader::stopLoading()
259 {
260     RefPtr<Frame> protectedFrame(m_frame);
261     Ref<DocumentLoader> protectedThis(*this);
262
263     // In some rare cases, calling FrameLoader::stopLoading could cause isLoading() to return false.
264     // (This can happen when there's a single XMLHttpRequest currently loading and stopLoading causes it
265     // to stop loading. Because of this, we need to save it so we don't return early.
266     bool loading = isLoading();
267
268     // We may want to audit the existing subresource loaders when we are on a page which has completed
269     // loading but there are subresource loads during cancellation. This must be done before the
270     // frame->stopLoading() call, which may evict the CachedResources, which we rely on to check
271     // the type of the resource loads.
272     if (loading && m_committed && !mainResourceLoader() && !m_subresourceLoaders.isEmpty())
273         m_subresourceLoadersArePageCacheAcceptable = areAllLoadersPageCacheAcceptable(m_subresourceLoaders);
274
275     if (m_committed) {
276         // Attempt to stop the frame if the document loader is loading, or if it is done loading but
277         // still  parsing. Failure to do so can cause a world leak.
278         Document* doc = m_frame->document();
279         
280         if (loading || doc->parsing())
281             m_frame->loader().stopLoading(UnloadEventPolicyNone);
282     }
283
284     // Always cancel multipart loaders
285     cancelAll(m_multipartSubresourceLoaders);
286
287     // Appcache uses ResourceHandle directly, DocumentLoader doesn't count these loads.
288     m_applicationCacheHost->stopLoadingInFrame(*m_frame);
289     
290 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
291     clearArchiveResources();
292 #endif
293
294     if (!loading) {
295         // If something above restarted loading we might run into mysterious crashes like 
296         // https://bugs.webkit.org/show_bug.cgi?id=62764 and <rdar://problem/9328684>
297         ASSERT(!isLoading());
298         return;
299     }
300
301     // We might run in to infinite recursion if we're stopping loading as the result of 
302     // detaching from the frame, so break out of that recursion here.
303     // See <rdar://problem/9673866> for more details.
304     if (m_isStopping)
305         return;
306
307     m_isStopping = true;
308
309     // The frame may have been detached from this document by the onunload handler
310     if (auto* frameLoader = DocumentLoader::frameLoader()) {
311         if (isLoadingMainResource()) {
312             // Stop the main resource loader and let it send the cancelled message.
313             cancelMainResourceLoad(frameLoader->cancelledError(m_request));
314         } else if (!m_subresourceLoaders.isEmpty() || !m_plugInStreamLoaders.isEmpty()) {
315             // The main resource loader already finished loading. Set the cancelled error on the
316             // document and let the subresourceLoaders and pluginLoaders send individual cancelled messages below.
317             setMainDocumentError(frameLoader->cancelledError(m_request));
318         } else {
319             // If there are no resource loaders, we need to manufacture a cancelled message.
320             // (A back/forward navigation has no resource loaders because its resources are cached.)
321             mainReceivedError(frameLoader->cancelledError(m_request));
322         }
323     }
324
325     // We always need to explicitly cancel the Document's parser when stopping the load.
326     // Otherwise cancelling the parser while starting the next page load might result
327     // in unexpected side effects such as erroneous event dispatch. ( http://webkit.org/b/117112 )
328     if (Document* document = this->document())
329         document->cancelParsing();
330     
331     stopLoadingSubresources();
332     stopLoadingPlugIns();
333     
334     m_isStopping = false;
335 }
336
337 void DocumentLoader::commitIfReady()
338 {
339     if (!m_committed) {
340         m_committed = true;
341         frameLoader()->commitProvisionalLoad();
342     }
343 }
344
345 bool DocumentLoader::isLoading() const
346 {
347     // if (document() && document()->hasActiveParser())
348     //     return true;
349     // FIXME: The above code should be enabled, but it seems to cause
350     // http/tests/security/feed-urls-from-remote.html to timeout on Mac WK1
351     // see http://webkit.org/b/110554 and http://webkit.org/b/110401
352
353     return isLoadingMainResource() || !m_subresourceLoaders.isEmpty() || !m_plugInStreamLoaders.isEmpty();
354 }
355
356 void DocumentLoader::notifyFinished(CachedResource& resource)
357 {
358 #if ENABLE(CONTENT_FILTERING)
359     if (m_contentFilter && !m_contentFilter->continueAfterNotifyFinished(resource))
360         return;
361 #endif
362
363     ASSERT_UNUSED(resource, m_mainResource == &resource);
364     ASSERT(m_mainResource);
365     if (!m_mainResource->errorOccurred() && !m_mainResource->wasCanceled()) {
366         finishedLoading();
367         return;
368     }
369
370     if (m_request.cachePolicy() == ReturnCacheDataDontLoad && !m_mainResource->wasCanceled()) {
371         frameLoader()->retryAfterFailedCacheOnlyMainResourceLoad();
372         return;
373     }
374
375     mainReceivedError(m_mainResource->resourceError());
376 }
377
378 void DocumentLoader::finishedLoading()
379 {
380     // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred.
381     // See <rdar://problem/6304600> for more details.
382 #if !USE(CF)
383     ASSERT(!m_frame->page()->defersLoading() || frameLoader()->stateMachine().creatingInitialEmptyDocument() || InspectorInstrumentation::isDebuggerPaused(m_frame));
384 #endif
385
386     Ref<DocumentLoader> protectedThis(*this);
387
388     if (m_identifierForLoadWithoutResourceLoader) {
389         // A didFinishLoading delegate might try to cancel the load (despite it
390         // being finished). Clear m_identifierForLoadWithoutResourceLoader
391         // before calling dispatchDidFinishLoading so that we don't later try to
392         // cancel the already-finished substitute load.
393         unsigned long identifier = m_identifierForLoadWithoutResourceLoader;
394         m_identifierForLoadWithoutResourceLoader = 0;
395         frameLoader()->notifier().dispatchDidFinishLoading(this, identifier);
396     }
397
398     maybeFinishLoadingMultipartContent();
399
400     MonotonicTime responseEndTime = m_timeOfLastDataReceived ? m_timeOfLastDataReceived : MonotonicTime::now();
401     timing().setResponseEnd(responseEndTime);
402
403     commitIfReady();
404     if (!frameLoader())
405         return;
406
407     if (!maybeCreateArchive()) {
408         // If this is an empty document, it will not have actually been created yet. Commit dummy data so that
409         // DocumentWriter::begin() gets called and creates the Document.
410         if (!m_gotFirstByte)
411             commitData(0, 0);
412         frameLoader()->client().finishedLoading(this);
413     }
414
415     m_writer.end();
416     if (!m_mainDocumentError.isNull())
417         return;
418     clearMainResourceLoader();
419     if (!frameLoader()->stateMachine().creatingInitialEmptyDocument())
420         frameLoader()->checkLoadComplete();
421
422     // If the document specified an application cache manifest, it violates the author's intent if we store it in the memory cache
423     // and deny the appcache the chance to intercept it in the future, so remove from the memory cache.
424     if (m_frame) {
425         if (m_mainResource && m_frame->document()->hasManifest())
426             MemoryCache::singleton().remove(*m_mainResource);
427     }
428     m_applicationCacheHost->finishedLoadingMainResource();
429 }
430
431 bool DocumentLoader::isPostOrRedirectAfterPost(const ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
432 {
433     if (newRequest.httpMethod() == "POST")
434         return true;
435
436     int status = redirectResponse.httpStatusCode();
437     if (((status >= 301 && status <= 303) || status == 307)
438         && m_originalRequest.httpMethod() == "POST")
439         return true;
440
441     return false;
442 }
443
444 void DocumentLoader::handleSubstituteDataLoadNow()
445 {
446     ResourceResponse response = m_substituteData.response();
447     if (response.url().isEmpty())
448         response = ResourceResponse(m_request.url(), m_substituteData.mimeType(), m_substituteData.content()->size(), m_substituteData.textEncoding());
449
450     responseReceived(response);
451 }
452
453 void DocumentLoader::startDataLoadTimer()
454 {
455     m_dataLoadTimer.startOneShot(0);
456
457 #if HAVE(RUNLOOP_TIMER)
458     if (SchedulePairHashSet* scheduledPairs = m_frame->page()->scheduledRunLoopPairs())
459         m_dataLoadTimer.schedule(*scheduledPairs);
460 #endif
461 }
462
463 void DocumentLoader::handleSubstituteDataLoadSoon()
464 {
465     if (!m_deferMainResourceDataLoad || frameLoader()->loadsSynchronously())
466         handleSubstituteDataLoadNow();
467     else
468         startDataLoadTimer();
469 }
470
471 void DocumentLoader::redirectReceived(CachedResource& resource, ResourceRequest& request, const ResourceResponse& redirectResponse)
472 {
473     ASSERT_UNUSED(resource, &resource == m_mainResource);
474     willSendRequest(request, redirectResponse);
475 }
476
477 void DocumentLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
478 {
479     // Note that there are no asserts here as there are for the other callbacks. This is due to the
480     // fact that this "callback" is sent when starting every load, and the state of callback
481     // deferrals plays less of a part in this function in preventing the bad behavior deferring 
482     // callbacks is meant to prevent.
483     ASSERT(!newRequest.isNull());
484
485     bool didReceiveRedirectResponse = !redirectResponse.isNull();
486     if (!frameLoader()->checkIfFormActionAllowedByCSP(newRequest.url(), didReceiveRedirectResponse)) {
487         cancelMainResourceLoad(frameLoader()->cancelledError(newRequest));
488         return;
489     }
490
491     ASSERT(timing().fetchStart());
492     if (didReceiveRedirectResponse) {
493         // If the redirecting url is not allowed to display content from the target origin,
494         // then block the redirect.
495         Ref<SecurityOrigin> redirectingOrigin(SecurityOrigin::create(redirectResponse.url()));
496         if (!redirectingOrigin.get().canDisplay(newRequest.url())) {
497             FrameLoader::reportLocalLoadFailed(m_frame, newRequest.url().string());
498             cancelMainResourceLoad(frameLoader()->cancelledError(newRequest));
499             return;
500         }
501         if (!portAllowed(newRequest.url())) {
502             FrameLoader::reportBlockedPortFailed(m_frame, newRequest.url().string());
503             cancelMainResourceLoad(frameLoader()->blockedError(newRequest));
504             return;
505         }
506         timing().addRedirect(redirectResponse.url(), newRequest.url());
507     }
508
509     ASSERT(m_frame);
510
511     Frame& topFrame = m_frame->tree().top();
512
513     ASSERT(m_frame->document());
514     ASSERT(topFrame.document());
515
516     ResourceLoadObserver::sharedObserver().logFrameNavigation(*m_frame, topFrame, newRequest, redirectResponse);
517     
518     // Update cookie policy base URL as URL changes, except for subframes, which use the
519     // URL of the main frame which doesn't change when we redirect.
520     if (m_frame->isMainFrame())
521         newRequest.setFirstPartyForCookies(newRequest.url());
522
523     // If we're fielding a redirect in response to a POST, force a load from origin, since
524     // this is a common site technique to return to a page viewing some data that the POST
525     // just modified.
526     // Also, POST requests always load from origin, but this does not affect subresources.
527     if (newRequest.cachePolicy() == UseProtocolCachePolicy && isPostOrRedirectAfterPost(newRequest, redirectResponse))
528         newRequest.setCachePolicy(ReloadIgnoringCacheData);
529
530     if (&topFrame != m_frame) {
531         if (!m_frame->loader().mixedContentChecker().canDisplayInsecureContent(m_frame->document()->securityOrigin(), MixedContentChecker::ContentType::Active, newRequest.url(), MixedContentChecker::AlwaysDisplayInNonStrictMode::Yes)) {
532             cancelMainResourceLoad(frameLoader()->cancelledError(newRequest));
533             return;
534         }
535         if (!frameLoader()->mixedContentChecker().canDisplayInsecureContent(topFrame.document()->securityOrigin(), MixedContentChecker::ContentType::Active, newRequest.url())) {
536             cancelMainResourceLoad(frameLoader()->cancelledError(newRequest));
537             return;
538         }
539     }
540
541 #if ENABLE(CONTENT_FILTERING)
542     if (m_contentFilter && !m_contentFilter->continueAfterWillSendRequest(newRequest, redirectResponse))
543         return;
544 #endif
545
546     setRequest(newRequest);
547
548     if (didReceiveRedirectResponse) {
549         // We checked application cache for initial URL, now we need to check it for redirected one.
550         ASSERT(!m_substituteData.isValid());
551         m_applicationCacheHost->maybeLoadMainResourceForRedirect(newRequest, m_substituteData);
552         if (m_substituteData.isValid()) {
553             RELEASE_ASSERT(m_mainResource);
554             ResourceLoader* loader = m_mainResource->loader();
555             m_identifierForLoadWithoutResourceLoader = loader ? loader->identifier() : m_mainResource->identifierForLoadWithoutResourceLoader();
556         }
557     }
558
559     // FIXME: Ideally we'd stop the I/O until we hear back from the navigation policy delegate
560     // listener. But there's no way to do that in practice. So instead we cancel later if the
561     // listener tells us to. In practice that means the navigation policy needs to be decided
562     // synchronously for these redirect cases.
563     if (!didReceiveRedirectResponse)
564         return;
565
566     ASSERT(!m_waitingForNavigationPolicy);
567     m_waitingForNavigationPolicy = true;
568     frameLoader()->policyChecker().checkNavigationPolicy(newRequest, didReceiveRedirectResponse, [this] (const ResourceRequest& request, FormState*, bool shouldContinue) {
569         continueAfterNavigationPolicy(request, shouldContinue);
570     });
571 }
572
573 void DocumentLoader::continueAfterNavigationPolicy(const ResourceRequest&, bool shouldContinue)
574 {
575     ASSERT(m_waitingForNavigationPolicy);
576     m_waitingForNavigationPolicy = false;
577     if (!shouldContinue)
578         stopLoadingForPolicyChange();
579     else if (m_substituteData.isValid()) {
580         // A redirect resulted in loading substitute data.
581         ASSERT(timing().redirectCount());
582
583         // We need to remove our reference to the CachedResource in favor of a SubstituteData load.
584         // This will probably trigger the cancellation of the CachedResource's underlying ResourceLoader, though there is a
585         // small chance that the resource is being loaded by a different Frame, preventing the ResourceLoader from being cancelled.
586         // If the ResourceLoader is indeed cancelled, it would normally send resource load callbacks.
587         // However, from an API perspective, this isn't a cancellation. Therefore, sever our relationship with the network load,
588         // but prevent the ResourceLoader from sending ResourceLoadNotifier callbacks.
589         RefPtr<ResourceLoader> resourceLoader = mainResourceLoader();
590         if (resourceLoader) {
591             ASSERT(resourceLoader->shouldSendResourceLoadCallbacks());
592             resourceLoader->setSendCallbackPolicy(DoNotSendCallbacks);
593         }
594
595         clearMainResource();
596
597         if (resourceLoader)
598             resourceLoader->setSendCallbackPolicy(SendCallbacks);
599         handleSubstituteDataLoadSoon();
600     }
601 }
602
603 void DocumentLoader::stopLoadingAfterXFrameOptionsOrContentSecurityPolicyDenied(unsigned long identifier, const ResourceResponse& response)
604 {
605     InspectorInstrumentation::continueAfterXFrameOptionsDenied(*m_frame, identifier, *this, response);
606     m_frame->document()->enforceSandboxFlags(SandboxOrigin);
607     if (HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement())
608         ownerElement->dispatchEvent(Event::create(eventNames().loadEvent, false, false));
609
610     // The load event might have detached this frame. In that case, the load will already have been cancelled during detach.
611     if (FrameLoader* frameLoader = this->frameLoader())
612         cancelMainResourceLoad(frameLoader->cancelledError(m_request));
613 }
614
615 void DocumentLoader::responseReceived(CachedResource& resource, const ResourceResponse& response)
616 {
617     ASSERT_UNUSED(resource, m_mainResource == &resource);
618     responseReceived(response);
619 }
620
621 void DocumentLoader::responseReceived(const ResourceResponse& response)
622 {
623 #if ENABLE(CONTENT_FILTERING)
624     if (m_contentFilter && !m_contentFilter->continueAfterResponseReceived(response))
625         return;
626 #endif
627
628     Ref<DocumentLoader> protectedThis(*this);
629     bool willLoadFallback = m_applicationCacheHost->maybeLoadFallbackForMainResponse(request(), response);
630
631     // The memory cache doesn't understand the application cache or its caching rules. So if a main resource is served
632     // from the application cache, ensure we don't save the result for future use.
633     if (willLoadFallback)
634         MemoryCache::singleton().remove(*m_mainResource);
635
636     if (willLoadFallback)
637         return;
638
639     ASSERT(m_identifierForLoadWithoutResourceLoader || m_mainResource);
640     unsigned long identifier = m_identifierForLoadWithoutResourceLoader ? m_identifierForLoadWithoutResourceLoader : m_mainResource->identifier();
641     ASSERT(identifier);
642     
643     auto url = response.url();
644
645     ContentSecurityPolicy contentSecurityPolicy(SecurityOrigin::create(url), m_frame);
646     contentSecurityPolicy.didReceiveHeaders(ContentSecurityPolicyResponseHeaders(response));
647     if (!contentSecurityPolicy.allowFrameAncestors(*m_frame, url)) {
648         stopLoadingAfterXFrameOptionsOrContentSecurityPolicyDenied(identifier, response);
649         return;
650     }
651
652     const auto& commonHeaders = response.httpHeaderFields().commonHeaders();
653     auto it = commonHeaders.find(HTTPHeaderName::XFrameOptions);
654     if (it != commonHeaders.end()) {
655         String content = it->value;
656         if (frameLoader()->shouldInterruptLoadForXFrameOptions(content, url, identifier)) {
657             String message = "Refused to display '" + url.stringCenterEllipsizedToLength() + "' in a frame because it set 'X-Frame-Options' to '" + content + "'.";
658             m_frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, message, identifier);
659             stopLoadingAfterXFrameOptionsOrContentSecurityPolicyDenied(identifier, response);
660             return;
661         }
662     }
663
664     // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred.
665     // See <rdar://problem/6304600> for more details.
666 #if !USE(CF)
667     ASSERT(!mainResourceLoader() || !mainResourceLoader()->defersLoading());
668 #endif
669
670     if (m_isLoadingMultipartContent) {
671         setupForReplace();
672         m_mainResource->clear();
673     } else if (response.isMultipart())
674         m_isLoadingMultipartContent = true;
675
676     m_response = response;
677
678     if (m_identifierForLoadWithoutResourceLoader) {
679         if (m_mainResource && m_mainResource->wasRedirected()) {
680             ASSERT(m_mainResource->status() == CachedResource::Status::Cached);
681             frameLoader()->client().dispatchDidReceiveServerRedirectForProvisionalLoad();
682         }
683         addResponse(m_response);
684         frameLoader()->notifier().dispatchDidReceiveResponse(this, m_identifierForLoadWithoutResourceLoader, m_response, 0);
685     }
686
687     ASSERT(!m_waitingForContentPolicy);
688     ASSERT(frameLoader());
689     m_waitingForContentPolicy = true;
690
691     // Always show content with valid substitute data.
692     if (m_substituteData.isValid()) {
693         continueAfterContentPolicy(PolicyUse);
694         return;
695     }
696
697 #if ENABLE(FTPDIR)
698     // Respect the hidden FTP Directory Listing pref so it can be tested even if the policy delegate might otherwise disallow it
699     if (m_frame->settings().forceFTPDirectoryListings() && m_response.mimeType() == "application/x-ftp-directory") {
700         continueAfterContentPolicy(PolicyUse);
701         return;
702     }
703 #endif
704
705     frameLoader()->policyChecker().checkContentPolicy(m_response, [this](PolicyAction policy) {
706         continueAfterContentPolicy(policy);
707     });
708 }
709
710 static bool isRemoteWebArchive(const DocumentLoader& documentLoader)
711 {
712     using MIMETypeHashSet = HashSet<String, ASCIICaseInsensitiveHash>;
713     static NeverDestroyed<MIMETypeHashSet> webArchiveMIMETypes {
714         MIMETypeHashSet {
715             ASCIILiteral("application/x-webarchive"),
716             ASCIILiteral("application/x-mimearchive"),
717             ASCIILiteral("multipart/related"),
718 #if PLATFORM(GTK)
719             ASCIILiteral("message/rfc822"),
720 #endif
721         }
722     };
723
724     const ResourceResponse& response = documentLoader.response();
725     String mimeType = response.mimeType();
726     if (mimeType.isNull() || !webArchiveMIMETypes.get().contains(mimeType))
727         return false;
728
729 #if USE(QUICK_LOOK)
730     if (response.url().protocolIs(QLPreviewProtocol()))
731         return false;
732 #endif
733
734     return !documentLoader.substituteData().isValid() && !SchemeRegistry::shouldTreatURLSchemeAsLocal(documentLoader.request().url().protocol().toStringWithoutCopying());
735 }
736
737 void DocumentLoader::continueAfterContentPolicy(PolicyAction policy)
738 {
739     ASSERT(m_waitingForContentPolicy);
740     m_waitingForContentPolicy = false;
741     if (isStopping())
742         return;
743
744     switch (policy) {
745     case PolicyUse: {
746         // Prevent remote web archives from loading because they can claim to be from any domain and thus avoid cross-domain security checks (4120255).
747         if (!frameLoader()->client().canShowMIMEType(m_response.mimeType()) || isRemoteWebArchive(*this)) {
748             frameLoader()->policyChecker().cannotShowMIMEType(m_response);
749             // Check reachedTerminalState since the load may have already been canceled inside of _handleUnimplementablePolicyWithErrorCode::.
750             stopLoadingForPolicyChange();
751             return;
752         }
753         break;
754     }
755
756     case PolicyDownload: {
757         // m_mainResource can be null, e.g. when loading a substitute resource from application cache.
758         if (!m_mainResource) {
759             mainReceivedError(frameLoader()->client().cannotShowURLError(m_request));
760             return;
761         }
762
763         if (ResourceLoader* mainResourceLoader = this->mainResourceLoader())
764             InspectorInstrumentation::continueWithPolicyDownload(*m_frame, mainResourceLoader->identifier(), *this, m_response);
765
766         // When starting the request, we didn't know that it would result in download and not navigation. Now we know that main document URL didn't change.
767         // Download may use this knowledge for purposes unrelated to cookies, notably for setting file quarantine data.
768         frameLoader()->setOriginalURLForDownloadRequest(m_request);
769
770         SessionID sessionID = SessionID::defaultSessionID();
771         if (frame() && frame()->page())
772             sessionID = frame()->page()->sessionID();
773
774         if (m_request.url().protocolIsData()) {
775             // We decode data URL internally, there is no resource load to convert.
776             frameLoader()->client().startDownload(m_request);
777         } else
778             frameLoader()->client().convertMainResourceLoadToDownload(this, sessionID, m_request, m_response);
779
780         // It might have gone missing
781         if (mainResourceLoader())
782             static_cast<ResourceLoader*>(mainResourceLoader())->didFail(interruptedForPolicyChangeError());
783         return;
784     }
785     case PolicyIgnore:
786         if (ResourceLoader* mainResourceLoader = this->mainResourceLoader())
787             InspectorInstrumentation::continueWithPolicyIgnore(*m_frame, mainResourceLoader->identifier(), *this, m_response);
788         stopLoadingForPolicyChange();
789         return;
790     }
791
792     if (m_response.isHTTP()) {
793         int status = m_response.httpStatusCode(); // Status may be zero when loading substitute data, in particular from a WebArchive.
794         if (status && (status < 200 || status >= 300)) {
795             bool hostedByObject = frameLoader()->isHostedByObjectElement();
796
797             frameLoader()->handleFallbackContent();
798             // object elements are no longer rendered after we fallback, so don't
799             // keep trying to process data from their load
800
801             if (hostedByObject)
802                 cancelMainResourceLoad(frameLoader()->cancelledError(m_request));
803         }
804     }
805
806     if (!isStopping() && m_substituteData.isValid() && isLoadingMainResource()) {
807         auto content = m_substituteData.content();
808         if (content && content->size())
809             dataReceived(content->data(), content->size());
810         if (isLoadingMainResource())
811             finishedLoading();
812     }
813 }
814
815 void DocumentLoader::commitLoad(const char* data, int length)
816 {
817     // Both unloading the old page and parsing the new page may execute JavaScript which destroys the datasource
818     // by starting a new load, so retain temporarily.
819     RefPtr<Frame> protectedFrame(m_frame);
820     Ref<DocumentLoader> protectedThis(*this);
821
822     commitIfReady();
823     FrameLoader* frameLoader = DocumentLoader::frameLoader();
824     if (!frameLoader)
825         return;
826 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
827     if (ArchiveFactory::isArchiveMimeType(response().mimeType()))
828         return;
829 #endif
830     frameLoader->client().committedLoad(this, data, length);
831
832     if (isMultipartReplacingLoad())
833         frameLoader->client().didReplaceMultipartContent();
834 }
835
836 ResourceError DocumentLoader::interruptedForPolicyChangeError() const
837 {
838     return frameLoader()->client().interruptedForPolicyChangeError(request());
839 }
840
841 void DocumentLoader::stopLoadingForPolicyChange()
842 {
843     ResourceError error = interruptedForPolicyChangeError();
844     error.setType(ResourceError::Type::Cancellation);
845     cancelMainResourceLoad(error);
846 }
847
848 void DocumentLoader::commitData(const char* bytes, size_t length)
849 {
850     if (!m_gotFirstByte) {
851         m_gotFirstByte = true;
852         m_writer.begin(documentURL(), false);
853         m_writer.setDocumentWasLoadedAsPartOfNavigation();
854
855         if (SecurityPolicy::allowSubstituteDataAccessToLocal() && m_originalSubstituteDataWasValid) {
856             // If this document was loaded with substituteData, then the document can
857             // load local resources. See https://bugs.webkit.org/show_bug.cgi?id=16756
858             // and https://bugs.webkit.org/show_bug.cgi?id=19760 for further
859             // discussion.
860             m_frame->document()->securityOrigin().grantLoadLocalResources();
861         }
862
863         if (frameLoader()->stateMachine().creatingInitialEmptyDocument())
864             return;
865
866 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
867         if (m_archive && m_archive->shouldOverrideBaseURL())
868             m_frame->document()->setBaseURLOverride(m_archive->mainResource()->url());
869 #endif
870
871         // Call receivedFirstData() exactly once per load. We should only reach this point multiple times
872         // for multipart loads, and FrameLoader::isReplacing() will be true after the first time.
873         if (!isMultipartReplacingLoad())
874             frameLoader()->receivedFirstData();
875
876         // The load could be canceled under receivedFirstData(), which makes delegate calls and even sometimes dispatches DOM events.
877         if (!isLoading())
878             return;
879
880         bool userChosen;
881         String encoding;
882         if (overrideEncoding().isNull()) {
883             userChosen = false;
884             encoding = response().textEncodingName();
885 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
886             if (m_archive && m_archive->shouldUseMainResourceEncoding())
887                 encoding = m_archive->mainResource()->textEncoding();
888 #endif
889         } else {
890             userChosen = true;
891             encoding = overrideEncoding();
892         }
893
894         m_writer.setEncoding(encoding, userChosen);
895     }
896
897 #if ENABLE(CONTENT_EXTENSIONS)
898     auto& extensionStyleSheets = m_frame->document()->extensionStyleSheets();
899
900     for (auto& pendingStyleSheet : m_pendingNamedContentExtensionStyleSheets)
901         extensionStyleSheets.maybeAddContentExtensionSheet(pendingStyleSheet.key, *pendingStyleSheet.value);
902     for (auto& pendingSelectorEntry : m_pendingContentExtensionDisplayNoneSelectors) {
903         for (const auto& pendingSelector : pendingSelectorEntry.value)
904             extensionStyleSheets.addDisplayNoneSelector(pendingSelectorEntry.key, pendingSelector.first, pendingSelector.second);
905     }
906
907     m_pendingNamedContentExtensionStyleSheets.clear();
908     m_pendingContentExtensionDisplayNoneSelectors.clear();
909 #endif
910
911     ASSERT(m_frame->document()->parsing());
912     m_writer.addData(bytes, length);
913 }
914
915 void DocumentLoader::dataReceived(CachedResource& resource, const char* data, int length)
916 {
917     ASSERT_UNUSED(resource, &resource == m_mainResource);
918     dataReceived(data, length);
919 }
920
921 void DocumentLoader::dataReceived(const char* data, int length)
922 {
923 #if ENABLE(CONTENT_FILTERING)
924     if (m_contentFilter && !m_contentFilter->continueAfterDataReceived(data, length))
925         return;
926 #endif
927
928     ASSERT(data);
929     ASSERT(length);
930     ASSERT(!m_response.isNull());
931
932     // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred.
933     // See <rdar://problem/6304600> for more details.
934 #if !USE(CF)
935     ASSERT(!mainResourceLoader() || !mainResourceLoader()->defersLoading());
936 #endif
937
938     if (m_identifierForLoadWithoutResourceLoader)
939         frameLoader()->notifier().dispatchDidReceiveData(this, m_identifierForLoadWithoutResourceLoader, data, length, -1);
940
941     m_applicationCacheHost->mainResourceDataReceived(data, length, -1, false);
942     m_timeOfLastDataReceived = MonotonicTime::now();
943
944     if (!isMultipartReplacingLoad())
945         commitLoad(data, length);
946 }
947
948 void DocumentLoader::setupForReplace()
949 {
950     if (!mainResourceData())
951         return;
952
953     frameLoader()->client().willReplaceMultipartContent();
954     
955     maybeFinishLoadingMultipartContent();
956     maybeCreateArchive();
957     m_writer.end();
958     frameLoader()->setReplacing();
959     m_gotFirstByte = false;
960     
961     stopLoadingSubresources();
962     stopLoadingPlugIns();
963 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
964     clearArchiveResources();
965 #endif
966 }
967
968 void DocumentLoader::checkLoadComplete()
969 {
970     if (!m_frame || isLoading())
971         return;
972
973     ASSERT(this == frameLoader()->activeDocumentLoader());
974     m_frame->document()->domWindow()->finishedLoading();
975 }
976
977 void DocumentLoader::attachToFrame(Frame& frame)
978 {
979     if (m_frame == &frame)
980         return;
981
982     ASSERT(!m_frame);
983     m_frame = &frame;
984     m_writer.setFrame(&frame);
985     attachToFrame();
986
987 #ifndef NDEBUG
988     m_hasEverBeenAttached = true;
989 #endif
990 }
991
992 void DocumentLoader::attachToFrame()
993 {
994     ASSERT(m_frame);
995 }
996
997 void DocumentLoader::detachFromFrame()
998 {
999 #ifndef NDEBUG
1000     if (m_hasEverBeenAttached)
1001         ASSERT_WITH_MESSAGE(m_frame, "detachFromFrame() is being called on a DocumentLoader twice without an attachToFrame() inbetween");
1002     else
1003         ASSERT_WITH_MESSAGE(m_frame, "detachFromFrame() is being called on a DocumentLoader that has never attached to any Frame");
1004 #endif
1005     RefPtr<Frame> protectedFrame(m_frame);
1006     Ref<DocumentLoader> protectedThis(*this);
1007
1008     // It never makes sense to have a document loader that is detached from its
1009     // frame have any loads active, so kill all the loads.
1010     stopLoading();
1011     if (m_mainResource && m_mainResource->hasClient(*this))
1012         m_mainResource->removeClient(*this);
1013 #if ENABLE(CONTENT_FILTERING)
1014     if (m_contentFilter)
1015         m_contentFilter->stopFilteringMainResource();
1016 #endif
1017
1018     m_applicationCacheHost->setDOMApplicationCache(nullptr);
1019
1020     cancelPolicyCheckIfNeeded();
1021
1022     // Even though we ASSERT at the top of this method that we have an m_frame, we're seeing crashes where m_frame is null.
1023     // This means either that a DocumentLoader is detaching twice, or is detaching before ever having attached.
1024     // Until we figure out how that is happening, null check m_frame before dereferencing it here.
1025     // <rdar://problem/21293082> and https://bugs.webkit.org/show_bug.cgi?id=146786
1026     if (m_frame)
1027         InspectorInstrumentation::loaderDetachedFromFrame(*m_frame, *this);
1028
1029     m_frame = nullptr;
1030 }
1031
1032 void DocumentLoader::clearMainResourceLoader()
1033 {
1034     m_loadingMainResource = false;
1035
1036     if (this == frameLoader()->activeDocumentLoader())
1037         checkLoadComplete();
1038 }
1039
1040 bool DocumentLoader::isLoadingInAPISense() const
1041 {
1042     // Once a frame has loaded, we no longer need to consider subresources,
1043     // but we still need to consider subframes.
1044     if (frameLoader()->state() != FrameStateComplete) {
1045         if (m_frame->settings().needsIsLoadingInAPISenseQuirk() && !m_subresourceLoaders.isEmpty())
1046             return true;
1047
1048         ASSERT(m_frame->document());
1049         auto& document = *m_frame->document();
1050         if ((isLoadingMainResource() || !document.loadEventFinished()) && isLoading())
1051             return true;
1052         if (m_cachedResourceLoader->requestCount())
1053             return true;
1054         if (document.processingLoadEvent())
1055             return true;
1056         if (document.hasActiveParser())
1057             return true;
1058         auto* scriptableParser = document.scriptableDocumentParser();
1059         if (scriptableParser && scriptableParser->hasScriptsWaitingForStylesheets())
1060             return true;
1061     }
1062     return frameLoader()->subframeIsLoading();
1063 }
1064
1065 bool DocumentLoader::maybeCreateArchive()
1066 {
1067 #if !ENABLE(WEB_ARCHIVE) && !ENABLE(MHTML)
1068     return false;
1069 #else
1070     // Give the archive machinery a crack at this document. If the MIME type is not an archive type, it will return 0.
1071     m_archive = ArchiveFactory::create(m_response.url(), mainResourceData().get(), m_response.mimeType());
1072     if (!m_archive)
1073         return false;
1074     
1075     addAllArchiveResources(*m_archive);
1076     ASSERT(m_archive->mainResource());
1077     auto& mainResource = *m_archive->mainResource();
1078     m_parsedArchiveData = &mainResource.data();
1079     m_writer.setMIMEType(mainResource.mimeType());
1080
1081     ASSERT(m_frame->document());
1082     commitData(mainResource.data().data(), mainResource.data().size());
1083     return true;
1084 #endif
1085 }
1086
1087 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
1088
1089 void DocumentLoader::setArchive(Ref<Archive>&& archive)
1090 {
1091     m_archive = WTFMove(archive);
1092     addAllArchiveResources(*m_archive);
1093 }
1094
1095 void DocumentLoader::addAllArchiveResources(Archive& archive)
1096 {
1097     if (!m_archiveResourceCollection)
1098         m_archiveResourceCollection = std::make_unique<ArchiveResourceCollection>();
1099     m_archiveResourceCollection->addAllResources(archive);
1100 }
1101
1102 // FIXME: Adding a resource directly to a DocumentLoader/ArchiveResourceCollection seems like bad design, but is API some apps rely on.
1103 // Can we change the design in a manner that will let us deprecate that API without reducing functionality of those apps?
1104 void DocumentLoader::addArchiveResource(Ref<ArchiveResource>&& resource)
1105 {
1106     if (!m_archiveResourceCollection)
1107         m_archiveResourceCollection = std::make_unique<ArchiveResourceCollection>();
1108     m_archiveResourceCollection->addResource(WTFMove(resource));
1109 }
1110
1111 RefPtr<Archive> DocumentLoader::popArchiveForSubframe(const String& frameName, const URL& url)
1112 {
1113     return m_archiveResourceCollection ? m_archiveResourceCollection->popSubframeArchive(frameName, url) : nullptr;
1114 }
1115
1116 void DocumentLoader::clearArchiveResources()
1117 {
1118     m_archiveResourceCollection = nullptr;
1119     m_substituteResourceDeliveryTimer.stop();
1120 }
1121
1122 SharedBuffer* DocumentLoader::parsedArchiveData() const
1123 {
1124     return m_parsedArchiveData.get();
1125 }
1126
1127 #endif // ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
1128
1129 ArchiveResource* DocumentLoader::archiveResourceForURL(const URL& url) const
1130 {
1131     if (!m_archiveResourceCollection)
1132         return nullptr;
1133     auto* resource = m_archiveResourceCollection->archiveResourceForURL(url);
1134     if (!resource || resource->shouldIgnoreWhenUnarchiving())
1135         return nullptr;
1136     return resource;
1137 }
1138
1139 RefPtr<ArchiveResource> DocumentLoader::mainResource() const
1140 {
1141     RefPtr<SharedBuffer> data = mainResourceData();
1142     if (!data)
1143         data = SharedBuffer::create();
1144     auto& response = this->response();
1145     return ArchiveResource::create(WTFMove(data), response.url(), response.mimeType(), response.textEncodingName(), frame()->tree().uniqueName());
1146 }
1147
1148 RefPtr<ArchiveResource> DocumentLoader::subresource(const URL& url) const
1149 {
1150     if (!isCommitted())
1151         return nullptr;
1152     
1153     auto* resource = m_cachedResourceLoader->cachedResource(url);
1154     if (!resource || !resource->isLoaded())
1155         return archiveResourceForURL(url);
1156
1157     if (resource->type() == CachedResource::MainResource)
1158         return nullptr;
1159
1160     auto* data = resource->resourceBuffer();
1161     if (!data)
1162         return nullptr;
1163
1164     return ArchiveResource::create(data, url, resource->response());
1165 }
1166
1167 Vector<Ref<ArchiveResource>> DocumentLoader::subresources() const
1168 {
1169     if (!isCommitted())
1170         return { };
1171
1172     Vector<Ref<ArchiveResource>> subresources;
1173     for (auto& handle : m_cachedResourceLoader->allCachedResources().values()) {
1174         if (auto subresource = this->subresource({ ParsedURLString, handle->url() }))
1175             subresources.append(subresource.releaseNonNull());
1176     }
1177     return subresources;
1178 }
1179
1180 void DocumentLoader::deliverSubstituteResourcesAfterDelay()
1181 {
1182     if (m_pendingSubstituteResources.isEmpty())
1183         return;
1184     ASSERT(m_frame);
1185     ASSERT(m_frame->page());
1186     if (m_frame->page()->defersLoading())
1187         return;
1188
1189     if (!m_substituteResourceDeliveryTimer.isActive())
1190         m_substituteResourceDeliveryTimer.startOneShot(0);
1191 }
1192
1193 void DocumentLoader::substituteResourceDeliveryTimerFired()
1194 {
1195     if (m_pendingSubstituteResources.isEmpty())
1196         return;
1197     ASSERT(m_frame);
1198     ASSERT(m_frame->page());
1199     if (m_frame->page()->defersLoading())
1200         return;
1201
1202     auto pendingSubstituteResources = WTFMove(m_pendingSubstituteResources);
1203     for (auto& pendingSubstituteResource : pendingSubstituteResources) {
1204         auto& loader = pendingSubstituteResource.key;
1205         if (auto& resource = pendingSubstituteResource.value)
1206             resource->deliver(*loader);
1207         else {
1208             // A null resource means that we should fail the load.
1209             // FIXME: Maybe we should use another error here - something like "not in cache".
1210             loader->didFail(loader->cannotShowURLError());
1211         }
1212     }
1213 }
1214
1215 #ifndef NDEBUG
1216
1217 bool DocumentLoader::isSubstituteLoadPending(ResourceLoader* loader) const
1218 {
1219     return m_pendingSubstituteResources.contains(loader);
1220 }
1221
1222 #endif
1223
1224 void DocumentLoader::cancelPendingSubstituteLoad(ResourceLoader* loader)
1225 {
1226     if (m_pendingSubstituteResources.isEmpty())
1227         return;
1228     m_pendingSubstituteResources.remove(loader);
1229     if (m_pendingSubstituteResources.isEmpty())
1230         m_substituteResourceDeliveryTimer.stop();
1231 }
1232
1233 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
1234
1235 bool DocumentLoader::scheduleArchiveLoad(ResourceLoader& loader, const ResourceRequest& request)
1236 {
1237     if (auto* resource = archiveResourceForURL(request.url())) {
1238         scheduleSubstituteResourceLoad(loader, *resource);
1239         return true;
1240     }
1241
1242     if (!m_archive)
1243         return false;
1244
1245 #if ENABLE(WEB_ARCHIVE)
1246     // The idea of WebArchiveDebugMode is that we should fail instead of trying to fetch from the network.
1247     // Returning true ensures the caller will not try to fetch from the network.
1248     if (m_frame->settings().webArchiveDebugModeEnabled() && responseMIMEType() == "application/x-webarchive")
1249         return true;
1250 #endif
1251
1252     // If we want to load from the archive only, then we should always return true so that the caller
1253     // does not try to fetch form the network.
1254     return m_archive->shouldLoadFromArchiveOnly();
1255 }
1256
1257 #endif
1258
1259 void DocumentLoader::scheduleSubstituteResourceLoad(ResourceLoader& loader, SubstituteResource& resource)
1260 {
1261     m_pendingSubstituteResources.set(&loader, &resource);
1262     deliverSubstituteResourcesAfterDelay();
1263 }
1264
1265 void DocumentLoader::addResponse(const ResourceResponse& response)
1266 {
1267     if (!m_stopRecordingResponses)
1268         m_responses.append(response);
1269 }
1270
1271 void DocumentLoader::stopRecordingResponses()
1272 {
1273     m_stopRecordingResponses = true;
1274     m_responses.shrinkToFit();
1275 }
1276
1277 void DocumentLoader::setTitle(const StringWithDirection& title)
1278 {
1279     if (m_pageTitle == title)
1280         return;
1281
1282     frameLoader()->willChangeTitle(this);
1283     m_pageTitle = title;
1284     frameLoader()->didChangeTitle(this);
1285 }
1286
1287 URL DocumentLoader::urlForHistory() const
1288 {
1289     // Return the URL to be used for history and B/F list.
1290     // Returns nil for WebDataProtocol URLs that aren't alternates
1291     // for unreachable URLs, because these can't be stored in history.
1292     if (m_substituteData.isValid() && !m_substituteData.shouldRevealToSessionHistory())
1293         return unreachableURL();
1294
1295     return m_originalRequestCopy.url();
1296 }
1297
1298 bool DocumentLoader::urlForHistoryReflectsFailure() const
1299 {
1300     return m_substituteData.isValid() || m_response.httpStatusCode() >= 400;
1301 }
1302
1303 URL DocumentLoader::documentURL() const
1304 {
1305     URL url = substituteData().response().url();
1306 #if ENABLE(WEB_ARCHIVE)
1307     if (url.isEmpty() && m_archive && m_archive->shouldUseMainResourceURL())
1308         url = m_archive->mainResource()->url();
1309 #endif
1310     if (url.isEmpty())
1311         url = m_request.url();
1312     if (url.isEmpty())
1313         url = m_response.url();
1314     return url;
1315 }
1316
1317 #if PLATFORM(IOS)
1318
1319 // FIXME: This method seems to violate the encapsulation of this class.
1320 void DocumentLoader::setResponseMIMEType(const String& responseMimeType)
1321 {
1322     m_response.setMimeType(responseMimeType);
1323 }
1324
1325 #endif
1326
1327 void DocumentLoader::setDefersLoading(bool defers)
1328 {
1329     // Multiple frames may be loading the same main resource simultaneously. If deferral state changes,
1330     // each frame's DocumentLoader will try to send a setDefersLoading() to the same underlying ResourceLoader. Ensure only
1331     // the "owning" DocumentLoader does so, as setDefersLoading() is not resilient to setting the same value repeatedly.
1332     if (mainResourceLoader() && mainResourceLoader()->documentLoader() == this)
1333         mainResourceLoader()->setDefersLoading(defers);
1334
1335     setAllDefersLoading(m_subresourceLoaders, defers);
1336     setAllDefersLoading(m_plugInStreamLoaders, defers);
1337     if (!defers)
1338         deliverSubstituteResourcesAfterDelay();
1339 }
1340
1341 void DocumentLoader::setMainResourceDataBufferingPolicy(DataBufferingPolicy dataBufferingPolicy)
1342 {
1343     if (m_mainResource)
1344         m_mainResource->setDataBufferingPolicy(dataBufferingPolicy);
1345 }
1346
1347 void DocumentLoader::stopLoadingPlugIns()
1348 {
1349     cancelAll(m_plugInStreamLoaders);
1350 }
1351
1352 void DocumentLoader::stopLoadingSubresources()
1353 {
1354     cancelAll(m_subresourceLoaders);
1355     ASSERT(m_subresourceLoaders.isEmpty());
1356 }
1357
1358 void DocumentLoader::addSubresourceLoader(ResourceLoader* loader)
1359 {
1360     // The main resource's underlying ResourceLoader will ask to be added here.
1361     // It is much simpler to handle special casing of main resource loads if we don't
1362     // let it be added. In the main resource load case, mainResourceLoader()
1363     // will still be null at this point, but m_gotFirstByte should be false here if and only
1364     // if we are just starting the main resource load.
1365     if (!m_gotFirstByte)
1366         return;
1367     ASSERT(loader->identifier());
1368     ASSERT(!m_subresourceLoaders.contains(loader->identifier()));
1369     ASSERT(!mainResourceLoader() || mainResourceLoader() != loader);
1370
1371     // A page in the PageCache or about to enter PageCache should not be able to start loads.
1372     ASSERT_WITH_SECURITY_IMPLICATION(!document() || document()->pageCacheState() == Document::NotInPageCache);
1373
1374     m_subresourceLoaders.add(loader->identifier(), loader);
1375 }
1376
1377 void DocumentLoader::removeSubresourceLoader(ResourceLoader* loader)
1378 {
1379     ASSERT(loader->identifier());
1380
1381     if (!m_subresourceLoaders.remove(loader->identifier()))
1382         return;
1383     checkLoadComplete();
1384     if (Frame* frame = m_frame)
1385         frame->loader().checkLoadComplete();
1386 }
1387
1388 void DocumentLoader::addPlugInStreamLoader(ResourceLoader& loader)
1389 {
1390     ASSERT(loader.identifier());
1391     ASSERT(!m_plugInStreamLoaders.contains(loader.identifier()));
1392
1393     m_plugInStreamLoaders.add(loader.identifier(), &loader);
1394 }
1395
1396 void DocumentLoader::removePlugInStreamLoader(ResourceLoader& loader)
1397 {
1398     ASSERT(loader.identifier());
1399     ASSERT(&loader == m_plugInStreamLoaders.get(loader.identifier()));
1400
1401     m_plugInStreamLoaders.remove(loader.identifier());
1402     checkLoadComplete();
1403 }
1404
1405 bool DocumentLoader::isMultipartReplacingLoad() const
1406 {
1407     return isLoadingMultipartContent() && frameLoader()->isReplacing();
1408 }
1409
1410 bool DocumentLoader::maybeLoadEmpty()
1411 {
1412     bool shouldLoadEmpty = !m_substituteData.isValid() && (m_request.url().isEmpty() || SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(m_request.url().protocol().toStringWithoutCopying()));
1413     if (!shouldLoadEmpty && !frameLoader()->client().representationExistsForURLScheme(m_request.url().protocol().toStringWithoutCopying()))
1414         return false;
1415
1416     if (m_request.url().isEmpty() && !frameLoader()->stateMachine().creatingInitialEmptyDocument()) {
1417         m_request.setURL(blankURL());
1418         if (isLoadingMainResource())
1419             frameLoader()->client().dispatchDidChangeProvisionalURL();
1420     }
1421
1422     String mimeType = shouldLoadEmpty ? "text/html" : frameLoader()->client().generatedMIMETypeForURLScheme(m_request.url().protocol().toStringWithoutCopying());
1423     m_response = ResourceResponse(m_request.url(), mimeType, 0, String());
1424     finishedLoading();
1425     return true;
1426 }
1427
1428 void DocumentLoader::startLoadingMainResource()
1429 {
1430     m_mainDocumentError = ResourceError();
1431     timing().markStartTimeAndFetchStart();
1432     ASSERT(!m_mainResource);
1433     ASSERT(!m_loadingMainResource);
1434     m_loadingMainResource = true;
1435
1436     if (maybeLoadEmpty()) {
1437         RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Returning empty document (frame = %p, main = %d)", m_frame, m_frame ? m_frame->isMainFrame() : false);
1438         return;
1439     }
1440
1441 #if ENABLE(CONTENT_FILTERING)
1442     m_contentFilter = !m_substituteData.isValid() ? ContentFilter::create(*this) : nullptr;
1443 #endif
1444
1445     // FIXME: Is there any way the extra fields could have not been added by now?
1446     // If not, it would be great to remove this line of code.
1447     // Note that currently, some requests may have incorrect extra fields even if this function has been called,
1448     // because we pass a wrong loadType (see FIXME in addExtraFieldsToMainResourceRequest()).
1449     frameLoader()->addExtraFieldsToMainResourceRequest(m_request);
1450
1451     ASSERT(timing().startTime());
1452     ASSERT(timing().fetchStart());
1453
1454     Ref<DocumentLoader> protectedThis(*this); // willSendRequest() may deallocate the provisional loader (which may be us) if it cancels the load.
1455     willSendRequest(m_request, ResourceResponse());
1456
1457     // willSendRequest() may lead to our Frame being detached or cancelling the load via nulling the ResourceRequest.
1458     if (!m_frame || m_request.isNull()) {
1459         RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Load canceled after willSendRequest (frame = %p, main = %d)", m_frame, m_frame ? m_frame->isMainFrame() : false);
1460         return;
1461     }
1462
1463     m_applicationCacheHost->maybeLoadMainResource(m_request, m_substituteData);
1464
1465     if (m_substituteData.isValid() && m_frame->page()) {
1466         RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Returning cached main resource (frame = %p, main = %d)", m_frame, m_frame->isMainFrame());
1467         m_identifierForLoadWithoutResourceLoader = m_frame->page()->progress().createUniqueIdentifier();
1468         frameLoader()->notifier().assignIdentifierToInitialRequest(m_identifierForLoadWithoutResourceLoader, this, m_request);
1469         frameLoader()->notifier().dispatchWillSendRequest(this, m_identifierForLoadWithoutResourceLoader, m_request, ResourceResponse());
1470         handleSubstituteDataLoadSoon();
1471         return;
1472     }
1473
1474     ResourceRequest request(m_request);
1475     request.setRequester(ResourceRequest::Requester::Main);
1476     // If this is a reload the cache layer might have made the previous request conditional. DocumentLoader can't handle 304 responses itself.
1477     request.makeUnconditional();
1478
1479     RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Starting load (frame = %p, main = %d)", m_frame, m_frame->isMainFrame());
1480
1481     static NeverDestroyed<ResourceLoaderOptions> mainResourceLoadOptions(SendCallbacks, SniffContent, BufferData, AllowStoredCredentials, ClientCredentialPolicy::MayAskClientForCredentials, FetchOptions::Credentials::Include, SkipSecurityCheck, FetchOptions::Mode::NoCors, IncludeCertificateInfo, ContentSecurityPolicyImposition::SkipPolicyCheck, DefersLoadingPolicy::AllowDefersLoading, CachingPolicy::AllowCaching);
1482     CachedResourceRequest mainResourceRequest(ResourceRequest(request), mainResourceLoadOptions);
1483     if (!m_frame->isMainFrame() && m_frame->document()) {
1484         // If we are loading the main resource of a subframe, use the cache partition of the main document.
1485         mainResourceRequest.setDomainForCachePartition(*m_frame->document());
1486     } else {
1487         auto origin = SecurityOrigin::create(request.url());
1488         origin->setStorageBlockingPolicy(frameLoader()->frame().settings().storageBlockingPolicy());
1489         mainResourceRequest.setDomainForCachePartition(origin->domainForCachePartition());
1490     }
1491     m_mainResource = m_cachedResourceLoader->requestMainResource(WTFMove(mainResourceRequest));
1492
1493 #if ENABLE(CONTENT_EXTENSIONS)
1494     if (m_mainResource && m_mainResource->errorOccurred() && m_frame->page() && m_mainResource->resourceError().domain() == ContentExtensions::WebKitContentBlockerDomain) {
1495         RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Blocked by content blocker error (frame = %p, main = %d)", m_frame, m_frame->isMainFrame());
1496         cancelMainResourceLoad(frameLoader()->blockedByContentBlockerError(m_request));
1497         return;
1498     }
1499 #endif
1500
1501     if (!m_mainResource) {
1502         if (!m_request.url().isValid()) {
1503             RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Unable to load main resource, URL is invalid (frame = %p, main = %d)", m_frame, m_frame->isMainFrame());
1504             cancelMainResourceLoad(frameLoader()->client().cannotShowURLError(m_request));
1505             return;
1506         }
1507
1508         RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Unable to load main resource, returning empty document (frame = %p, main = %d)", m_frame, m_frame->isMainFrame());
1509
1510         setRequest(ResourceRequest());
1511         // If the load was aborted by clearing m_request, it's possible the ApplicationCacheHost
1512         // is now in a state where starting an empty load will be inconsistent. Replace it with
1513         // a new ApplicationCacheHost.
1514         m_applicationCacheHost = std::make_unique<ApplicationCacheHost>(*this);
1515         maybeLoadEmpty();
1516         return;
1517     }
1518
1519     if (!mainResourceLoader()) {
1520         m_identifierForLoadWithoutResourceLoader = m_frame->page()->progress().createUniqueIdentifier();
1521         frameLoader()->notifier().assignIdentifierToInitialRequest(m_identifierForLoadWithoutResourceLoader, this, request);
1522         frameLoader()->notifier().dispatchWillSendRequest(this, m_identifierForLoadWithoutResourceLoader, request, ResourceResponse());
1523     }
1524
1525     becomeMainResourceClient();
1526
1527     // A bunch of headers are set when the underlying ResourceLoader is created, and m_request needs to include those.
1528     if (mainResourceLoader())
1529         request = mainResourceLoader()->originalRequest();
1530     // If there was a fragment identifier on m_request, the cache will have stripped it. m_request should include
1531     // the fragment identifier, so add that back in.
1532     if (equalIgnoringFragmentIdentifier(m_request.url(), request.url()))
1533         request.setURL(m_request.url());
1534     setRequest(request);
1535 }
1536
1537 void DocumentLoader::cancelPolicyCheckIfNeeded()
1538 {
1539     RELEASE_ASSERT(frameLoader());
1540
1541     if (m_waitingForContentPolicy || m_waitingForNavigationPolicy) {
1542         frameLoader()->policyChecker().cancelCheck();
1543         m_waitingForContentPolicy = false;
1544         m_waitingForNavigationPolicy = false;
1545     }
1546 }
1547
1548 void DocumentLoader::cancelMainResourceLoad(const ResourceError& resourceError)
1549 {
1550     Ref<DocumentLoader> protectedThis(*this);
1551     ResourceError error = resourceError.isNull() ? frameLoader()->cancelledError(m_request) : resourceError;
1552
1553     m_dataLoadTimer.stop();
1554
1555     cancelPolicyCheckIfNeeded();
1556
1557     if (mainResourceLoader())
1558         mainResourceLoader()->cancel(error);
1559
1560     clearMainResource();
1561
1562     mainReceivedError(error);
1563 }
1564
1565 void DocumentLoader::willContinueMainResourceLoadAfterRedirect(const ResourceRequest& newRequest)
1566 {
1567     setRequest(newRequest);
1568 }
1569
1570 void DocumentLoader::clearMainResource()
1571 {
1572     if (m_mainResource && m_mainResource->hasClient(*this))
1573         m_mainResource->removeClient(*this);
1574 #if ENABLE(CONTENT_FILTERING)
1575     if (m_contentFilter)
1576         m_contentFilter->stopFilteringMainResource();
1577 #endif
1578
1579     m_mainResource = nullptr;
1580 }
1581
1582 void DocumentLoader::subresourceLoaderFinishedLoadingOnePart(ResourceLoader* loader)
1583 {
1584     unsigned long identifier = loader->identifier();
1585     ASSERT(identifier);
1586
1587     if (!m_multipartSubresourceLoaders.add(identifier, loader).isNewEntry) {
1588         ASSERT(m_multipartSubresourceLoaders.get(identifier) == loader);
1589         ASSERT(!m_subresourceLoaders.contains(identifier));
1590     } else {
1591         ASSERT(m_subresourceLoaders.contains(identifier));
1592         m_subresourceLoaders.remove(identifier);
1593     }
1594
1595     checkLoadComplete();
1596     if (Frame* frame = m_frame)
1597         frame->loader().checkLoadComplete();    
1598 }
1599
1600 void DocumentLoader::maybeFinishLoadingMultipartContent()
1601 {
1602     if (!isMultipartReplacingLoad())
1603         return;
1604
1605     frameLoader()->setupForReplace();
1606     m_committed = false;
1607     RefPtr<SharedBuffer> resourceData = mainResourceData();
1608     commitLoad(resourceData->data(), resourceData->size());
1609 }
1610
1611 void DocumentLoader::iconLoadDecisionAvailable()
1612 {
1613     if (m_frame)
1614         m_frame->loader().icon().loadDecisionReceived(iconDatabase().synchronousLoadDecisionForIconURL(frameLoader()->icon().url(), this));
1615 }
1616
1617 static void iconLoadDecisionCallback(IconLoadDecision decision, void* context)
1618 {
1619     static_cast<DocumentLoader*>(context)->continueIconLoadWithDecision(decision);
1620 }
1621
1622 void DocumentLoader::getIconLoadDecisionForIconURL(const String& urlString)
1623 {
1624     if (m_iconLoadDecisionCallback)
1625         m_iconLoadDecisionCallback->invalidate();
1626     m_iconLoadDecisionCallback = IconLoadDecisionCallback::create(this, iconLoadDecisionCallback);
1627     iconDatabase().loadDecisionForIconURL(urlString, *m_iconLoadDecisionCallback);
1628 }
1629
1630 void DocumentLoader::continueIconLoadWithDecision(IconLoadDecision decision)
1631 {
1632     ASSERT(m_iconLoadDecisionCallback);
1633     m_iconLoadDecisionCallback = nullptr;
1634     if (m_frame)
1635         m_frame->loader().icon().continueLoadWithDecision(decision);
1636 }
1637
1638 static void iconDataCallback(SharedBuffer*, void*)
1639 {
1640     // FIXME: Implement this once we know what parts of WebCore actually need the icon data returned.
1641 }
1642
1643 void DocumentLoader::getIconDataForIconURL(const String& urlString)
1644 {   
1645     if (m_iconDataCallback)
1646         m_iconDataCallback->invalidate();
1647     m_iconDataCallback = IconDataCallback::create(this, iconDataCallback);
1648     iconDatabase().iconDataForIconURL(urlString, *m_iconDataCallback);
1649 }
1650
1651 void DocumentLoader::startIconLoading()
1652 {
1653     ASSERT(m_frame->loader().client().useIconLoadingClient());
1654
1655     static uint64_t nextIconCallbackID = 1;
1656
1657     auto* document = this->document();
1658     if (!document)
1659         return;
1660
1661     Vector<LinkIcon> icons = LinkIconCollector { *document }.iconsOfTypes({ LinkIconType::Favicon, LinkIconType::TouchIcon, LinkIconType::TouchPrecomposedIcon });
1662
1663     if (icons.isEmpty())
1664         icons.append({ m_frame->document()->completeURL(ASCIILiteral("/favicon.ico")), LinkIconType::Favicon, String(), std::nullopt });
1665
1666     for (auto& icon : icons) {
1667         auto result = m_iconsPendingLoadDecision.add(nextIconCallbackID++, icon);
1668         m_frame->loader().client().getLoadDecisionForIcon(icon, result.iterator->key);
1669     }
1670 }
1671
1672 void DocumentLoader::didGetLoadDecisionForIcon(bool decision, uint64_t loadIdentifier, uint64_t newCallbackID)
1673 {
1674     auto icon = m_iconsPendingLoadDecision.take(loadIdentifier);
1675     if (!decision || icon.url.isEmpty() || !m_frame)
1676         return;
1677
1678     auto iconLoader = std::make_unique<IconLoader>(*this, icon.url);
1679     iconLoader->startLoading();
1680     m_iconLoaders.set(WTFMove(iconLoader), newCallbackID);
1681 }
1682
1683 void DocumentLoader::finishedLoadingIcon(IconLoader& loader, SharedBuffer* buffer)
1684 {
1685     auto loadIdentifier = m_iconLoaders.take(&loader);
1686     ASSERT(loadIdentifier);
1687
1688     m_frame->loader().client().finishedLoadingIcon(loadIdentifier, buffer);
1689 }
1690
1691 void DocumentLoader::dispatchOnloadEvents()
1692 {
1693     m_wasOnloadDispatched = true;
1694     m_applicationCacheHost->stopDeferringEvents();
1695 }
1696
1697 void DocumentLoader::setTriggeringAction(const NavigationAction& action)
1698 {
1699     m_triggeringAction = action.copyWithShouldOpenExternalURLsPolicy(m_frame ? shouldOpenExternalURLsPolicyToPropagate() : m_shouldOpenExternalURLsPolicy);
1700 }
1701
1702 ShouldOpenExternalURLsPolicy DocumentLoader::shouldOpenExternalURLsPolicyToPropagate() const
1703 {
1704     if (!m_frame || !m_frame->isMainFrame())
1705         return ShouldOpenExternalURLsPolicy::ShouldNotAllow;
1706
1707     return m_shouldOpenExternalURLsPolicy;
1708 }
1709
1710 void DocumentLoader::becomeMainResourceClient()
1711 {
1712 #if ENABLE(CONTENT_FILTERING)
1713     if (m_contentFilter)
1714         m_contentFilter->startFilteringMainResource(*m_mainResource);
1715 #endif
1716     m_mainResource->addClient(*this);
1717 }
1718
1719 #if ENABLE(CONTENT_EXTENSIONS)
1720 void DocumentLoader::addPendingContentExtensionSheet(const String& identifier, StyleSheetContents& sheet)
1721 {
1722     ASSERT(!m_gotFirstByte);
1723     m_pendingNamedContentExtensionStyleSheets.set(identifier, &sheet);
1724 }
1725
1726 void DocumentLoader::addPendingContentExtensionDisplayNoneSelector(const String& identifier, const String& selector, uint32_t selectorID)
1727 {
1728     ASSERT(!m_gotFirstByte);
1729     auto addResult = m_pendingContentExtensionDisplayNoneSelectors.add(identifier, Vector<std::pair<String, uint32_t>>());
1730     addResult.iterator->value.append(std::make_pair(selector, selectorID));
1731 }
1732 #endif
1733
1734 bool DocumentLoader::isAlwaysOnLoggingAllowed() const
1735 {
1736     return !m_frame || m_frame->isAlwaysOnLoggingAllowed();
1737 }
1738
1739 #if USE(QUICK_LOOK)
1740
1741 void DocumentLoader::setPreviewConverter(std::unique_ptr<PreviewConverter>&& previewConverter)
1742 {
1743     m_previewConverter = WTFMove(previewConverter);
1744 }
1745
1746 PreviewConverter* DocumentLoader::previewConverter() const
1747 {
1748     return m_previewConverter.get();
1749 }
1750
1751 #endif
1752
1753 } // namespace WebCore