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