Remove PassRefPtr from "loader" directory of WebCore
[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 "ArchiveResourceCollection.h"
35 #include "CachedPage.h"
36 #include "CachedRawResource.h"
37 #include "CachedResourceLoader.h"
38 #include "ContentExtensionError.h"
39 #include "ContentSecurityPolicy.h"
40 #include "DOMWindow.h"
41 #include "Document.h"
42 #include "DocumentParser.h"
43 #include "DocumentWriter.h"
44 #include "ElementChildIterator.h"
45 #include "Event.h"
46 #include "EventNames.h"
47 #include "ExtensionStyleSheets.h"
48 #include "FormState.h"
49 #include "FrameLoader.h"
50 #include "FrameLoaderClient.h"
51 #include "FrameTree.h"
52 #include "HTMLFormElement.h"
53 #include "HTMLFrameOwnerElement.h"
54 #include "HTTPHeaderNames.h"
55 #include "HistoryItem.h"
56 #include "IconController.h"
57 #include "IconLoader.h"
58 #include "InspectorInstrumentation.h"
59 #include "LinkIconCollector.h"
60 #include "LinkIconType.h"
61 #include "Logging.h"
62 #include "MainFrame.h"
63 #include "MemoryCache.h"
64 #include "Page.h"
65 #include "PolicyChecker.h"
66 #include "ProgressTracker.h"
67 #include "ResourceHandle.h"
68 #include "ResourceLoadObserver.h"
69 #include "SchemeRegistry.h"
70 #include "SecurityPolicy.h"
71 #include "Settings.h"
72 #include "SubresourceLoader.h"
73 #include "TextResourceDecoder.h"
74 #include <wtf/Assertions.h>
75 #include <wtf/NeverDestroyed.h>
76 #include <wtf/Ref.h>
77 #include <wtf/text/CString.h>
78 #include <wtf/text/WTFString.h>
79
80 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
81 #include "ArchiveFactory.h"
82 #endif
83
84 #if ENABLE(CONTENT_FILTERING)
85 #include "ContentFilter.h"
86 #endif
87
88 #if USE(QUICK_LOOK)
89 #include "QuickLook.h"
90 #endif
91
92 #define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), Network, "%p - DocumentLoader::" fmt, this, ##__VA_ARGS__)
93
94 namespace WebCore {
95
96 static void cancelAll(const ResourceLoaderMap& loaders)
97 {
98     Vector<RefPtr<ResourceLoader>> loadersCopy;
99     copyValuesToVector(loaders, loadersCopy);
100     for (auto& loader : loadersCopy)
101         loader->cancel();
102 }
103
104 static void setAllDefersLoading(const ResourceLoaderMap& loaders, bool defers)
105 {
106     Vector<RefPtr<ResourceLoader>> loadersCopy;
107     copyValuesToVector(loaders, loadersCopy);
108     for (auto& loader : loadersCopy)
109         loader->setDefersLoading(defers);
110 }
111
112 static bool areAllLoadersPageCacheAcceptable(const ResourceLoaderMap& loaders)
113 {
114     Vector<RefPtr<ResourceLoader>> loadersCopy;
115     copyValuesToVector(loaders, loadersCopy);
116     for (auto& loader : loadersCopy) {
117         if (!loader->frameLoader() || !loader->frameLoader()->frame().page())
118             return false;
119
120         CachedResource* cachedResource = MemoryCache::singleton().resourceForRequest(loader->request(), loader->frameLoader()->frame().page()->sessionID());
121         if (!cachedResource)
122             return false;
123
124         // Only image and XHR loads do prevent the page from entering the PageCache.
125         // All non-image loads will prevent the page from entering the PageCache.
126         if (!cachedResource->isImage() && !cachedResource->areAllClientsXMLHttpRequests())
127             return false;
128     }
129     return true;
130 }
131
132 DocumentLoader::DocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
133     : m_cachedResourceLoader(CachedResourceLoader::create(this))
134     , m_writer(m_frame)
135     , m_originalRequest(request)
136     , m_substituteData(substituteData)
137     , m_originalRequestCopy(request)
138     , m_request(request)
139     , m_originalSubstituteDataWasValid(substituteData.isValid())
140     , m_substituteResourceDeliveryTimer(*this, &DocumentLoader::substituteResourceDeliveryTimerFired)
141     , m_dataLoadTimer(*this, &DocumentLoader::handleSubstituteDataLoadNow)
142     , m_applicationCacheHost(std::make_unique<ApplicationCacheHost>(*this))
143 {
144 }
145
146 FrameLoader* DocumentLoader::frameLoader() const
147 {
148     if (!m_frame)
149         return nullptr;
150     return &m_frame->loader();
151 }
152
153 SubresourceLoader* DocumentLoader::mainResourceLoader() const
154 {
155     if (!m_mainResource)
156         return nullptr;
157     return m_mainResource->loader();
158 }
159
160 DocumentLoader::~DocumentLoader()
161 {
162     ASSERT(!m_frame || frameLoader()->activeDocumentLoader() != this || !isLoading());
163     ASSERT_WITH_MESSAGE(!m_waitingForContentPolicy, "The content policy callback should never outlive its DocumentLoader.");
164     ASSERT_WITH_MESSAGE(!m_waitingForNavigationPolicy, "The navigation policy callback should never outlive its DocumentLoader.");
165     if (m_iconLoadDecisionCallback)
166         m_iconLoadDecisionCallback->invalidate();
167     if (m_iconDataCallback)
168         m_iconDataCallback->invalidate();
169     m_cachedResourceLoader->clearDocumentLoader();
170
171     clearMainResource();
172 }
173
174 RefPtr<SharedBuffer> DocumentLoader::mainResourceData() const
175 {
176     if (m_substituteData.isValid())
177         return m_substituteData.content()->copy();
178     if (m_mainResource)
179         return m_mainResource->resourceBuffer();
180     return nullptr;
181 }
182
183 Document* DocumentLoader::document() const
184 {
185     if (m_frame && m_frame->loader().documentLoader() == this)
186         return m_frame->document();
187     return nullptr;
188 }
189
190 void DocumentLoader::replaceRequestURLForSameDocumentNavigation(const URL& url)
191 {
192     m_originalRequestCopy.setURL(url);
193     m_request.setURL(url);
194 }
195
196 void DocumentLoader::setRequest(const ResourceRequest& req)
197 {
198     // Replacing an unreachable URL with alternate content looks like a server-side
199     // redirect at this point, but we can replace a committed dataSource.
200     bool handlingUnreachableURL = false;
201
202     handlingUnreachableURL = m_substituteData.isValid() && !m_substituteData.failingURL().isEmpty();
203
204     bool shouldNotifyAboutProvisionalURLChange = false;
205     if (handlingUnreachableURL)
206         m_committed = false;
207     else if (isLoadingMainResource() && req.url() != m_request.url())
208         shouldNotifyAboutProvisionalURLChange = true;
209
210     // We should never be getting a redirect callback after the data
211     // source is committed, except in the unreachable URL case. It 
212     // would be a WebFoundation bug if it sent a redirect callback after commit.
213     ASSERT(!m_committed);
214
215     m_request = req;
216     if (shouldNotifyAboutProvisionalURLChange)
217         frameLoader()->client().dispatchDidChangeProvisionalURL();
218 }
219
220 void DocumentLoader::setMainDocumentError(const ResourceError& error)
221 {
222     m_mainDocumentError = error;    
223     frameLoader()->client().setMainDocumentError(this, error);
224 }
225
226 void DocumentLoader::mainReceivedError(const ResourceError& error)
227 {
228     ASSERT(!error.isNull());
229
230     if (!frameLoader())
231         return;
232
233     if (m_identifierForLoadWithoutResourceLoader) {
234         ASSERT(!mainResourceLoader());
235         frameLoader()->client().dispatchDidFailLoading(this, m_identifierForLoadWithoutResourceLoader, error);
236     }
237
238     // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred.
239     // See <rdar://problem/6304600> for more details.
240 #if !USE(CF)
241     ASSERT(!mainResourceLoader() || !mainResourceLoader()->defersLoading());
242 #endif
243
244     m_applicationCacheHost->failedLoadingMainResource();
245
246     setMainDocumentError(error);
247     clearMainResourceLoader();
248     frameLoader()->receivedMainResourceError(error);
249 }
250
251 // Cancels the data source's pending loads.  Conceptually, a data source only loads
252 // one document at a time, but one document may have many related resources. 
253 // stopLoading will stop all loads initiated by the data source, 
254 // but not loads initiated by child frames' data sources -- that's the WebFrame's job.
255 void DocumentLoader::stopLoading()
256 {
257     RefPtr<Frame> protectedFrame(m_frame);
258     Ref<DocumentLoader> protectedThis(*this);
259
260     // In some rare cases, calling FrameLoader::stopLoading could cause isLoading() to return false.
261     // (This can happen when there's a single XMLHttpRequest currently loading and stopLoading causes it
262     // to stop loading. Because of this, we need to save it so we don't return early.
263     bool loading = isLoading();
264
265     // We may want to audit the existing subresource loaders when we are on a page which has completed
266     // loading but there are subresource loads during cancellation. This must be done before the
267     // frame->stopLoading() call, which may evict the CachedResources, which we rely on to check
268     // the type of the resource loads.
269     if (loading && m_committed && !mainResourceLoader() && !m_subresourceLoaders.isEmpty())
270         m_subresourceLoadersArePageCacheAcceptable = areAllLoadersPageCacheAcceptable(m_subresourceLoaders);
271
272     if (m_committed) {
273         // Attempt to stop the frame if the document loader is loading, or if it is done loading but
274         // still  parsing. Failure to do so can cause a world leak.
275         Document* doc = m_frame->document();
276         
277         if (loading || doc->parsing())
278             m_frame->loader().stopLoading(UnloadEventPolicyNone);
279     }
280
281     // Always cancel multipart loaders
282     cancelAll(m_multipartSubresourceLoaders);
283
284     // Appcache uses ResourceHandle directly, DocumentLoader doesn't count these loads.
285     m_applicationCacheHost->stopLoadingInFrame(*m_frame);
286     
287 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
288     clearArchiveResources();
289 #endif
290
291     if (!loading) {
292         // If something above restarted loading we might run into mysterious crashes like 
293         // https://bugs.webkit.org/show_bug.cgi?id=62764 and <rdar://problem/9328684>
294         ASSERT(!isLoading());
295         return;
296     }
297
298     // We might run in to infinite recursion if we're stopping loading as the result of 
299     // detaching from the frame, so break out of that recursion here.
300     // See <rdar://problem/9673866> for more details.
301     if (m_isStopping)
302         return;
303
304     m_isStopping = true;
305
306     FrameLoader* frameLoader = DocumentLoader::frameLoader();
307     
308     if (isLoadingMainResource()) {
309         // Stop the main resource loader and let it send the cancelled message.
310         cancelMainResourceLoad(frameLoader->cancelledError(m_request));
311     } else if (!m_subresourceLoaders.isEmpty() || !m_plugInStreamLoaders.isEmpty()) {
312         // The main resource loader already finished loading. Set the cancelled error on the
313         // document and let the subresourceLoaders and pluginLoaders send individual cancelled messages below.
314         setMainDocumentError(frameLoader->cancelledError(m_request));
315     } else {
316         // If there are no resource loaders, we need to manufacture a cancelled message.
317         // (A back/forward navigation has no resource loaders because its resources are cached.)
318         mainReceivedError(frameLoader->cancelledError(m_request));
319     }
320
321     // We always need to explicitly cancel the Document's parser when stopping the load.
322     // Otherwise cancelling the parser while starting the next page load might result
323     // in unexpected side effects such as erroneous event dispatch. ( http://webkit.org/b/117112 )
324     if (Document* document = this->document())
325         document->cancelParsing();
326     
327     stopLoadingSubresources();
328     stopLoadingPlugIns();
329     
330     m_isStopping = false;
331 }
332
333 void DocumentLoader::commitIfReady()
334 {
335     if (!m_committed) {
336         m_committed = true;
337         frameLoader()->commitProvisionalLoad();
338     }
339 }
340
341 bool DocumentLoader::isLoading() const
342 {
343     // if (document() && document()->hasActiveParser())
344     //     return true;
345     // FIXME: The above code should be enabled, but it seems to cause
346     // http/tests/security/feed-urls-from-remote.html to timeout on Mac WK1
347     // see http://webkit.org/b/110554 and http://webkit.org/b/110401
348
349     return isLoadingMainResource() || !m_subresourceLoaders.isEmpty() || !m_plugInStreamLoaders.isEmpty();
350 }
351
352 void DocumentLoader::notifyFinished(CachedResource& resource)
353 {
354 #if ENABLE(CONTENT_FILTERING)
355     if (m_contentFilter && !m_contentFilter->continueAfterNotifyFinished(resource))
356         return;
357 #endif
358
359     ASSERT_UNUSED(resource, m_mainResource == &resource);
360     ASSERT(m_mainResource);
361     if (!m_mainResource->errorOccurred() && !m_mainResource->wasCanceled()) {
362         finishedLoading(m_mainResource->loadFinishTime());
363         return;
364     }
365
366     if (m_request.cachePolicy() == ReturnCacheDataDontLoad && !m_mainResource->wasCanceled()) {
367         frameLoader()->retryAfterFailedCacheOnlyMainResourceLoad();
368         return;
369     }
370
371     mainReceivedError(m_mainResource->resourceError());
372 }
373
374 void DocumentLoader::finishedLoading(double finishTime)
375 {
376     // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred.
377     // See <rdar://problem/6304600> for more details.
378 #if !USE(CF)
379     ASSERT(!m_frame->page()->defersLoading() || frameLoader()->stateMachine().creatingInitialEmptyDocument() || InspectorInstrumentation::isDebuggerPaused(m_frame));
380 #endif
381
382     Ref<DocumentLoader> protectedThis(*this);
383
384     if (m_identifierForLoadWithoutResourceLoader) {
385         // A didFinishLoading delegate might try to cancel the load (despite it
386         // being finished). Clear m_identifierForLoadWithoutResourceLoader
387         // before calling dispatchDidFinishLoading so that we don't later try to
388         // cancel the already-finished substitute load.
389         unsigned long identifier = m_identifierForLoadWithoutResourceLoader;
390         m_identifierForLoadWithoutResourceLoader = 0;
391         frameLoader()->notifier().dispatchDidFinishLoading(this, identifier, finishTime);
392     }
393
394     maybeFinishLoadingMultipartContent();
395
396     double responseEndTime = finishTime;
397     if (!responseEndTime)
398         responseEndTime = m_timeOfLastDataReceived;
399     if (!responseEndTime)
400         responseEndTime = monotonicallyIncreasingTime();
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(0);
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 (m_archive && m_archive->shouldOverrideBaseURL())
867             m_frame->document()->setBaseURLOverride(m_archive->mainResource()->url());
868
869         // Call receivedFirstData() exactly once per load. We should only reach this point multiple times
870         // for multipart loads, and FrameLoader::isReplacing() will be true after the first time.
871         if (!isMultipartReplacingLoad())
872             frameLoader()->receivedFirstData();
873
874         // The load could be canceled under receivedFirstData(), which makes delegate calls and even sometimes dispatches DOM events.
875         if (!isLoading())
876             return;
877
878         bool userChosen;
879         String encoding;
880         if (overrideEncoding().isNull()) {
881             userChosen = false;
882             encoding = response().textEncodingName();
883             if (m_archive && m_archive->shouldUseMainResourceEncoding())
884                 encoding = m_archive->mainResource()->textEncoding();
885         } else {
886             userChosen = true;
887             encoding = overrideEncoding();
888         }
889
890         m_writer.setEncoding(encoding, userChosen);
891     }
892
893 #if ENABLE(CONTENT_EXTENSIONS)
894     auto& extensionStyleSheets = m_frame->document()->extensionStyleSheets();
895
896     for (auto& pendingStyleSheet : m_pendingNamedContentExtensionStyleSheets)
897         extensionStyleSheets.maybeAddContentExtensionSheet(pendingStyleSheet.key, *pendingStyleSheet.value);
898     for (auto& pendingSelectorEntry : m_pendingContentExtensionDisplayNoneSelectors) {
899         for (const auto& pendingSelector : pendingSelectorEntry.value)
900             extensionStyleSheets.addDisplayNoneSelector(pendingSelectorEntry.key, pendingSelector.first, pendingSelector.second);
901     }
902
903     m_pendingNamedContentExtensionStyleSheets.clear();
904     m_pendingContentExtensionDisplayNoneSelectors.clear();
905 #endif
906
907     ASSERT(m_frame->document()->parsing());
908     m_writer.addData(bytes, length);
909 }
910
911 void DocumentLoader::dataReceived(CachedResource& resource, const char* data, int length)
912 {
913     ASSERT_UNUSED(resource, &resource == m_mainResource);
914     dataReceived(data, length);
915 }
916
917 void DocumentLoader::dataReceived(const char* data, int length)
918 {
919 #if ENABLE(CONTENT_FILTERING)
920     if (m_contentFilter && !m_contentFilter->continueAfterDataReceived(data, length))
921         return;
922 #endif
923
924     ASSERT(data);
925     ASSERT(length);
926     ASSERT(!m_response.isNull());
927
928     // There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred.
929     // See <rdar://problem/6304600> for more details.
930 #if !USE(CF)
931     ASSERT(!mainResourceLoader() || !mainResourceLoader()->defersLoading());
932 #endif
933
934     if (m_identifierForLoadWithoutResourceLoader)
935         frameLoader()->notifier().dispatchDidReceiveData(this, m_identifierForLoadWithoutResourceLoader, data, length, -1);
936
937     m_applicationCacheHost->mainResourceDataReceived(data, length, -1, false);
938     m_timeOfLastDataReceived = monotonicallyIncreasingTime();
939
940     if (!isMultipartReplacingLoad())
941         commitLoad(data, length);
942 }
943
944 void DocumentLoader::setupForReplace()
945 {
946     if (!mainResourceData())
947         return;
948
949     frameLoader()->client().willReplaceMultipartContent();
950     
951     maybeFinishLoadingMultipartContent();
952     maybeCreateArchive();
953     m_writer.end();
954     frameLoader()->setReplacing();
955     m_gotFirstByte = false;
956     
957     stopLoadingSubresources();
958     stopLoadingPlugIns();
959 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
960     clearArchiveResources();
961 #endif
962 }
963
964 void DocumentLoader::checkLoadComplete()
965 {
966     if (!m_frame || isLoading())
967         return;
968
969     ASSERT(this == frameLoader()->activeDocumentLoader());
970     m_frame->document()->domWindow()->finishedLoading();
971 }
972
973 void DocumentLoader::attachToFrame(Frame& frame)
974 {
975     if (m_frame == &frame)
976         return;
977
978     ASSERT(!m_frame);
979     m_frame = &frame;
980     m_writer.setFrame(&frame);
981     attachToFrame();
982
983 #ifndef NDEBUG
984     m_hasEverBeenAttached = true;
985 #endif
986 }
987
988 void DocumentLoader::attachToFrame()
989 {
990     ASSERT(m_frame);
991 }
992
993 void DocumentLoader::detachFromFrame()
994 {
995 #ifndef NDEBUG
996     if (m_hasEverBeenAttached)
997         ASSERT_WITH_MESSAGE(m_frame, "detachFromFrame() is being called on a DocumentLoader twice without an attachToFrame() inbetween");
998     else
999         ASSERT_WITH_MESSAGE(m_frame, "detachFromFrame() is being called on a DocumentLoader that has never attached to any Frame");
1000 #endif
1001     RefPtr<Frame> protectedFrame(m_frame);
1002     Ref<DocumentLoader> protectedThis(*this);
1003
1004     // It never makes sense to have a document loader that is detached from its
1005     // frame have any loads active, so kill all the loads.
1006     stopLoading();
1007     if (m_mainResource && m_mainResource->hasClient(*this))
1008         m_mainResource->removeClient(*this);
1009 #if ENABLE(CONTENT_FILTERING)
1010     if (m_contentFilter)
1011         m_contentFilter->stopFilteringMainResource();
1012 #endif
1013
1014     m_applicationCacheHost->setDOMApplicationCache(nullptr);
1015
1016     cancelPolicyCheckIfNeeded();
1017
1018     // 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.
1019     // This means either that a DocumentLoader is detaching twice, or is detaching before ever having attached.
1020     // Until we figure out how that is happening, null check m_frame before dereferencing it here.
1021     // <rdar://problem/21293082> and https://bugs.webkit.org/show_bug.cgi?id=146786
1022     if (m_frame)
1023         InspectorInstrumentation::loaderDetachedFromFrame(*m_frame, *this);
1024
1025     m_frame = nullptr;
1026 }
1027
1028 void DocumentLoader::clearMainResourceLoader()
1029 {
1030     m_loadingMainResource = false;
1031
1032     if (this == frameLoader()->activeDocumentLoader())
1033         checkLoadComplete();
1034 }
1035
1036 bool DocumentLoader::isLoadingInAPISense() const
1037 {
1038     // Once a frame has loaded, we no longer need to consider subresources,
1039     // but we still need to consider subframes.
1040     if (frameLoader()->state() != FrameStateComplete) {
1041         if (m_frame->settings().needsIsLoadingInAPISenseQuirk() && !m_subresourceLoaders.isEmpty())
1042             return true;
1043
1044         ASSERT(m_frame->document());
1045         auto& document = *m_frame->document();
1046         if ((isLoadingMainResource() || !document.loadEventFinished()) && isLoading())
1047             return true;
1048         if (m_cachedResourceLoader->requestCount())
1049             return true;
1050         if (document.processingLoadEvent())
1051             return true;
1052         if (document.hasActiveParser())
1053             return true;
1054     }
1055     return frameLoader()->subframeIsLoading();
1056 }
1057
1058 bool DocumentLoader::maybeCreateArchive()
1059 {
1060 #if !ENABLE(WEB_ARCHIVE) && !ENABLE(MHTML)
1061     return false;
1062 #else
1063     // Give the archive machinery a crack at this document. If the MIME type is not an archive type, it will return 0.
1064     m_archive = ArchiveFactory::create(m_response.url(), mainResourceData().get(), m_response.mimeType());
1065     if (!m_archive)
1066         return false;
1067     
1068     addAllArchiveResources(*m_archive);
1069     ASSERT(m_archive->mainResource());
1070     auto& mainResource = *m_archive->mainResource();
1071     m_parsedArchiveData = &mainResource.data();
1072     m_writer.setMIMEType(mainResource.mimeType());
1073
1074     ASSERT(m_frame->document());
1075     commitData(mainResource.data().data(), mainResource.data().size());
1076     return true;
1077 #endif
1078 }
1079
1080 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
1081
1082 void DocumentLoader::setArchive(Ref<Archive>&& archive)
1083 {
1084     m_archive = WTFMove(archive);
1085     addAllArchiveResources(*m_archive);
1086 }
1087
1088 void DocumentLoader::addAllArchiveResources(Archive& archive)
1089 {
1090     if (!m_archiveResourceCollection)
1091         m_archiveResourceCollection = std::make_unique<ArchiveResourceCollection>();
1092     m_archiveResourceCollection->addAllResources(archive);
1093 }
1094
1095 // FIXME: Adding a resource directly to a DocumentLoader/ArchiveResourceCollection seems like bad design, but is API some apps rely on.
1096 // Can we change the design in a manner that will let us deprecate that API without reducing functionality of those apps?
1097 void DocumentLoader::addArchiveResource(Ref<ArchiveResource>&& resource)
1098 {
1099     if (!m_archiveResourceCollection)
1100         m_archiveResourceCollection = std::make_unique<ArchiveResourceCollection>();
1101     m_archiveResourceCollection->addResource(WTFMove(resource));
1102 }
1103
1104 RefPtr<Archive> DocumentLoader::popArchiveForSubframe(const String& frameName, const URL& url)
1105 {
1106     return m_archiveResourceCollection ? m_archiveResourceCollection->popSubframeArchive(frameName, url) : nullptr;
1107 }
1108
1109 void DocumentLoader::clearArchiveResources()
1110 {
1111     m_archiveResourceCollection = nullptr;
1112     m_substituteResourceDeliveryTimer.stop();
1113 }
1114
1115 SharedBuffer* DocumentLoader::parsedArchiveData() const
1116 {
1117     return m_parsedArchiveData.get();
1118 }
1119
1120 #endif // ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
1121
1122 ArchiveResource* DocumentLoader::archiveResourceForURL(const URL& url) const
1123 {
1124     if (!m_archiveResourceCollection)
1125         return nullptr;
1126     auto* resource = m_archiveResourceCollection->archiveResourceForURL(url);
1127     if (!resource || resource->shouldIgnoreWhenUnarchiving())
1128         return nullptr;
1129     return resource;
1130 }
1131
1132 RefPtr<ArchiveResource> DocumentLoader::mainResource() const
1133 {
1134     RefPtr<SharedBuffer> data = mainResourceData();
1135     if (!data)
1136         data = SharedBuffer::create();
1137     auto& response = this->response();
1138     return ArchiveResource::create(WTFMove(data), response.url(), response.mimeType(), response.textEncodingName(), frame()->tree().uniqueName());
1139 }
1140
1141 RefPtr<ArchiveResource> DocumentLoader::subresource(const URL& url) const
1142 {
1143     if (!isCommitted())
1144         return nullptr;
1145     
1146     auto* resource = m_cachedResourceLoader->cachedResource(url);
1147     if (!resource || !resource->isLoaded())
1148         return archiveResourceForURL(url);
1149
1150     if (resource->type() == CachedResource::MainResource)
1151         return nullptr;
1152
1153     auto* data = resource->resourceBuffer();
1154     if (!data)
1155         return nullptr;
1156
1157     return ArchiveResource::create(data, url, resource->response());
1158 }
1159
1160 Vector<Ref<ArchiveResource>> DocumentLoader::subresources() const
1161 {
1162     if (!isCommitted())
1163         return { };
1164
1165     Vector<Ref<ArchiveResource>> subresources;
1166     for (auto& handle : m_cachedResourceLoader->allCachedResources().values()) {
1167         if (auto subresource = this->subresource({ ParsedURLString, handle->url() }))
1168             subresources.append(subresource.releaseNonNull());
1169     }
1170     return subresources;
1171 }
1172
1173 void DocumentLoader::deliverSubstituteResourcesAfterDelay()
1174 {
1175     if (m_pendingSubstituteResources.isEmpty())
1176         return;
1177     ASSERT(m_frame);
1178     ASSERT(m_frame->page());
1179     if (m_frame->page()->defersLoading())
1180         return;
1181
1182     if (!m_substituteResourceDeliveryTimer.isActive())
1183         m_substituteResourceDeliveryTimer.startOneShot(0);
1184 }
1185
1186 void DocumentLoader::substituteResourceDeliveryTimerFired()
1187 {
1188     if (m_pendingSubstituteResources.isEmpty())
1189         return;
1190     ASSERT(m_frame);
1191     ASSERT(m_frame->page());
1192     if (m_frame->page()->defersLoading())
1193         return;
1194
1195     auto pendingSubstituteResources = WTFMove(m_pendingSubstituteResources);
1196     for (auto& pendingSubstituteResource : pendingSubstituteResources) {
1197         auto& loader = pendingSubstituteResource.key;
1198         if (auto& resource = pendingSubstituteResource.value)
1199             resource->deliver(*loader);
1200         else {
1201             // A null resource means that we should fail the load.
1202             // FIXME: Maybe we should use another error here - something like "not in cache".
1203             loader->didFail(loader->cannotShowURLError());
1204         }
1205     }
1206 }
1207
1208 #ifndef NDEBUG
1209
1210 bool DocumentLoader::isSubstituteLoadPending(ResourceLoader* loader) const
1211 {
1212     return m_pendingSubstituteResources.contains(loader);
1213 }
1214
1215 #endif
1216
1217 void DocumentLoader::cancelPendingSubstituteLoad(ResourceLoader* loader)
1218 {
1219     if (m_pendingSubstituteResources.isEmpty())
1220         return;
1221     m_pendingSubstituteResources.remove(loader);
1222     if (m_pendingSubstituteResources.isEmpty())
1223         m_substituteResourceDeliveryTimer.stop();
1224 }
1225
1226 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
1227
1228 bool DocumentLoader::scheduleArchiveLoad(ResourceLoader& loader, const ResourceRequest& request)
1229 {
1230     if (auto* resource = archiveResourceForURL(request.url())) {
1231         scheduleSubstituteResourceLoad(loader, *resource);
1232         return true;
1233     }
1234
1235     if (!m_archive)
1236         return false;
1237
1238 #if ENABLE(WEB_ARCHIVE)
1239     // The idea of WebArchiveDebugMode is that we should fail instead of trying to fetch from the network.
1240     // Returning true ensures the caller will not try to fetch from the network.
1241     if (m_frame->settings().webArchiveDebugModeEnabled() && responseMIMEType() == "application/x-webarchive")
1242         return true;
1243 #endif
1244
1245     // If we want to load from the archive only, then we should always return true so that the caller
1246     // does not try to fetch form the network.
1247     return m_archive->shouldLoadFromArchiveOnly();
1248 }
1249
1250 #endif
1251
1252 void DocumentLoader::scheduleSubstituteResourceLoad(ResourceLoader& loader, SubstituteResource& resource)
1253 {
1254     m_pendingSubstituteResources.set(&loader, &resource);
1255     deliverSubstituteResourcesAfterDelay();
1256 }
1257
1258 void DocumentLoader::addResponse(const ResourceResponse& response)
1259 {
1260     if (!m_stopRecordingResponses)
1261         m_responses.append(response);
1262 }
1263
1264 void DocumentLoader::stopRecordingResponses()
1265 {
1266     m_stopRecordingResponses = true;
1267     m_responses.shrinkToFit();
1268 }
1269
1270 void DocumentLoader::setTitle(const StringWithDirection& title)
1271 {
1272     if (m_pageTitle == title)
1273         return;
1274
1275     frameLoader()->willChangeTitle(this);
1276     m_pageTitle = title;
1277     frameLoader()->didChangeTitle(this);
1278 }
1279
1280 URL DocumentLoader::urlForHistory() const
1281 {
1282     // Return the URL to be used for history and B/F list.
1283     // Returns nil for WebDataProtocol URLs that aren't alternates
1284     // for unreachable URLs, because these can't be stored in history.
1285     if (m_substituteData.isValid() && !m_substituteData.shouldRevealToSessionHistory())
1286         return unreachableURL();
1287
1288     return m_originalRequestCopy.url();
1289 }
1290
1291 bool DocumentLoader::urlForHistoryReflectsFailure() const
1292 {
1293     return m_substituteData.isValid() || m_response.httpStatusCode() >= 400;
1294 }
1295
1296 URL DocumentLoader::documentURL() const
1297 {
1298     URL url = substituteData().response().url();
1299 #if ENABLE(WEB_ARCHIVE)
1300     if (url.isEmpty() && m_archive && m_archive->shouldUseMainResourceURL())
1301         url = m_archive->mainResource()->url();
1302 #endif
1303     if (url.isEmpty())
1304         url = m_request.url();
1305     if (url.isEmpty())
1306         url = m_response.url();
1307     return url;
1308 }
1309
1310 #if PLATFORM(IOS)
1311
1312 // FIXME: This method seems to violate the encapsulation of this class.
1313 void DocumentLoader::setResponseMIMEType(const String& responseMimeType)
1314 {
1315     m_response.setMimeType(responseMimeType);
1316 }
1317
1318 #endif
1319
1320 void DocumentLoader::setDefersLoading(bool defers)
1321 {
1322     // Multiple frames may be loading the same main resource simultaneously. If deferral state changes,
1323     // each frame's DocumentLoader will try to send a setDefersLoading() to the same underlying ResourceLoader. Ensure only
1324     // the "owning" DocumentLoader does so, as setDefersLoading() is not resilient to setting the same value repeatedly.
1325     if (mainResourceLoader() && mainResourceLoader()->documentLoader() == this)
1326         mainResourceLoader()->setDefersLoading(defers);
1327
1328     setAllDefersLoading(m_subresourceLoaders, defers);
1329     setAllDefersLoading(m_plugInStreamLoaders, defers);
1330     if (!defers)
1331         deliverSubstituteResourcesAfterDelay();
1332 }
1333
1334 void DocumentLoader::setMainResourceDataBufferingPolicy(DataBufferingPolicy dataBufferingPolicy)
1335 {
1336     if (m_mainResource)
1337         m_mainResource->setDataBufferingPolicy(dataBufferingPolicy);
1338 }
1339
1340 void DocumentLoader::stopLoadingPlugIns()
1341 {
1342     cancelAll(m_plugInStreamLoaders);
1343 }
1344
1345 void DocumentLoader::stopLoadingSubresources()
1346 {
1347     cancelAll(m_subresourceLoaders);
1348     ASSERT(m_subresourceLoaders.isEmpty());
1349 }
1350
1351 void DocumentLoader::addSubresourceLoader(ResourceLoader* loader)
1352 {
1353     // The main resource's underlying ResourceLoader will ask to be added here.
1354     // It is much simpler to handle special casing of main resource loads if we don't
1355     // let it be added. In the main resource load case, mainResourceLoader()
1356     // will still be null at this point, but m_gotFirstByte should be false here if and only
1357     // if we are just starting the main resource load.
1358     if (!m_gotFirstByte)
1359         return;
1360     ASSERT(loader->identifier());
1361     ASSERT(!m_subresourceLoaders.contains(loader->identifier()));
1362     ASSERT(!mainResourceLoader() || mainResourceLoader() != loader);
1363
1364     // A page in the PageCache or about to enter PageCache should not be able to start loads.
1365     ASSERT_WITH_SECURITY_IMPLICATION(!document() || document()->pageCacheState() == Document::NotInPageCache);
1366
1367     m_subresourceLoaders.add(loader->identifier(), loader);
1368 }
1369
1370 void DocumentLoader::removeSubresourceLoader(ResourceLoader* loader)
1371 {
1372     ASSERT(loader->identifier());
1373
1374     if (!m_subresourceLoaders.remove(loader->identifier()))
1375         return;
1376     checkLoadComplete();
1377     if (Frame* frame = m_frame)
1378         frame->loader().checkLoadComplete();
1379 }
1380
1381 void DocumentLoader::addPlugInStreamLoader(ResourceLoader& loader)
1382 {
1383     ASSERT(loader.identifier());
1384     ASSERT(!m_plugInStreamLoaders.contains(loader.identifier()));
1385
1386     m_plugInStreamLoaders.add(loader.identifier(), &loader);
1387 }
1388
1389 void DocumentLoader::removePlugInStreamLoader(ResourceLoader& loader)
1390 {
1391     ASSERT(loader.identifier());
1392     ASSERT(&loader == m_plugInStreamLoaders.get(loader.identifier()));
1393
1394     m_plugInStreamLoaders.remove(loader.identifier());
1395     checkLoadComplete();
1396 }
1397
1398 bool DocumentLoader::isMultipartReplacingLoad() const
1399 {
1400     return isLoadingMultipartContent() && frameLoader()->isReplacing();
1401 }
1402
1403 bool DocumentLoader::maybeLoadEmpty()
1404 {
1405     bool shouldLoadEmpty = !m_substituteData.isValid() && (m_request.url().isEmpty() || SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(m_request.url().protocol().toStringWithoutCopying()));
1406     if (!shouldLoadEmpty && !frameLoader()->client().representationExistsForURLScheme(m_request.url().protocol().toStringWithoutCopying()))
1407         return false;
1408
1409     if (m_request.url().isEmpty() && !frameLoader()->stateMachine().creatingInitialEmptyDocument()) {
1410         m_request.setURL(blankURL());
1411         if (isLoadingMainResource())
1412             frameLoader()->client().dispatchDidChangeProvisionalURL();
1413     }
1414
1415     String mimeType = shouldLoadEmpty ? "text/html" : frameLoader()->client().generatedMIMETypeForURLScheme(m_request.url().protocol().toStringWithoutCopying());
1416     m_response = ResourceResponse(m_request.url(), mimeType, 0, String());
1417     finishedLoading(monotonicallyIncreasingTime());
1418     return true;
1419 }
1420
1421 void DocumentLoader::startLoadingMainResource()
1422 {
1423     m_mainDocumentError = ResourceError();
1424     timing().markStartTimeAndFetchStart();
1425     ASSERT(!m_mainResource);
1426     ASSERT(!m_loadingMainResource);
1427     m_loadingMainResource = true;
1428
1429     if (maybeLoadEmpty()) {
1430         RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Returning empty document (frame = %p, main = %d)", m_frame, m_frame ? m_frame->isMainFrame() : false);
1431         return;
1432     }
1433
1434 #if ENABLE(CONTENT_FILTERING)
1435     m_contentFilter = !m_substituteData.isValid() ? ContentFilter::create(*this) : nullptr;
1436 #endif
1437
1438     // FIXME: Is there any way the extra fields could have not been added by now?
1439     // If not, it would be great to remove this line of code.
1440     // Note that currently, some requests may have incorrect extra fields even if this function has been called,
1441     // because we pass a wrong loadType (see FIXME in addExtraFieldsToMainResourceRequest()).
1442     frameLoader()->addExtraFieldsToMainResourceRequest(m_request);
1443
1444     ASSERT(timing().startTime());
1445     ASSERT(timing().fetchStart());
1446
1447     Ref<DocumentLoader> protectedThis(*this); // willSendRequest() may deallocate the provisional loader (which may be us) if it cancels the load.
1448     willSendRequest(m_request, ResourceResponse());
1449
1450     // willSendRequest() may lead to our Frame being detached or cancelling the load via nulling the ResourceRequest.
1451     if (!m_frame || m_request.isNull()) {
1452         RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Load canceled after willSendRequest (frame = %p, main = %d)", m_frame, m_frame ? m_frame->isMainFrame() : false);
1453         return;
1454     }
1455
1456     m_applicationCacheHost->maybeLoadMainResource(m_request, m_substituteData);
1457
1458     if (m_substituteData.isValid() && m_frame->page()) {
1459         RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Returning cached main resource (frame = %p, main = %d)", m_frame, m_frame->isMainFrame());
1460         m_identifierForLoadWithoutResourceLoader = m_frame->page()->progress().createUniqueIdentifier();
1461         frameLoader()->notifier().assignIdentifierToInitialRequest(m_identifierForLoadWithoutResourceLoader, this, m_request);
1462         frameLoader()->notifier().dispatchWillSendRequest(this, m_identifierForLoadWithoutResourceLoader, m_request, ResourceResponse());
1463         handleSubstituteDataLoadSoon();
1464         return;
1465     }
1466
1467     ResourceRequest request(m_request);
1468     request.setRequester(ResourceRequest::Requester::Main);
1469     // If this is a reload the cache layer might have made the previous request conditional. DocumentLoader can't handle 304 responses itself.
1470     request.makeUnconditional();
1471
1472     RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Starting load (frame = %p, main = %d)", m_frame, m_frame->isMainFrame());
1473
1474     static NeverDestroyed<ResourceLoaderOptions> mainResourceLoadOptions(SendCallbacks, SniffContent, BufferData, AllowStoredCredentials, ClientCredentialPolicy::MayAskClientForCredentials, FetchOptions::Credentials::Include, SkipSecurityCheck, FetchOptions::Mode::NoCors, IncludeCertificateInfo, ContentSecurityPolicyImposition::SkipPolicyCheck, DefersLoadingPolicy::AllowDefersLoading, CachingPolicy::AllowCaching);
1475     m_mainResource = m_cachedResourceLoader->requestMainResource(CachedResourceRequest(ResourceRequest(request), mainResourceLoadOptions));
1476
1477 #if ENABLE(CONTENT_EXTENSIONS)
1478     if (m_mainResource && m_mainResource->errorOccurred() && m_frame->page() && m_mainResource->resourceError().domain() == ContentExtensions::WebKitContentBlockerDomain) {
1479         RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Blocked by content blocker error (frame = %p, main = %d)", m_frame, m_frame->isMainFrame());
1480         cancelMainResourceLoad(frameLoader()->blockedByContentBlockerError(m_request));
1481         return;
1482     }
1483 #endif
1484
1485     if (!m_mainResource) {
1486         if (!m_request.url().isValid()) {
1487             RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Unable to load main resource, URL is invalid (frame = %p, main = %d)", m_frame, m_frame->isMainFrame());
1488             cancelMainResourceLoad(frameLoader()->client().cannotShowURLError(m_request));
1489             return;
1490         }
1491
1492         RELEASE_LOG_IF_ALLOWED("startLoadingMainResource: Unable to load main resource, returning empty document (frame = %p, main = %d)", m_frame, m_frame->isMainFrame());
1493
1494         setRequest(ResourceRequest());
1495         // If the load was aborted by clearing m_request, it's possible the ApplicationCacheHost
1496         // is now in a state where starting an empty load will be inconsistent. Replace it with
1497         // a new ApplicationCacheHost.
1498         m_applicationCacheHost = std::make_unique<ApplicationCacheHost>(*this);
1499         maybeLoadEmpty();
1500         return;
1501     }
1502
1503     if (!mainResourceLoader()) {
1504         m_identifierForLoadWithoutResourceLoader = m_frame->page()->progress().createUniqueIdentifier();
1505         frameLoader()->notifier().assignIdentifierToInitialRequest(m_identifierForLoadWithoutResourceLoader, this, request);
1506         frameLoader()->notifier().dispatchWillSendRequest(this, m_identifierForLoadWithoutResourceLoader, request, ResourceResponse());
1507     }
1508
1509     becomeMainResourceClient();
1510
1511     // A bunch of headers are set when the underlying ResourceLoader is created, and m_request needs to include those.
1512     if (mainResourceLoader())
1513         request = mainResourceLoader()->originalRequest();
1514     // If there was a fragment identifier on m_request, the cache will have stripped it. m_request should include
1515     // the fragment identifier, so add that back in.
1516     if (equalIgnoringFragmentIdentifier(m_request.url(), request.url()))
1517         request.setURL(m_request.url());
1518     setRequest(request);
1519 }
1520
1521 void DocumentLoader::cancelPolicyCheckIfNeeded()
1522 {
1523     RELEASE_ASSERT(frameLoader());
1524
1525     if (m_waitingForContentPolicy || m_waitingForNavigationPolicy) {
1526         frameLoader()->policyChecker().cancelCheck();
1527         m_waitingForContentPolicy = false;
1528         m_waitingForNavigationPolicy = false;
1529     }
1530 }
1531
1532 void DocumentLoader::cancelMainResourceLoad(const ResourceError& resourceError)
1533 {
1534     Ref<DocumentLoader> protectedThis(*this);
1535     ResourceError error = resourceError.isNull() ? frameLoader()->cancelledError(m_request) : resourceError;
1536
1537     m_dataLoadTimer.stop();
1538
1539     cancelPolicyCheckIfNeeded();
1540
1541     if (mainResourceLoader())
1542         mainResourceLoader()->cancel(error);
1543
1544     clearMainResource();
1545
1546     mainReceivedError(error);
1547 }
1548
1549 void DocumentLoader::willContinueMainResourceLoadAfterRedirect(const ResourceRequest& newRequest)
1550 {
1551     setRequest(newRequest);
1552 }
1553
1554 void DocumentLoader::clearMainResource()
1555 {
1556     if (m_mainResource && m_mainResource->hasClient(*this))
1557         m_mainResource->removeClient(*this);
1558 #if ENABLE(CONTENT_FILTERING)
1559     if (m_contentFilter)
1560         m_contentFilter->stopFilteringMainResource();
1561 #endif
1562
1563     m_mainResource = nullptr;
1564 }
1565
1566 void DocumentLoader::subresourceLoaderFinishedLoadingOnePart(ResourceLoader* loader)
1567 {
1568     unsigned long identifier = loader->identifier();
1569     ASSERT(identifier);
1570
1571     if (!m_multipartSubresourceLoaders.add(identifier, loader).isNewEntry) {
1572         ASSERT(m_multipartSubresourceLoaders.get(identifier) == loader);
1573         ASSERT(!m_subresourceLoaders.contains(identifier));
1574     } else {
1575         ASSERT(m_subresourceLoaders.contains(identifier));
1576         m_subresourceLoaders.remove(identifier);
1577     }
1578
1579     checkLoadComplete();
1580     if (Frame* frame = m_frame)
1581         frame->loader().checkLoadComplete();    
1582 }
1583
1584 void DocumentLoader::maybeFinishLoadingMultipartContent()
1585 {
1586     if (!isMultipartReplacingLoad())
1587         return;
1588
1589     frameLoader()->setupForReplace();
1590     m_committed = false;
1591     RefPtr<SharedBuffer> resourceData = mainResourceData();
1592     commitLoad(resourceData->data(), resourceData->size());
1593 }
1594
1595 void DocumentLoader::iconLoadDecisionAvailable()
1596 {
1597     if (m_frame)
1598         m_frame->loader().icon().loadDecisionReceived(iconDatabase().synchronousLoadDecisionForIconURL(frameLoader()->icon().url(), this));
1599 }
1600
1601 static void iconLoadDecisionCallback(IconLoadDecision decision, void* context)
1602 {
1603     static_cast<DocumentLoader*>(context)->continueIconLoadWithDecision(decision);
1604 }
1605
1606 void DocumentLoader::getIconLoadDecisionForIconURL(const String& urlString)
1607 {
1608     if (m_iconLoadDecisionCallback)
1609         m_iconLoadDecisionCallback->invalidate();
1610     m_iconLoadDecisionCallback = IconLoadDecisionCallback::create(this, iconLoadDecisionCallback);
1611     iconDatabase().loadDecisionForIconURL(urlString, *m_iconLoadDecisionCallback);
1612 }
1613
1614 void DocumentLoader::continueIconLoadWithDecision(IconLoadDecision decision)
1615 {
1616     ASSERT(m_iconLoadDecisionCallback);
1617     m_iconLoadDecisionCallback = nullptr;
1618     if (m_frame)
1619         m_frame->loader().icon().continueLoadWithDecision(decision);
1620 }
1621
1622 static void iconDataCallback(SharedBuffer*, void*)
1623 {
1624     // FIXME: Implement this once we know what parts of WebCore actually need the icon data returned.
1625 }
1626
1627 void DocumentLoader::getIconDataForIconURL(const String& urlString)
1628 {   
1629     if (m_iconDataCallback)
1630         m_iconDataCallback->invalidate();
1631     m_iconDataCallback = IconDataCallback::create(this, iconDataCallback);
1632     iconDatabase().iconDataForIconURL(urlString, *m_iconDataCallback);
1633 }
1634
1635 void DocumentLoader::startIconLoading()
1636 {
1637     ASSERT(m_frame->loader().client().useIconLoadingClient());
1638
1639     static uint64_t nextIconCallbackID = 1;
1640
1641     auto* document = this->document();
1642     if (!document)
1643         return;
1644
1645     Vector<LinkIcon> icons = LinkIconCollector { *document }.iconsOfTypes({ LinkIconType::Favicon, LinkIconType::TouchIcon, LinkIconType::TouchPrecomposedIcon });
1646
1647     if (icons.isEmpty())
1648         icons.append({ m_frame->document()->completeURL(ASCIILiteral("/favicon.ico")), LinkIconType::Favicon, String(), std::nullopt });
1649
1650     for (auto& icon : icons) {
1651         auto result = m_iconsPendingLoadDecision.add(nextIconCallbackID++, icon);
1652         m_frame->loader().client().getLoadDecisionForIcon(icon, result.iterator->key);
1653     }
1654 }
1655
1656 void DocumentLoader::didGetLoadDecisionForIcon(bool decision, uint64_t loadIdentifier, uint64_t newCallbackID)
1657 {
1658     auto icon = m_iconsPendingLoadDecision.take(loadIdentifier);
1659     if (!decision || icon.url.isEmpty() || !m_frame)
1660         return;
1661
1662     auto iconLoader = std::make_unique<IconLoader>(*this, icon.url);
1663     iconLoader->startLoading();
1664     m_iconLoaders.set(WTFMove(iconLoader), newCallbackID);
1665 }
1666
1667 void DocumentLoader::finishedLoadingIcon(IconLoader& loader, SharedBuffer* buffer)
1668 {
1669     auto loadIdentifier = m_iconLoaders.take(&loader);
1670     ASSERT(loadIdentifier);
1671
1672     m_frame->loader().client().finishedLoadingIcon(loadIdentifier, buffer);
1673 }
1674
1675 void DocumentLoader::dispatchOnloadEvents()
1676 {
1677     m_wasOnloadDispatched = true;
1678     m_applicationCacheHost->stopDeferringEvents();
1679 }
1680
1681 void DocumentLoader::setTriggeringAction(const NavigationAction& action)
1682 {
1683     m_triggeringAction = action.copyWithShouldOpenExternalURLsPolicy(m_frame ? shouldOpenExternalURLsPolicyToPropagate() : m_shouldOpenExternalURLsPolicy);
1684 }
1685
1686 ShouldOpenExternalURLsPolicy DocumentLoader::shouldOpenExternalURLsPolicyToPropagate() const
1687 {
1688     if (!m_frame || !m_frame->isMainFrame())
1689         return ShouldOpenExternalURLsPolicy::ShouldNotAllow;
1690
1691     return m_shouldOpenExternalURLsPolicy;
1692 }
1693
1694 void DocumentLoader::becomeMainResourceClient()
1695 {
1696 #if ENABLE(CONTENT_FILTERING)
1697     if (m_contentFilter)
1698         m_contentFilter->startFilteringMainResource(*m_mainResource);
1699 #endif
1700     m_mainResource->addClient(*this);
1701 }
1702
1703 #if ENABLE(CONTENT_EXTENSIONS)
1704 void DocumentLoader::addPendingContentExtensionSheet(const String& identifier, StyleSheetContents& sheet)
1705 {
1706     ASSERT(!m_gotFirstByte);
1707     m_pendingNamedContentExtensionStyleSheets.set(identifier, &sheet);
1708 }
1709
1710 void DocumentLoader::addPendingContentExtensionDisplayNoneSelector(const String& identifier, const String& selector, uint32_t selectorID)
1711 {
1712     ASSERT(!m_gotFirstByte);
1713     auto addResult = m_pendingContentExtensionDisplayNoneSelectors.add(identifier, Vector<std::pair<String, uint32_t>>());
1714     addResult.iterator->value.append(std::make_pair(selector, selectorID));
1715 }
1716 #endif
1717
1718 bool DocumentLoader::isAlwaysOnLoggingAllowed() const
1719 {
1720     return !m_frame || m_frame->isAlwaysOnLoggingAllowed();
1721 }
1722
1723 #if USE(QUICK_LOOK)
1724
1725 void DocumentLoader::setQuickLookHandle(std::unique_ptr<QuickLookHandle> quickLookHandle)
1726 {
1727     m_quickLookHandle = WTFMove(quickLookHandle);
1728 }
1729
1730 #endif
1731
1732 } // namespace WebCore