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